프로젝트

일반

사용자정보

통계
| 개정판:

hytos / DTI_PID / DTI_PID / AppDocData.py @ b2e32d43

이력 | 보기 | 이력해설 | 다운로드 (211 KB)

1
# coding: utf-8
2
""" This is document data(SDI) class """
3

    
4
import sys
5
import os
6
import sqlite3
7
from datetime import datetime
8
from enum import Enum
9
from PIL import PngImagePlugin, JpegImagePlugin
10
from PIL import Image
11
from PIL.ImageQt import ImageQt
12

    
13
try:
14
    from PyQt5.QtCore import *
15
    from PyQt5.QtGui import *
16
    from PyQt5 import QtWidgets
17
except ImportError:
18
    from PyQt4.QtCore import *
19
    from PyQt4.QtGui import *
20

    
21
from SingletonInstance import SingletonInstance
22
import symbol
23
from NominalPipeSize import NominalPipeSize
24
from QtImageViewerScene import QtImageViewerScene
25

    
26

    
27
class Config:
28
    def __init__(self, section, key, value):
29
        """constructor"""
30
        self.section = section
31
        self.key = key
32
        self.value = value
33

    
34
    '''
35
        @brief  return size value string
36
        @author humkyung
37
        @date   2018.04.24
38
    '''
39
    def sizeValue(self):
40
        return self.inchStr if 'Inch' == self.sizeUnit else self.metricStr
41

    
42

    
43
'''
44
    @brief  Pipe color class
45
'''
46
class Color:
47
    def __init__(self, index, red, green, blue):
48
        self.index = index
49
        self.red = red
50
        self.green = green
51
        self.blue = blue
52

    
53

    
54
'''
55
    @brief      MessageType
56
    @author     humkyung 
57
    @date       2018.07.31
58
'''
59
class MessageType(Enum):
60
    Normal = 1
61
    Error = 2
62
    Check = 3
63

    
64

    
65
class AppDocData(SingletonInstance):
66
    DATABASE = 'ITI_PID.db'
67

    
68
    def __init__(self):
69
        from DisplayColors import DisplayColors
70

    
71
        self.delimiter = '!-!'
72

    
73
        self._imgFilePath = None
74
        self.imgName = None
75
        self._OCRData = None
76
        self._imgSrc = None
77

    
78
        self._areas = []
79
        self._colors = None
80
        self._lineNoProperties = None
81
        self._lineTypes = None
82
        self._lineTypeConfigs = None
83
        self._activeDrawing = None
84
        #self._hmbTable = None
85
        self._hmbColors = {}
86
        self._hmbData = None
87
        self._arsColors = {}
88
        self._streamLineListModelDatas = []
89
        self._titleBlockProperties = None
90
        self.needReOpening = None
91
        self.SpecBreakUpDownIndicator = []
92
        self.readOnly = False
93

    
94
        # item members are used only recognition except tracerLineNos for trim line no
95
        self.equipments = []
96
        self.lineNos = []
97
        self.lines = []
98
        self.texts = []
99
        self.symbols = []
100
        self.unknowns = []
101
        self.allItems = []
102
        self.tracerLineNos = []
103
        self.lineIndicators = []
104

    
105
        # for cad graphic items to sppid
106
        self.cadGraphics = []
107

    
108
        # caches
109
        self._lineNoPropertiesUID = {}
110
        self._attributeByType = {}
111
        self._connected_items_lists = None
112

    
113
        # caches not need to be clear
114
        self._configs = None
115
        self._symbolType = {}
116
        self._symbolNametList = {}
117
        self._symbolBase = {}
118

    
119
        # for load drawing data from database
120
        self._connecterss = {}
121
        self._associationss = {}
122
        self._attributess = {}
123

    
124
    def clearTempDBData(self):
125
        self._connecterss = {}
126
        self._associationss = {}
127
        self._attributess = {}
128

    
129
    def clearItemList(self, trim):
130
        '''
131
            @brief      clear item list
132
            @author     euisung
133
            @date       2018.11.28
134
        '''
135
        from QEngineeringInstLineNoTextItem import QEngineeringInstLineNoTextItem
136

    
137
        self.equipments.clear()
138
        self.symbols.clear()
139
        self.lineNos.clear()
140
        self.texts.clear()
141
        self.unknowns.clear()
142
        self.allItems.clear()
143
        self.lineIndicators.clear()
144
        if trim:
145
            self.tracerLineNos.clear()
146
            self.lines.clear()
147
            self._connected_items_lists = QEngineeringInstLineNoTextItem()
148

    
149
    def clearData(self):
150
        self._configs = None
151
        self._symbolType = {}
152
        self._symbolNametList = {}
153
        self._symbolBase = {}
154

    
155
        self._lineNoProperties = None
156
        self._lineNoPropertiesUID = {}
157
        self._attributeByType = {}
158

    
159
    '''
160
        @brief      clear
161
        @author     humkyung
162
        @date       2018.09.06
163
    '''
164
    def clear(self, past=None):
165
        from QEngineeringInstLineNoTextItem import QEngineeringInstLineNoTextItem
166

    
167
        if self.activeDrawing and self.activeDrawing.UID and self.activeDrawing.UID != past:
168
            self.clear_occupying_drawing(self.activeDrawing.UID)
169

    
170
        self._imgFilePath = None
171
        self.imgName = None
172
        self._imgSrc = None
173

    
174
        self._areas.clear()
175
        self.equipments.clear()
176
        self.lineNos.clear()
177
        self.lines.clear()
178
        self.texts.clear()
179
        self.symbols.clear()
180
        self.unknowns.clear()
181
        self.allItems.clear()
182
        self.tracerLineNos.clear()
183
        self.cadGraphics.clear()
184
        self.lineIndicators.clear()
185
        self.SpecBreakUpDownIndicator.clear()
186
        #self._colors = None
187
        #self._lineNoProperties = None
188
        self._lineTypeConfigs = None
189
        self._activeDrawing = None
190
        #self._hmbTable = None
191
        self._hmbColors = {}
192
        self._hmbData = None
193
        #self._arsColors = {}
194
        self._streamLineListModelDatas = []
195
        self._titleBlockProperties = None
196

    
197
        #self._configs = None# if not past else self._configs
198
        #self._symbolBase = {}# if not past else self._symbolBase
199
        #self._symbolType = {}# if not past else self._symbolType
200
        #self._lineNoPropertiesUID = {}
201
        self._attributeByType = {}
202
        self._connected_items_lists = QEngineeringInstLineNoTextItem()
203

    
204
        self._connecterss = {}
205
        self._associationss = {}
206
        self._attributess = {}
207

    
208
    def clear_occupying_drawing(self, drawing):
209
        """ clear drawing access """
210
        conn = self.project.database.connect()
211
        with conn:
212
            try:
213
                # Get a cursor object
214
                cursor = conn.cursor()
215
                if drawing:
216
                    sql = "UPDATE Drawings SET [OCCUPIED]=null WHERE [OCCUPIED]='{}' and UID='{}'".format(os.environ['COMPUTERNAME'], drawing)
217
                else:
218
                    sql = "UPDATE Drawings SET [OCCUPIED]=null"
219
                cursor.execute(sql)
220

    
221
                conn.commit()
222
            # Catch the exception
223
            except Exception as ex:
224
                conn.rollback()
225

    
226
                from App import App 
227
                message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename, sys.exc_info()[-1].tb_lineno)
228
                App.mainWnd().addMessage.emit(MessageType.Error, message)
229

    
230
    def set_occupying_drawing(self, drawing) -> str:
231
        """ set drawing access return true if success"""
232
        with self.project.database.connect() as conn:
233
            try:
234
                # Get a cursor object
235
                cursor = conn.cursor()
236
                sql = f"select OCCUPIED from Drawings where [UID]='{drawing}'"
237
                cursor.execute(sql)
238

    
239
                rows = cursor.fetchall()
240
                if not rows[0]['OCCUPIED'] or rows[0]['OCCUPIED'] == os.environ['COMPUTERNAME']:
241
                    sql = f"UPDATE Drawings SET [OCCUPIED]='{os.environ['COMPUTERNAME']}' WHERE UID='{drawing}'"
242
                    cursor.execute(sql)
243
                    conn.commit()
244
                    return None
245
                else:
246
                    return rows[0]['OCCUPIED']
247

    
248
            # Catch the exception
249
            except Exception as ex:
250
                conn.rollback()
251

    
252
                from App import App 
253
                message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename, sys.exc_info()[-1].tb_lineno)
254
                App.mainWnd().addMessage.emit(MessageType.Error, message)
255

    
256
                return None
257

    
258
    def winsort(self, data):
259
        """ Windows sort """
260

    
261
        from ctypes import wintypes, windll
262
        from functools import cmp_to_key
263

    
264
        _StrCmpLogicalW = windll.Shlwapi.StrCmpLogicalW
265
        _StrCmpLogicalW.argtypes = [wintypes.LPWSTR, wintypes.LPWSTR]
266
        _StrCmpLogicalW.restype  = wintypes.INT
267

    
268
        cmp_fnc = lambda psz1, psz2: _StrCmpLogicalW(psz1, psz2)
269

    
270
        #return sorted(data, key=cmp_to_key(cmp_fnc), reverse=True) #kitech
271
        return sorted(data, key=cmp_to_key(cmp_fnc))
272

    
273
    '''
274
        @brief      Get drawing file list
275
        @author     euisung
276
        @date       2018.09.28
277
    '''
278
    def getDrawingFileList(self):
279
        """ get drawing files which's extension is .png or jpg from drawing folder """
280
        drawingFileList = []
281

    
282
        try:
283
            project = AppDocData.instance().getCurrentProject()
284
            path = project.getDrawingFilePath()
285
            drawingFileList = [f for f in os.listdir(path) if os.path.isfile(os.path.join(path, f)) and
286
                               (os.path.splitext(f)[1].upper() == '.PNG' or os.path.splitext(f)[1].upper() == '.JPG' or
287
                                os.path.splitext(f)[1].upper() == '.JPEG')]
288
            
289
            drawingFileList = self.winsort(drawingFileList)
290
            #drawingFileList.sort()
291
        except Exception as ex:
292
            print('error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
293
                                                      sys.exc_info()[-1].tb_lineno))
294

    
295
        return drawingFileList
296

    
297
    '''
298
        @brief      Get Training file list
299
        @author     euisung
300
        @date       2018.10.16
301
    '''
302
    def getTrainingFileList(self):
303
        try:
304
            project = AppDocData.instance().getCurrentProject()
305
            path = project.getTrainingFilePath()
306
            trainingFileList = os.listdir(path)
307
            trainingFileList.sort()
308
        except Exception as ex:
309
            from App import App
310
            message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
311
                                                          sys.exc_info()[-1].tb_lineno)
312
            App.mainWnd().addMessage.emit(MessageType.Error, message)
313

    
314
        return trainingFileList
315

    
316
    def getTrainingSymbolFileList(self):
317
        """  Get Symbol Training file list """
318
        try:
319
            project = AppDocData.instance().getCurrentProject()
320
            path = project.getTrainingSymbolFilePath()
321
            symbolTrainingFileList = os.listdir(path)
322
            symbolTrainingFileList.sort()
323
        except Exception as ex:
324
            from App import App
325
            message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
326
                                                          sys.exc_info()[-1].tb_lineno)
327
            App.mainWnd().addMessage.emit(MessageType.Error, message)
328

    
329
        return symbolTrainingFileList
330

    
331
    '''
332
        @brief      Get DB file path in ProgramData
333
        @author     Jeongwoo
334
        @date       2018.06.27
335
        @history    2018.06.29  Jeongwoo    Change method to get template db path
336
    '''
337
    def getTemplateDbPath(self):
338
        path = os.path.join(os.getenv('ALLUSERSPROFILE'), 'Digital PID')
339
        templateDbPath = os.path.join(path, 'Template.db')
340
        return templateDbPath
341

    
342
    def get_template_symbol_library_path(self):
343
        """return template symbol library path"""
344

    
345
        path = os.path.join(os.getenv('USERPROFILE'), 'Digital PID')
346
        return os.path.join(path, 'SymbolLibrary.syl')
347

    
348
    def getAppDbPath(self):
349
        """
350
        @brief      Get application DB file path in ProgramData
351
        @author     humkyung
352
        @date       2018.10.01
353
        """
354

    
355
        path = os.path.join(os.getenv('USERPROFILE'), 'Digital PID')
356
        app_database = os.path.join(path, 'App.db')
357
        return app_database
358

    
359
    '''
360
        @brief  getter of colors 
361
        @author humkyung
362
        @date   2018.06.18
363
    '''
364
    @property
365
    def colors(self):
366
        import random
367

    
368
        if self._colors is None or self._colors == []:
369
            self._colors = []
370
            with self.project.database.connect() as conn:
371
                try:
372
                    cursor = conn.cursor()
373
                    sql = 'SELECT UID,RED,GREEN,BLUE FROM Colors'
374
                    cursor.execute(sql)
375
                    rows = cursor.fetchall()
376
                    for row in rows:
377
                        self._colors.append(Color(row['UID'], row['RED'], row['GREEN'], row['BLUE']))
378
                # Catch the exception
379
                except Exception as ex:
380
                    from App import App
381
                    message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
382
                                                                  sys.exc_info()[-1].tb_lineno)
383
                    App.mainWnd().addMessage.emit(MessageType.Error, message)
384

    
385
        return self._colors.pop(random.randrange(0, len(self._colors)))
386

    
387
    '''
388
        @brief  setter of colors
389
        @author humkyung
390
        @date   2018.06.18
391
    '''
392
    @colors.setter
393
    def colors(self, value):
394
        self._colors = value
395

    
396
    '''
397
        @brief      set image file path
398
        @author     humkyung
399
        @date       2018.07.30
400
    '''
401
    def setImgFilePath(self, path):
402
        self._imgFilePath = path
403
        self.imgName = os.path.splitext(os.path.basename(self._imgFilePath))[0]
404

    
405
    @staticmethod
406
    def my_imread(file_path):
407
        """ read a file which's name contains unicode string : ref http://devdoftech.co.kr:82/redmine/issues/631 """
408
        import numpy as np
409
        import cv2
410

    
411
        _bytes = None
412
        with open(file_path.encode('utf-8'), 'rb') as stream:
413
            _bytes = bytearray(stream.read())
414

    
415
        numpyArray = np.asarray(_bytes, dtype=np.uint8)
416
        res = cv2.imdecode(numpyArray, cv2.IMREAD_UNCHANGED)
417
        return res
418

    
419
    @property
420
    def imgSrc(self):
421
        """return the image of active drawing"""
422

    
423
        if self.activeDrawing:
424
            return self.activeDrawing.image
425

    
426
        return None
427

    
428
    @imgSrc.setter
429
    def imgSrc(self, value):
430
        """set the image of active drawing with given value"""
431

    
432
        if self.activeDrawing:
433
            self.activeDrawing.image = value
434

    
435
    '''
436
        @brief  getter of line type configs
437
        @author humkyung
438
        @date   2018.06.28
439
    '''
440
    @property
441
    def lineTypeConfigs(self):
442
        from PyQt5.QtCore import Qt
443

    
444
        if self._lineTypeConfigs is None:
445
            self._lineTypeConfigs = []
446

    
447
            styleMap = [('SolidLine', Qt.SolidLine), ('DashLine', Qt.DashLine), ('DotLine', Qt.DotLine),
448
                        ('DashDotLine', Qt.DashDotLine),
449
                        ('DashDotDotLine', Qt.DashDotDotLine), ('CustomDashLine', Qt.CustomDashLine)]
450

    
451
            configs = self.getConfigs('LineTypes')
452
            for config in configs:
453
                color, width, _style, transparent = config.value.split(',')
454
                matches = [param for param in styleMap if param[0] == _style]
455
                style = matches[0][1] if matches else Qt.SolidLine
456
                self._lineTypeConfigs.append((config.key, color, int(width), style, float(transparent)))
457

    
458
        return self._lineTypeConfigs
459

    
460
    '''
461
        @brief  setter of line type configs
462
        @author humkyung
463
        @date   2018.06.28
464
    '''
465
    @lineTypeConfigs.setter
466
    def lineTypeConfigs(self, value):
467
        self._lineTypeConfigs = value
468

    
469
    @property
470
    def drain_size(self):
471
        """ getter of drain_size """
472
        if not hasattr(self, '_drain_size') or not self._drain_size:
473
            configs = self.getConfigs('Drain Size Rule', 'Size')
474
            self._drain_size = configs[0].value if configs else '1"'
475

    
476
        return self._drain_size
477

    
478
    @drain_size.setter
479
    def drain_size(self, value):
480
        """ setter of drain_size """
481
        self._drain_size = value
482

    
483
    '''
484
        @brief      getter of hmb table
485
        @author     humkyung
486
        @date       2018.07.16
487
    '''
488
    '''
489
    @property
490
    def hmbTable(self):
491
        from HMBTable import HMBTable
492

493
        if self._hmbTable is None:
494
            self._hmbTable = HMBTable()
495
            self._hmbTable.load_data()
496

497
        return self._hmbTable
498
    '''
499

    
500
    '''
501
        @brief      setter of hmb table
502
        @author     humkyung
503
        @date       2018.07.16
504
    '''
505
    '''
506
    @hmbTable.setter
507
    def hmbTable(self, value):
508
        self._hmbTable = value
509
    '''
510

    
511
    '''
512
        @brief  get line type config of given line type
513
        @author humkyung
514
        @date   2018.06.28
515
    '''
516
    def getLineTypeConfig(self, lineType):
517
        from PyQt5.QtCore import Qt
518

    
519
        matches = [config for config in self.lineTypeConfigs if config[0] == lineType]
520
        return matches[0] if matches else (lineType, '#0000FF', 5, Qt.SolidLine, 50)
521

    
522
    def getCurrentPidSource(self):
523
        return self.activeDrawing.currentPidSource
524

    
525
    '''
526
        @brief      Check if exist file name or not
527
        @author     Jeongwoo
528
        @date       2018.05.03
529
    '''
530
    def isExistFileName(self, name):
531
        rows = None
532
        with self.project.database.connect() as conn:
533
            try:
534
                cursor = conn.cursor()
535
                sql = "SELECT * FROM Symbol WHERE name = '" + name + "'"
536
                cursor.execute(sql)
537
                rows = cursor.fetchall()
538
            # Catch the exception
539
            except Exception as ex:
540
                # Roll back any change if something goes wrong
541
                conn.rollback()
542
                print('error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
543
                                                          sys.exc_info()[-1].tb_lineno))
544
            finally:
545
                if rows is not None and len(rows) > 0:
546
                    return True
547
                else:
548
                    return False
549

    
550
    '''
551
        @brief      Insert new symbol into Symbol Table, Moved from SG_DbHelper
552
        @author     Jeongwoo
553
        @date       2018.05.03
554
    '''
555
    def insertSymbol(self, symbol):
556
        isAdded = False
557
        with self.project.database.connect() as conn:
558
            try:
559
                sql = self.project.database.to_sql("""
560
                    INSERT INTO Symbol(name, SymbolType_UID, threshold, minMatchPoint, isDetectOrigin, rotationCount, ocrOption, isContainChild, originalPoint, connectionPoint, baseSymbol, additionalSymbol, isExceptDetect, hasInstrumentLabel, width, height, flip, TextArea, type) 
561
                    VALUES(?, (select UID from SymbolType where Type=?), ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?);
562
                """)
563

    
564
                cursor = conn.cursor()
565
                query = (symbol.getName(), symbol.getType(), symbol.getThreshold()
566
                         , symbol.getMinMatchCount(), symbol.getIsDetectOnOrigin(), symbol.getRotationCount()
567
                         , symbol.getOcrOption(), symbol.getIsContainChild()
568
                         , symbol.getOriginalConvertingPoint(), symbol.getConnectionPoint()
569
                         , symbol.getBaseSymbol(), symbol.getAdditionalSymbol(), symbol.getIsExceptDetect(),
570
                         symbol.getHasInstrumentLabel()
571
                         , symbol.width, symbol.height, symbol.detectFlip, symbol.text_area_str, symbol.getDescAndInfoAndScale())
572
                cursor.execute(sql, query)
573
                conn.commit()
574
                isAdded = True
575
            # Catch the exception
576
            except Exception as ex:
577
                # Roll back any change if something goes wrong
578
                conn.rollback()
579

    
580
                from App import App
581
                message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
582
                                                              sys.exc_info()[-1].tb_lineno)
583
                App.mainWnd().addMessage.emit(MessageType.Error, message)
584
            finally:
585
                return (isAdded, symbol.getType(), symbol.getName(), symbol.getPath())
586

    
587
    '''
588
        @brief      Update symbol in Symbol Table, Moved from SG_DbHelper
589
        @author     Jeongwoo
590
        @date       2018.05.03
591
    '''
592
    def updateSymbol(self, symbol):
593
        isUpdated = False
594

    
595
        with self.project.database.connect() as conn:
596
            try:
597
                sql = self.project.database.to_sql("""
598
                    UPDATE Symbol
599
                    SET
600
                        name = ?, SymbolType_UID=(select UID from SymbolType where Type=?), threshold=?, 
601
                        minMatchPoint=?, isDetectOrigin=?, rotationCount=?, ocrOption=?, isContainChild=?, 
602
                        originalPoint=?, connectionPoint=?, baseSymbol=?, additionalSymbol=?, isExceptDetect=?, 
603
                        hasInstrumentLabel=?, width=?, height=?, flip=?, TextArea=?, type=? WHERE uid = ?
604
                """)
605

    
606
                cursor = conn.cursor()
607
                query = (symbol.getName(), symbol.getType(), symbol.getThreshold()
608
                         , symbol.getMinMatchCount(), symbol.getIsDetectOnOrigin(), symbol.getRotationCount()
609
                         , symbol.getOcrOption(), symbol.getIsContainChild()
610
                         , symbol.getOriginalConvertingPoint(), symbol.getConnectionPoint()
611
                         , symbol.getBaseSymbol(), symbol.getAdditionalSymbol(), symbol.getIsExceptDetect(),
612
                         symbol.getHasInstrumentLabel(), symbol.width, symbol.height, symbol.detectFlip, symbol.text_area_str, symbol.getDescAndInfoAndScale(), 
613
                         symbol.getUid())
614
                cursor.execute(sql, query)
615
                conn.commit()
616
                isUpdated = True
617
            # Catch the exception
618
            except Exception as ex:
619
                # Roll back any change if something goes wrong
620
                conn.rollback()
621

    
622
                from App import App
623
                message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
624
                                                              sys.exc_info()[-1].tb_lineno)
625
                App.mainWnd().addMessage.emit(MessageType.Error, message)
626
            finally:
627
                self._symbolBase = {}
628
                return (isUpdated, symbol.getType(), symbol.getName(), symbol.getPath())
629

    
630
    def getSymbolPreset(self):
631
        """ get symbol preset """
632
        presets = []
633
        with self.project.database.connect() as conn:
634
            try:
635
                cursor = conn.cursor()
636
                sql = 'SELECT [UID], [Find], [Target], [Action], [Condition] FROM SymbolPreset'
637
                cursor.execute(sql)
638
                rows = cursor.fetchall()
639
                for row in rows:
640
                    presets.append([row['Find'], row['Target'], row['Action'], row['Condition']])
641
            # Catch the exception
642
            except Exception as ex:
643
                from App import App
644
                message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
645
                                                                sys.exc_info()[-1].tb_lineno)
646
                App.mainWnd().addMessage.emit(MessageType.Error, message)
647

    
648
                return []
649

    
650
        return presets
651

    
652
    def saveSymbolPreset(self, presets):
653
        """ save symbol preset """
654
        import uuid
655

    
656
        conn = self.project.database.connect()
657
        with conn:
658
            try:
659
                # Get a cursor object
660
                cursor = conn.cursor()
661

    
662
                sql = "delete from SymbolPreset"
663
                cursor.execute(sql)
664

    
665
                for preset in presets:
666
                    sql = self.project.database.to_sql("insert into [SymbolPreset]([UID], [Find], [Target], [Action], [Condition]) values(?,?,?,?,?)")
667
                    param = (str(uuid.uuid4()), preset[0], preset[1], preset[2], preset[3])
668
                    cursor.execute(sql, param)
669
                conn.commit()
670

    
671
            except Exception as ex:
672
                # Roll back any change if something goes wrong
673
                conn.rollback()
674
                from App import App
675
                from AppDocData import MessageType
676
                message = 'error occurred({}) in {}:{}'.format(repr(ex), sys.exc_info()[-1].tb_frame.f_code.co_filename,
677
                                                                sys.exc_info()[-1].tb_lineno)
678
                App.mainWnd().addMessage.emit(MessageType.Error, message)
679
        
680

    
681
    def getTargetSymbolList(self, all=False):
682
        """get symbol list to be detected except isExceptDetect field is unset"""
683
        targetSymbolList = []
684

    
685
        with self.project.database.connect() as conn:
686
            cursor = conn.cursor()
687
            if not all:
688
                sql = """SELECT a.UID,a.Name,b.Type,a.Threshold,a.MinMatchPoint,a.IsDetectOrigin,a.RotationCount,
689
                a.OCROption,a.IsContainChild,a.OriginalPoint,a.ConnectionPoint,a.BaseSymbol,a.AdditionalSymbol,a.Width,a.Height,
690
                a.IsExceptDetect,a.HasInstrumentLabel,a.flip,a.TextArea,b.UID as DB_UID,a.Type as [Desc] FROM Symbol a inner join SymbolType b on 
691
                a.SymbolType_UID=b.UID WHERE a.IsExceptDetect = 0 and a.[SymbolType_UID] != -1 order by width * height desc"""
692
            else:
693
                sql = """SELECT a.UID,a.Name,b.Type,a.Threshold,a.MinMatchPoint,a.IsDetectOrigin,a.RotationCount,
694
                a.OCROption,a.IsContainChild,a.OriginalPoint,a.ConnectionPoint,a.BaseSymbol,a.AdditionalSymbol,a.Width,a.Height,
695
                a.IsExceptDetect,a.HasInstrumentLabel,a.flip,a.TextArea,b.UID as DB_UID,a.Type as [Desc] FROM Symbol a inner join SymbolType b on 
696
                a.SymbolType_UID=b.UID WHERE a.[SymbolType_UID] != -1 order by width * height desc"""
697
            try:
698
                cursor.execute(sql)
699
                rows = cursor.fetchall()
700
                for row in rows:
701
                    sym = symbol.SymbolBase(row['Name'], row['Type'], row['Threshold'],
702
                                                row['MinMatchPoint'], row['IsDetectOrigin'],
703
                                                row['RotationCount'], row['OCROption'],
704
                                                row['IsContainChild'], row['OriginalPoint'],
705
                                                row['ConnectionPoint'], row['BaseSymbol'],
706
                                                row['AdditionalSymbol'], row['IsExceptDetect'],
707
                                                row['HasInstrumentLabel'], row['UID'],
708
                                                iType=row['DB_UID'], width=row['Width'], height=row['Height'],
709
                                                detectFlip=row['flip'], text_area=row['TextArea'], desc=row['Desc'])
710
                    targetSymbolList.append(sym)
711
            except Exception as ex:
712
                print('error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
713
                                                          sys.exc_info()[-1].tb_lineno))
714

    
715
        return targetSymbolList
716

    
717
    def get_favorite_libraries(self):
718
        res = []
719

    
720
        with self.project.database.connect() as conn:
721
            cursor = conn.cursor()
722
            sql = f"select UID,Symbol_UID from Libraries where [User]='{os.environ['COMPUTERNAME'].upper()}'"
723
            try:
724
                cursor.execute(sql)
725
                return cursor.fetchall()
726
            except Exception as ex:
727
                print('error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
728
                                                          sys.exc_info()[-1].tb_lineno))
729

    
730
        return None
731

    
732
    def buildAppDatabase(self):
733
        """build application database"""
734
        path = os.path.join(os.getenv('USERPROFILE'), 'Digital PID')
735
        appDatabaseFilePath = os.path.join(path, 'App.db')
736

    
737
        # Creates or opens a file called mydb with a SQLite3 DB
738
        with sqlite3.connect(appDatabaseFilePath) as conn:
739
            try:
740
                # Get a cursor object
741
                cursor = conn.cursor()
742

    
743
                sqlFiles = ['App.Configuration.sql', 'App.Styles.sql']
744
                for sqlFile in sqlFiles:
745
                    filePath = os.path.join(os.path.dirname(os.path.realpath(__file__)), 'Scripts', sqlFile)
746
                    try:
747
                        file = QFile(filePath)
748
                        file.open(QFile.ReadOnly)
749
                        sql = file.readAll()
750
                        sql = str(sql, encoding='utf8')
751
                        cursor.executescript(sql)
752
                    finally:
753
                        file.close()
754
                conn.commit()
755
            # Catch the exception
756
            except Exception as ex:
757
                # Roll back any change if something goes wrong
758
                conn.rollback()
759
                print('error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
760
                                                          sys.exc_info()[-1].tb_lineno))
761

    
762
        # expiration date is 2019-11-9-23-59-59 : e52SoJJRdZ-apJuhlFWtnFWC
763
        # configs = [Config('app', 'error origin point', '51,72'), Config('app', 'expiration', 'e52SoJJRdZ-apJuhlFWtnFWC')]
764

    
765
        configs = self.getAppConfigs('app', 'license')
766
        if configs and len(configs[0].value.split('.')) == 3:
767
            pass
768
        else:
769
            configs = self.getAppConfigs('app', 'expiration')
770
            if not configs:
771
                configs = self.getAppConfigs('app', 'license')
772
                if configs and 'DOFTECH' in configs[0].value:
773
                    self.deleteAppConfigs('app', 'mode')
774
                    configs = None
775
                else:
776
                    configs = [Config('app', 'mode', 'advanced')]
777
            else:
778
                configs = None
779

    
780
            if configs:
781
                self.saveAppConfigs(configs)
782

    
783
    '''
784
        @brief  load app style
785
        @author humkyung
786
        @date   2018.04.20
787
    '''
788
    def loadAppStyle(self):
789
        style = 'Fusion'
790

    
791
        path = os.path.join(os.getenv('USERPROFILE'), 'Digital PID')
792
        if not os.path.exists(path): os.makedirs(path)
793

    
794
        self.buildAppDatabase()
795
        try:
796
            appDatabaseFilePath = os.path.join(path, 'App.db')
797
            # Creates or opens a file called mydb with a SQLite3 DB
798
            conn = sqlite3.connect(appDatabaseFilePath)
799
            # Get a cursor object
800
            cursor = conn.cursor()
801

    
802
            sql = "select Value from Configuration where Section='App' and Key='Style'"
803
            cursor.execute(sql)
804
            rows = cursor.fetchall()
805
            style = rows[0][0] if 1 == len(rows) else 'Fusion'
806
        # Catch the exception
807
        except Exception as ex:
808
            # Roll back any change if something goes wrong
809
            conn.rollback()
810
            print('error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
811
                                                      sys.exc_info()[-1].tb_lineno))
812
        finally:
813
            # Close the db connection
814
            conn.close()
815

    
816
        return style
817

    
818
    '''
819
        @brief  load app styles and then return a list
820
        @author humkyung
821
        @date   2018.04.20
822
    '''
823
    def loadAppStyles(self):
824
        styles = []
825

    
826
        try:
827
            self.buildAppDatabase()
828

    
829
            path = os.path.join(os.getenv('USERPROFILE'), 'Digital PID')
830
            appDatabaseFilePath = os.path.join(path, 'App.db')
831

    
832
            # Creates or opens a file called mydb with a SQLite3 DB
833
            conn = sqlite3.connect(appDatabaseFilePath)
834
            # Get a cursor object
835
            cursor = conn.cursor()
836

    
837
            sql = 'select UID,Value from Styles'
838
            cursor.execute(sql)
839
            rows = cursor.fetchall()
840
            for row in rows: styles.append(row[1])
841
            if 0 == len(rows): rows.append('fusion')
842
        # Catch the exception
843
        except Exception as ex:
844
            # Roll back any change if something goes wrong
845
            conn.rollback()
846
            print('error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
847
                                                      sys.exc_info()[-1].tb_lineno))
848
        finally:
849
            # Close the db connection
850
            conn.close()
851

    
852
        return styles
853

    
854
    '''
855
        @brief  Set current Project
856
        @history    2018.06.27  Jeongwoo    If DB file is not, copy DB file from ProgramData
857
    '''
858
    def setCurrentProject(self, project):
859
        self.project = project
860
        project.make_sub_directories()
861
        try:
862
            # save size unit
863
            #self.saveConfigs([Config('Project', 'Unit', project.prj_unit)])
864

    
865
            if self.project.database.db_type == 'SQLite':
866
                # Creates or opens a file called mydb with a SQLite3 DB
867
                db_path = self.project.database.file_path
868

    
869
                if not os.path.isfile(db_path):
870
                    templatePath = self.getTemplateDbPath()
871
                    templateFile = QFile(templatePath)
872
                    templateFile.copy(db_path)
873

    
874
                try:
875
                    conn = self.project.database.connect()
876
                    with conn:
877
                        # Get a cursor object
878
                        cursor = conn.cursor()
879

    
880
                        fileNames = os.listdir(os.path.join(os.path.dirname(os.path.realpath(__file__)), 'Scripts'))
881
                        for fileName in fileNames:
882
                            if fileName.endswith(".sql") and ('SQLite_Project' == os.path.splitext(fileName)[0].split('.')[0]):
883
                                try:
884
                                    file = QFile(
885
                                        os.path.join(os.path.dirname(os.path.realpath(__file__)), 'Scripts', fileName))
886
                                    file.open(QFile.ReadOnly)
887
                                    sql = file.readAll()
888
                                    sql = str(sql, encoding='utf8')
889
                                    cursor.executescript(sql)
890
                                finally:
891
                                    file.close()
892
                        conn.commit()
893
                except Exception as ex:
894
                    print('error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
895
                                                              sys.exc_info()[-1].tb_lineno))
896
        # Catch the exception
897
        except Exception as ex:
898
            # Roll back any change if something goes wrong
899
            print('error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
900
                                                      sys.exc_info()[-1].tb_lineno))
901
        finally:
902
            pass
903

    
904
    '''
905
        @brief  Get current Project
906
    '''
907
    def getCurrentProject(self):
908
        return self.project
909

    
910
    '''
911
        @brief      return project database path
912
        @history    humkyung 2018.04.19 return Project.db in Program Data folder instead of PROJECT_DB_PATH variable
913
    '''
914
    def getPrjDatabasePath(self):
915
        path = os.path.join(os.getenv('USERPROFILE'), 'Digital PID')
916
        if not os.path.exists(path): os.makedirs(path)
917

    
918
        prjDatabaseFilePath = os.path.join(path, 'Project.db')
919
        try:
920
            # Creates or opens a file called mydb with a SQLite3 DB
921
            conn = sqlite3.connect(prjDatabaseFilePath)
922
            # Get a cursor object
923
            cursor = conn.cursor()
924

    
925
            filePath = os.path.join(os.path.dirname(os.path.realpath(__file__)), 'Scripts', 'Project.Projects.sql')
926
            try:
927
                file = QFile(filePath)
928
                file.open(QFile.ReadOnly)
929
                sql = file.readAll()
930
                sql = str(sql, encoding='utf8')
931
                cursor.executescript(sql)
932
            finally:
933
                file.close()
934
            conn.commit()
935
        # Catch the exception
936
        except Exception as ex:
937
            # Roll back any change if something goes wrong
938
            conn.rollback()
939
            print('error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
940
                                                      sys.exc_info()[-1].tb_lineno))
941
        finally:
942
            # Close the db connection
943
            conn.close()
944

    
945
        return prjDatabaseFilePath
946

    
947
    def getErrorItemSvgPath(self):
948
        '''
949
            @brief  return error item svg path
950
            @author euisung
951
            @date   2019.04.02
952
        '''
953
        return os.path.join(os.getenv('USERPROFILE'), 'Digital PID', 'Explode.svg')
954

    
955
    def updateTitleBlockProperties(self, titleBlockProps):
956
        '''
957
            @brief  update title block properties
958
            @author euisung
959
            @date   2018.11.09
960
        '''
961
        try:
962
            originTitleBlockProps = self.getTitleBlockProperties()
963
            deletedTitleBlockProps = []
964
            for originTitleBlockProp in originTitleBlockProps:
965
                for titleBlockProp in titleBlockProps:
966
                    # uid compare for determine delete props
967
                    if originTitleBlockProp[0] == titleBlockProp[0]:
968
                        break
969
                deletedTitleBlockProps.append(originTitleBlockProp[0])
970

    
971
            # Creates or opens a file called mydb with a SQLite3 DB
972
            conn = self.project.database.connect()
973
            with conn:
974
                try:
975
                    # Get a cursor object
976
                    cursor = conn.cursor()
977

    
978
                    for deletedTitleBlockProp in deletedTitleBlockProps:
979
                        sql = "delete from TitleBlockValues where TitleBlockProperties_UID='{}'".format(deletedTitleBlockProp)
980
                        cursor.execute(sql)
981
                        sql = "delete from TitleBlockProperties where UID='{}'".format(deletedTitleBlockProp)
982
                        cursor.execute(sql)
983

    
984
                    for titleBlockProp in titleBlockProps:
985
                        sql = self.project.database.to_sql("insert into [TitleBlockProperties]([UID], [NAME], [AREA], [TEXT]) values(?,?,?,?)")
986
                        param = (titleBlockProp[0], titleBlockProp[1], titleBlockProp[2], titleBlockProp[3])  # uid, name, area, text
987
                        cursor.execute(sql, param)
988
                    conn.commit()
989
                    # Catch the exception
990
                except Exception as ex:
991
                    # Roll back any change if something goes wrong
992
                    conn.rollback()
993
                    from App import App
994
                    from AppDocData import MessageType
995
                    message = 'error occurred({}) in {}:{}'.format(repr(ex), sys.exc_info()[-1].tb_frame.f_code.co_filename,
996
                                                                   sys.exc_info()[-1].tb_lineno)
997
                    App.mainWnd().addMessage.emit(MessageType.Error, message)
998
        # Catch the exception
999
        except Exception as ex:
1000
            from App import App
1001
            from AppDocData import MessageType
1002
            message = 'error occurred({}) in {}:{}'.format(repr(ex), sys.exc_info()[-1].tb_frame.f_code.co_filename,
1003
                                                           sys.exc_info()[-1].tb_lineno)
1004
            App.mainWnd().addMessage.emit(MessageType.Error, message)
1005

    
1006
        self._titleBlockProperties = None
1007

    
1008
    def getTitleBlockProperties(self):
1009
        """"return title block properties"""
1010

    
1011
        res = None
1012
        if self._titleBlockProperties is None:
1013
            self._titleBlockProperties = []
1014

    
1015
            with self.project.database.connect() as conn:
1016
                try:
1017
                    # Get a cursor object
1018
                    cursor = conn.cursor()
1019

    
1020
                    sql = "select UID, Name, AREA, [TEXT] from TitleBlockProperties"
1021
                    cursor.execute(sql)
1022
                    rows = cursor.fetchall()
1023
                    for row in rows:
1024
                        attr = []
1025
                        attr.append(row['UID'])  # uid
1026
                        attr.append(row['Name'])  # name
1027
                        attr.append(row['AREA'])  # area
1028
                        attr.append(row['TEXT'])  # text
1029
                        self._titleBlockProperties.append(attr)
1030

    
1031
                    res = self._titleBlockProperties
1032
                # Catch the exception
1033
                except Exception as ex:
1034
                    print('error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
1035
                                                              sys.exc_info()[-1].tb_lineno))
1036
        else:
1037
            res = self._titleBlockProperties
1038

    
1039
        return res
1040

    
1041
    def clearLineNoProperties(self):
1042
        self._lineNoProperties = None
1043
        self._lineNoPropertiesUID = {}
1044

    
1045
    def getLineProperties(self):
1046
        """return line no properties"""
1047
        from SymbolAttr import SymbolAttr
1048

    
1049
        res = None
1050
        if self._lineNoProperties is None:
1051
            self._lineNoProperties = []
1052

    
1053
            with self.project.database.connect() as conn:
1054
                try:
1055
                    # Get a cursor object
1056
                    cursor = conn.cursor()
1057

    
1058
                    sql = "select UID, Name, DisplayName, Type, LimitNumber, [index] from LineProperties " \
1059
                          "order by [index]"
1060
                    cursor.execute(sql)
1061
                    rows = cursor.fetchall()
1062
                    for row in rows:
1063
                        attr = SymbolAttr()
1064
                        attr.UID = row['UID']
1065
                        attr.Attribute = row['Name']
1066
                        attr.DisplayAttribute = row['DisplayName']
1067
                        attr.AttributeType = row['Type']
1068
                        attr.Length = row['LimitNumber']
1069
                        attr.IsProp = 5
1070
                        attr.Index = -1
1071
                        self._lineNoProperties.append(attr)
1072

    
1073
                    res = self._lineNoProperties
1074

    
1075
                    # update cache
1076
                    if res:
1077
                        for _prop in res:
1078
                            if str(_prop.UID) not in self._lineNoPropertiesUID:
1079
                                self._lineNoPropertiesUID[str(_prop.UID)] = [_prop]
1080
                # Catch the exception
1081
                except Exception as ex:
1082
                    print('error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
1083
                                                              sys.exc_info()[-1].tb_lineno))
1084
        else:
1085
            res = self._lineNoProperties
1086

    
1087
        return res
1088

    
1089
    def get_equipment_attributes(self):
1090
        """ return equipment attributes """
1091

    
1092
        from SymbolAttr import SymbolAttr
1093

    
1094
        res = None
1095
        if not hasattr(self, '_equipment_attributes'):
1096
            self._equipment_attributes = []
1097

    
1098
            with self.project.database.connect() as conn:
1099
                try:
1100
                    # Get a cursor object
1101
                    cursor = conn.cursor()
1102

    
1103
                    sql = "select distinct A.Attribute from SymbolAttribute A join SymbolType B on " \
1104
                          "A.SymbolType_UID=B.UID where B.Category in ('Equipment', 'Package')"#,'Equipment Components')"
1105
                    cursor.execute(sql)
1106
                    rows = cursor.fetchall()
1107
                    for row in rows:
1108
                        attr = SymbolAttr()
1109
                        attr.Attribute = row['Attribute']
1110
                        self._equipment_attributes.append(attr)
1111

    
1112
                    res = self._equipment_attributes
1113
                # Catch the exception
1114
                except Exception as ex:
1115
                    print('error occurred({}) in {}:{}'.format(repr(ex), sys.exc_info()[-1].tb_frame.f_code.co_filename,
1116
                                                               sys.exc_info()[-1].tb_lineno))
1117
        else:
1118
            res = self._equipment_attributes
1119

    
1120
        return res
1121

    
1122
    '''
1123
        @brief  return line properties
1124
        @author humkyung
1125
        @date   2018.04.09
1126
    '''
1127
    def getLinePropertiesByUID(self, UID):
1128
        from SymbolAttr import SymbolAttr
1129

    
1130
        res = []
1131
        if UID in self._lineNoPropertiesUID:
1132
            res = self._lineNoPropertiesUID[UID]
1133
            return res
1134

    
1135
        with self.project.database.connect() as conn:
1136
            try:
1137
                # Get a cursor object
1138
                cursor = conn.cursor()
1139

    
1140
                sql = f"select UID, Name, DisplayName, Type, LimitNumber, [index] from LineProperties where " \
1141
                      f"uid = '{UID}'"
1142
                cursor.execute(sql)
1143
                rows = cursor.fetchall()
1144
                for row in rows:
1145
                    attr = SymbolAttr()
1146
                    attr.UID = row['UID']
1147
                    attr.Attribute = row['Name']
1148
                    attr.DisplayAttribute = row['DisplayName']
1149
                    attr.AttributeType = row['Type']
1150
                    attr.Length = row['LimitNumber']
1151
                    attr.IsProp = 5
1152
                    attr.Index = -1
1153
                    res.append(attr)
1154
                self._lineNoPropertiesUID[UID] = res
1155
            # Catch the exception
1156
            except Exception as ex:
1157
                print('error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
1158
                                                          sys.exc_info()[-1].tb_lineno))
1159

    
1160
        return res
1161

    
1162
    '''
1163
        @brief  return line types 
1164
        @author humkyung
1165
        @date   2018.06.27
1166
    '''
1167
    def getLineTypes(self):
1168
        from LineTypeConditions import LineTypeConditions
1169

    
1170
        res = []
1171
        conn = self.project.database.connect()
1172
        with conn:
1173
            try:
1174
                cursor = conn.cursor()
1175
                sql = "select UID,Name,Type1,Conditions1,Type2,Conditions2 from LineTypes order by Name"
1176
                cursor.execute(sql)
1177
                rows = cursor.fetchall()
1178
                for row in rows:
1179
                    line_type = LineTypeConditions(row['UID'], row['Name'])
1180
                    line_type._conditions[0][0] = row['Type1']
1181
                    line_type._conditions[0][1] = row['Conditions1']
1182
                    line_type._conditions[1][0] = row['Type2']
1183
                    line_type._conditions[1][1] = row['Conditions2']
1184
                    res.append(line_type)
1185
            # Catch the exception
1186
            except Exception as ex:
1187
                print('error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
1188
                                                          sys.exc_info()[-1].tb_lineno))
1189

    
1190
        return res
1191

    
1192
    '''
1193
        @brief      Insert New Project Info
1194
        @author     Jeongwoo
1195
        @date       2018.04.06
1196
        @history    humkyung 2018.04.19 use getPrjDatabasePath function instead of PROJECT_DB_PATH variable
1197
    '''
1198
    def insertProjectInfo(self, desc, prj_unit, dir):
1199
        prjDatabaseFilePath = self.getPrjDatabasePath()
1200
        conn = sqlite3.connect(prjDatabaseFilePath)
1201
        with conn:
1202
            try:
1203
                folderName = dir.split('/')[-1]
1204
                if folderName:
1205
                    nowDate = datetime.now().strftime('%Y.%m.%d %H:%M')
1206
                    sql = "insert or replace into Projects(Name, [Desc], [Unit], Path, CreatedDate, UpdatedDate) values(?, ?, ?, ?, ?, ?)"
1207
                    param = (folderName, desc, prj_unit, dir, nowDate, nowDate)
1208

    
1209
                    cursor = conn.cursor()
1210
                    cursor.execute(sql, param)
1211
                    conn.commit()
1212
                else:
1213
                    print("Empty folder name")
1214
            except Exception as ex:
1215
                # Roll back any change if something goes wrong
1216
                conn.rollback()
1217
                print('error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
1218
                                                          sys.exc_info()[-1].tb_lineno))
1219

    
1220
    def removeProjectInfo(self, targetProject):
1221
        '''
1222
        @brief      Remove Project Info
1223
        @author     Euisung
1224
        @date       2019.01.28
1225
        '''
1226
        prjDatabaseFilePath = self.getPrjDatabasePath()
1227
        conn = sqlite3.connect(prjDatabaseFilePath)
1228
        with conn:
1229
            try:
1230
                sql = "delete from Projects where Id = '{}'".format(targetProject.id)
1231
                cur = conn.cursor()
1232
                cur.execute(sql)
1233
                conn.commit()
1234
            except Exception as ex:
1235
                # Roll back any change if something goes wrong
1236
                conn.rollback()
1237
                print('error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
1238
                                                          sys.exc_info()[-1].tb_lineno))
1239

    
1240
    '''
1241
        @brief      update project
1242
        @author     Jeongwoo
1243
        @date       2018.04.06
1244
        @history    humkyung 2018.04.19 use getPrjDatabasePath function instead of PROJECT_DB_PATH variable
1245
    '''
1246
    def updateProjectUpdatedDate(self, project):
1247
        prjDatabaseFilePath = self.getPrjDatabasePath()
1248
        conn = sqlite3.connect(prjDatabaseFilePath)
1249
        with conn:
1250
            try:
1251
                nowDate = datetime.now().strftime('%Y.%m.%d %H:%M')
1252
                sql = '''
1253
                    UPDATE Projects
1254
                    SET UpdatedDate = ?,[Desc]=?,[Unit]=? 
1255
                    WHERE Id = ?
1256
                '''
1257
                cur = conn.cursor()
1258
                cur.execute(sql, (nowDate, project.desc, project.prj_unit, project.getId()))
1259

    
1260
                if project.database.host and project.database.port:
1261
                    _host = project.database.host + ':' + project.database.port
1262
                else:
1263
                    _host = None
1264
                sql = 'insert or replace into DBSettings(Projects_UID, DBTypes_UID, Host, User, Password, FilePath) values(?,(select UID from DBTypes where Name=?),?,?,?,?)'
1265
                cur = conn.cursor()
1266
                cur.execute(sql, (
1267
                    project.getId(), project.database.db_type, _host, project.database.user,
1268
                    project.database.password, project.database.file_path))
1269
                conn.commit()
1270
            except Exception as ex:
1271
                # Roll back any change if something goes wrong
1272
                conn.rollback()
1273
                print('error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
1274
                                                          sys.exc_info()[-1].tb_lineno))
1275

    
1276
    '''
1277
        @brief  get project list from database
1278
        @history    humkyung 2018.04.18 add only project which's project exists
1279
    '''
1280
    def getProjectList(self):
1281
        from Project import Project
1282

    
1283
        projectList = []
1284

    
1285
        conn = sqlite3.connect(self.getPrjDatabasePath())
1286
        with conn:
1287
            conn.row_factory = sqlite3.Row
1288
            cursor = conn.cursor()
1289
            sql = "select a.Id,a.Name,a.[Desc],a.[Unit],a.Path,a.CreatedDate,a.UpdatedDate,\
1290
                (select \
1291
                CASE \
1292
                WHEN b.DBTypes_UID is NULL THEN 'SQLite' \
1293
                ELSE (select Name from DBTypes where UID=b.DBTypes_UID) \
1294
                END \
1295
                ) DBType,b.Host,b.User,b.Password \
1296
                from projects a left join dbsettings b on a.Id=b.Projects_UID order by strftime(a.UpdatedDate) desc"
1297
            try:
1298
                cursor.execute(sql)
1299
                rows = cursor.fetchall()
1300
                for row in rows:
1301
                    if os.path.isdir(row['Path']):  # check if folder exists
1302
                        projectList.append(Project(row))
1303
            except Exception as ex:
1304
                print('error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
1305
                                                          sys.exc_info()[-1].tb_lineno))
1306

    
1307
        return projectList
1308

    
1309
    '''
1310
        @brief  get sliding window size
1311
        @author humkyung
1312
    '''
1313
    def getSlidingWindowSize(self):
1314
        res = [25, 20]
1315
        try:
1316
            configs = self.getConfigs('Sliding Window')
1317
            for config in configs:
1318
                if config.key == 'Width':
1319
                    res[0] = int(config.value)
1320
                elif config.key == 'Height':
1321
                    res[1] = int(config.value)
1322
        # Catch the exception
1323
        except Exception as ex:
1324
            print('error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
1325
                                                      sys.exc_info()[-1].tb_lineno))
1326

    
1327
        return res
1328

    
1329
    '''
1330
        @brief  get line no configuration
1331
        @author humkyung
1332
        @date   2018.04.16
1333
    '''
1334
    def getLineNoConfiguration(self):
1335
        res = None
1336

    
1337
        conn = self.project.database.connect()
1338
        with conn:
1339
            try:
1340
                # Get a cursor object
1341
                cursor = conn.cursor()
1342

    
1343
                delimiter = None
1344
                sql = "select * from configuration where section='Line No' and key='Delimiter"
1345
                cursor.execute(sql)
1346
                rows = cursor.fetchall()
1347
                if len(rows) == 1:
1348
                    delimiter = rows[0][2]
1349

    
1350
                if delimiter is not None:
1351
                    sql = "select * from configuration where section='Line No' and key='Configuration'"
1352
                    cursor.execute(sql)
1353
                    rows = cursor.fetchall()
1354
                    if len(rows) == 1:
1355
                        res = rows[0][2].split(delimiter)
1356
            # Catch the exception
1357
            except Exception as ex:
1358
                print('error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
1359
                                                          sys.exc_info()[-1].tb_lineno))
1360

    
1361
        return res
1362

    
1363
    '''
1364
        @brief  get area list
1365
        @author humkyung
1366
        @history    euisung     2018.11.20 (0,0),(0,0) process add
1367
    '''
1368
    def getAreaList(self, size=False):
1369
        from Area import Area
1370

    
1371
        if len(self._areas) == 0:
1372
            conn = self.project.database.connect()
1373
            with conn:
1374
                try:
1375
                    # Get a cursor object
1376
                    cursor = conn.cursor()
1377

    
1378
                    sql = "select * from configuration where section='Area'"
1379
                    cursor.execute(sql)
1380
                    rows = cursor.fetchall()
1381
                    for row in rows:
1382
                        name = row['Key']
1383
                        area = Area(name)
1384
                        area.parse(row['Value'])
1385
                        self._areas.append(area)
1386
                # Catch the exception
1387
                except Exception as ex:
1388
                    print('error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
1389
                                                              sys.exc_info()[-1].tb_lineno))
1390

    
1391
        return self._areas if size else [area for area in self._areas if area.name != 'Size']
1392

    
1393
    '''
1394
        @brief  get area of given name
1395
        @author humkyung
1396
        @date   2018.04.07
1397
    '''
1398
    def getArea(self, name):
1399
        areas = self.getAreaList(size=True)
1400
        matches = [area for area in areas if area.name == name]
1401
        if 1 == len(matches) and matches[0].height is not 0 and matches[0].width is not 0:
1402
            return matches[0]
1403

    
1404
        return None
1405

    
1406
    def getConfigs(self, section, key=None):
1407
        """ get configurations from database """
1408
        res = []
1409

    
1410
        if self._configs is None:
1411
            self._configs = []
1412
            with self.project.database.connect() as conn:
1413
                try:
1414
                    # Get a cursor object
1415
                    cursor = conn.cursor()
1416

    
1417
                    sql = "select * from configuration"
1418

    
1419
                    cursor.execute(sql)
1420
                    rows = cursor.fetchall()
1421
                    for row in rows:
1422
                        self._configs.append(Config(row['Section'], row['Key'], row['Value']))
1423
                # Catch the exception
1424
                except Exception as ex:
1425
                    print('error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
1426
                                                              sys.exc_info()[-1].tb_lineno))
1427

    
1428
        if key is not None:
1429
            return [con for con in self._configs if con.section == section and con.key == key]
1430
        else:
1431
            return [con for con in self._configs if con.section == section]
1432

    
1433
    def getAppConfigs(self, section, key=None):
1434
        """get application configurations"""
1435

    
1436
        res = []
1437

    
1438
        # Creates or opens a file called mydb with a SQLite3 DB
1439
        dbPath = self.getAppDbPath()
1440
        with sqlite3.connect(dbPath) as conn:
1441
            try:
1442
                # Get a cursor object
1443
                cursor = conn.cursor()
1444

    
1445
                if key is not None:
1446
                    sql = "select * from configuration where section=? and key=?"
1447
                    param = (section, key)
1448
                else:
1449
                    sql = "select * from configuration where section=?"
1450
                    param = (section,)
1451

    
1452
                cursor.execute(sql, param)
1453
                rows = cursor.fetchall()
1454
                for row in rows:
1455
                    res.append(Config(row[0], row[1], row[2]))
1456
            # Catch the exception
1457
            except Exception as ex:
1458
                print('error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
1459
                                                          sys.exc_info()[-1].tb_lineno))
1460

    
1461
        return res
1462

    
1463
    '''
1464
        @brief      save configurations
1465
        @author     humkyung
1466
        @date       2018.04.16
1467
        @history    humkyung 2018.07.03 replace ' with " if value has '
1468
                    kyouho 2018.07.09 change query method
1469
    '''
1470
    def saveConfigs(self, configs):
1471
        from LineTypeConditions import LineTypeConditions
1472

    
1473
        with self.project.database.connect() as conn:
1474
            try:
1475
                # Get a cursor object
1476
                cursor = conn.cursor()
1477
                if self.project.database.db_type == 'SQLite':
1478
                    cursor.execute('begin')
1479

    
1480
                for config in configs:
1481
                    if type(config) is Config:
1482
                        value = config.value
1483
                        #if type(value) is str and "'" in value:
1484
                        #    value = value.replace("'", "''")
1485

    
1486
                        sql = self.project.database.to_sql(
1487
                            "insert into configuration(Section,[Key],Value) select ?,?,? where not exists(select 1 from configuration where Section=? and [Key]=?)")
1488
                        param = (config.section, config.key, str(value), config.section, config.key)
1489
                        cursor.execute(sql, param)
1490
                        sql = self.project.database.to_sql(
1491
                            "update configuration set Value=? where Section=? and [Key]=?")
1492
                        param = (str(value), config.section, config.key)
1493
                        cursor.execute(sql, param)
1494
                    elif hasattr(config, 'toSql'):
1495
                        sql = config.toSql()
1496
                        if type(sql) is list:
1497
                            for item in sql:
1498
                                if item is not None and 2 == len(item):
1499
                                    cursor.execute(self.project.database.to_sql(item[0]), item[1])
1500
                        else:
1501
                            if sql is not None and 2 == len(sql):
1502
                                cursor.execute(self.project.database.to_sql(sql[0]), sql[1])
1503
                self._configs = None  # reset config table
1504
                LineTypeConditions.CONDITIONS = None
1505

    
1506
                if self.project.database.db_type == 'SQLite':
1507
                    cursor.execute('commit')
1508
                else:
1509
                    conn.commit()
1510
            # Catch the exception
1511
            except Exception as ex:
1512
                # Roll back any change if something goes wrong
1513
                conn.rollback()
1514

    
1515
                from App import App
1516
                message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
1517
                                                              sys.exc_info()[-1].tb_lineno)
1518
                App.mainWnd().addMessage.emit(MessageType.Error, message)
1519

    
1520
    def saveAppConfigs(self, configs):
1521
        """save application configurations"""
1522

    
1523
        # Creates or opens a file called mydb with a SQLite3 DB
1524
        dbPath = self.getAppDbPath()
1525
        with sqlite3.connect(dbPath) as conn:
1526
            try:
1527
                # Get a cursor object
1528
                cursor = conn.cursor()
1529

    
1530
                for config in configs:
1531
                    value = config.value
1532
                    if type(value) is str and "'" in value:
1533
                        value = value.replace("'", "''")
1534

    
1535
                    sql = "insert or replace into configuration values(?,?,?)"
1536
                    param = (config.section, config.key, value)
1537

    
1538
                    cursor.execute(sql, param)
1539
                conn.commit()
1540
            # Catch the exception
1541
            except Exception as ex:
1542
                # Roll back any change if something goes wrong
1543
                conn.rollback()
1544
                print('error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
1545
                                                          sys.exc_info()[-1].tb_lineno))
1546

    
1547
    def updateProjectUnit(self, unit):
1548
        """save project configurations"""
1549

    
1550
        # Creates or opens a file called mydb with a SQLite3 DB
1551
        dbPath = self.getPrjDatabasePath()
1552
        with sqlite3.connect(dbPath) as conn:
1553
            try:
1554
                # Get a cursor object
1555
                cursor = conn.cursor()
1556

    
1557
                sql = "update Projects set [Unit]=? where [Id]=?"
1558
                param = (unit, self.project.getId())
1559

    
1560
                cursor.execute(sql, param)
1561
                conn.commit()
1562
            # Catch the exception
1563
            except Exception as ex:
1564
                # Roll back any change if something goes wrong
1565
                conn.rollback()
1566
                
1567
                from App import App
1568
                message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
1569
                                                              sys.exc_info()[-1].tb_lineno)
1570
                App.mainWnd().addMessage.emit(MessageType.Error, message)
1571

    
1572
    def deleteConfigs(self, section, key=None):
1573
        """
1574
        delete configurations by using section and key
1575
        :param section:
1576
        :param key:
1577
        :return: None
1578
        """
1579
        with self.project.database.connect() as conn:
1580
            try:
1581
                # Get a cursor object
1582
                cursor = conn.cursor()
1583

    
1584
                if key is not None:
1585
                    sql = "delete from configuration where section='{}' and [key]='{}'".format(section, key)
1586
                else:
1587
                    sql = "delete from configuration where section='{}'".format(section)
1588
                cursor.execute(sql)
1589

    
1590
                conn.commit()
1591
            # Catch the exception
1592
            except Exception as ex:
1593
                # Roll back any change if something goes wrong
1594
                conn.rollback()
1595

    
1596
                message = f'error occurred({ex}) in {sys.exc_info()[-1].tb_frame.f_code.co_filename}:' \
1597
                          f'{sys.exc_info()[-1].tb_lineno}'
1598
                print(message)
1599

    
1600
    def deleteAppConfigs(self, section, key=None):
1601
        """
1602
        @brief  delete application configurations
1603
        @author humkyung
1604
        @date   2018.11.01
1605
        """
1606

    
1607
        # Creates or opens a file called mydb with a SQLite3 DB
1608
        dbPath = self.getAppDbPath()
1609
        conn = sqlite3.connect(dbPath)
1610
        with conn:
1611
            try:
1612
                # Get a cursor object
1613
                cursor = conn.cursor()
1614

    
1615
                if key is not None:
1616
                    sql = "delete from configuration where section='{}' and key='{}'".format(section, key)
1617
                else:
1618
                    sql = "delete from configuration where section='{}'".format(section)
1619
                cursor.execute(sql)
1620

    
1621
                conn.commit()
1622
            # Catch the exception
1623
            except Exception as ex:
1624
                # Roll back any change if something goes wrong
1625
                conn.rollback()
1626
                print('error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
1627
                                                          sys.exc_info()[-1].tb_lineno))
1628

    
1629
    '''
1630
        @brief      set area list
1631
        @history    humkyung 2018.05.18 round area coordinate and dimension before saving
1632
        @history    euisung  2018.11.20 add self._area reset process
1633
    '''
1634
    def setAreaList(self, areas):
1635
        for area in areas:
1636
            matches = [x for x in self._areas if x.name == area.name]
1637
            if 1 == len(matches):
1638
                matches[0].x = area.x
1639
                matches[0].y = area.y
1640
                matches[0].width = area.width
1641
                matches[0].height = area.height
1642
            elif 0 == len(matches):
1643
                self._areas.append(area)
1644

    
1645
        # Creates or opens a file called mydb with a SQLite3 DB
1646
        conn = self.project.database.connect()
1647
        with conn:
1648
            try:
1649
                # Get a cursor object
1650
                cursor = conn.cursor()
1651

    
1652
                for area in self._areas:
1653
                    sql = "insert into configuration select 'Area','{}','({},{}),({},{})' where not exists(select 1 from configuration where Section='Area' and [Key]='{}')".format(
1654
                        area.name, round(area.x), round(area.y), round(area.width), round(area.height), area.name)
1655
                    cursor.execute(sql)
1656
                    sql = "update configuration set Value='({},{}),({},{})' where Section='Area' and [Key]='{}'".format(
1657
                        round(area.x), round(area.y), round(area.width), round(area.height), area.name)
1658
                    cursor.execute(sql)
1659
                conn.commit()
1660
            # Catch the exception
1661
            except Exception as ex:
1662
                # Roll back any change if something goes wrong
1663
                conn.rollback()
1664

    
1665
                from App import App
1666
                message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
1667
                                                              sys.exc_info()[-1].tb_lineno)
1668
                App.mainWnd().addMessage.emit(MessageType.Error, message)
1669
            finally:
1670
                # Close the db connection
1671
                self._areas = []
1672

    
1673
    def getSymbolNameList(self):
1674
        """ get symbol name list """
1675
        symbolNametList = []
1676

    
1677
        conn = self.project.database.connect()
1678
        with conn:
1679
            cursor = conn.cursor()
1680
            sql = 'SELECT * FROM SymbolName'
1681
            try:
1682
                cursor.execute(sql)
1683
                rows = cursor.fetchall()
1684
                for row in rows:
1685
                    symbolNametList.append(row['Name'])  # Name String
1686
            except Exception as ex:
1687
                print('error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
1688
                                                          sys.exc_info()[-1].tb_lineno))
1689

    
1690
        return symbolNametList
1691
    
1692
    def getSymbolNameListByUnused(self):
1693
        """ get unused symbol name list """
1694
        symbolNametList = []
1695

    
1696
        conn = self.project.database.connect()
1697
        with conn:
1698
            cursor = conn.cursor()
1699
            #sql = 'select s.[Name] from [Symbol] s where [SymbolType_UID] != -1 and s.[Name] not in (select distinct s.[name] from [Symbol] s inner join [Components] c on c.[Symbol_UID] = s.[UID])'
1700
            sql = 'select s.[UID], s.[Name] from [Symbol] s where [SymbolType_UID] != -1 and s.[UID] not in (select distinct c.[Symbol_UID] from [Components] c)'
1701
            try:
1702
                cursor.execute(sql)
1703
                rows = cursor.fetchall()
1704
                for row in rows:
1705
                    symbolNametList.append([row['UID'], row['Name']])  # Name String
1706
            except Exception as ex:
1707
                # Roll back any change if something goes wrong
1708
                conn.rollback()
1709

    
1710
                from App import App
1711
                message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
1712
                                                              sys.exc_info()[-1].tb_lineno)
1713
                App.mainWnd().addMessage.emit(MessageType.Error, message)
1714

    
1715
        return symbolNametList
1716

    
1717
    '''
1718
        @brief      get symbol name list by symbol Type
1719
        @author     Jeongwoo
1720
        @date       18.04.06
1721
        @history    .
1722
    '''
1723
    def getSymbolNameListByType(self, type):
1724
        symbolNametList = []
1725
        if type in self._symbolNametList:
1726
            return self._symbolNametList[type]
1727

    
1728
        conn = self.project.database.connect()
1729
        with conn:
1730
            cursor = conn.cursor()
1731
            sql = ''
1732
            if type is not None:
1733
                sql = self.project.database.to_sql('SELECT * FROM SymbolName WHERE [Type]=?')
1734
                try:
1735
                    cursor.execute(sql, (type,))
1736
                    rows = cursor.fetchall()
1737
                    for row in rows:
1738
                        symbolNametList.append(row['Name'])  # Name String
1739
                    self._symbolNametList[type] = symbolNametList
1740
                except Exception as ex:
1741
                    print('error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
1742
                                                              sys.exc_info()[-1].tb_lineno))
1743

    
1744
        return symbolNametList
1745

    
1746
    '''
1747
        @brief  delete added symbol data
1748
    '''
1749
    def deleteSymbol(self, fileName):
1750
        ret = False
1751

    
1752
        conn = self.project.database.connect()
1753
        with conn:
1754
            try:
1755
                cursor = conn.cursor()
1756
                sql = self.project.database.to_sql("DELETE FROM Symbol WHERE name = ?")
1757
                try:
1758
                    cursor.execute(sql, (fileName,))
1759
                    conn.commit()
1760
                    ret = True
1761
                except Exception as ex:
1762
                    conn.rollback()
1763
                    from App import App
1764
                    message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
1765
                                                                sys.exc_info()[-1].tb_lineno)
1766
                    App.mainWnd().addMessage.emit(MessageType.Error, message)
1767
                    ret = False
1768
            finally:
1769
                self._symbolBase = {}
1770
                return (ret, fileName)
1771

    
1772
    def getDuplicatedAttrs(self, param):
1773
        """ get duplicated attributes """
1774

    
1775
        res = []
1776
        
1777
        with self.project.database.connect() as conn:
1778
            cursor = conn.cursor()
1779
            sql = self.project.database.to_sql(f"SELECT t.Value, c.UID, d.Name FROM "
1780
                                               f"(SELECT a.[Value] FROM Attributes a GROUP BY a.[value] HAVING COUNT(a.[value]) > 1) t "
1781
                                               f"INNER JOIN Attributes a ON a.Value=t.value "
1782
                                               f"INNER JOIN SymbolAttribute b ON a.SymbolAttribute_UID=b.UID "
1783
                                               f"INNER JOIN Components c ON a.Components_UID=c.UID "
1784
                                               f"INNER JOIN Drawings d ON c.Drawings_UID=d.UID "
1785
                                               f"WHERE b.Attribute=? AND t.value != '' AND t.value != 'None' AND t.value IS NOT null")
1786
            try:
1787
                cursor.execute(sql, (param,))
1788
                rows = cursor.fetchall()
1789
                for row in rows:
1790
                    res.append([row['Name'], row['UID'], row['Value']])
1791

    
1792
                res = sorted(res, key=lambda pram: param[2])
1793
                return res
1794

    
1795
            except Exception as ex:
1796
                from App import App
1797
                message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
1798
                                                              sys.exc_info()[-1].tb_lineno)
1799
                App.mainWnd().addMessage.emit(MessageType.Error, message)
1800

    
1801
    '''
1802
        @brief  get symbol name
1803
        @history    18.04.24    Jeongwoo    Add isExceptDetect Field
1804
    '''
1805
    def getSymbolByQuery(self, fieldName, param):
1806
        ret = None
1807

    
1808
        if fieldName in self._symbolBase:
1809
            if param in self._symbolBase[fieldName]:
1810
                ret = self._symbolBase[fieldName][param]
1811
                return ret
1812
        else:
1813
            self._symbolBase[fieldName] = {}
1814

    
1815
        with self.project.database.connect() as conn:
1816
            cursor = conn.cursor()
1817
            sql = self.project.database.to_sql(f"SELECT a.UID as UID,a.Name,b.Type,a.Threshold,a.MinMatchPoint,"
1818
                                               f"a.IsDetectOrigin,a.RotationCount,a.OCROption,a.IsContainChild,"
1819
                                               f"a.OriginalPoint,a.ConnectionPoint,a.BaseSymbol,a.AdditionalSymbol,"
1820
                                               f"a.IsExceptDetect,a.HasInstrumentLabel,a.flip,a.TextArea,b.UID as DB_UID,a.Type as [Desc] FROM "
1821
                                               f"Symbol a inner join SymbolType b on a.SymbolType_UID=b.UID WHERE "
1822
                                               f"a.{fieldName}=?")
1823
            try:
1824
                cursor.execute(sql, (param,))
1825
                rows = cursor.fetchall()
1826
                if rows is not None and len(rows) > 0:
1827
                    symbolTuple = rows[0]
1828
                    ret = symbol.SymbolBase(symbolTuple['Name'], symbolTuple['Type'], symbolTuple['Threshold']
1829
                                            , symbolTuple['MinMatchPoint'], symbolTuple['IsDetectOrigin'],
1830
                                            symbolTuple['RotationCount'], symbolTuple['OCROption'],
1831
                                            symbolTuple['IsContainChild'], symbolTuple['OriginalPoint'],
1832
                                            symbolTuple['ConnectionPoint'], symbolTuple['BaseSymbol'],
1833
                                            symbolTuple['AdditionalSymbol'], symbolTuple['IsExceptDetect'],
1834
                                            symbolTuple['HasInstrumentLabel'], symbolTuple['UID'],
1835
                                            iType=symbolTuple['DB_UID'], detectFlip=symbolTuple['flip'],
1836
                                            text_area=symbolTuple['TextArea'], desc=symbolTuple['Desc'])
1837
                    self._symbolBase[fieldName][param] = ret
1838
            except Exception as ex:
1839
                from App import App
1840
                message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
1841
                                                              sys.exc_info()[-1].tb_lineno)
1842
                App.mainWnd().addMessage.emit(MessageType.Error, message)
1843

    
1844
        return ret
1845

    
1846
    '''
1847
        @brief  get symbol name list
1848
        @history    18.04.24    Jeongwoo    Add isExceptDetect Field
1849
    '''
1850
    def getSymbolListByType(self, field_name=None, param=None):
1851
        ret = []
1852

    
1853
        with self.project.database.connect() as conn:
1854
            cursor = conn.cursor()
1855
            if field_name is not None and param is not None:
1856
                sql = """SELECT a.UID,a.Name,b.Type,a.Threshold,a.MinMatchPoint,a.IsDetectOrigin,a.RotationCount,
1857
                a.OCROption,a.IsContainChild,a.OriginalPoint,a.ConnectionPoint,a.BaseSymbol,a.AdditionalSymbol,a.Width,a.Height,
1858
                a.IsExceptDetect,a.HasInstrumentLabel,a.flip,a.TextArea,b.UID as DB_UID,a.Type as [Desc] FROM Symbol a 
1859
                inner join SymbolType b on a.SymbolType_UID=b.UID WHERE 
1860
                SymbolType_UID = (select UID from SymbolType where {}={})""".format(
1861
                    field_name, self.project.database.place_holder)
1862
            else:
1863
                sql = """SELECT a.UID,a.Name,b.Type,a.Threshold,a.MinMatchPoint,a.IsDetectOrigin,a.RotationCount, 
1864
                a.OCROption,a.IsContainChild,a.OriginalPoint,a.ConnectionPoint,a.BaseSymbol,a.AdditionalSymbol,a.Width,a.Height,
1865
                a.IsExceptDetect,a.HasInstrumentLabel,a.flip,a.TextArea,b.UID as DB_UID,a.Type as [Desc] FROM Symbol a 
1866
                inner join SymbolType b on a.SymbolType_UID=b.UID"""
1867
            try:
1868
                cursor.execute(sql, (param,)) if param is not None else cursor.execute(sql)
1869
                rows = cursor.fetchall()
1870
                if rows is not None and len(rows) > 0:
1871
                    for symbolTuple in rows:
1872
                        sym = symbol.SymbolBase(symbolTuple['Name'], symbolTuple['Type'], symbolTuple['Threshold'],
1873
                                                symbolTuple['MinMatchPoint'], symbolTuple['IsDetectOrigin'],
1874
                                                symbolTuple['RotationCount'], symbolTuple['OCROption'],
1875
                                                symbolTuple['IsContainChild'], symbolTuple['OriginalPoint'],
1876
                                                symbolTuple['ConnectionPoint'], symbolTuple['BaseSymbol'],
1877
                                                symbolTuple['AdditionalSymbol'], symbolTuple['IsExceptDetect'],
1878
                                                symbolTuple['HasInstrumentLabel'], symbolTuple['UID'],
1879
                                                iType=symbolTuple['DB_UID'],width=symbolTuple['Width'], height=symbolTuple['Height'],
1880
                                                detectFlip=symbolTuple['flip'], text_area=symbolTuple['TextArea'], desc=symbolTuple['Desc'])
1881
                        ret.append(sym)
1882

    
1883
                # update cache
1884
                if ret:
1885
                    if 'UID' not in self._symbolBase:
1886
                        self._symbolBase['UID'] = {}
1887
                    if 'name' not in self._symbolBase:
1888
                        self._symbolBase['name'] = {}
1889

    
1890
                    for _symbol in ret:
1891
                        if _symbol.uid not in self._symbolBase['UID']:
1892
                            self._symbolBase['UID'][_symbol.uid] = _symbol
1893
                        if _symbol.sName not in self._symbolBase['name']:
1894
                            self._symbolBase['name'][_symbol.sName] = _symbol
1895
            except Exception as ex:
1896
                from App import App
1897
                message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
1898
                                                              sys.exc_info()[-1].tb_lineno)
1899
                App.mainWnd().addMessage.emit(MessageType.Error, message)
1900

    
1901
        return ret
1902

    
1903
    '''
1904
        @brief      get NominalDiameter
1905
        @author     humkyung
1906
        @date       2018.04.20
1907
        @history    humkyung 2018.04.24 read MetricStr column and set size unit
1908
                    kyouho 2018.07.04 forCheckLineNumber get only inch or metric
1909
                    kyouho 2018.07.16 edit query order by code
1910
    '''
1911
    def getNomialPipeSizeData(self, forCheckLineNumber=False, orderStr="MetricStr"):
1912
        res = []
1913
        configs = self.getConfigs('Line No', 'Size Unit')
1914
        sizeUnit = configs[0].value if 1 == len(configs) else 'Metric'
1915

    
1916
        conn = self.project.database.connect()
1917
        with conn:
1918
            try:
1919
                # Get a cursor object
1920
                cursor = conn.cursor()
1921

    
1922
                sql = f"select UID,Code,Metric,Inch,InchStr,AllowableInchStr,MetricStr,AllowableMetricStr from " \
1923
                      f"NominalDiameter ORDER BY {orderStr} DESC"
1924
                cursor.execute(sql)
1925
                rows = cursor.fetchall()
1926
                for row in rows:
1927
                    pipeSize = NominalPipeSize(row['UID'], row['Code'], float(row['Metric']) if row['Metric'] else None,
1928
                                               float(row['Inch']) if row['Inch'] else None, row['InchStr'],
1929
                                               row['AllowableInchStr'], row['MetricStr'], row['AllowableMetricStr'])
1930
                    pipeSize.sizeUnit = sizeUnit
1931
                    if forCheckLineNumber:
1932
                        if sizeUnit == 'Inch' and pipeSize.inchStr:
1933
                            res.append(pipeSize.inchStr)
1934
                        elif sizeUnit == 'Metric' and pipeSize.metricStr:
1935
                            res.append(pipeSize.metricStr)
1936
                    else:
1937
                        res.append(pipeSize)
1938

    
1939
                if 'Inch' in sizeUnit:
1940
                    res = sorted(res, key=lambda param:len(param.inchStr), reverse=True)
1941
                else:
1942
                    res = sorted(res, key=lambda param:len(param.metricStr), reverse=True)
1943
            # Catch the exception
1944
            except Exception as ex:
1945
                from App import App
1946
                message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
1947
                                                              sys.exc_info()[-1].tb_lineno)
1948
                App.mainWnd().addMessage.emit(MessageType.Error, message)
1949

    
1950
        return res
1951

    
1952
    '''
1953
        @brief      insert NominalDiameter table
1954
        @author     kyouho
1955
        @date       2018.07.16
1956
    '''
1957
    def insertNomialPipeSize(self, pipeSizes):
1958
        conn = self.project.database.connect()
1959
        with conn:
1960
            try:
1961
                # Get a cursor object
1962
                cursor = conn.cursor()
1963
                for pipeSize in pipeSizes:
1964
                    sql = pipeSize.toSql()
1965
                    if type(sql) is list and len(sql) == 1:
1966
                        cursor.execute(self.project.database.to_sql(sql[0][0]), sql[0][1])
1967

    
1968
                conn.commit()
1969
            # Catch the exception
1970
            except Exception as ex:
1971
                # Roll back any change if something goes wrong
1972
                conn.rollback()
1973

    
1974
                from App import App
1975
                message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
1976
                                                              sys.exc_info()[-1].tb_lineno)
1977
                App.mainWnd().addMessage.emit(MessageType.Error, message)
1978

    
1979
    '''
1980
        @brief      delete NominalDiameter table
1981
        @author     kyouho
1982
        @date       2018.07.16
1983
    '''
1984
    def deleteNomialPipeSize(self):
1985
        conn = self.project.database.connect()
1986
        with conn:
1987
            cursor = conn.cursor()
1988
            sql = "DELETE FROM NominalDiameter"
1989
            try:
1990
                cursor.execute(sql)
1991
                conn.commit()
1992
            except Exception as ex:
1993
                conn.rollback()
1994
                print('error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
1995
                                                          sys.exc_info()[-1].tb_lineno))
1996

    
1997
    '''
1998
        @brief      convert inch to metric
1999
        @author     kyouho
2000
        @date       2018.07.09
2001
    '''
2002
    def convertInchToMetric(self, inch):
2003
        result = ''
2004
        conn = self.project.database.connect()
2005
        with conn:
2006
            try:
2007
                # Get a cursor object
2008
                cursor = conn.cursor()
2009

    
2010
                sql = "select MetricStr from NominalDiameter WHERE InchStr = ?"
2011
                param = (inch,)
2012
                cursor.execute(sql, param)
2013
                rows = cursor.fetchall()
2014

    
2015
                if rows:
2016
                    result = rows[0][0]
2017
                # Catch the exception
2018
            except Exception as ex:
2019
                print('error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
2020
                                                          sys.exc_info()[-1].tb_lineno))
2021

    
2022
        return result
2023

    
2024
    '''
2025
        @brief      get Color MaxUID
2026
        @author     kyouho
2027
        @date       2018.07.03
2028
    '''
2029
    def getMaxColorUID(self):
2030
        result = 0
2031

    
2032
        conn = self.project.database.connect()
2033
        with conn:
2034
            try:
2035
                # Get a cursor object
2036
                cursor = conn.cursor()
2037

    
2038
                sql = "select MAX(UID) from Colors"
2039
                cursor.execute(sql)
2040
                rows = cursor.fetchall()
2041

    
2042
                result = rows[0][0]
2043
                # Catch the exception
2044
            except Exception as ex:
2045
                print('error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
2046
                                                          sys.exc_info()[-1].tb_lineno))
2047

    
2048
        return result
2049

    
2050
    '''
2051
        @brief      insert Color property
2052
        @author     kyouho
2053
        @date       2018.07.09
2054
    '''
2055
    def setPropertyColor(self, _color):
2056
        conn = self.project.database.connect()
2057
        with conn:
2058
            try:
2059
                # Get a cursor object
2060
                cursor = conn.cursor()
2061
                sql = "INSERT INTO Colors(UID, RED, GREEN, BLUE, PROPERTY, VALUE) VALUES(?,?,?,?,?,?)"
2062
                param = (_color.index, _color.red, _color.green, _color.blue, _color._property, _color.value)
2063
                cursor.execute(sql, param)
2064
                conn.commit()
2065
            # Catch the exception
2066
            except Exception as ex:
2067
                # Roll back any change if something goes wrong
2068
                conn.rollback()
2069
                print('error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
2070
                                                          sys.exc_info()[-1].tb_lineno))
2071

    
2072
    '''
2073
        @brief      delete Color property
2074
        @author     kyouho
2075
        @date       2018.07.09
2076
    '''
2077
    def deletePropertyColor(self, property):
2078
        conn = self.project.database.connect()
2079
        with conn:
2080
            try:
2081
                # Get a cursor object
2082
                cursor = conn.cursor()
2083

    
2084
                sql = "DELETE FROM Colors WHERE PROPERTY = '{}'".format(property)
2085
                cursor.execute(sql)
2086
                conn.commit()
2087
                # Catch the exception
2088
            except Exception as ex:
2089
                # Roll back any change if something goes wrong
2090
                conn.rollback()
2091
                print('error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
2092
                                                          sys.exc_info()[-1].tb_lineno))
2093

    
2094
    '''
2095
        @brief      get Fluid Code
2096
        @author     kyouho
2097
        @date       2018.07.03
2098
        @history    kyouho 2018.07.04 kyouho 2018.07.04 forCheckLineNumber get only code
2099
    '''
2100
    def getFluidCodeData(self, forCheckLineNumber=False):
2101
        from FluidCodeData import FluidCodeData
2102
        result = []
2103

    
2104
        conn = self.project.database.connect()
2105
        with conn:
2106
            try:
2107
                # Get a cursor object
2108
                cursor = conn.cursor()
2109

    
2110
                sql = 'select uid, code, description from FluidCode order by length(code) DESC'
2111
                cursor.execute(sql)
2112
                rows = cursor.fetchall()
2113
                for row in rows:
2114
                    data = FluidCodeData(row[0], row[1], row[2])
2115
                    if forCheckLineNumber:
2116
                        result.append(data.code)
2117
                    else:
2118
                        result.append(data)
2119
                # Catch the exception
2120
            except Exception as ex:
2121
                print('error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
2122
                                                          sys.exc_info()[-1].tb_lineno))
2123

    
2124
        return result
2125

    
2126
    '''
2127
        @brief      get Symbol Attribute
2128
        @author     kyouho
2129
        @date       2018.07.18
2130
        @ no more used
2131
    '''
2132
    def checkAttribute(self, attr):
2133
        conn = self.project.database.connect()
2134
        with conn:
2135
            try:
2136
                # Get a cursor object
2137
                cursor = conn.cursor()
2138

    
2139
                sql = 'select UID from SymbolAttribute where UID = ?'
2140
                param = (attr,)
2141
                cursor.execute(sql, param)
2142
                rows = cursor.fetchall()
2143
                if len(rows):
2144
                    return True
2145
                else:
2146
                    return False
2147
                # Catch the exception
2148
            except Exception as ex:
2149
                print('error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
2150
                                                          sys.exc_info()[-1].tb_lineno))
2151

    
2152
        return False
2153

    
2154
    def read_drawing_shape(self, drawing):
2155
        """read drawing shape"""
2156

    
2157
        res = None
2158

    
2159
        with self.project.database.connect() as conn:
2160
            try:
2161
                # Get a cursor object
2162
                cursor = conn.cursor()
2163

    
2164
                sql = f"select Image from Drawings where UID='{drawing}'"
2165
                cursor.execute(sql)
2166
                records = cursor.fetchall()
2167
                for record in records:
2168
                    res = record[0]
2169
                    break
2170

    
2171
            # Catch the exception
2172
            except Exception as ex:
2173
                from App import App
2174
                # Roll back any change if something goes wrong
2175
                conn.rollback()
2176

    
2177
                message = 'error occurred({}) in {}:{}'.format(repr(ex), sys.exc_info()[-1].tb_frame.f_code.co_filename,
2178
                                                               sys.exc_info()[-1].tb_lineno)
2179
                App.mainWnd().addMessage.emit(MessageType.Error, message)
2180

    
2181
        return res
2182

    
2183
    def read_symbol_shape(self, symbol_name):
2184
        """read symbol shape(image and svg)"""
2185
        
2186
        res = (None, None)
2187

    
2188
        # need to test on mssql
2189
        return res
2190

    
2191
        with self.project.database.connect() as conn:
2192
            try:
2193
                # Get a cursor object
2194
                cursor = conn.cursor()
2195

    
2196
                sql = f"select Image, Svg from Symbol where Name='{symbol_name}'"
2197
                cursor.execute(sql)
2198
                records = cursor.fetchall()
2199
                for record in records:
2200
                    res = (record[0], record[1])
2201
                    break
2202

    
2203
            # Catch the exception
2204
            except Exception as ex:
2205
                from App import App
2206
                # Roll back any change if something goes wrong
2207
                conn.rollback()
2208

    
2209
                message = 'error occurred({}) in {}:{}'.format(repr(ex), sys.exc_info()[-1].tb_frame.f_code.co_filename,
2210
                                                               sys.exc_info()[-1].tb_lineno)
2211
                App.mainWnd().addMessage.emit(MessageType.Error, message)
2212

    
2213
        return res
2214

    
2215

    
2216
    def update_symbol_shape(self, symbol_name, image_file, svg_file, image_display_file):
2217
        """update symbol shape"""
2218

    
2219
        # need to test on mssql
2220
        return
2221

    
2222
        with self.project.database.connect() as conn:
2223
            try:
2224
                # Get a cursor object
2225
                cursor = conn.cursor()
2226

    
2227
                cols = []
2228
                params = []
2229

    
2230
                image_blob_data = None
2231
                if image_file and os.path.isfile(image_file):
2232
                    with open(image_file, 'rb') as file:
2233
                        image_blob_data = file.read()
2234
                    cols.append('Image=?')
2235
                    params.append(image_blob_data)
2236

    
2237
                svg_blob_data = None
2238
                if svg_file and os.path.isfile(svg_file):
2239
                    with open(svg_file, 'rb') as file:
2240
                        svg_blob_data = file.read()
2241
                    cols.append('Svg=?')
2242
                    params.append(svg_blob_data)
2243

    
2244
                image_display_blob_data = None
2245
                if image_file and image_display_file and os.path.isfile(image_display_file):
2246
                    with open(image_file, 'rb') as file:
2247
                        image_display_blob_data = file.read()
2248
                    cols.append('Image_display=?')
2249
                    params.append(image_display_blob_data)
2250

    
2251
                sql = f"update Symbol set {','.join(cols)} where Name='{symbol_name}'"
2252
                # Convert data into tuple format
2253
                cursor.execute(self.project.database.to_sql(sql), tuple(params))
2254
                conn.commit()
2255

    
2256
            # Catch the exception
2257
            except Exception as ex:
2258
                from App import App
2259
                # Roll back any change if something goes wrong
2260
                conn.rollback()
2261

    
2262
                message = 'error occurred({}) in {}:{}'.format(repr(ex), sys.exc_info()[-1].tb_frame.f_code.co_filename,
2263
                                                               sys.exc_info()[-1].tb_lineno)
2264
                App.mainWnd().addMessage.emit(MessageType.Error, message)
2265

    
2266
    def getReplaceTables(self):
2267
        ''' get replace(inst) code tables '''
2268

    
2269
        import uuid
2270
        from CodeTables import CodeTable
2271

    
2272
        with self.project.database.connect() as conn:
2273
            try:
2274
                result = []
2275

    
2276
                # Get a cursor object
2277
                cursor = conn.cursor()
2278

    
2279
                sql = self.project.database.to_sql('select UID, Name, Description from InstTables')
2280
                cursor.execute(sql)
2281
                rows = cursor.fetchall()
2282
                for row in rows:
2283
                    table = []
2284
                    table.append(uuid.UUID(row['UID']))
2285
                    table.append(row['Name'])
2286
                    table.append(row['Description'])
2287
                    table.append(CodeTable.instance('InstCodes', inst_table_uid=row['UID']))
2288
                    result.append(table)
2289
            # Catch the exception
2290
            except Exception as ex:
2291
                from App import App
2292
                message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
2293
                                                              sys.exc_info()[-1].tb_lineno)
2294
                App.mainWnd().addMessage.emit(MessageType.Error, message)
2295

    
2296
        return result
2297

    
2298
    def getCustomTables(self):
2299
        ''' get custom code tables '''
2300

    
2301
        import uuid
2302
        from CodeTables import CodeTable
2303

    
2304
        with self.project.database.connect() as conn:
2305
            try:
2306
                result = []
2307

    
2308
                # Get a cursor object
2309
                cursor = conn.cursor()
2310

    
2311
                sql = self.project.database.to_sql('select UID, Name, Description from CustomTables')
2312
                cursor.execute(sql)
2313
                rows = cursor.fetchall()
2314
                for row in rows:
2315
                    table = []
2316
                    table.append(uuid.UUID(row['UID']))
2317
                    table.append(row['Name'])
2318
                    table.append(row['Description'])
2319
                    table.append(CodeTable.instance('CustomCodes', custom_table_uid=row['UID']))
2320
                    result.append(table)
2321
            # Catch the exception
2322
            except Exception as ex:
2323
                from App import App
2324
                message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
2325
                                                              sys.exc_info()[-1].tb_lineno)
2326
                App.mainWnd().addMessage.emit(MessageType.Error, message)
2327

    
2328
        return result
2329

    
2330
    def loadSymbolAttributeCodeTables(self):
2331
        ''' load symbol attribute code tables '''
2332

    
2333
        try:
2334
            types = self.getSymbolTypeList()
2335

    
2336
            for _type in types:
2337
                self.getSymbolAttribute(_type[2])
2338

    
2339
        except Exception as ex:
2340
            from App import App
2341
            message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
2342
                                                            sys.exc_info()[-1].tb_lineno)
2343
            App.mainWnd().addMessage.emit(MessageType.Error, message)
2344

    
2345
    '''
2346
        @brief      get Symbol Attribute
2347
        @author     kyouho
2348
        @date       2018.07.18
2349
        @history    humkyung 2018.10.13 load expression
2350
    '''
2351
    def getSymbolAttribute(self, _type):
2352
        import uuid
2353
        from SymbolAttr import SymbolAttr
2354
        from CodeTables import CodeTable
2355

    
2356
        result = []
2357

    
2358
        if self._attributeByType and _type in self._attributeByType:
2359
            new_attr_without_any_binding_data = []
2360
            for attr_old in self._attributeByType[_type]:
2361
                attr = SymbolAttr()
2362
                attr.UID = attr_old.UID
2363
                attr.Attribute = attr_old.Attribute
2364
                attr.DisplayAttribute = attr_old.DisplayAttribute
2365
                attr.AttributeType = attr_old.AttributeType
2366
                attr.AttrAt = attr_old.AttrAt
2367
                attr.Expression = attr_old.Expression
2368
                attr.Target = attr_old.Target
2369
                attr.IsProp = attr_old.IsProp
2370
                attr.Codes = attr_old.Codes
2371
                attr.Index = attr_old.Index
2372
                attr.Desc = attr_old.Desc
2373
                new_attr_without_any_binding_data.append(attr)
2374
            self._attributeByType[_type] = new_attr_without_any_binding_data
2375

    
2376
            return self._attributeByType[_type]
2377

    
2378
        with self.project.database.connect() as conn:
2379
            try:
2380
                # Get a cursor object
2381
                cursor = conn.cursor()
2382

    
2383
                sql = self.project.database.to_sql(
2384
                    'select a.UID, a.Attribute, a.DisplayAttribute, a.AttributeType, a.[AttrAt], a.[Expression], '
2385
                    'a.[index], a.[Target], a.[Property], a.[index] from SymbolAttribute a inner join SymbolType t '
2386
                    'on a.SymbolType_UID = t.UID and t.type = ? order by a.[index]')
2387
                param = (_type,)
2388
                cursor.execute(sql, param)
2389
                rows = cursor.fetchall()
2390
                for row in rows:
2391
                    attr = SymbolAttr()
2392
                    attr.UID = uuid.UUID(row['UID'].replace('\n', ""))
2393
                    attr.Attribute = row['Attribute']
2394
                    attr.DisplayAttribute = row['DisplayAttribute'] if self.delimiter not in row['DisplayAttribute'] else row['DisplayAttribute'].split(self.delimiter)[0]
2395
                    attr.AttributeType = row['AttributeType']
2396
                    attr.AttrAt = row['AttrAt']
2397
                    attr.Expression = row['Expression']
2398
                    attr.Target = row['Target']
2399
                    attr.IsProp = row['Property']
2400
                    attr.Index = row['index']
2401
                    attr.Codes = CodeTable.instance('SymbolAttributeCodeTable', symbol_attribute_uid=row['UID'])
2402
                    attr.Desc = '' if self.delimiter not in row['DisplayAttribute'] else row['DisplayAttribute'].split(self.delimiter)[1]
2403
                    result.append(attr)
2404
            # Catch the exception
2405
            except Exception as ex:
2406
                from App import App
2407
                message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
2408
                                                              sys.exc_info()[-1].tb_lineno)
2409
                App.mainWnd().addMessage.emit(MessageType.Error, message)
2410

    
2411
        self._attributeByType[_type] = result
2412
        return result
2413

    
2414
    '''
2415
        @brief      get Symbol Attribute by UID
2416
        @author     kyouho
2417
        @date       2018.08.17
2418
        @history    humkyung 2018.10.13 load expression
2419
        @ no more used
2420
    '''
2421
    def getSymbolAttributeByUID(self, UID):
2422
        from SymbolAttr import SymbolAttr
2423

    
2424
        res = None
2425

    
2426
        with self.project.database.connect() as conn:
2427
            try:
2428
                # Get a cursor object
2429
                cursor = conn.cursor()
2430

    
2431
                sql = f"select Attribute, DisplayAttribute, AttributeType, AttrAt, Expression, Target, Property, [index] from " \
2432
                      f"SymbolAttribute where uid = '{UID}'"
2433
                cursor.execute(sql)
2434
                rows = cursor.fetchall()
2435
                if len(rows):
2436
                    res = SymbolAttr()
2437
                    res.UID = UID
2438
                    res.Attribute = rows[0]['Attribute']
2439
                    res.DisplayAttribute = rows[0]['DisplayAttribute']
2440
                    res.AttributeType = rows[0]['AttributeType']
2441
                    res.AttrAt = rows[0]['AttrAt']
2442
                    res.Expression = rows[0]['Expression']
2443
                    res.Target = rows[0]['Target']
2444
                    res.IsProp = rows[0]['Property']
2445
                    res.Index = rows[0]['index']
2446
                # Catch the exception
2447
            except Exception as ex:
2448
                from App import App
2449
                message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
2450
                                                              sys.exc_info()[-1].tb_lineno)
2451
                App.mainWnd().addMessage.emit(MessageType.Error, message)
2452

    
2453
        return res
2454

    
2455
    '''
2456
        @brief      save symbol attributes
2457
        @author     humkyung
2458
        @date       2018.08.14
2459
        @history    humkyung 2018.10.13 save expression
2460
    '''
2461
    def saveSymbolAttributes(self, type, attrs, type_str):
2462
        from CodeTables import CodeTable
2463

    
2464
        with self.project.database.connect() as conn:
2465
            try:
2466
                # Get a cursor object
2467
                cursor = conn.cursor()
2468

    
2469
                # delete symbol attribute code table data
2470
                origin_attrs = self.getSymbolAttribute(type_str)
2471
                for origin_attr in origin_attrs:
2472
                    '''
2473
                    # delete symbol attribute code table data for deleted symbol attribute, and backup not edited attribute code table data
2474
                    remain = False
2475
                    for attr in attrs:
2476
                        if str(origin_attr.UID) == attr[0]:
2477
                            remain = True
2478
                            break
2479
                    if remain and attr[-1] and type(attr[-1][0][3]) is list: # this means not edited and need backup
2480
                        attr[-1] = self.getCodeTable('SymbolAttributeCodeTable', forCheckLineNumber=False, symbol_attribute_uid=origin_attr.UID)
2481
                    '''
2482
                    
2483
                    sql = "delete from SymbolAttributeCodeTable where SymbolAttribute_UID = '{}'".format(origin_attr.UID)
2484
                    cursor.execute(sql)
2485
                # up to here
2486

    
2487
                # update symbol attribute
2488
                sql = self.project.database.to_sql('delete from SymbolAttribute where SymbolType_UID = ?')
2489
                param = (type,)
2490
                cursor.execute(sql, param)
2491

    
2492
                for attr in attrs:
2493
                    sql = self.project.database.to_sql(
2494
                        'insert into SymbolAttribute(UID, SymbolType_UID, Attribute, DisplayAttribute, AttributeType, '
2495
                        'AttrAt, Expression, Target, [index], [Property]) values(?, ?, ?, ?, ?, ?, ?, ?, ?, ?)')
2496
                    attr.insert(1, type)
2497
                    cursor.execute(sql, tuple(attr[:-1]))
2498
                # up to here
2499

    
2500
                # update symbol attribute code table data
2501
                for attr in attrs:
2502
                    if attr[-1]:
2503
                        for code in attr[-1]:
2504
                            sql = self.project.database.to_sql( \
2505
                                "insert into SymbolAttributeCodeTable(UID, Code, Description, Allowables, "
2506
                                "SymbolAttribute_UID) VALUES(?,?,?,?,?)")
2507
                            param = (code[0], code[1], code[2], ','.join(code[3]), attr[0])
2508
                            cursor.execute(sql, param)
2509
                # up to here
2510

    
2511
                conn.commit()
2512

    
2513
                if hasattr(self, '_equipment_attributes'):
2514
                    del self._equipment_attributes
2515

    
2516
                if hasattr(self, '_valve_attributes'):
2517
                    del self._valve_attributes
2518

    
2519
                if hasattr(self, '_inst_attributes'):
2520
                    del self._inst_attributes
2521

    
2522
                if hasattr(self, '_note_attributes'):
2523
                    del self._note_attributes
2524
            # Catch the exception
2525
            except Exception as ex:
2526
                # Roll back any change if something goes wrong
2527
                conn.rollback()
2528

    
2529
                from App import App
2530
                message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
2531
                                                              sys.exc_info()[-1].tb_lineno)
2532
                App.mainWnd().addMessage.emit(MessageType.Error, message)
2533

    
2534
            self._attributeByType = {}
2535
            CodeTable.clearTables()
2536

    
2537
    def save_hmb_data(self, hmb_list: list):
2538
        import uuid
2539

    
2540
        app_doc_data = AppDocData.instance()
2541
        with app_doc_data.project.database.connect() as conn:
2542
            try:
2543
                cursor = conn.cursor()
2544
                sql = 'delete from HMB_VALUE'
2545
                cursor.execute(sql)
2546
                sql = 'delete from HMB_LIST'
2547
                cursor.execute(sql)
2548
                sql = 'delete from Stream_No'
2549
                cursor.execute(sql)
2550

    
2551
                list_uids = []
2552
                if hmb_list and hmb_list[0].datas:
2553
                    """save hmb data catalog""" 
2554
                    for data in hmb_list[0].datas[0]:
2555
                        sql = f"insert into HMB_LIST(UID, Name, Unit, [index], [Type]) values(?,?,?,?,?)"
2556
                        sql = self.project.database.to_sql(sql)
2557
                        list_uid = str(uuid.uuid4())
2558
                        params = (list_uid, data.name, data.unit, data.index, data.phase)
2559
                        list_uids.append(list_uid)
2560
                        cursor.execute(sql, params)
2561

    
2562
                for hmb in hmb_list:
2563
                    """stream no save"""
2564
                    sql = f'insert into Stream_No(UID, Stream_No, [From], [To]) values(?,?,?,?)'
2565
                    sql = self.project.database.to_sql(sql)
2566
                    hmb.uid = hmb.uid if hmb.uid else str(uuid.uuid4())
2567
                    params = (str(hmb.uid), hmb.stream_no, hmb.hfrom, hmb.hto)
2568
                    cursor.execute(sql, params)
2569

    
2570
                    """save hmb data value"""
2571
                    params = []
2572
                    sql = f"insert into HMB_Value(UID, HMB_LIST_UID, Stream_No_UID, Value, [Case]) values(?,?,?,?,?)"
2573
                    sql = self.project.database.to_sql(sql)
2574
                    for data_case in hmb.datas:
2575
                        index = 0
2576
                        for data in data_case:
2577
                            params.append((str(uuid.uuid4()), list_uids[index], hmb.uid, data.value, data.case))
2578
                            index = index + 1
2579
                    cursor.executemany(sql, tuple(params))
2580

    
2581
                conn.commit()
2582
                self._hmbData = None
2583
                        
2584
            except Exception as ex:
2585
                # Roll back any change if something goes wrong
2586
                conn.rollback()
2587

    
2588
                from App import App
2589
                message = f"error occurred({repr(ex)}) in {sys.exc_info()[-1].tb_frame.f_code.co_filename}:" \
2590
                          f"{sys.exc_info()[-1].tb_lineno}"
2591
                App.mainWnd().addMessage.emit(MessageType.Error, message)
2592

    
2593
    def get_hmb_data(self, file_path: str):
2594
        """get hmb data from pap database if file_path is given otherwise get hmb data from id2 database"""
2595

    
2596
        from HMBTable import HMBData
2597

    
2598
        if not file_path:
2599
            if self._hmbData is None:
2600
                app_doc_data = AppDocData.instance()
2601
                with app_doc_data.project.database.connect() as conn:
2602
                    try:
2603
                        cursor = conn.cursor()
2604
                        sql = f"SELECT v.Value, v.[Case], r.Name, r.Unit, r.[index], r.[Type], s.Stream_No, s.[From], s.[To], s.UID FROM " \
2605
                                f"HMB_VALUE v " \
2606
                                f"INNER JOIN HMB_LIST r ON v.HMB_LIST_UID=r.UID " \
2607
                                f"INNER JOIN Stream_No s ON v.Stream_No_UID=s.UID " \
2608
                                f"ORDER BY s.stream_no"
2609
                        cursor.execute(sql)
2610
                        rows = cursor.fetchall()
2611

    
2612
                        hmbs = HMBData.from_row(rows)
2613
                        self._hmbData = hmbs
2614
                        return self._hmbData
2615
                    except Exception as ex:
2616
                        # Roll back any change if something goes wrong
2617
                        conn.rollback()
2618

    
2619
                        from App import App
2620
                        message = f"error occurred({repr(ex)}) in {sys.exc_info()[-1].tb_frame.f_code.co_filename}:" \
2621
                                f"{sys.exc_info()[-1].tb_lineno}"
2622
                        App.mainWnd().addMessage.emit(MessageType.Error, message)
2623
            else:
2624
                return self._hmbData
2625
        else:
2626
            with sqlite3.connect(file_path) as conn:
2627
                try:
2628
                    conn.row_factory = sqlite3.Row
2629
                    cursor = conn.cursor()
2630
                    sql = 'select * from HMB_condition'
2631
                    cursor.execute(sql)
2632
                    rows = cursor.fetchall()
2633
                    return rows
2634
                except Exception as ex:
2635
                    # Roll back any change if something goes wrong
2636
                    conn.rollback()
2637

    
2638
                    from App import App
2639
                    message = f"error occurred({repr(ex)}) in {sys.exc_info()[-1].tb_frame.f_code.co_filename}:" \
2640
                              f"{sys.exc_info()[-1].tb_lineno}"
2641
                    App.mainWnd().addMessage.emit(MessageType.Error, message)
2642

    
2643
        return None
2644

    
2645
    def get_hmb_attributes(self):
2646
        """get hmb attributes"""
2647
        """no more used"""
2648
        from SymbolAttr import SymbolAttr
2649

    
2650
        attrs = []
2651
        with self.project.database.connect() as conn:
2652
            try:
2653
                # Get a cursor object
2654
                cursor = conn.cursor()
2655

    
2656
                sql = f"select * from SymbolAttribute where SymbolType_UID = " \
2657
                      f"(select UID from SymbolType where Type='HMB') order by [index]"
2658
                sql = self.project.database.to_sql(sql)
2659
                cursor.execute(sql)
2660
                rows = cursor.fetchall()
2661
                for row in rows:
2662
                    attr = SymbolAttr(row['UID'])
2663
                    attr.Attribute = row['Attribute']
2664
                    attr.DisplayAttribute = row['DisplayAttribute']
2665
                    attr.AttributeType = row['AttributeType']
2666
                    attr.AttrAt = row['AttrAt']
2667
                    attr.Expression = row['Expression']
2668
                    attr.Target = row['Target']
2669
                    attr.IsProp = row['Property']
2670
                    attr.Index = row['index']
2671

    
2672
                    attrs.append(attr)
2673

    
2674
            # Catch the exception
2675
            except Exception as ex:
2676
                # Roll back any change if something goes wrong
2677
                conn.rollback()
2678

    
2679
                from App import App
2680
                message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
2681
                                                               sys.exc_info()[-1].tb_lineno)
2682
                App.mainWnd().addMessage.emit(MessageType.Error, message)
2683

    
2684
        return attrs
2685

    
2686
    def save_hmb_model(self, model: QStandardItemModel):
2687
        """ no more used """
2688
        """save hmb model to database"""
2689

    
2690
        with self.project.database.connect() as conn:
2691
            try:
2692
                # get a cursor object
2693
                cursor = conn.cursor()
2694

    
2695
                # delete hmb table
2696
                sql = 'delete from HMB'
2697
                sql = self.project.database.to_sql(sql)
2698
                cursor.execute(sql)
2699
                # up to here
2700

    
2701
                for row in range(model.rowCount()):
2702
                    params = []
2703
                    for col in range(model.columnCount()):
2704
                        data = model.data(model.index(row, col))
2705
                        params.append(data)
2706

    
2707
                    values = ['?' for col in range(model.columnCount())]
2708
                    sql = f"insert into HMB values({','.join(values)})"
2709
                    cursor.execute(sql, params)
2710

    
2711
                conn.commit()
2712
            except Exception as ex:
2713
                # Roll back any change if something goes wrong
2714
                conn.rollback()
2715

    
2716
                from App import App
2717
                message = f"error occurred({repr(ex)}) in {sys.exc_info()[-1].tb_frame.f_code.co_filename}:" \
2718
                          f"{sys.exc_info()[-1].tb_lineno}"
2719
                App.mainWnd().addMessage.emit(MessageType.Error, message)
2720

    
2721
    def save_hmb_attributes(self, attrs):
2722
        """save hmb attributes"""
2723
        """no more used"""
2724
        from CodeTables import CodeTable
2725

    
2726
        with self.project.database.connect() as conn:
2727
            try:
2728
                # Get a cursor object
2729
                cursor = conn.cursor()
2730

    
2731
                # delete hmb attributes
2732
                sql = f"delete from SymbolAttribute where SymbolType_UID = (select UID from SymbolType where Type='HMB')"
2733
                sql = self.project.database.to_sql(sql)
2734
                cursor.execute(sql)
2735
                # up to here
2736

    
2737
                for idx, attr in enumerate(attrs):
2738
                    sql = self.project.database.to_sql(
2739
                        'insert into SymbolAttribute(UID, SymbolType_UID, Attribute, DisplayAttribute, AttributeType, '
2740
                        'AttrAt, Expression, Target, [index], [Property]) values(?, '
2741
                        '(select uid from SymbolType where Type=\'HMB\'), ?, ?, ?, ?, ?, ?, ?, ?)')
2742
                    params = (str(attr.UID), attr.Attribute, attr.Attribute, 'String', attr.AttrAt,
2743
                              attr.Expression if attr.Expression else None, attr.Target, idx, attr.IsProp)
2744

    
2745
                    cursor.execute(sql, params)
2746
                # up to here
2747

    
2748
                conn.commit()
2749

    
2750
            # Catch the exception
2751
            except Exception as ex:
2752
                # Roll back any change if something goes wrong
2753
                conn.rollback()
2754

    
2755
                from App import App
2756
                message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
2757
                                                               sys.exc_info()[-1].tb_lineno)
2758
                App.mainWnd().addMessage.emit(MessageType.Error, message)
2759

    
2760
    @staticmethod
2761
    def save_stream_line_data(stream_line_list: list):
2762
        """ save stream line from to """
2763
        import uuid
2764

    
2765
        app_doc_data = AppDocData.instance()
2766
        with app_doc_data.project.database.connect() as conn:
2767
            try:
2768
                cursor = conn.cursor()
2769
                """delete stream line which has stream number is given data"""
2770
                sql = "delete from HMB_From_To where Stream_No=?"
2771
                sql = app_doc_data.project.database.to_sql(sql)
2772
                params = (stream_line_list[0],)
2773
                cursor.execute(sql, params)
2774
                """up to here"""
2775

    
2776
                for stream_line in stream_line_list[1]:
2777
                    sql = f"insert into HMB_From_To(UID,[Drawing_UID],[From_Component_UID],[To_Component_UID],[Stream_No],[Case]) values" \
2778
                          f"(?,?,?,?,?,?)"
2779
                    sql = app_doc_data.project.database.to_sql(sql)
2780
                    params = (str(uuid.uuid4()), stream_line[0], stream_line[1], stream_line[2], stream_line[3], stream_line[4])
2781
                    cursor.execute(sql, params)
2782

    
2783
                conn.commit()
2784
            except Exception as ex:
2785
                # Roll back any change if something goes wrong
2786
                conn.rollback()
2787

    
2788
                from App import App
2789
                message = f"error occurred({repr(ex)}) in {sys.exc_info()[-1].tb_frame.f_code.co_filename}:" \
2790
                          f"{sys.exc_info()[-1].tb_lineno}"
2791
                App.mainWnd().addMessage.emit(MessageType.Error, message)
2792

    
2793
    def get_stream_line_list_data(self, drawing_names=None):
2794
        """ get stream line list data from """
2795
        with self.project.database.connect() as conn:
2796
            try:
2797
                # Get a cursor object
2798
                cursor = conn.cursor()
2799

    
2800
                if drawing_names is None:
2801
                    doc_names = self.activeDrawing.name
2802
                else:
2803
                    doc_names = "','".join(drawing_names)
2804

    
2805
                sql = f"select S.PnIDNumber, S.Tag_Seq_No, S.PipingMaterialsClass, S.InsulationPurpose, S.FluidCode, " \
2806
                      f"S.UnitNumber, S.NominalDiameter, S.[From], S.[To], S.Stream_No, S.[Case], S.[Index], D.Name from Stream_Line_List S " \
2807
                      f"join Drawings D on S.Drawing_UID=D.UID " \
2808
                      f"where S.Drawing_UID in (select UID from Drawings where Name in ('{doc_names}'))"
2809
                sql = self.project.database.to_sql(sql)
2810
                cursor.execute(sql)
2811
                rows = cursor.fetchall()
2812

    
2813
                datas = []
2814
                for row in rows:
2815
                    data = {}
2816
                    data['PnIDNumber'] = row['PnIDNumber']
2817
                    data['Tag Seq No'] = row['Tag_Seq_No']
2818
                    data['PipingMaterialsClass'] = row['PipingMaterialsClass']
2819
                    data['InsulationPurpose'] = row['InsulationPurpose']
2820
                    data['FluidCode'] = row['FluidCode']
2821
                    data['UnitNumber'] = row['UnitNumber']
2822
                    data['NominalDiameter'] = row['NominalDiameter']
2823
                    data['FROM'] = row['From']
2824
                    data['TO'] = row['To']
2825
                    data['Stream No'] = row['Stream_No']
2826
                    data['Case'] = row['Case'] if row['Case'] else ''
2827
                    data['index'] = row['Index']
2828
                    data['Drawing Name'] = row['Name']
2829
                    
2830
                    datas.append(data)
2831

    
2832
                return datas
2833

    
2834
            # Catch the exception
2835
            except Exception as ex:
2836
                # Roll back any change if something goes wrong
2837
                conn.rollback()
2838

    
2839
                from App import App
2840
                message = f"error occurred({repr(ex)}) in {sys.exc_info()[-1].tb_frame.f_code.co_filename}:" \
2841
                          f"{sys.exc_info()[-1].tb_lineno}"
2842
                App.mainWnd().addMessage.emit(MessageType.Error, message)
2843

    
2844
    def get_stream_from_to(self, stream_no: str = None, drawing_uid: str = None) -> list:
2845
        """ get stream lines related to hmb """
2846

    
2847
        with self.project.database.connect() as conn:
2848
            try:
2849
                # Get a cursor object
2850
                cursor = conn.cursor()
2851

    
2852
                if stream_no:
2853
                    sql = f"select h.Drawing_UID, h.From_Component_UID, h.To_Component_UID, d.Name, h.[Case] from HMB_From_To h " \
2854
                          f"inner join Drawings d on d.UID=h.Drawing_UID " \
2855
                          f"where Stream_No = ?"
2856
                    params = (stream_no,)
2857
                else:
2858
                    sql = f"select h.From_Component_UID, h.To_Component_UID, s.Stream_No, h.[Case] from HMB_From_To h " \
2859
                          f"inner join Stream_No s on s.Stream_No=h.Stream_No " \
2860
                          f"where Drawing_UID = ?"
2861
                    params = (drawing_uid,)
2862
                sql = self.project.database.to_sql(sql)
2863
                cursor.execute(sql, params)
2864
                return cursor.fetchall()
2865
            # Catch the exception
2866
            except Exception as ex:
2867
                # Roll back any change if something goes wrong
2868
                conn.rollback()
2869

    
2870
                from App import App
2871
                message = f"error occurred({repr(ex)}) in {sys.exc_info()[-1].tb_frame.f_code.co_filename}:" \
2872
                          f"{sys.exc_info()[-1].tb_lineno}"
2873
                App.mainWnd().addMessage.emit(MessageType.Error, message)
2874

    
2875

    
2876
    def saveCustomCodes(self, tables):
2877
        ''' save custom code tables and codes '''
2878

    
2879
        from CodeTables import CodeTable
2880

    
2881
        conn = self.project.database.connect()
2882
        with conn:
2883
            try:
2884
                # Get a cursor object
2885
                cursor = conn.cursor()
2886

    
2887
                # delete custom codes and tables
2888
                sql = "delete from CustomCodes"
2889
                cursor.execute(sql)
2890

    
2891
                sql = "delete from CustomTables"
2892
                cursor.execute(sql)
2893
                # up to here
2894

    
2895
                # update symbol attribute code table data
2896
                for table in tables:
2897
                    sql = self.project.database.to_sql("insert into CustomTables (UID, Name, Description) VALUES(?,?,?)")
2898
                    param = (table[0], table[1], table[2])
2899
                    cursor.execute(sql, param)
2900

    
2901
                    for code in table[3]:
2902
                        sql = self.project.database.to_sql( \
2903
                            "insert into CustomCodes(UID, Code, Description, Allowables, Table_UID) VALUES(?,?,?,?,?)")
2904
                        param = (code[0], code[1], code[2], ','.join(code[3]), table[0])
2905
                        cursor.execute(sql, param)
2906
                # up to here
2907

    
2908
                conn.commit()
2909

    
2910
            # Catch the exception
2911
            except Exception as ex:
2912
                # Roll back any change if something goes wrong
2913
                conn.rollback()
2914

    
2915
                from App import App
2916
                message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
2917
                                                              sys.exc_info()[-1].tb_lineno)
2918
                App.mainWnd().addMessage.emit(MessageType.Error, message)
2919

    
2920
            CodeTable.clearTables()
2921

    
2922
    def saveReplaceCodes(self, tables):
2923
        ''' save repalce(inst) code tables and codes '''
2924

    
2925
        from CodeTables import CodeTable
2926

    
2927
        conn = self.project.database.connect()
2928
        with conn:
2929
            try:
2930
                # Get a cursor object
2931
                cursor = conn.cursor()
2932

    
2933
                # delete custom codes and tables
2934
                sql = "delete from InstCodes"
2935
                cursor.execute(sql)
2936

    
2937
                sql = "delete from InstTables"
2938
                cursor.execute(sql)
2939
                # up to here
2940

    
2941
                # update symbol attribute code table data
2942
                for table in tables:
2943
                    sql = self.project.database.to_sql("insert into InstTables (UID, Name, Description) VALUES(?,?,?)")
2944
                    param = (table[0], table[1], table[2])
2945
                    cursor.execute(sql, param)
2946

    
2947
                    for code in table[3]:
2948
                        sql = self.project.database.to_sql( \
2949
                            "insert into InstCodes(UID, Code, Symbols, Attribute, NewCode, Expression, Priority, Table_UID) VALUES(?,?,?,?,?,?,?,?)")
2950
                        param = (code[0], ','.join(code[1]), ','.join(code[2]), ','.join(code[3]), code[4], code[5], code[6], table[0])
2951
                        cursor.execute(sql, param)
2952
                # up to here
2953

    
2954
                conn.commit()
2955

    
2956
            # Catch the exception
2957
            except Exception as ex:
2958
                # Roll back any change if something goes wrong
2959
                conn.rollback()
2960

    
2961
                from App import App
2962
                message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
2963
                                                              sys.exc_info()[-1].tb_lineno)
2964
                App.mainWnd().addMessage.emit(MessageType.Error, message)
2965

    
2966
            CodeTable.clearTables()
2967

    
2968
    '''
2969
        @brief      save symbol attributes
2970
        @author     humkyung
2971
        @date       2018.08.14
2972
    '''
2973
    def saveLineAttributes(self, attrs):
2974
        with self.project.database.connect() as conn:
2975
            try:
2976
                # Get a cursor object
2977
                cursor = conn.cursor()
2978

    
2979
                sql = 'delete from LineProperties'
2980
                cursor.execute(sql)
2981

    
2982
                for attr in attrs:
2983
                    sql = self.project.database.to_sql(
2984
                        'insert into LineProperties(UID, Name, DisplayName, Type, LimitNumber, [index]) values(?, ?, ?, ?, ?, ?)')
2985
                    cursor.execute(sql, tuple(attr))
2986

    
2987
                conn.commit()
2988

    
2989
                self._lineNoProperties = None
2990
                self._lineNoPropertiesUID = {}
2991
            # Catch the exception
2992
            except Exception as ex:
2993
                # Roll back any change if something goes wrong
2994
                conn.rollback()
2995

    
2996
                from App import App
2997
                message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
2998
                                                              sys.exc_info()[-1].tb_lineno)
2999
                App.mainWnd().addMessage.emit(MessageType.Error, message)
3000

    
3001
    '''
3002
        @brief      get symbol type id
3003
        @author     kyouho
3004
        @date       2018.08.17
3005
    '''
3006
    def getSymbolTypeId(self, symbolType):
3007
        result = []
3008

    
3009
        with self.project.database.connect() as conn:
3010
            try:
3011
                # Get a cursor object
3012
                cursor = conn.cursor()
3013

    
3014
                sql = self.project.database.to_sql('select UID from SymbolType where Type = ?')
3015
                param = (symbolType,)
3016
                cursor.execute(sql, param)
3017
                rows = cursor.fetchall()
3018

    
3019
                if len(rows):
3020
                    result = rows[0]['UID']
3021
                else:
3022
                    result = -1
3023
                # Catch the exception
3024
            except Exception as ex:
3025
                print('error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
3026
                                                          sys.exc_info()[-1].tb_lineno))
3027

    
3028
        return result
3029

    
3030
    '''
3031
        @brief      get Code Table Data
3032
        @author     kyouho
3033
        @date       2018.07.10
3034
    '''
3035
    def getCodeTable(self, property, forCheckLineNumber=False, symbol_attribute_uid=None, custom_table_uid=None, custom=False, \
3036
                                                    inst_table_uid=None, inst=False):
3037
        result = []
3038
        with self.project.database.connect() as conn:
3039
            try:
3040
                # Get a cursor object
3041
                cursor = conn.cursor()
3042

    
3043
                if property.upper().replace(' ', '') == "NOMINALDIAMETER" and forCheckLineNumber:
3044
                    cols = ['InchStr', 'MetricStr']
3045
                    sql = f"select {cols[0]}, {cols[1]} from [{property}] order by Metric ASC"
3046
                    cursor.execute(sql)
3047
                    rows = cursor.fetchall()
3048
                    for index in range(2):
3049
                        for row in rows:
3050
                            if row[cols[index]] != '' and result.count(row[cols[index]].replace("'", '"')) == 0:
3051
                                result.append(row[cols[index]].replace("'", '"'))
3052
                else:
3053
                    """
3054
                    sql = "select name from sqlite_master where type='table'"# AND name={}".format(property)
3055
                    cursor.execute(sql)
3056
                    rows = cursor.fetchall()
3057
                    if property.upper() in [name[0].upper() for name in rows]:
3058
                    """
3059
                    if not symbol_attribute_uid and not custom_table_uid and not custom and not inst_table_uid and not inst:
3060
                        sql = 'select uid, code, description, Allowables from [{}] order by code DESC'.format(property)
3061
                    elif symbol_attribute_uid and not custom_table_uid and not inst_table_uid and not inst:
3062
                        sql = "select uid, code, description, Allowables from [{}] where SymbolAttribute_UID='{}' " \
3063
                              "order by code DESC".format(property, symbol_attribute_uid)
3064
                    elif not symbol_attribute_uid and custom_table_uid and not inst_table_uid:
3065
                        sql = "select uid, code, description, Allowables from [{}] where Table_UID='{}' " \
3066
                              "order by code DESC".format(property, custom_table_uid)
3067
                    elif not symbol_attribute_uid and not custom_table_uid and inst_table_uid:
3068
                        sql = "select uid, code, symbols, attribute, newcode, expression, priority from [{}] where Table_UID='{}' " \
3069
                              "order by code DESC".format(property, inst_table_uid)
3070
                    elif custom:
3071
                        sql = "select uid, code, description, Allowables from CustomCodes \
3072
                                    where table_uid = (select uid from CustomTables where upper(name) like upper('{}'))".format(property)
3073
                    elif inst:
3074
                        sql = "select uid, code, symbols, attribute, newcode, expression, priority from InstCodes \
3075
                                    where table_uid = (select uid from InstTables where upper(name) like upper('{}'))".format(property)
3076
                    cursor.execute(sql)
3077
                    rows = cursor.fetchall()
3078
                    if not inst:
3079
                        for row in rows:
3080
                            if forCheckLineNumber:
3081
                                data = row['code']
3082
                            else:
3083
                                data = (row['uid'], row['code'], row['description'], row['Allowables'])
3084
                            result.append(data)
3085
                        # else:
3086
                        #    result = None
3087
                    else:
3088
                        for row in rows:
3089
                            data = (row['uid'], row['code'], row['symbols'], row['attribute'], row['newcode'], row['expression'], row['priority'])
3090
                            result.append(data)
3091
            # Catch the exception
3092
            except Exception as ex:
3093
                from App import App
3094
                message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
3095
                                                              sys.exc_info()[-1].tb_lineno)
3096
                App.mainWnd().addMessage.emit(MessageType.Error, message)
3097

    
3098
        return result
3099

    
3100
    def get_components(self, drawing):
3101
        """ get components in given drawing """
3102

    
3103
        with self.project.database.connect() as conn:
3104
            try:
3105
                # Get a cursor object
3106
                cursor = conn.cursor()
3107

    
3108
                sql = "select a.*,b.Name,b.SymbolType_UID,b.[Type],b.OriginalPoint,b.ConnectionPoint,b.BaseSymbol," \
3109
                      "b.AdditionalSymbol,b.HasInstrumentLabel,b.Flip as DetectFlip from Components a " \
3110
                      "join Symbol b on a.Symbol_UID=b.UID where a.Drawings_UID='{}'".format(drawing)
3111
                cursor.execute(sql)
3112
                return cursor.fetchall()
3113
                # Catch the exception
3114
            except Exception as ex:
3115
                from App import App
3116
                message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
3117
                                                              sys.exc_info()[-1].tb_lineno)
3118
                App.mainWnd().addMessage.emit(MessageType.Error, message)
3119

    
3120
    def check_runs(self):
3121
        """ check run item duplication """
3122

    
3123
        with self.project.database.connect() as conn:
3124
            try:
3125
                # Get a cursor object
3126
                cursor = conn.cursor()
3127

    
3128
                sql = "select [Components_UID], count([Components_UID]) as count from [PipeRunItems] " \
3129
                      "group by [Components_UID] having count([Components_UID]) > 1"
3130

    
3131
                cursor.execute(sql)
3132

    
3133
                rows = cursor.fetchall()
3134

    
3135
                items = []
3136
                if rows:
3137
                    for row in rows:
3138
                        sql = "select c.[UID], d.[Name] from [Components] c inner join [Drawings] d on c.Drawings_UID=d.[UID]" \
3139
                              "where c.[UID]='" + row["Components_UID"] + "'"
3140
                        cursor.execute(sql)
3141

    
3142
                        _rows = cursor.fetchall()
3143
                        if _rows:
3144
                            items = items + _rows
3145

    
3146
                return items
3147
                # Catch the exception
3148
            except Exception as ex:
3149
                from App import App
3150
                message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
3151
                                                              sys.exc_info()[-1].tb_lineno)
3152
                App.mainWnd().addMessage.emit(MessageType.Error, message)
3153

    
3154
    def get_opcs(self):
3155
        """ get opc in project """
3156
        configs = self.getConfigs('PSN', 'Symbols')
3157
        target = configs[0].value if configs else 'ALL'
3158

    
3159
        with self.project.database.connect() as conn:
3160
            try:
3161
                # Get a cursor object
3162
                cursor = conn.cursor()
3163

    
3164
                '''
3165
                if target == "ALL" or target == '':
3166
                    sql = "select (select Name from Drawings where UID=a.Drawings_UID) as Drawing," \
3167
                        "(select Value from Components where UID=a.Owner) as [Line No]," \
3168
                        "(select Name from Symbol where a.Symbol_UID=UID) as Symbol," \
3169
                        "(select stuff((select ',' + convert(NVARCHAR(10),[index]) from [Points] where Connected = a.UID for XML PAth('')),1,1,'')) as [Count]," \
3170
                        "UID as OPC from Components a " \
3171
                        "where Symbol_UID in (select UID from Symbol where SymbolType_UID in " \
3172
                        "(select UID from SymbolType where Type='Instrument OPC''s' or Type='Piping OPC''s'))"
3173
                else:
3174
                    sql = "select (select Name from Drawings where UID=a.Drawings_UID) as Drawing," \
3175
                        "(select Value from Components where UID=a.Owner) as [Line No]," \
3176
                        "(select Name from Symbol where a.Symbol_UID=UID) as Symbol," \
3177
                        "(select stuff((select ',' + convert(NVARCHAR(10),[index]) from [Points] where Connected = a.UID for XML PAth('')),1,1,'')) as [Count]," \
3178
                        "UID as OPC from Components a " \
3179
                        "where Symbol_UID in (" + target + ")"
3180
                '''
3181
                if target == "ALL" or target == '':
3182
                    sql = "select (select Name from Drawings where UID=a.Drawings_UID) as Drawing," \
3183
                        "(select Value from Components where UID=a.Owner) as [Line No]," \
3184
                        "(select Name from Symbol where a.Symbol_UID=UID) as Symbol," \
3185
                        "(select Count(1) from [Points] where Connected = a.UID) as [Count]," \
3186
                        "(select [Index] from [PipeRunItems] where Components_UID = a.UID) as [Index]," \
3187
                        "UID as OPC from Components a " \
3188
                        "where Symbol_UID in (select UID from Symbol where SymbolType_UID in " \
3189
                        "(select UID from SymbolType where Type='Instrument OPC''s' or Type='Piping OPC''s'))"
3190
                else:
3191
                    sql = "select (select Name from Drawings where UID=a.Drawings_UID) as Drawing," \
3192
                        "(select Value from Components where UID=a.Owner) as [Line No]," \
3193
                        "(select Name from Symbol where a.Symbol_UID=UID) as Symbol," \
3194
                        "(select Count(1) from [Points] where Connected = a.UID) as [Count]," \
3195
                        "(select [Index] from [PipeRunItems] where Components_UID = a.UID) as [Index]," \
3196
                        "UID as OPC from Components a " \
3197
                        "where Symbol_UID in (" + target + ")"
3198

    
3199
                cursor.execute(sql)
3200

    
3201
                rows = cursor.fetchall()
3202

    
3203
                opcs = []
3204
                if self.project.database.db_type == 'SQLite':
3205
                    for row in rows:
3206
                        #count = str(len(row["Count"].split(',')))
3207
                        opcs.append({ "Drawing":row["Drawing"], "Line No":row["Line No"].replace('\n', ''), "Symbol":row["Symbol"], "Count":row["Count"], "OPC":row["OPC"], "Index": row["Index"]})
3208
                else:
3209
                    for row in rows:
3210
                        row["Line No"] = rows[0]["Line No"].replace('\n', '')
3211
                    opcs = rows
3212

    
3213
                for opc in opcs:
3214
                    opc['Index'] = 0 if opc['Index'] == 1 else 1 # 0 : start with opc, 1 : end with opc
3215

    
3216
                return opcs
3217
                # Catch the exception
3218
            except Exception as ex:
3219
                from App import App
3220
                message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
3221
                                                              sys.exc_info()[-1].tb_lineno)
3222
                App.mainWnd().addMessage.emit(MessageType.Error, message)
3223

    
3224
    def get_opc_relations(self):
3225
        """ get opc relations """
3226
        conn = self.project.database.connect()
3227
        with conn:
3228
            try:
3229
                # Get a cursor object
3230
                cursor = conn.cursor()
3231

    
3232
                sql = "select (select Name from Drawings where UID=a.From_Drawings_UID) as From_Drawing,\
3233
                a.From_LineNo_UID as From_LineNo,\
3234
                a.From_OPC_UID,\
3235
                (select Name from Drawings where UID=a.To_Drawings_UID) as To_Drawing,\
3236
                a.To_LineNo_UID as To_LineNo,\
3237
                a.To_OPC_UID \
3238
                from OPCRelations a"
3239
                cursor.execute(sql)
3240
                return cursor.fetchall()
3241
                # Catch the exception
3242
            except Exception as ex:
3243
                from App import App
3244
                message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
3245
                                                              sys.exc_info()[-1].tb_lineno)
3246
                App.mainWnd().addMessage.emit(MessageType.Error, message)
3247

    
3248
    def save_opc_relations(self, opcs):
3249
        """ save opc relations """
3250
        conn = self.project.database.connect()
3251
        with conn:
3252
            try:
3253
                # Get a cursor object
3254
                cursor = conn.cursor()
3255
                sql = 'delete from OPCRelations'
3256
                cursor.execute(sql)
3257

    
3258
                for opc in opcs:
3259
                    sql = 'insert into OPCRelations(From_Drawings_UID,From_LineNo_UID,From_OPC_UID,To_Drawings_UID,To_LineNo_UID,To_OPC_UID) \
3260
                        values({},{},{},{},{},{})'.format(
3261
                        "(select UID from Drawings where Name='{}')".format(opc[0]),
3262
                        "'{}'".format(opc[1]) if opc[1] else 'null',
3263
                        "'{}'".format(opc[2]) if opc[2] else 'null',
3264
                        "(select UID from Drawings where Name='{}')".format(opc[3]) if opc[3] else 'null',
3265
                        "'{}'".format(opc[4]) if opc[4] else 'null',
3266
                        "'{}'".format(opc[5]) if opc[5] else 'null')
3267
                    cursor.execute(sql)
3268

    
3269
                conn.commit()
3270
            # Catch the exception
3271
            except Exception as ex:
3272
                conn.rollback()
3273

    
3274
                from App import App
3275
                message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
3276
                                                              sys.exc_info()[-1].tb_lineno)
3277
                App.mainWnd().addMessage.emit(MessageType.Error, message)
3278

    
3279
    def get_component_connectors(self, component):
3280
        """ get connectors of given component """
3281
        if self._connecterss and component in self._connecterss:
3282
            return self._connecterss[component]
3283

    
3284
        conn = self.project.database.connect()
3285
        with conn:
3286
            try:
3287
                # Get a cursor object
3288
                cursor = conn.cursor()
3289

    
3290
                sql = f"select a.* from Points a join Components b on a.Components_UID=b.[UID] where Drawings_UID=" \
3291
                      f"'{self.activeDrawing.UID}' order by Components_UID, [Index]"
3292
                cursor.execute(sql)
3293

    
3294
                pre = ''
3295
                rows = cursor.fetchall()
3296
                for row in rows:
3297
                    if pre != row['Components_UID']:
3298
                        if pre != '':
3299
                            self._connecterss[pre] = compo
3300
                        pre = row['Components_UID']
3301
                        compo = []
3302
                        compo.append(row)
3303
                        if row is rows[-1]:
3304
                            self._connecterss[row['Components_UID']] = compo
3305
                    else:
3306
                        compo.append(row)
3307
                        if row is rows[-1]:
3308
                            self._connecterss[row['Components_UID']] = compo
3309

    
3310
                return self._connecterss[component] if component in self._connecterss else []
3311
                # Catch the exception
3312
            except Exception as ex:
3313
                from App import App
3314
                message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
3315
                                                              sys.exc_info()[-1].tb_lineno)
3316
                App.mainWnd().addMessage.emit(MessageType.Error, message)
3317

    
3318
    def get_component_associations(self, component):
3319
        """ get associations of given component """
3320
        if self._associationss and component in self._associationss:
3321
            return self._associationss[component]
3322
        elif self._associationss:
3323
            return []
3324

    
3325
        conn = self.project.database.connect()
3326
        with conn:
3327
            try:
3328
                # Get a cursor object
3329
                cursor = conn.cursor()
3330

    
3331
                # sql = "select * from Associations where Components_UID='{}'".format(component)
3332
                sql = "select a.* from Associations a \
3333
                            join Components b on a.Components_UID=b.[UID] where Drawings_UID='{}' order by Components_UID".format(
3334
                    self.activeDrawing.UID)
3335
                cursor.execute(sql)
3336

    
3337
                pre = ''
3338
                rows = cursor.fetchall()
3339
                for row in rows:
3340
                    if pre != row['Components_UID']:
3341
                        if pre != '':
3342
                            self._associationss[pre] = compo
3343
                        pre = row['Components_UID']
3344
                        compo = []
3345
                        compo.append(row)
3346
                        if row is rows[-1]:
3347
                            self._associationss[row['Components_UID']] = compo
3348
                    else:
3349
                        compo.append(row)
3350
                        if row is rows[-1]:
3351
                            self._associationss[row['Components_UID']] = compo
3352

    
3353
                return self._associationss[component] if component in self._associationss else []
3354
                # Catch the exception
3355
            except Exception as ex:
3356
                from App import App
3357
                message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
3358
                                                              sys.exc_info()[-1].tb_lineno)
3359
                App.mainWnd().addMessage.emit(MessageType.Error, message)
3360

    
3361
    def get_component_attributes(self, component):
3362
        """ get attributes of given component """
3363
        if self._attributess and component in self._attributess:
3364
            return self._attributess[component]
3365
        elif self._attributess:
3366
            return []
3367

    
3368
        conn = self.project.database.connect()
3369
        with conn:
3370
            try:
3371
                # Get a cursor object
3372
                cursor = conn.cursor()
3373

    
3374
                sql = "select a.*, b.* from Attributes a \
3375
                            join SymbolAttribute b on a.SymbolAttribute_UID=b.UID \
3376
                            join Components c on a.Components_UID=c.UID \
3377
                        where Drawings_UID='{}' order by a.Components_UID, b.[index]".format(self.activeDrawing.UID)
3378
                cursor.execute(sql)
3379

    
3380
                pre = ''
3381
                rows = cursor.fetchall()
3382
                for row in rows:
3383
                    if pre != row['Components_UID']:
3384
                        if pre != '':
3385
                            self._attributess[pre] = compo
3386
                        pre = row['Components_UID']
3387
                        compo = []
3388
                        compo.append(row)
3389
                        if row is rows[-1]:
3390
                            self._attributess[row['Components_UID']] = compo
3391
                    else:
3392
                        compo.append(row)
3393
                        if row is rows[-1]:
3394
                            self._attributess[row['Components_UID']] = compo
3395

    
3396
                return self._attributess[component] if component in self._attributess else []
3397
                # Catch the exception
3398
            except Exception as ex:
3399
                from App import App
3400
                message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
3401
                                                              sys.exc_info()[-1].tb_lineno)
3402
                App.mainWnd().addMessage.emit(MessageType.Error, message)
3403

    
3404
    def get_pipe_runs(self, component):
3405
        """ get line runs of given component """
3406
        conn = self.project.database.connect()
3407
        with conn:
3408
            try:
3409
                # Get a cursor object
3410
                cursor = conn.cursor()
3411

    
3412
                sql = "select * from PipeRuns where Owner='{}' order by [Index]".format(component)
3413
                cursor.execute(sql)
3414
                return cursor.fetchall()
3415
                # Catch the exception
3416
            except Exception as ex:
3417
                from App import App
3418
                message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
3419
                                                              sys.exc_info()[-1].tb_lineno)
3420
                App.mainWnd().addMessage.emit(MessageType.Error, message)
3421

    
3422
    def get_pipe_run_items(self, pipe_run):
3423
        """ get line run items of given pipe run """
3424
        conn = self.project.database.connect()
3425
        with conn:
3426
            try:
3427
                # Get a cursor object
3428
                cursor = conn.cursor()
3429

    
3430
                sql = "select * from PipeRunItems where PipeRuns_UID='{}' order by [Index]".format(pipe_run)
3431
                cursor.execute(sql)
3432
                return cursor.fetchall()
3433
                # Catch the exception
3434
            except Exception as ex:
3435
                from App import App
3436
                message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
3437
                                                              sys.exc_info()[-1].tb_lineno)
3438
                App.mainWnd().addMessage.emit(MessageType.Error, message)
3439

    
3440
    '''
3441
        @brief      get special item types from database
3442
        @author     humkyung
3443
        @date       2019.08.10
3444
    '''
3445
    def get_special_item_types(self):
3446
        conn = self.project.database.connect()
3447
        with conn:
3448
            try:
3449
                # Get a cursor object
3450
                cursor = conn.cursor()
3451

    
3452
                sql = 'select UID, Code, Type, Allowables from SpecialItemTypes order by Code DESC'
3453
                cursor.execute(sql)
3454
                return cursor.fetchall()
3455
                # Catch the exception
3456
            except Exception as ex:
3457
                from App import App
3458
                message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
3459
                                                              sys.exc_info()[-1].tb_lineno)
3460
                App.mainWnd().addMessage.emit(MessageType.Error, message)
3461

    
3462
    '''
3463
        @brief      save special item types
3464
        @author     humkyung
3465
        @date       2019.08.10
3466
    '''
3467
    def save_special_item_types(self, datas):
3468
        import uuid
3469

    
3470
        conn = self.project.database.connect()
3471
        with conn:
3472
            try:
3473
                # Get a cursor object
3474
                cursor = conn.cursor()
3475

    
3476
                for data in datas:
3477
                    uid, code, _type, allowables = data[0], data[1], data[2], data[3]
3478
                    if not uid:
3479
                        sql = self.project.database.to_sql(
3480
                            'insert into SpecialItemTypes(UID, Code, Type, Allowables) values(?, ?, ?, ?)')
3481
                        param = (str(uuid.uuid4()), data[1], data[2], data[3])
3482
                    elif uid == '-1':
3483
                        sql = self.project.database.to_sql('delete from SpecialItemTypes where uid=?')
3484
                        param = (data[-1],)
3485
                    else:
3486
                        sql = self.project.database.to_sql(
3487
                            'update SpecialItemTypes SET Code=?, Type=?, Allowables=? WHERE UID = ?')
3488
                        param = (data[1], data[2], data[3], data[0])
3489
                    cursor.execute(sql, param)
3490

    
3491
                conn.commit()
3492
            # Catch the exception
3493
            except Exception as ex:
3494
                # Roll back any change if something goes wrong
3495
                conn.rollback()
3496

    
3497
                from App import App
3498
                message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
3499
                                                              sys.exc_info()[-1].tb_lineno)
3500
                App.mainWnd().addMessage.emit(MessageType.Error, message)
3501

    
3502
    def get_special_items(self, drawings=None):
3503
        """ get special items from database """
3504
        result = []
3505

    
3506
        conn = self.project.database.connect()
3507
        with conn:
3508
            try:
3509
                # get a cursor object
3510
                cursor = conn.cursor()
3511

    
3512
                sql = 'select distinct (select Value from Components where UID=D.Owner) as "Line No",C.Code from Components A \
3513
                    left join Drawings B on A.Drawings_UID=B.UID \
3514
                    left join SpecialItemTypes C on A.SpecialItemTypes_UID=C.UID \
3515
                    left join Components D on A.Connected=D.UID \
3516
                    where A.SpecialItemTypes_UID is not null'
3517
                if drawings is not None:
3518
                    doc_names = "','".join(drawings)
3519
                    sql += f" and A.Drawings_UID in (select UID from Drawings where Name in ('{doc_names}'))"
3520
                sql += ' order by "Line No"'
3521
                cursor.execute(sql)
3522

    
3523
                return cursor.fetchall()
3524
            # catch the exception
3525
            except Exception as ex:
3526
                from App import App
3527
                message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
3528
                                                              sys.exc_info()[-1].tb_lineno)
3529
                App.mainWnd().addMessage.emit(MessageType.Error, message)
3530

    
3531
        return None
3532

    
3533
    '''
3534
        @brief      Set Common Code Data
3535
        @author     kyouho
3536
        @date       2018.07.12
3537
    '''
3538
    def saveCommonCodeData(self, tableName, datas):
3539
        import uuid
3540

    
3541
        conn = self.project.database.connect()
3542
        with conn:
3543
            try:
3544
                # Get a cursor object
3545
                cursor = conn.cursor()
3546

    
3547
                sql = self.project.database.to_sql('delete from {}'.format(tableName))
3548
                cursor.execute(sql)
3549

    
3550
                for data in datas:
3551
                    '''
3552
                    uid, code, description, allowables = data[0], data[1], data[2], data[3]
3553
                    if not uid:
3554
                        sql = self.project.database.to_sql(
3555
                            "insert into {}(UID, CODE, DESCRIPTION, ALLOWABLES) values(?, ?, ?, ?)".format(tableName))
3556
                        param = (str(uuid.uuid4()), data[1], data[2], data[3])
3557
                    elif uid == '-1':
3558
                        sql = self.project.database.to_sql('delete from {} where uid=?'.format(tableName))
3559
                        param = (data[-1],)
3560
                    else:
3561
                        sql = self.project.database.to_sql(
3562
                            "update {} SET CODE=?, DESCRIPTION=?, ALLOWABLES=? WHERE UID = ?".format(tableName))
3563
                        param = (data[1], data[2], data[3], data[0])
3564
                    cursor.execute(sql, param)
3565
                    '''
3566
                    if data[0]:
3567
                        uid = data[0]
3568
                    else:
3569
                        uid = str(uuid.uuid4())
3570
                    sql = self.project.database.to_sql(
3571
                        "insert into {}(UID, CODE, DESCRIPTION, ALLOWABLES) values(?, ?, ?, ?)".format(tableName))
3572
                    param = (uid, data[1], data[2], data[3])
3573
                    cursor.execute(sql, param)
3574

    
3575
                conn.commit()
3576
            # Catch the exception
3577
            except Exception as ex:
3578
                # Roll back any change if something goes wrong
3579
                conn.rollback()
3580

    
3581
                from App import App
3582
                message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
3583
                                                              sys.exc_info()[-1].tb_lineno)
3584
                App.mainWnd().addMessage.emit(MessageType.Error, message)
3585

    
3586
    def selectView(self):
3587
        """ get document name list """
3588
        result = []
3589

    
3590
        with self.project.database.connect() as conn:
3591
            try:
3592
                # Get a cursor object
3593
                cursor = conn.cursor()
3594

    
3595
                sql = "select * from T_PSN_VIEW"
3596
                cursor.execute(sql)
3597

    
3598
                rows = cursor.fetchall()
3599
                for row in rows:
3600
                    result.append(row['OID'])
3601

    
3602
                result.sort()
3603
            # Catch the exception
3604
            except Exception as ex:
3605
                print('error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
3606
                                                          sys.exc_info()[-1].tb_lineno))
3607

    
3608
        return result
3609

    
3610
    '''
3611
        @brief      Set Common Code Data
3612
        @author     kyouho
3613
        @date       2018.07.12
3614
    '''
3615
    def deleteCommonCodeData(self, datas):
3616
        try:
3617
            conn = self.project.database.connect()
3618
            with conn:
3619
                # Get a cursor object
3620
                cursor = conn.cursor()
3621

    
3622
                for data in datas:
3623
                    uid = data[0]
3624
                    tableName = data[1]
3625

    
3626
                    if uid:
3627
                        sql = "delete from {} where UID = ?".format(tableName)
3628
                        param = (uid,)
3629
                        cursor.execute(sql, param)
3630

    
3631
                    cursor.execute(sql, param)
3632

    
3633
                conn.commit()
3634

    
3635
        # Catch the exception
3636
        except Exception as ex:
3637
            # Roll back any change if something goes wrong
3638
            conn.rollback()
3639

    
3640
            from App import App
3641
            message = f"error occurred({repr(ex)}) in {sys.exc_info()[-1].tb_frame.f_code.co_filename}:" \
3642
                        f"{sys.exc_info()[-1].tb_lineno}"
3643
            App.mainWnd().addMessage.emit(MessageType.Error, message)
3644

    
3645
    '''
3646
        @brief      delete data list
3647
        @author     kyouho
3648
        @date       2018.08.16
3649
    '''
3650
    def deleteDataList(self, tableName, UID):
3651
        conn = self.project.database.connect()
3652
        with conn:
3653
            try:
3654
                # Get a cursor object
3655
                cursor = conn.cursor()
3656
                sql = 'delete from {} where UID = {}'.format(tableName, UID)
3657
                cursor.execute(sql)
3658
                conn.commit()
3659

    
3660
            # Catch the exception
3661
            except Exception as ex:
3662
                # Roll back any change if something goes wrong
3663
                conn.rollback()
3664

    
3665
                from App import App
3666
                message = f"error occurred({repr(ex)}) in {sys.exc_info()[-1].tb_frame.f_code.co_filename}:" \
3667
                          f"{sys.exc_info()[-1].tb_lineno}"
3668
                App.mainWnd().addMessage.emit(MessageType.Error, message)
3669

    
3670
    def get_document_name_list(self):
3671
        """ get document name list """
3672
        result = []
3673

    
3674
        with self.project.database.connect() as conn:
3675
            try:
3676
                # Get a cursor object
3677
                cursor = conn.cursor()
3678

    
3679
                sql = "select distinct B.Name as 'Drawing_Name' from Components A join Drawings B on " \
3680
                      "A.Drawings_UID=B.UID"
3681
                cursor.execute(sql)
3682

    
3683
                rows = cursor.fetchall()
3684
                for row in rows:
3685
                    result.append(row['Drawing_Name'])
3686

    
3687
                result.sort()
3688
            # Catch the exception
3689
            except Exception as ex:
3690
                print('error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
3691
                                                          sys.exc_info()[-1].tb_lineno))
3692

    
3693
        return result
3694

    
3695
    '''
3696
        @brief      get line documentName list
3697
        @author     kyouho
3698
        @date       2018.08.13
3699
    '''
3700
    def getLineDocumentNameList(self):
3701
        result = []
3702

    
3703
        conn = self.project.database.connect()
3704
        with conn:
3705
            try:
3706
                # Get a cursor object
3707
                cursor = conn.cursor()
3708

    
3709
                sql = 'select DISTINCT(PNID_NO) from LINE_DATA_LIST'
3710

    
3711
                cursor.execute(sql)
3712
                rows = cursor.fetchall()
3713
                for row in rows:
3714
                    result.append(row[0])
3715
            # Catch the exception
3716
            except Exception as ex:
3717
                print('error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
3718
                                                          sys.exc_info()[-1].tb_lineno))
3719

    
3720
        return result
3721

    
3722
    '''
3723
        @brief      get line data list
3724
        @author     kyouho
3725
        @date       2018.08.13
3726
    '''
3727
    def get_line_data_list(self, drawings=None):
3728
        result = []
3729

    
3730
        with self.project.database.connect() as conn:
3731
            try:
3732
                # Get a cursor object
3733
                cursor = conn.cursor()
3734

    
3735
                '''
3736
                sql = 'select A.UID,B.Name,A.Value as [Line No] from Components A left join Drawings B on A.Drawings_UID=B.UID'
3737
                if drawings is not None:
3738
                    doc_names = "','".join(drawings)
3739
                    sql += f" where A.Symbol_UID=1 and Drawings_UID in (select UID from Drawings where Name in ('{doc_names}'))"
3740
                cursor.execute(sql)
3741
                comps = [(row['UID'], row['Name'], row['Line No']) for row in cursor.fetchall()]
3742
                for comp in comps:
3743
                    sql = f"select b.Name,a.Value from LineNoAttributes a left join LineProperties b " \
3744
                          f"on a.LineProperties_UID=b.UID where a.Components_UID='{comp[0]}'"
3745
                    cursor.execute(sql)
3746
                    attrs = cursor.fetchall()
3747
                    data = []
3748
                    for attr in attrs:
3749
                        data.append([attr['Name'], attr['Value']])
3750
                    if data:
3751
                        data.insert(0, ['Drawing Name', comp[1]])
3752
                        data.insert(0, ['UID', comp[0]])
3753
                        data.insert(0, ['Line No', comp[2]])
3754
                        result.append(data)
3755
                '''
3756

    
3757
                sql = 'select A.UID,A.[X],A.[Y],B.Name,A.Value as [Line No],D.[Name] as AttrN,C.[Value] as [AttrV] from Components A left join Drawings B on A.Drawings_UID=B.UID \
3758
                        left join LineNoAttributes C on A.[UID]=C.Components_UID left join LineProperties D on C.LineProperties_UID=D.UID'
3759
                if drawings is not None:
3760
                    doc_names = "','".join(drawings)
3761
                    sql += f" where A.Symbol_UID=1 and Drawings_UID in (select UID from Drawings where Name in ('{doc_names}'))"
3762
                cursor.execute(sql)
3763

    
3764
                comps = [[row['UID'], row['Name'], row['Line No'], row['AttrN'], row['AttrV'], row['X'], row['Y']] for row in cursor.fetchall()]
3765
                lineNos = {}
3766

    
3767
                for comp in comps:
3768
                    if comp[0] not in lineNos:
3769
                        lineNos[comp[0]] = [['Line No', comp[2]], ['UID', comp[0]], ['Drawing Name', comp[1]], ['X', str(comp[5])], ['Y', str(comp[6])]]
3770
                    lineNos[comp[0]].append([comp[3], comp[4]])
3771

    
3772
                result = list(lineNos.values())
3773

    
3774
            # catch the exception
3775
            except Exception as ex:
3776
                print('error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
3777
                                                          sys.exc_info()[-1].tb_lineno))
3778

    
3779
        return result
3780

    
3781
    def get_equipment_data_list(self, drawings=None):
3782
        """ get equipment data list """
3783

    
3784
        result = []
3785

    
3786
        with self.project.database.connect() as conn:
3787
            try:
3788
                # Get a cursor object
3789
                cursor = conn.cursor()
3790

    
3791
                sql = "select A.UID,A.[X],A.[Y],B.NAME,C.SymbolType_UID,D.Type,C.NAME as symbol from Components A join Drawings B on A.Drawings_UID=B.UID\
3792
                        join Symbol C on A.Symbol_UID=C.UID\
3793
                        join SymbolType D on C.SymbolType_UID=D.UID\
3794
                        where (D.Category in ('Equipment') or A.Symbol_UID=7)"#,'Equipment Components')"
3795

    
3796
                if drawings is not None:
3797
                    doc_names = "','".join(drawings)
3798
                    sql += f" and A.Drawings_UID in (select UID from Drawings where Name in ('{doc_names}'))"
3799

    
3800
                cursor.execute(sql)
3801
                comps = [(row['UID'], row['NAME'], row['SymbolType_UID'], row['Type'], row['symbol'], row['X'], row['Y']) for row in cursor.fetchall()]
3802
                for comp in comps:
3803
                    sql = f"select distinct B.Attribute,A.Value from Attributes A left join SymbolAttribute B on " \
3804
                          f"A.SymbolAttribute_UID=B.UID where A.Components_UID='{comp[0]}'"
3805
                    cursor.execute(sql)
3806
                    attrs = cursor.fetchall()
3807
                    data = []
3808
                    for attr in attrs:
3809
                        data.append([attr['Attribute'], attr['Value']])
3810
                    if data:
3811
                        data.insert(0, ['Type', comp[3]])
3812
                        data.insert(0, ['Drawing Name', comp[1]])
3813
                        data.insert(0, ['ITEM_NO', comp[4]])
3814
                        data.insert(0, ['UID', comp[0]])
3815
                        data.insert(0, ['X', str(comp[5])])
3816
                        data.insert(0, ['Y', str(comp[6])])
3817
                        result.append(data)
3818

    
3819
            # catch the exception
3820
            except Exception as ex:
3821
                print('error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
3822
                                                           sys.exc_info()[-1].tb_lineno))
3823

    
3824
        return result
3825

    
3826
    '''
3827
        @brief      set line data list
3828
        @author     kyouho
3829
        @date       2018.08.13
3830
    '''
3831
    def setLineDataList(self, dataLists):
3832
        conn = self.project.database.connect()
3833
        with conn:
3834
            try:
3835
                # Get a cursor object
3836
                cursor = conn.cursor()
3837

    
3838
                for data in dataLists:
3839
                    sql = "insert into LINE_DATA_LIST(UID, LINE_SIZE, LINE_SYMBOL, LINE_NO, LINE_CLASS, LINE_ROUTING_FROM, LINE_ROUTING_TO, SERVICE_FLUID, SERVICE_DENSITY, SERVICE_STATE, OPERATION_CONDITION_TEMP, OPERATION_CONDITION_PRESS, DESIGN_CONDITION_TEMP, DESIGN_CONDITION_PRESS, TEST_CONDITION_TEMP, TEST_CONDITION_PRESS, INSUL_CODE, PAINT_CODE, NDE_CODE, PWHT, PNID_NO) values(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"
3840
                    param = tuple(data)
3841
                    cursor.execute(sql, param)
3842

    
3843
                conn.commit()
3844

    
3845
            # Catch the exception
3846
            except Exception as ex:
3847
                # Roll back any change if something goes wrong
3848
                conn.rollback()
3849

    
3850
                from App import App
3851
                message = f"error occurred({repr(ex)}) in {sys.exc_info()[-1].tb_frame.f_code.co_filename}:" \
3852
                          f"{sys.exc_info()[-1].tb_lineno}"
3853
                App.mainWnd().addMessage.emit(MessageType.Error, message)
3854

    
3855
    '''
3856
        @brief      delete line data list
3857
        @author     kyouho
3858
        @date       2018.08.13
3859
    '''
3860
    def deleteLineDataList(self, removeUID):
3861
        conn = self.project.database.connect()
3862
        with conn:
3863
            try:
3864
                # Get a cursor object
3865
                cursor = conn.cursor()
3866

    
3867
                for uid in removeUID:
3868
                    sql = "delete from LINE_DATA_LIST where uid = '{}'".format(uid)
3869
                    cursor.execute(sql)
3870

    
3871
                conn.commit()
3872

    
3873
            # Catch the exception
3874
            except Exception as ex:
3875
                # Roll back any change if something goes wrong
3876
                conn.rollback()
3877

    
3878
                from App import App
3879
                message = f"error occurred({repr(ex)}) in {sys.exc_info()[-1].tb_frame.f_code.co_filename}:" \
3880
                          f"{sys.exc_info()[-1].tb_lineno}"
3881
                App.mainWnd().addMessage.emit(MessageType.Error, message)
3882

    
3883
    '''
3884
        @brief      delete line data list
3885
        @author     kyouho
3886
        @date       2018.08.13
3887
    '''
3888
    def deleteLineDataList_LineNo(self, removeUID):
3889
        conn = self.project.database.connect()
3890
        with conn:
3891
            try:
3892
                # Get a cursor object
3893
                cursor = conn.cursor()
3894

    
3895
                for uid in removeUID:
3896
                    sql = "delete from LINE_DATA_LIST where LINE_NO = ?"
3897
                    param = (uid,)
3898
                    cursor.execute(sql, param)
3899

    
3900
                conn.commit()
3901

    
3902
            # Catch the exception
3903
            except Exception as ex:
3904
                # Roll back any change if something goes wrong
3905
                conn.rollback()
3906

    
3907
                from App import App
3908
                message = f"error occurred({repr(ex)}) in {sys.exc_info()[-1].tb_frame.f_code.co_filename}:" \
3909
                          f"{sys.exc_info()[-1].tb_lineno}"
3910
                App.mainWnd().addMessage.emit(MessageType.Error, message)
3911

    
3912
    '''
3913
        @brief      delete equip data list
3914
        @author     kyouho
3915
        @date       2018.08.14
3916
    '''
3917
    def deleteEquipDataList(self, removeUID):
3918
        conn = self.project.database.connect()
3919
        with conn:
3920
            try:
3921
                # Get a cursor object
3922
                cursor = conn.cursor()
3923

    
3924
                for uid in removeUID:
3925
                    sql = "delete from EQUIPMENT_DATA_LIST where uid = '{}'".format(uid)
3926
                    cursor.execute(sql)
3927

    
3928
                conn.commit()
3929

    
3930
            # Catch the exception
3931
            except Exception as ex:
3932
                # Roll back any change if something goes wrong
3933
                conn.rollback()
3934

    
3935
                from App import App
3936
                message = f"error occurred({repr(ex)}) in {sys.exc_info()[-1].tb_frame.f_code.co_filename}:" \
3937
                          f"{sys.exc_info()[-1].tb_lineno}"
3938
                App.mainWnd().addMessage.emit(MessageType.Error, message)
3939

    
3940
    '''
3941
        @brief      delete inst data list
3942
        @author     kyouho
3943
        @date       2018.08.14
3944
    '''
3945
    def deleteInstDataList(self, removeUID):
3946
        conn = self.project.database.connect()
3947
        with conn:
3948
            try:
3949
                # Get a cursor object
3950
                cursor = conn.cursor()
3951

    
3952
                for uid in removeUID:
3953
                    sql = "delete from INSTRUMENT_DATA_LIST where uid = '{}'".format(uid)
3954
                    cursor.execute(sql)
3955

    
3956
                conn.commit()
3957

    
3958
            # Catch the exception
3959
            except Exception as ex:
3960
                # Roll back any change if something goes wrong
3961
                conn.rollback()
3962

    
3963
                from App import App
3964
                message = f"error occurred({repr(ex)}) in {sys.exc_info()[-1].tb_frame.f_code.co_filename}:" \
3965
                          f"{sys.exc_info()[-1].tb_lineno}"
3966
                App.mainWnd().addMessage.emit(MessageType.Error, message)
3967

    
3968
    '''
3969
        @brief      delete note data list
3970
        @author     kyouho
3971
        @date       2018.10.10
3972
    '''
3973
    def deleteNoteDataList(self, removeUID):
3974
        conn = self.project.database.connect()
3975
        with conn:
3976
            try:
3977
                # Get a cursor object
3978
                cursor = conn.cursor()
3979

    
3980
                for uid in removeUID:
3981
                    sql = "delete from NOTE_DATA_LIST where uid = '{}'".format(uid)
3982
                    cursor.execute(sql)
3983

    
3984
                conn.commit()
3985

    
3986
            # Catch the exception
3987
            except Exception as ex:
3988
                # Roll back any change if something goes wrong
3989
                conn.rollback()
3990

    
3991
                from App import App
3992
                message = f"error occurred({repr(ex)}) in {sys.exc_info()[-1].tb_frame.f_code.co_filename}:" \
3993
                          f"{sys.exc_info()[-1].tb_lineno}"
3994
                App.mainWnd().addMessage.emit(MessageType.Error, message)
3995

    
3996
    def get_valve_attributes(self):
3997
        """ return valve attributes """
3998

    
3999
        from SymbolAttr import SymbolAttr
4000

    
4001
        res = None
4002
        if not hasattr(self, '_valve_attributes'):
4003
            self._valve_attributes = []
4004

    
4005
            with self.project.database.connect() as conn:
4006
                try:
4007
                    # Get a cursor object
4008
                    cursor = conn.cursor()
4009

    
4010
                    sql = "select distinct A.Attribute from SymbolAttribute A join SymbolType B on " \
4011
                          "A.SymbolType_UID=B.UID where B.Category = 'Piping'"
4012
                    cursor.execute(sql)
4013
                    rows = cursor.fetchall()
4014
                    for row in rows:
4015
                        attr = SymbolAttr()
4016
                        attr.Attribute = row['Attribute']
4017
                        self._valve_attributes.append(attr)
4018

    
4019
                    res = self._valve_attributes
4020
                # Catch the exception
4021
                except Exception as ex:
4022
                    from App import App
4023
                    message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
4024
                                                                sys.exc_info()[-1].tb_lineno)
4025
                    App.mainWnd().addMessage.emit(MessageType.Error, message)
4026
        else:
4027
            res = self._valve_attributes
4028

    
4029
        return res
4030

    
4031
    def get_valve_data_list(self, drawings=None):
4032
        """get valve data list"""
4033

    
4034
        result = []
4035
        conn = self.project.database.connect()
4036
        with conn:
4037
            try:
4038
                # Get a cursor object
4039
                cursor = conn.cursor()
4040

    
4041
                sql = "select a.[UID],a.[X],a.[Y],D.Name,E.Name as 'Drawing Name',C.Attribute,B.Value,a.[Owner] from Components a " \
4042
                      "join Attributes B on a.UID=B.Components_UID " \
4043
                      "join SymbolAttribute C on B.SymbolAttribute_UID=C.UID " \
4044
                      "join Symbol D on a.Symbol_UID=D.UID " \
4045
                      "join Drawings E on a.Drawings_UID=E.UID " \
4046
                      "where a.Symbol_UID in (select UID from Symbol where SymbolType_UID in " \
4047
                      "(select UID from SymbolType where Category in ('Piping')))"
4048
                if drawings is not None:
4049
                    doc_names = "','".join(drawings)
4050
                    sql += f" and A.Drawings_UID in (select UID from Drawings where Name in ('{doc_names}'))"
4051

    
4052
                cursor.execute(sql)
4053
                rows = cursor.fetchall()
4054
                '''
4055
                for row in rows:
4056
                    matches = [res for res in result if res['UID'] == row['UID']]
4057
                    if matches:
4058
                        matches[0][row['Attribute']] = row['Value']
4059
                    else:
4060
                        data = {'UID': row['UID'], 'ITEM_NO': row['Name'], 'Drawing Name': row['Drawing Name'],
4061
                                'Owner': row['Owner'], row['Attribute']: row['Value']}
4062
                        result.append(data)
4063

4064
                '''
4065
                valves = {}
4066

    
4067
                for row in rows:
4068
                    if row['UID'] not in valves:
4069
                        valves[row['UID']] = {'UID': row['UID'], 'ITEM_NO': row['Name'], 'Drawing Name': row['Drawing Name'],
4070
                                'Owner': row['Owner'], 'X': str(row['X']), 'Y': str(row['Y'])}
4071
                    valves[row['UID']][row['Attribute']] = row['Value']
4072

    
4073
                result = list(valves.values())
4074

    
4075
            # Catch the exception
4076
            except Exception as ex:
4077
                from App import App
4078
                message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
4079
                                                              sys.exc_info()[-1].tb_lineno)
4080
                App.mainWnd().addMessage.emit(MessageType.Error, message)
4081

    
4082
        return result
4083

    
4084
    def get_instrument_attributes(self):
4085
        """ return valve attributes """
4086

    
4087
        from SymbolAttr import SymbolAttr
4088

    
4089
        res = None
4090
        if not hasattr(self, '_inst_attributes'):
4091
            self._inst_attributes = []
4092

    
4093
            with self.project.database.connect() as conn:
4094
                try:
4095
                    # Get a cursor object
4096
                    cursor = conn.cursor()
4097

    
4098
                    sql = "select distinct A.Attribute from SymbolAttribute A join SymbolType B on " \
4099
                          "A.SymbolType_UID=B.UID where B.Category = 'Instrumentation'"
4100
                    cursor.execute(sql)
4101
                    rows = cursor.fetchall()
4102
                    for row in rows:
4103
                        attr = SymbolAttr()
4104
                        attr.Attribute = row['Attribute']
4105
                        self._inst_attributes.append(attr)
4106

    
4107
                    res = self._inst_attributes
4108
                # Catch the exception
4109
                except Exception as ex:
4110
                    from App import App
4111
                    message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
4112
                                                                sys.exc_info()[-1].tb_lineno)
4113
                    App.mainWnd().addMessage.emit(MessageType.Error, message)
4114
        else:
4115
            res = self._inst_attributes
4116

    
4117
        return res
4118

    
4119
    '''
4120
        @brief      get instrument data list
4121
        @author     kyouho
4122
        @date       2018.08.14
4123
    '''
4124
    def get_instrument_data_list(self, drawings=None):
4125
        result = []
4126
        conn = self.project.database.connect()
4127
        with conn:
4128
            try:
4129
                # Get a cursor object
4130
                cursor = conn.cursor()
4131

    
4132
                sql = "select a.[UID],a.[X],a.[Y],D.Name,E.Name as 'Drawing Name',C.Attribute,B.Value,a.Symbol_UID,a.[Owner] from Components a " \
4133
                      "join Attributes B on a.UID=B.Components_UID " \
4134
                      "join SymbolAttribute C on B.SymbolAttribute_UID=C.UID " \
4135
                      "join Symbol D on a.Symbol_UID=D.UID " \
4136
                      "join Drawings E on a.Drawings_UID=E.UID " \
4137
                      "where a.Symbol_UID in (select UID from Symbol where SymbolType_UID in " \
4138
                      "(select UID from SymbolType where Category in ('Instrumentation')))"
4139
                if drawings is not None:
4140
                    doc_names = "','".join(drawings)
4141
                    sql += f" and A.Drawings_UID in (select UID from Drawings where Name in ('{doc_names}'))"
4142

    
4143
                cursor.execute(sql)
4144
                rows = cursor.fetchall()
4145
                '''
4146
                for row in rows:
4147
                    matches = [res for res in result if res['UID'] == row['UID']]
4148
                    if matches:
4149
                        matches[0][row['Attribute']] = row['Value']
4150
                    else:
4151
                        data = {'UID': row['UID'], 'ITEM_NO': row['Name'], 'Drawing Name': row['Drawing Name'], 'Owner': row['Owner'], 
4152
                                'Symbol_UID': int(row['Symbol_UID']), row['Attribute']: row['Value']}
4153
                        result.append(data)
4154
                '''
4155
                insts = {}
4156

    
4157
                for row in rows:
4158
                    if row['UID'] not in insts:
4159
                        insts[row['UID']] = {'UID': row['UID'], 'ITEM_NO': row['Name'], 'Drawing Name': row['Drawing Name'], 'Owner': row['Owner'], 
4160
                                'Symbol_UID': int(row['Symbol_UID']), 'X': str(row['X']), 'Y': str(row['Y'])}
4161
                    insts[row['UID']][row['Attribute']] = row['Value']
4162

    
4163
                result = list(insts.values())
4164
            # Catch the exception
4165
            except Exception as ex:
4166
                from App import App
4167
                message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
4168
                                                              sys.exc_info()[-1].tb_lineno)
4169
                App.mainWnd().addMessage.emit(MessageType.Error, message)
4170

    
4171
        return result
4172

    
4173
    def get_note_attributes(self):
4174
        """ return note attributes """
4175

    
4176
        from SymbolAttr import SymbolAttr
4177

    
4178
        res = None
4179
        if not hasattr(self, '_note_attributes'):
4180
            self._note_attributes = []
4181

    
4182
            with self.project.database.connect() as conn:
4183
                try:
4184
                    # Get a cursor object
4185
                    cursor = conn.cursor()
4186

    
4187
                    sql = "select distinct A.Attribute from SymbolAttribute A join SymbolType B on " \
4188
                          "A.SymbolType_UID=B.UID where B.Category='General' and B.Type='Notes'"
4189
                    cursor.execute(sql)
4190
                    rows = cursor.fetchall()
4191
                    for row in rows:
4192
                        attr = SymbolAttr()
4193
                        attr.Attribute = row['Attribute']
4194
                        self._note_attributes.append(attr)
4195

    
4196
                    res = self._note_attributes
4197
                # Catch the exception
4198
                except Exception as ex:
4199
                    from App import App
4200
                    message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
4201
                                                                sys.exc_info()[-1].tb_lineno)
4202
                    App.mainWnd().addMessage.emit(MessageType.Error, message)
4203
        else:
4204
            res = self._note_attributes
4205

    
4206
        return res
4207

    
4208
    def get_note_data_list(self, drawings=None):
4209
        """ get note data list """
4210
        result = []
4211

    
4212
        conn = self.project.database.connect()
4213
        with conn:
4214
            try:
4215
                # Get a cursor object
4216
                cursor = conn.cursor()
4217

    
4218
                sql = "select a.UID,D.Name,E.Name as 'Drawing Name',C.Attribute,B.Value from Components a " \
4219
                      "join Attributes B on a.UID=B.Components_UID " \
4220
                      "join SymbolAttribute C on B.SymbolAttribute_UID=C.UID " \
4221
                      "join Symbol D on a.Symbol_UID=D.UID " \
4222
                      "join Drawings E on a.Drawings_UID=E.UID " \
4223
                      "where a.Symbol_UID in (select UID from Symbol where SymbolType_UID in " \
4224
                      "(select UID from SymbolType where Category='General' and Type='Notes'))"
4225
                if drawings is not None:
4226
                    doc_names = "','".join(drawings)
4227
                    sql += f" and A.Drawings_UID in (select UID from Drawings where Name in ('{doc_names}'))"
4228

    
4229
                cursor.execute(sql)
4230
                rows = cursor.fetchall()
4231
                for row in rows:
4232
                    matches = [res for res in result if res['UID'] == row['UID']]
4233
                    if matches:
4234
                        matches[0][row['Attribute']] = row['Value']
4235
                    else:
4236
                        data = {'UID': row['UID'], 'ITEM_NO': row['Name'], 'Drawing Name': row['Drawing Name'],
4237
                                row['Attribute']: row['Value']}
4238
                        result.append(data)
4239
            # Catch the exception
4240
            except Exception as ex:
4241
                from App import App
4242
                message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
4243
                                                              sys.exc_info()[-1].tb_lineno)
4244
                App.mainWnd().addMessage.emit(MessageType.Error, message)
4245

    
4246
        return result
4247

    
4248
    def clearAllDrawingDataFromDatabase(self):
4249
        """ clear all drawing data from database """
4250

    
4251
        sql = ''
4252

    
4253
        with self.project.database.connect() as conn:
4254
            try:
4255
                # Get a cursor object
4256
                cursor = conn.cursor()
4257

    
4258
                sql = "delete from LINE_DATA_LIST"
4259
                cursor.execute(sql)
4260
                sql = "delete from TitleBlockValues"
4261
                cursor.execute(sql)
4262
                sql = "delete from LineNoAttributes"
4263
                cursor.execute(sql)
4264
                sql = "delete from Attributes"
4265
                cursor.execute(sql)
4266
                sql = "delete from Associations"
4267
                cursor.execute(sql)
4268
                sql = "delete from Points"
4269
                cursor.execute(sql)
4270
                sql = "delete from PipeRunItems"
4271
                cursor.execute(sql)
4272
                sql = "delete from PipeRuns"
4273
                cursor.execute(sql)
4274
                sql = "delete from Components"
4275
                cursor.execute(sql)
4276
                sql = "delete from Stream_Line_List"
4277
                cursor.execute(sql)
4278
                sql = "delete from [Views]"
4279
                cursor.execute(sql)
4280
                sql = "delete from Drawings"
4281
                cursor.execute(sql)
4282
                sql = "delete from Libraries"
4283
                cursor.execute(sql)
4284

    
4285
                """
4286
                for drawing in drawings:
4287
                    sql = "delete from LINE_DATA_LIST where PNID_NO = '{}'".format(drawing.UID)
4288
                    cursor.execute(sql)
4289
                    sql = "delete from TitleBlockValues where Drawings_UID = '{}'".format(drawing.UID)
4290
                    cursor.execute(sql)
4291
                    sql = f"delete from LineNoAttributes where Components_UID in " \
4292
                                f"(select UID from Components where Drawings_UID='{drawing.UID}')"
4293
                    cursor.execute(sql)
4294
                    sql = f"delete from Attributes where Components_UID in " \
4295
                                f"(select UID from Components where Drawings_UID='{drawing.UID}')"
4296
                    cursor.execute(sql)
4297
                    sql = f"delete from Associations where Components_UID in " \
4298
                                f"(select UID from Components where Drawings_UID='{drawing.UID}')"
4299
                    cursor.execute(sql)
4300
                    sql = f"delete from Points where Components_UID in " \
4301
                                f"(select UID from Components where Drawings_UID='{drawing.UID}')"
4302
                    cursor.execute(sql)
4303
                    sql = f"delete from PipeRunItems where PipeRuns_UID in " \
4304
                                f"(select UID from PipeRuns where Drawings_UID='{drawing.UID}')"
4305
                    cursor.execute(sql)
4306
                    sql = f"delete from PipeRuns where Drawings_UID='{drawing.UID}'"
4307
                    cursor.execute(sql)
4308
                    sql = "delete from Components where Drawings_UID='{}'".format(drawing.UID)
4309
                    cursor.execute(sql)
4310
                    sql = "delete from Stream_Line_List where Drawing_UID='{}'".format(drawing.UID)
4311
                    cursor.execute(sql)
4312
                    sql = "delete from [Views] where Drawings_UID='{}'".format(drawing.UID)
4313
                    cursor.execute(sql)
4314
                    sql = "delete from Drawings where [UID]='{}'".format(drawing.UID)
4315
                    cursor.execute(sql)
4316

4317
                    # multi table delete not support in mssql
4318
                    ''' 
4319
                    sql = f"delete LINE_DATA_LIST, TitleBlockValues, LineNoAttributes, Attributes, Associations, Points, PipeRunItems, PipeRuns, Components, Stream_Line_List, [Views], Drawings " \
4320
                            f"from LINE_DATA_LIST a " \
4321
                            f"join TitleBlockValues b on a.PNID_NO = b.Drawings_UID " \
4322
                            f"join LineNoAttributes c on b.Drawings_UID = c.Drawings_UID " \
4323
                            f"join Attributes d on c.Drawings_UID = d.Drawings_UID " \
4324
                            f"join Associations e on d.Drawings_UID = e.Drawings_UID " \
4325
                            f"join Points f on e.Drawings_UID = f.Drawings_UID " \
4326
                            f"join PipeRunItems g on f.Drawings_UID = g.Drawings_UID " \
4327
                            f"join PipeRuns h on g.Drawings_UID = h.Drawings_UID " \
4328
                            f"join Components i on h.Drawings_UID = i.Drawings_UID " \
4329
                            f"join Stream_Line_List j on i.Drawings_UID = j.Drawing_UID " \
4330
                            f"join [Views] k on j.Drawing_UID = k.Drawings_UID " \
4331
                            f"join Drawings l on k.Drawings_UID = l.[UID] " \
4332
                            f"where l.[uid] = '{drawing.UID}'"
4333
                    cursor.execute(sql)
4334
                    '''
4335
                """
4336

    
4337
                if self.project.database.db_type == 'SQLite':
4338
                    cursor.execute('commit')
4339
                else:
4340
                    conn.commit()
4341

    
4342
                # Catch the exception
4343
            except Exception as ex:
4344
                # Roll back any change if something goes wrong
4345
                conn.rollback()
4346

    
4347
                from App import App
4348
                message = 'error occurred({}\\n{}) in {}:{}'.format(repr(ex), sql,
4349
                                                                    sys.exc_info()[-1].tb_frame.f_code.co_filename,
4350
                                                                    sys.exc_info()[-1].tb_lineno)
4351
                App.mainWnd().addMessage.emit(MessageType.Error, message)
4352

    
4353
    def checkDatabaseCascade(self):
4354
        if self.project.database.db_type == 'SQLite':
4355
            return True
4356
        
4357
        #configs = self.getConfigs('Database', 'Cascade')
4358
        #if 1 == len(configs):
4359
        #    return True
4360
        
4361
        with self.project.database.connect() as conn:
4362
            try:
4363
                # Get a cursor object
4364
                cursor = conn.cursor()
4365
                sql = "select * from INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS where DELETE_RULE ='CASCADE'"
4366
                cursor.execute(sql)
4367
                rows = cursor.fetchall()
4368
                if rows:
4369
                    return True
4370
                else:
4371
                    return False
4372

    
4373
            # Catch the exception
4374
            except Exception as ex:
4375
                from App import App
4376
                message = f"error occurred({repr(ex)}) in {sys.exc_info()[-1].tb_frame.f_code.co_filename}:" \
4377
                          f"{sys.exc_info()[-1].tb_lineno}"
4378
                App.mainWnd().addMessage.emit(MessageType.Error, message)
4379
        
4380
        return False
4381

    
4382
    def setDatabaseCascade(self):
4383
        # temp not finished
4384
        with self.project.database.connect() as conn:
4385
            try:
4386
                # Get a cursor object
4387
                cursor = conn.cursor()
4388
                sql = "select * from INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS "
4389
                cursor.execute(sql)
4390
                rows = cursor.fetchall()
4391
                if rows:
4392
                    return True
4393
                else:
4394
                    return False
4395

    
4396
            # Catch the exception
4397
            except Exception as ex:
4398
                # Roll back any change if something goes wrong
4399
                conn.rollback()
4400

    
4401
                from App import App
4402
                message = 'error occurred({}\\n{}) in {}:{}'.format(repr(ex), sql,
4403
                                                                    sys.exc_info()[-1].tb_frame.f_code.co_filename,
4404
                                                                    sys.exc_info()[-1].tb_lineno)
4405
                App.mainWnd().addMessage.emit(MessageType.Error, message)
4406

    
4407

    
4408
    def saveToDatabase(self, items, rect: QRectF, show_progress=None):
4409
        """ save given items to database """
4410
        import uuid
4411

    
4412
        # delete all datas of current drawing
4413
        drawing_name = self.activeDrawing.name
4414
        drawing_uid = self.activeDrawing.UID
4415
        sql = ''
4416

    
4417
        isCascade = self.checkDatabaseCascade()
4418

    
4419
        queries = {'first': [], 'second': []}
4420
        for item in items:
4421
            if hasattr(item, 'toSql_return_separately'):
4422
                sql, sqlLater = item.toSql_return_separately()
4423
                queries['first'].append(sql)
4424
                queries['second'].append(sqlLater)
4425
            else:
4426
                queries['first'].append(item.toSql())
4427

    
4428
        """
4429
        # Drawing Cascade test
4430
        if self.project.database.db_type != 'SQLite':
4431
            ''' update drawing's modified time for MSSQL '''
4432
            drawings = self.getDrawings()
4433
            drawing = [drawing for drawing in drawings if self.imgName == os.path.splitext(drawing.name)[0]]
4434
            if drawing[0]:
4435
                drawing[0].datetime = datetime.now().strftime('%Y-%m-%d %H:%M:%S')
4436

4437
            ''' hmb backup '''
4438
            #from_to = self.get_stream_from_to(drawing_uid = self.activeDrawing.UID)
4439
        """
4440

    
4441
        with self.project.database.connect() as conn:
4442
            try:
4443
                # Get a cursor object
4444
                cursor = conn.cursor()
4445
                if self.project.database.db_type == 'SQLite':
4446
                    #import timeit
4447
                    #_start = timeit.default_timer()
4448
                    cursor.execute('begin')
4449

    
4450
                    sql = "delete from LINE_DATA_LIST where PNID_NO = '{}'".format(drawing_name)
4451
                    cursor.execute(sql)
4452

    
4453
                    sql = "delete from TitleBlockValues where Drawings_UID = '{}'".format(drawing_uid)
4454
                    cursor.execute(sql)
4455

    
4456
                    # delete LineNoAttributes
4457
                    sql = f"delete from LineNoAttributes where Components_UID in " \
4458
                        f"(select UID from Components where Drawings_UID='{drawing_uid}')"
4459
                    cursor.execute(sql)
4460

    
4461
                    # delete Attributes
4462
                    sql = f"delete from Attributes where Components_UID in " \
4463
                        f"(select UID from Components where Drawings_UID='{drawing_uid}')"
4464
                    cursor.execute(sql)
4465

    
4466
                    # delete Associations
4467
                    sql = f"delete from Associations where Components_UID in " \
4468
                        f"(select UID from Components where Drawings_UID='{drawing_uid}')"
4469
                    cursor.execute(sql)
4470

    
4471
                    # delete Points
4472
                    sql = f"delete from Points where Components_UID in " \
4473
                        f"(select UID from Components where Drawings_UID='{drawing_uid}')"
4474
                    cursor.execute(sql)
4475

    
4476
                    # delete PipeRunItems
4477
                    sql = f"delete from PipeRunItems where PipeRuns_UID in " \
4478
                        f"(select UID from PipeRuns where Drawings_UID='{drawing_uid}')"
4479
                    cursor.execute(sql)
4480

    
4481
                    # delete PipeRuns
4482
                    sql = f"delete from PipeRuns where Drawings_UID='{drawing_uid}'"
4483
                    cursor.execute(sql)
4484

    
4485
                    # delete Components 
4486
                    sql = "delete from Components where Drawings_UID='{}'".format(drawing_uid)
4487
                    cursor.execute(sql)
4488

    
4489
                    # delete Stream Line List
4490
                    sql = "delete from Stream_Line_List where Drawing_UID='{}'".format(drawing_uid)
4491
                    cursor.execute(sql)
4492
                    #_stop = timeit.default_timer()
4493
                    #seconds = _stop - _start
4494
                    #print(seconds)
4495
                else:
4496
                    #import timeit
4497
                    #_start = timeit.default_timer()
4498
                    if not isCascade:
4499
                        sql = f"delete from LINE_DATA_LIST where PNID_NO = '{drawing_name}'" \
4500
                            f"delete from TitleBlockValues where Drawings_UID = '{drawing_uid}'" \
4501
                            f"delete from LineNoAttributes where Components_UID in " \
4502
                            f"(select UID from Components where Drawings_UID='{drawing_uid}')" \
4503
                            f"delete from Attributes where Components_UID in " \
4504
                            f"(select UID from Components where Drawings_UID='{drawing_uid}')" \
4505
                            f"delete from Associations where Components_UID in " \
4506
                            f"(select UID from Components where Drawings_UID='{drawing_uid}')" \
4507
                            f"delete from Points where Components_UID in " \
4508
                            f"(select UID from Components where Drawings_UID='{drawing_uid}')" \
4509
                            f"delete from PipeRunItems where PipeRuns_UID in " \
4510
                            f"(select UID from PipeRuns where Drawings_UID='{drawing_uid}')" \
4511
                            f"delete from PipeRuns where Drawings_UID='{drawing_uid}'" \
4512
                            f"delete from Components where Drawings_UID='{drawing_uid}'" \
4513
                            f"delete from Stream_Line_List where Drawing_UID='{drawing_uid}'"
4514
                        cursor.execute(sql)
4515
                        #_stop = timeit.default_timer()
4516
                        #seconds = _stop - _start
4517
                        #print(seconds)
4518
                    else:
4519
                        sql = f"delete from LINE_DATA_LIST where PNID_NO = '{drawing_name}'" \
4520
                            f"delete from TitleBlockValues where Drawings_UID = '{drawing_uid}'" \
4521
                            f"delete from Components where Drawings_UID='{drawing_uid}'" \
4522
                            f"delete from Stream_Line_List where Drawing_UID='{drawing_uid}'"
4523
                        cursor.execute(sql)
4524

    
4525
                        '''
4526
                        sql = f"delete from Drawings where [UID] = '{drawing_uid}'"
4527
                        cursor.execute(sql)
4528

4529
                        sql = self.project.database.to_sql(
4530
                            'insert into Drawings(UID, [NAME], [DATETIME], [OCCUPIED], [Image]) values(?, ?, ?, ?, ?)')
4531
                        param = tuple([str(drawing[0].UID), drawing[0].name, drawing[0].datetime, os.environ['COMPUTERNAME'], None])
4532
                        cursor.execute(sql, param)
4533
                        _stop = timeit.default_timer()
4534
                        seconds = _stop - _start
4535
                        print(seconds)
4536
                        '''
4537
                
4538
                progress = 0
4539
                length = len(queries['first']) + len(queries['second'])
4540
                for sql in queries['first']:
4541
                    if type(sql) is list:
4542
                        for item in sql:
4543
                            if item is not None and 2 == len(item):
4544
                                cursor.executemany(self.project.database.to_sql(item[0]), item[1])
4545
                    else:
4546
                        if sql is not None and 2 == len(sql):
4547
                            cursor.executemany(self.project.database.to_sql(sql[0]), sql[1])
4548

    
4549
                    if show_progress:
4550
                        show_progress.emit(int((progress / length)*100))
4551
                    progress += 1
4552

    
4553
                for sql in queries['second']:
4554
                    if type(sql) is list:
4555
                        for item in sql:
4556
                            if item is not None and 2 == len(item):
4557
                                cursor.executemany(self.project.database.to_sql(item[0]), item[1])
4558
                    else:
4559
                        if sql is not None and 2 == len(sql):
4560
                            cursor.executemany(self.project.database.to_sql(sql[0]), sql[1])
4561

    
4562
                    if show_progress:
4563
                        show_progress.emit(int((progress / length)*100))
4564
                    progress += 1
4565

    
4566
                # save Stream No Line List
4567
                index = 1
4568
                for model_data in self._streamLineListModelDatas:
4569
                    sql = f"insert into Stream_Line_List (UID, Drawing_UID, PnIDNumber, Tag_Seq_No, PipingMaterialsClass, InsulationPurpose, FluidCode, " \
4570
                          f"UnitNumber, NominalDiameter, [From], [To], Stream_No, [Case], [Index]) values(?,?,?,?,?,?,?,?,?,?,?,?,?,?)"
4571
                    sql = self.project.database.to_sql(sql)
4572
                    params = (str(uuid.uuid4()), drawing_uid, model_data['PnIDNumber'], model_data['Tag Seq No'], model_data['PipingMaterialsClass'], model_data['InsulationPurpose'], \
4573
                              model_data['FluidCode'], model_data['UnitNumber'], model_data['NominalDiameter'], model_data['FROM'], model_data['TO'], model_data['Stream No'], model_data['Case'], index)
4574
                    cursor.execute(sql, params)
4575
                    index += 1
4576

    
4577
                if show_progress:
4578
                    show_progress.emit(99)
4579

    
4580
                if self.project.database.db_type == 'SQLite':
4581
                    cursor.execute('commit')
4582
                else:
4583
                    conn.commit()
4584
            # Catch the exception
4585
            except Exception as ex:
4586
                # Roll back any change if something goes wrong
4587
                conn.rollback()
4588

    
4589
                from App import App
4590
                message = 'error occurred({}\\n{}) in {}:{}'.format(repr(ex), sql,
4591
                                                                    sys.exc_info()[-1].tb_frame.f_code.co_filename,
4592
                                                                    sys.exc_info()[-1].tb_lineno)
4593
                App.mainWnd().addMessage.emit(MessageType.Error, message)
4594

    
4595
        if rect:
4596
            self.activeDrawing.view_rect = rect
4597
            self.update_view_region(self.activeDrawing)
4598

    
4599
    def update_view_region(self, drawing):
4600
        """update view region"""
4601
        with self.project.database.connect() as conn:
4602
            try:
4603
                # Get a cursor object
4604
                cursor = conn.cursor()
4605

    
4606
                # check if there is view region
4607
                sql = f"select Drawings_UID from Views where Drawings_UID=?"
4608
                params = (drawing.UID,)
4609
                cursor.execute(self.project.database.to_sql(sql), params)
4610
                rows = cursor.fetchall()
4611
                if rows:
4612
                    sql = f"update Views set X=?,Y=?,Width=?,Height=? where Drawings_UID=?"
4613
                    params = (drawing.view_rect.x(), drawing.view_rect.y(),
4614
                              drawing.view_rect.width(), drawing.view_rect.height(), drawing.UID)
4615
                else:
4616
                    sql = f"insert into Views(Drawings_UID,X,Y,Width,Height) values(?,?,?,?,?)"
4617
                    params = (drawing.UID, drawing.view_rect.x(), drawing.view_rect.y(),
4618
                              drawing.view_rect.width(), drawing.view_rect.height())
4619

    
4620
                sql = self.project.database.to_sql(sql)
4621
                cursor.execute(sql, params)
4622
                conn.commit()
4623
            # Catch the exception
4624
            except Exception as ex:
4625

    
4626
                from App import App
4627
                message = 'error occurred({}\\n{}) in {}:{}'.format(repr(ex), sql,
4628
                                                                    sys.exc_info()[-1].tb_frame.f_code.co_filename,
4629
                                                                    sys.exc_info()[-1].tb_lineno)
4630
                App.mainWnd().addMessage.emit(MessageType.Error, message)
4631

    
4632
    '''
4633
        @brief      set equipment data list
4634
        @author     humkyung
4635
        @date       2018.05.03
4636
    '''
4637
    def setEquipmentDataList(self, dataList):
4638
        conn = self.project.database.connect()
4639
        with conn:
4640
            try:
4641
                # Get a cursor object
4642
                cursor = conn.cursor()
4643

    
4644
                for data in dataList:
4645
                    sql = "insert into EQUIPMENT_DATA_LIST(UID, ITEM_NO, SERVICE, NO_REQ, FLUID, DESC_OF_PART, OPERATION_CONDITION_TEMP, OPERATION_CONDITION_PRESS, DESIGN_CONDITION_TEMP, DESIGN_CONDITION_PRESS, MATERIAL, WEIGHT, POWER, INSULATION, PNID_NO, REV) values(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"
4646
                    param = tuple(data)
4647
                    cursor.execute(self.project.database.to_sql(sql), param)
4648
                conn.commit()
4649
            # Catch the exception
4650
            except Exception as ex:
4651
                # Roll back any change if something goes wrong
4652
                conn.rollback()
4653

    
4654
                from App import App
4655
                message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
4656
                                                              sys.exc_info()[-1].tb_lineno)
4657
                App.mainWnd().addMessage.emit(MessageType.Error, message)
4658

    
4659
    '''
4660
        @brief      set instrumnet data list
4661
        @author     kyoyho
4662
        @date       2018.08.14
4663
    '''
4664
    def setInstrumentDataList(self, dataList):
4665
        conn = self.project.database.connect()
4666
        with conn:
4667
            try:
4668
                # Get a cursor object
4669
                cursor = conn.cursor()
4670

    
4671
                for data in dataList:
4672
                    sql = "insert into INSTRUMENT_DATA_LIST(UID, ITEM_NO, SERVICE, FLOW_RATE, PRESSURE, TEMPERATURE, TPYE, RANGE, NOR_LEVEL_MM, NOR_LEVEL_PERCENT, DEL_PRESS, SHUT_OFF, LOCATION, PNID_NO, REV) values(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"
4673
                    param = tuple(data)
4674
                    cursor.execute(sql, param)
4675
                conn.commit()
4676

    
4677
            # Catch the exception
4678
            except Exception as ex:
4679
                # Roll back any change if something goes wrong
4680
                conn.rollback()
4681

    
4682
                from App import App
4683
                message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
4684
                                                              sys.exc_info()[-1].tb_lineno)
4685
                App.mainWnd().addMessage.emit(MessageType.Error, message)
4686

    
4687
    def getDrawings(self):
4688
        """ get drawings """
4689
        from Drawing import Drawing
4690

    
4691
        res = []
4692

    
4693
        with self.project.database.connect() as conn:
4694
            try:
4695
                cursor = conn.cursor()
4696
                if self.project.database.db_type == 'SQLite':
4697
                    sql = 'select UID, [NAME], [DATETIME], IFNULL(B.[X], 0) as X, IFNULL(B.[Y], 0) as Y, ' \
4698
                          'IFNULL(B.[Width], 0) as Width, IFNULL(B.[Height], 0) as Height from Drawings A ' \
4699
                          'left join Views B on A.UID = B.Drawings_UID'
4700
                else:
4701
                    sql = 'select UID, [NAME], [DATETIME], ISNULL(B.[X], 0) as X, ISNULL(B.[Y], 0) as Y, ' \
4702
                          'ISNULL(B.[Width], 0) as Width, ISNULL(B.[Height], 0) as Height from Drawings A ' \
4703
                          'left join Views B on A.UID = B.Drawings_UID'
4704

    
4705
                cursor.execute(self.project.database.to_sql(sql))
4706
                for row in cursor.fetchall():
4707
                    rect = QRectF(float(row['X']), float(row['Y']), float(row['Width']), float(row['Height']))
4708
                    res.append(Drawing(row['UID'], row['NAME'], row['DATETIME'], rect))
4709
            # Catch the exception
4710
            except Exception as ex:
4711
                from App import App
4712
                message = 'error occurred({}) in {}:{}'.format(repr(ex), sys.exc_info()[-1].tb_frame.f_code.co_filename,
4713
                                                              sys.exc_info()[-1].tb_lineno)
4714
                App.mainWnd().addMessage.emit(MessageType.Error, message)
4715

    
4716
        return res
4717

    
4718
    def saveDrawings(self, drawings):
4719
        """save given drawings"""
4720

    
4721
        import uuid
4722

    
4723
        if not drawings:
4724
            return
4725

    
4726
        with self.project.database.connect() as conn:
4727
            try:
4728
                # Get a cursor object
4729
                cursor = conn.cursor()
4730
                if self.project.database.db_type == 'SQLite':
4731
                    cursor.execute('begin')
4732

    
4733
                for drawing in drawings:
4734
                    if drawing.UID is None:
4735
                        # get image data
4736
                        image_blob_data = None
4737
                        #file_path = os.path.join(self.project.getDrawingFilePath(), drawing.name)
4738
                        #if drawing.name and os.path.isfile(file_path):
4739
                        #    with open(file_path.encode('utf-8'), 'rb') as file:
4740
                        #        image_blob_data = file.read()
4741
                        # up to here
4742

    
4743
                        sql = self.project.database.to_sql(
4744
                            'insert into Drawings(UID, [NAME], [DATETIME], [Image]) values(?, ?, ?, ?)')
4745
                        param = tuple([str(uuid.uuid4()), drawing.name, '', image_blob_data])
4746
                        drawing.UID = param[0]
4747
                    else:
4748
                        sql = self.project.database.to_sql("update Drawings set [NAME]=?,[DATETIME]=? where UID=?")
4749
                        param = (drawing.name, drawing.datetime, str(drawing.UID))
4750
                        #param = (drawing.name, drawing.datetime, image_blob_data, str(drawing.UID))
4751

    
4752
                    cursor.execute(sql, param)
4753

    
4754
                if self.project.database.db_type == 'SQLite':
4755
                    cursor.execute('commit')
4756
                else:
4757
                    conn.commit()
4758
            # Catch the exception
4759
            except Exception as ex:
4760
                # Roll back any change if something goes wrong
4761
                conn.rollback()
4762

    
4763
                from App import App
4764
                message = 'error occurred({}) in {}:{}'.format(repr(ex), sys.exc_info()[-1].tb_frame.f_code.co_filename,
4765
                                                              sys.exc_info()[-1].tb_lineno)
4766
                App.mainWnd().addMessage.emit(MessageType.Error, message)
4767

    
4768
    '''
4769
        @brief  get IsOriginDetect ComboBox Items
4770
    '''
4771
    def getIsOriginDetectComboBoxItems(self):
4772
        return [("원본 도면", 0), ("텍스트 제거 도면", 1)]
4773

    
4774
    '''
4775
        @brief  get IsOriginDetect ComboBox Items
4776
    '''
4777
    def getOcrOptionComboBoxItems(self):
4778
        return [("OCR 미적용", 0), ("일반 심볼", 1), ("Instrument 계통", 2)]
4779

    
4780
    '''
4781
        @brief      Return Symbol Type Items
4782
        @author     Jeongwoo
4783
        @date       18.04.20
4784
        @history    18.05.08    Jeongwoo type index changed
4785
    '''
4786
    def getSymbolTypeList(self):
4787
        symbolTypeList = []
4788

    
4789
        with self.project.database.connect() as conn:
4790
            cursor = conn.cursor()
4791
            sql = 'SELECT * FROM SymbolType ORDER BY Type ASC'
4792
            try:
4793
                cursor.execute(sql)
4794
                rows = cursor.fetchall()
4795
                for row in rows:
4796
                    symbolTypeList.append((row['UID'], row['Category'], row['Type']))  # UID, category, type
4797
            except Exception as ex:
4798
                from App import App
4799
                message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
4800
                                                              sys.exc_info()[-1].tb_lineno)
4801
                App.mainWnd().addMessage.emit(MessageType.Error, message)
4802

    
4803
        return symbolTypeList
4804

    
4805
    def getSymbolCategoryByType(self, type: str):
4806
        """get symbol category by using symbol type"""
4807
        category = None
4808
        if type in self._symbolType:
4809
            return self._symbolType[type]
4810

    
4811
        with self.project.database.connect() as conn:
4812
            try:
4813
                cursor = conn.cursor()
4814
                sql = self.project.database.to_sql('SELECT Category FROM SymbolType WHERE [Type] = ?')
4815
                cursor.execute(sql, (type,))
4816
                rows = cursor.fetchall()
4817
                if rows is not None and len(rows) > 0:
4818
                    category = rows[0]['Category']
4819
                    self._symbolType[type] = category
4820
            except Exception as ex:
4821
                print('error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
4822
                                                          sys.exc_info()[-1].tb_lineno))
4823

    
4824
        return category
4825

    
4826
    '''
4827
        @brief      Check Symbol Type is included in 'Equipment' Category
4828
        @author     Jeongwoo
4829
        @date       2018.05.09
4830
    '''
4831
    def isEquipmentType(self, type):
4832
        category = self.getSymbolCategoryByType(type)
4833
        return category is not None and category == 'Equipment'
4834

    
4835
    '''
4836
        @brief      Return Symbol Type Items with "None"
4837
        @author     Jeongwoo
4838
        @date       18.04.06
4839
        @history    Seperate SymbolTypeList and "None"
4840
    '''
4841
    def getSymbolTypeComboBoxItems(self):
4842
        symbolTypeList = [symbol_type for symbol_type in self.getSymbolTypeList() if symbol_type[1]]
4843
        symbolTypeList.insert(0, ('None', 'None', 'None'))
4844

    
4845
        return symbolTypeList
4846

    
4847
    '''
4848
        @brief  get Base Symbol ComboBox Items
4849
    '''
4850
    def getBaseSymbolComboBoxItems(self, type=None):
4851
        bsymbolNameList = self.getSymbolNameListByType(type)
4852
        bsymbolNameList = bsymbolNameList.copy()
4853
        bsymbolNameList.sort()
4854
        bsymbolNameList.insert(0, "None")
4855
        return bsymbolNameList
4856

    
4857
    '''
4858
        @brief  get Additional Symbol ComboBox Items
4859
    '''
4860
    def getAdditionalSymbolComboBoxItems(self):
4861
        asymbolNameList = self.getSymbolNameList()
4862
        asymbolNameList.sort()
4863
        asymbolNameList.insert(0, "None")
4864
        return asymbolNameList
4865

    
4866
    '''
4867
        @brief  get Additional Symbol's default direction ComboBox Items
4868
    '''
4869
    def getDefaultSymbolDirectionComboBoxItems(self):
4870
        return [("UP", 0), ("DOWN", 2), ("LEFT", 3), ("RIGHT", 1)]
4871

    
4872
    '''
4873
        @brief  getter of activeDrawing
4874
        @author humkyung
4875
        @date   2018.07.07
4876
    '''
4877
    @property
4878
    def activeDrawing(self):
4879
        return self._activeDrawing
4880

    
4881
    '''
4882
        @brief  setter of activeDrawing
4883
        @author humkyung
4884
        @date   2018.07.07
4885
    '''
4886
    @activeDrawing.setter
4887
    def activeDrawing(self, value):
4888
        if self._activeDrawing:
4889
            del self._activeDrawing
4890

    
4891
        self._activeDrawing = value
4892

    
4893
    def getColNames(self, table):
4894
        """ return column names of given table and attribute names if tabe is VALVE_DATA_LIST or EQUIPMET_DATA_LIST """
4895
        res = None
4896

    
4897
        conn = self.project.database.connect()
4898
        with conn:
4899
            try:
4900
                cursor = conn.cursor()
4901
                cursor.execute('select * from {}'.format(table))
4902
                res = [col_name[0] for col_name in cursor.description]
4903

    
4904
                if table == 'EQUIPMET_DATA_LIST' or table == 'VALVE_DATA_LIST':
4905
                    sql = 'select distinct c.Attribute from {} a left join Attributes b on a.uid=b.Components_UID ' \
4906
                          'left join SymbolAttribute c on b.SymbolAttribute_UID=c.UID where c.Attribute is not NULL'.format(
4907
                        table)
4908
                    cursor.execute(sql)
4909
                    rows = cursor.fetchall()
4910
                    for row in rows:
4911
                        res.append(row['Attribute'])
4912
            # Catch the exception
4913
            except Exception as ex:
4914
                print('error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
4915
                                                          sys.exc_info()[-1].tb_lineno))
4916

    
4917
        return res
4918

    
4919

    
4920
    def get_ext_apps(self):
4921
        """get external application information from App.db"""
4922

    
4923
        path = os.path.join(os.getenv('USERPROFILE'), 'Digital PID')
4924
        app_database_path = os.path.join(path, 'App.db')
4925
        with sqlite3.connect(app_database_path) as conn:
4926
            try:
4927
                conn.row_factory = sqlite3.Row
4928
                cursor = conn.cursor()
4929
                sql = 'select * from ExtApps'
4930
                cursor.execute(sql)
4931
                rows = cursor.fetchall()
4932
                return rows
4933
            except Exception as ex:
4934
                # Roll back any change if something goes wrong
4935
                conn.rollback()
4936

    
4937
                from App import App
4938
                message = f"error occurred({repr(ex)}) in {sys.exc_info()[-1].tb_frame.f_code.co_filename}:" \
4939
                          f"{sys.exc_info()[-1].tb_lineno}"
4940
                App.mainWnd().addMessage.emit(MessageType.Error, message)
4941

    
4942
        return None
4943

    
4944
    def set_ext_apps(self, model:QStandardItemModel) -> None:
4945
        """ save ext apps to database """
4946

    
4947
        path = os.path.join(os.getenv('USERPROFILE'), 'Digital PID')
4948
        app_database_path = os.path.join(path, 'App.db')
4949
        with sqlite3.connect(app_database_path) as conn:
4950
            try:
4951
                # Get a cursor object
4952
                cursor = conn.cursor()
4953

    
4954
                names = ','.join([f"'{model.item(row, 0).text()}'" for row in range(model.rowCount())])
4955
                sql = f"delete from ExtApps where [Name] not in (?)"
4956
                cursor.execute(sql, (names, ))
4957

    
4958
                for row in range(model.rowCount()):
4959
                    param = (model.item(row, 0).text(), model.item(row, 1).text(), model.item(row, 2).text())
4960

    
4961
                    sql = "insert into ExtApps([Name], Executable, Argument) select ?,?,? where not exists" \
4962
                          "(select [Name] from ExtApps where [Name]=?)"
4963
                    cursor.execute(sql, (param[0], param[1], param[2], param[0]))
4964

    
4965
                    sql = f"update ExtApps set Executable=?, Argument=? where [Name]=?"
4966
                    cursor.execute(sql, (param[1], param[2], param[0]))
4967

    
4968
                conn.commit()
4969
            # Catch the exception
4970
            except Exception as ex:
4971
                conn.rollback()
4972

    
4973
                from App import App
4974
                message = f'error occurred({ex}) in {sys.exc_info()[-1].tb_frame.f_code.co_filename}:' \
4975
                          f'{sys.exc_info()[-1].tb_lineno}'
4976
                App.mainWnd().addMessage.emit(MessageType.Error, message)
4977

    
4978
        return None
4979

    
4980
    '''
4981
        @brief  getter of OCRData
4982
        @author humkyung
4983
        @date   2018.11.19
4984
    '''
4985
    @property
4986
    def OCRData(self):
4987
        if self._OCRData is None:
4988
            configs = self.getConfigs('Text Recognition', 'OCR Data')
4989
            self._OCRData = configs[0].value if 1 == len(configs) else 'eng'
4990

    
4991
        return self._OCRData
4992

    
4993
    '''
4994
        @brief  setter of OCRData
4995
        @author humkyung
4996
        @date   2018.11.19
4997
    '''
4998
    @OCRData.setter
4999
    def OCRData(self, value):
5000
        self._OCRData = value
5001

    
5002

    
5003
if __name__ == '__main__':
5004
    from AppDocData import AppDocData
5005

    
5006
    instance = AppDocData.instance()
클립보드 이미지 추가 (최대 크기: 500 MB)