프로젝트

일반

사용자정보

통계
| 브랜치(Branch): | 개정판:

hytos / DTI_PID / DTI_PID / AppDocData.py @ f0a86602

이력 | 보기 | 이력해설 | 다운로드 (209 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._imgFilePath = None
72
        self.imgName = None
73
        self._OCRData = None
74
        self._imgSrc = None
75

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

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

    
103
        # for cad graphic items to sppid
104
        self.cadGraphics = []
105

    
106
        # caches
107
        self._lineNoPropertiesUID = {}
108
        self._attributeByType = {}
109
        self._connected_items_lists = None
110

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

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

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

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

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

    
147
    '''
148
        @brief      clear
149
        @author     humkyung
150
        @date       2018.09.06
151
    '''
152
    def clear(self, past=None):
153
        from QEngineeringInstLineNoTextItem import QEngineeringInstLineNoTextItem
154

    
155
        if self.activeDrawing and self.activeDrawing.UID and self.activeDrawing.UID != past:
156
            self.clear_occupying_drawing(self.activeDrawing.UID)
157

    
158
        self._imgFilePath = None
159
        self.imgName = None
160
        self._imgSrc = None
161

    
162
        self._areas.clear()
163
        self.equipments.clear()
164
        self.lineNos.clear()
165
        self.lines.clear()
166
        self.texts.clear()
167
        self.symbols.clear()
168
        self.unknowns.clear()
169
        self.allItems.clear()
170
        self.tracerLineNos.clear()
171
        self.cadGraphics.clear()
172
        self.lineIndicators.clear()
173
        self.SpecBreakUpDownIndicator.clear()
174
        #self._colors = None
175
        #self._lineNoProperties = None
176
        self._lineTypeConfigs = None
177
        self._activeDrawing = None
178
        #self._hmbTable = None
179
        self._hmbColors = {}
180
        self._hmbData = None
181
        #self._arsColors = {}
182
        self._streamLineListModelDatas = []
183
        self._titleBlockProperties = None
184

    
185
        #self._configs = None# if not past else self._configs
186
        #self._symbolBase = {}# if not past else self._symbolBase
187
        #self._symbolType = {}# if not past else self._symbolType
188
        #self._lineNoPropertiesUID = {}
189
        self._attributeByType = {}
190
        self._connected_items_lists = QEngineeringInstLineNoTextItem()
191

    
192
        self._connecterss = {}
193
        self._associationss = {}
194
        self._attributess = {}
195

    
196
    def clear_occupying_drawing(self, drawing):
197
        """ clear drawing access """
198
        conn = self.project.database.connect()
199
        with conn:
200
            try:
201
                # Get a cursor object
202
                cursor = conn.cursor()
203
                if drawing:
204
                    sql = "UPDATE Drawings SET [OCCUPIED]=null WHERE [OCCUPIED]='{}' and UID='{}'".format(os.environ['COMPUTERNAME'], drawing)
205
                else:
206
                    sql = "UPDATE Drawings SET [OCCUPIED]=null"
207
                cursor.execute(sql)
208

    
209
                conn.commit()
210
            # Catch the exception
211
            except Exception as ex:
212
                conn.rollback()
213

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

    
218
    def set_occupying_drawing(self, drawing) -> str:
219
        """ set drawing access return true if success"""
220
        with self.project.database.connect() as conn:
221
            try:
222
                # Get a cursor object
223
                cursor = conn.cursor()
224
                sql = f"select OCCUPIED from Drawings where [UID]='{drawing}'"
225
                cursor.execute(sql)
226

    
227
                rows = cursor.fetchall()
228
                if not rows[0]['OCCUPIED'] or rows[0]['OCCUPIED'] == os.environ['COMPUTERNAME']:
229
                    sql = f"UPDATE Drawings SET [OCCUPIED]='{os.environ['COMPUTERNAME']}' WHERE UID='{drawing}'"
230
                    cursor.execute(sql)
231
                    conn.commit()
232
                    return None
233
                else:
234
                    return rows[0]['OCCUPIED']
235

    
236
            # Catch the exception
237
            except Exception as ex:
238
                conn.rollback()
239

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

    
244
                return None
245

    
246
    def winsort(self, data):
247
        """ Windows sort """
248

    
249
        from ctypes import wintypes, windll
250
        from functools import cmp_to_key
251

    
252
        _StrCmpLogicalW = windll.Shlwapi.StrCmpLogicalW
253
        _StrCmpLogicalW.argtypes = [wintypes.LPWSTR, wintypes.LPWSTR]
254
        _StrCmpLogicalW.restype  = wintypes.INT
255

    
256
        cmp_fnc = lambda psz1, psz2: _StrCmpLogicalW(psz1, psz2)
257

    
258
        #return sorted(data, key=cmp_to_key(cmp_fnc), reverse=True) #kitech
259
        return sorted(data, key=cmp_to_key(cmp_fnc))
260

    
261
    '''
262
        @brief      Get drawing file list
263
        @author     euisung
264
        @date       2018.09.28
265
    '''
266
    def getDrawingFileList(self):
267
        """ get drawing files which's extension is .png or jpg from drawing folder """
268
        drawingFileList = []
269

    
270
        try:
271
            project = AppDocData.instance().getCurrentProject()
272
            path = project.getDrawingFilePath()
273
            drawingFileList = [f for f in os.listdir(path) if os.path.isfile(os.path.join(path, f)) and
274
                               (os.path.splitext(f)[1].upper() == '.PNG' or os.path.splitext(f)[1].upper() == '.JPG' or
275
                                os.path.splitext(f)[1].upper() == '.JPEG')]
276
            
277
            drawingFileList = self.winsort(drawingFileList)
278
            #drawingFileList.sort()
279
        except Exception as ex:
280
            print('error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
281
                                                      sys.exc_info()[-1].tb_lineno))
282

    
283
        return drawingFileList
284

    
285
    '''
286
        @brief      Get Training file list
287
        @author     euisung
288
        @date       2018.10.16
289
    '''
290
    def getTrainingFileList(self):
291
        try:
292
            project = AppDocData.instance().getCurrentProject()
293
            path = project.getTrainingFilePath()
294
            trainingFileList = os.listdir(path)
295
            trainingFileList.sort()
296
        except Exception as ex:
297
            from App import App
298
            message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
299
                                                          sys.exc_info()[-1].tb_lineno)
300
            App.mainWnd().addMessage.emit(MessageType.Error, message)
301

    
302
        return trainingFileList
303

    
304
    def getTrainingSymbolFileList(self):
305
        """  Get Symbol Training file list """
306
        try:
307
            project = AppDocData.instance().getCurrentProject()
308
            path = project.getTrainingSymbolFilePath()
309
            symbolTrainingFileList = os.listdir(path)
310
            symbolTrainingFileList.sort()
311
        except Exception as ex:
312
            from App import App
313
            message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
314
                                                          sys.exc_info()[-1].tb_lineno)
315
            App.mainWnd().addMessage.emit(MessageType.Error, message)
316

    
317
        return symbolTrainingFileList
318

    
319
    '''
320
        @brief      Get DB file path in ProgramData
321
        @author     Jeongwoo
322
        @date       2018.06.27
323
        @history    2018.06.29  Jeongwoo    Change method to get template db path
324
    '''
325
    def getTemplateDbPath(self):
326
        path = os.path.join(os.getenv('ALLUSERSPROFILE'), 'Digital PID')
327
        templateDbPath = os.path.join(path, 'Template.db')
328
        return templateDbPath
329

    
330
    def get_template_symbol_library_path(self):
331
        """return template symbol library path"""
332

    
333
        path = os.path.join(os.getenv('USERPROFILE'), 'Digital PID')
334
        return os.path.join(path, 'SymbolLibrary.syl')
335

    
336
    def getAppDbPath(self):
337
        """
338
        @brief      Get application DB file path in ProgramData
339
        @author     humkyung
340
        @date       2018.10.01
341
        """
342

    
343
        path = os.path.join(os.getenv('USERPROFILE'), 'Digital PID')
344
        app_database = os.path.join(path, 'App.db')
345
        return app_database
346

    
347
    '''
348
        @brief  getter of colors 
349
        @author humkyung
350
        @date   2018.06.18
351
    '''
352
    @property
353
    def colors(self):
354
        import random
355

    
356
        if self._colors is None or self._colors == []:
357
            self._colors = []
358
            with self.project.database.connect() as conn:
359
                try:
360
                    cursor = conn.cursor()
361
                    sql = 'SELECT UID,RED,GREEN,BLUE FROM Colors'
362
                    cursor.execute(sql)
363
                    rows = cursor.fetchall()
364
                    for row in rows:
365
                        self._colors.append(Color(row['UID'], row['RED'], row['GREEN'], row['BLUE']))
366
                # Catch the exception
367
                except Exception as ex:
368
                    from App import App
369
                    message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
370
                                                                  sys.exc_info()[-1].tb_lineno)
371
                    App.mainWnd().addMessage.emit(MessageType.Error, message)
372

    
373
        return self._colors.pop(random.randrange(0, len(self._colors)))
374

    
375
    '''
376
        @brief  setter of colors
377
        @author humkyung
378
        @date   2018.06.18
379
    '''
380
    @colors.setter
381
    def colors(self, value):
382
        self._colors = value
383

    
384
    '''
385
        @brief      set image file path
386
        @author     humkyung
387
        @date       2018.07.30
388
    '''
389
    def setImgFilePath(self, path):
390
        self._imgFilePath = path
391
        self.imgName = os.path.splitext(os.path.basename(self._imgFilePath))[0]
392

    
393
    @staticmethod
394
    def my_imread(file_path):
395
        """ read a file which's name contains unicode string : ref http://devdoftech.co.kr:82/redmine/issues/631 """
396
        import numpy as np
397
        import cv2
398

    
399
        _bytes = None
400
        with open(file_path.encode('utf-8'), 'rb') as stream:
401
            _bytes = bytearray(stream.read())
402

    
403
        numpyArray = np.asarray(_bytes, dtype=np.uint8)
404
        res = cv2.imdecode(numpyArray, cv2.IMREAD_UNCHANGED)
405
        return res
406

    
407
    @property
408
    def imgSrc(self):
409
        """return the image of active drawing"""
410

    
411
        if self.activeDrawing:
412
            return self.activeDrawing.image
413

    
414
        return None
415

    
416
    @imgSrc.setter
417
    def imgSrc(self, value):
418
        """set the image of active drawing with given value"""
419

    
420
        if self.activeDrawing:
421
            self.activeDrawing.image = value
422

    
423
    '''
424
        @brief  getter of line type configs
425
        @author humkyung
426
        @date   2018.06.28
427
    '''
428
    @property
429
    def lineTypeConfigs(self):
430
        from PyQt5.QtCore import Qt
431

    
432
        if self._lineTypeConfigs is None:
433
            self._lineTypeConfigs = []
434

    
435
            styleMap = [('SolidLine', Qt.SolidLine), ('DashLine', Qt.DashLine), ('DotLine', Qt.DotLine),
436
                        ('DashDotLine', Qt.DashDotLine),
437
                        ('DashDotDotLine', Qt.DashDotDotLine), ('CustomDashLine', Qt.CustomDashLine)]
438

    
439
            configs = self.getConfigs('LineTypes')
440
            for config in configs:
441
                color, width, _style, transparent = config.value.split(',')
442
                matches = [param for param in styleMap if param[0] == _style]
443
                style = matches[0][1] if matches else Qt.SolidLine
444
                self._lineTypeConfigs.append((config.key, color, int(width), style, float(transparent)))
445

    
446
        return self._lineTypeConfigs
447

    
448
    '''
449
        @brief  setter of line type configs
450
        @author humkyung
451
        @date   2018.06.28
452
    '''
453
    @lineTypeConfigs.setter
454
    def lineTypeConfigs(self, value):
455
        self._lineTypeConfigs = value
456

    
457
    @property
458
    def drain_size(self):
459
        """ getter of drain_size """
460
        if not hasattr(self, '_drain_size') or not self._drain_size:
461
            configs = self.getConfigs('Drain Size Rule', 'Size')
462
            self._drain_size = configs[0].value if configs else '1"'
463

    
464
        return self._drain_size
465

    
466
    @drain_size.setter
467
    def drain_size(self, value):
468
        """ setter of drain_size """
469
        self._drain_size = value
470

    
471
    '''
472
        @brief      getter of hmb table
473
        @author     humkyung
474
        @date       2018.07.16
475
    '''
476
    '''
477
    @property
478
    def hmbTable(self):
479
        from HMBTable import HMBTable
480

481
        if self._hmbTable is None:
482
            self._hmbTable = HMBTable()
483
            self._hmbTable.load_data()
484

485
        return self._hmbTable
486
    '''
487

    
488
    '''
489
        @brief      setter of hmb table
490
        @author     humkyung
491
        @date       2018.07.16
492
    '''
493
    '''
494
    @hmbTable.setter
495
    def hmbTable(self, value):
496
        self._hmbTable = value
497
    '''
498

    
499
    '''
500
        @brief  get line type config of given line type
501
        @author humkyung
502
        @date   2018.06.28
503
    '''
504
    def getLineTypeConfig(self, lineType):
505
        from PyQt5.QtCore import Qt
506

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

    
510
    def getCurrentPidSource(self):
511
        return self.activeDrawing.currentPidSource
512

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

    
538
    '''
539
        @brief      Insert new symbol into Symbol Table, Moved from SG_DbHelper
540
        @author     Jeongwoo
541
        @date       2018.05.03
542
    '''
543
    def insertSymbol(self, symbol):
544
        isAdded = False
545
        with self.project.database.connect() as conn:
546
            try:
547
                sql = self.project.database.to_sql("""
548
                    INSERT INTO Symbol(name, SymbolType_UID, threshold, minMatchPoint, isDetectOrigin, rotationCount, ocrOption, isContainChild, originalPoint, connectionPoint, baseSymbol, additionalSymbol, isExceptDetect, hasInstrumentLabel, width, height, flip, TextArea, type) 
549
                    VALUES(?, (select UID from SymbolType where Type=?), ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?);
550
                """)
551

    
552
                cursor = conn.cursor()
553
                query = (symbol.getName(), symbol.getType(), symbol.getThreshold()
554
                         , symbol.getMinMatchCount(), symbol.getIsDetectOnOrigin(), symbol.getRotationCount()
555
                         , symbol.getOcrOption(), symbol.getIsContainChild()
556
                         , symbol.getOriginalConvertingPoint(), symbol.getConnectionPoint()
557
                         , symbol.getBaseSymbol(), symbol.getAdditionalSymbol(), symbol.getIsExceptDetect(),
558
                         symbol.getHasInstrumentLabel()
559
                         , symbol.width, symbol.height, symbol.detectFlip, symbol.text_area_str, symbol.getDesc())
560
                cursor.execute(sql, query)
561
                conn.commit()
562
                isAdded = True
563
            # Catch the exception
564
            except Exception as ex:
565
                # Roll back any change if something goes wrong
566
                conn.rollback()
567

    
568
                from App import App
569
                message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
570
                                                              sys.exc_info()[-1].tb_lineno)
571
                App.mainWnd().addMessage.emit(MessageType.Error, message)
572
            finally:
573
                return (isAdded, symbol.getType(), symbol.getName(), symbol.getPath())
574

    
575
    '''
576
        @brief      Update symbol in Symbol Table, Moved from SG_DbHelper
577
        @author     Jeongwoo
578
        @date       2018.05.03
579
    '''
580
    def updateSymbol(self, symbol):
581
        isUpdated = False
582

    
583
        with self.project.database.connect() as conn:
584
            try:
585
                sql = self.project.database.to_sql("""
586
                    UPDATE Symbol
587
                    SET
588
                        name = ?, SymbolType_UID=(select UID from SymbolType where Type=?), threshold=?, 
589
                        minMatchPoint=?, isDetectOrigin=?, rotationCount=?, ocrOption=?, isContainChild=?, 
590
                        originalPoint=?, connectionPoint=?, baseSymbol=?, additionalSymbol=?, isExceptDetect=?, 
591
                        hasInstrumentLabel=?, width=?, height=?, flip=?, TextArea=?, type=? WHERE uid = ?
592
                """)
593

    
594
                cursor = conn.cursor()
595
                query = (symbol.getName(), symbol.getType(), symbol.getThreshold()
596
                         , symbol.getMinMatchCount(), symbol.getIsDetectOnOrigin(), symbol.getRotationCount()
597
                         , symbol.getOcrOption(), symbol.getIsContainChild()
598
                         , symbol.getOriginalConvertingPoint(), symbol.getConnectionPoint()
599
                         , symbol.getBaseSymbol(), symbol.getAdditionalSymbol(), symbol.getIsExceptDetect(),
600
                         symbol.getHasInstrumentLabel(), symbol.width, symbol.height, symbol.detectFlip, symbol.text_area_str, symbol.getDesc(), 
601
                         symbol.getUid())
602
                cursor.execute(sql, query)
603
                conn.commit()
604
                isUpdated = True
605
            # Catch the exception
606
            except Exception as ex:
607
                # Roll back any change if something goes wrong
608
                conn.rollback()
609

    
610
                from App import App
611
                message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
612
                                                              sys.exc_info()[-1].tb_lineno)
613
                App.mainWnd().addMessage.emit(MessageType.Error, message)
614
            finally:
615
                self._symbolBase = {}
616
                return (isUpdated, symbol.getType(), symbol.getName(), symbol.getPath())
617

    
618
    def getSymbolPreset(self):
619
        """ get symbol preset """
620
        presets = []
621
        with self.project.database.connect() as conn:
622
            try:
623
                cursor = conn.cursor()
624
                sql = 'SELECT [UID], [Find], [Target], [Action], [Condition] FROM SymbolPreset'
625
                cursor.execute(sql)
626
                rows = cursor.fetchall()
627
                for row in rows:
628
                    presets.append([row['Find'], row['Target'], row['Action'], row['Condition']])
629
            # Catch the exception
630
            except Exception as ex:
631
                from App import App
632
                message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
633
                                                                sys.exc_info()[-1].tb_lineno)
634
                App.mainWnd().addMessage.emit(MessageType.Error, message)
635

    
636
                return []
637

    
638
        return presets
639

    
640
    def saveSymbolPreset(self, presets):
641
        """ save symbol preset """
642
        import uuid
643

    
644
        conn = self.project.database.connect()
645
        with conn:
646
            try:
647
                # Get a cursor object
648
                cursor = conn.cursor()
649

    
650
                sql = "delete from SymbolPreset"
651
                cursor.execute(sql)
652

    
653
                for preset in presets:
654
                    sql = self.project.database.to_sql("insert into [SymbolPreset]([UID], [Find], [Target], [Action], [Condition]) values(?,?,?,?,?)")
655
                    param = (str(uuid.uuid4()), preset[0], preset[1], preset[2], preset[3])
656
                    cursor.execute(sql, param)
657
                conn.commit()
658

    
659
            except Exception as ex:
660
                # Roll back any change if something goes wrong
661
                conn.rollback()
662
                from App import App
663
                from AppDocData import MessageType
664
                message = 'error occurred({}) in {}:{}'.format(repr(ex), sys.exc_info()[-1].tb_frame.f_code.co_filename,
665
                                                                sys.exc_info()[-1].tb_lineno)
666
                App.mainWnd().addMessage.emit(MessageType.Error, message)
667
        
668

    
669
    def getTargetSymbolList(self, all=False):
670
        """get symbol list to be detected except isExceptDetect field is unset"""
671
        targetSymbolList = []
672

    
673
        with self.project.database.connect() as conn:
674
            cursor = conn.cursor()
675
            if not all:
676
                sql = """SELECT a.UID,a.Name,b.Type,a.Threshold,a.MinMatchPoint,a.IsDetectOrigin,a.RotationCount,
677
                a.OCROption,a.IsContainChild,a.OriginalPoint,a.ConnectionPoint,a.BaseSymbol,a.AdditionalSymbol,a.Width,a.Height,
678
                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 
679
                a.SymbolType_UID=b.UID WHERE a.IsExceptDetect = 0 and a.[SymbolType_UID] != -1 order by width * height desc"""
680
            else:
681
                sql = """SELECT a.UID,a.Name,b.Type,a.Threshold,a.MinMatchPoint,a.IsDetectOrigin,a.RotationCount,
682
                a.OCROption,a.IsContainChild,a.OriginalPoint,a.ConnectionPoint,a.BaseSymbol,a.AdditionalSymbol,a.Width,a.Height,
683
                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 
684
                a.SymbolType_UID=b.UID WHERE a.[SymbolType_UID] != -1 order by width * height desc"""
685
            try:
686
                cursor.execute(sql)
687
                rows = cursor.fetchall()
688
                for row in rows:
689
                    sym = symbol.SymbolBase(row['Name'], row['Type'], row['Threshold'],
690
                                                row['MinMatchPoint'], row['IsDetectOrigin'],
691
                                                row['RotationCount'], row['OCROption'],
692
                                                row['IsContainChild'], row['OriginalPoint'],
693
                                                row['ConnectionPoint'], row['BaseSymbol'],
694
                                                row['AdditionalSymbol'], row['IsExceptDetect'],
695
                                                row['HasInstrumentLabel'], row['UID'],
696
                                                iType=row['DB_UID'], width=row['Width'], height=row['Height'],
697
                                                detectFlip=row['flip'], text_area=row['TextArea'], desc=row['Desc'])
698
                    targetSymbolList.append(sym)
699
            except Exception as ex:
700
                print('error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
701
                                                          sys.exc_info()[-1].tb_lineno))
702

    
703
        return targetSymbolList
704

    
705
    def get_favorite_libraries(self):
706
        res = []
707

    
708
        with self.project.database.connect() as conn:
709
            cursor = conn.cursor()
710
            sql = f"select UID,Symbol_UID from Libraries where [User]='{os.environ['COMPUTERNAME'].upper()}'"
711
            try:
712
                cursor.execute(sql)
713
                return cursor.fetchall()
714
            except Exception as ex:
715
                print('error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
716
                                                          sys.exc_info()[-1].tb_lineno))
717

    
718
        return None
719

    
720
    def buildAppDatabase(self):
721
        """build application database"""
722
        path = os.path.join(os.getenv('USERPROFILE'), 'Digital PID')
723
        appDatabaseFilePath = os.path.join(path, 'App.db')
724

    
725
        # Creates or opens a file called mydb with a SQLite3 DB
726
        with sqlite3.connect(appDatabaseFilePath) as conn:
727
            try:
728
                # Get a cursor object
729
                cursor = conn.cursor()
730

    
731
                sqlFiles = ['App.Configuration.sql', 'App.Styles.sql']
732
                for sqlFile in sqlFiles:
733
                    filePath = os.path.join(os.path.dirname(os.path.realpath(__file__)), 'Scripts', sqlFile)
734
                    try:
735
                        file = QFile(filePath)
736
                        file.open(QFile.ReadOnly)
737
                        sql = file.readAll()
738
                        sql = str(sql, encoding='utf8')
739
                        cursor.executescript(sql)
740
                    finally:
741
                        file.close()
742
                conn.commit()
743
            # Catch the exception
744
            except Exception as ex:
745
                # Roll back any change if something goes wrong
746
                conn.rollback()
747
                print('error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
748
                                                          sys.exc_info()[-1].tb_lineno))
749

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

    
753
        configs = self.getAppConfigs('app', 'license')
754
        if configs and len(configs[0].value.split('.')) == 3:
755
            pass
756
        else:
757
            configs = self.getAppConfigs('app', 'expiration')
758
            if not configs:
759
                configs = self.getAppConfigs('app', 'license')
760
                if configs and 'DOFTECH' in configs[0].value:
761
                    self.deleteAppConfigs('app', 'mode')
762
                    configs = None
763
                else:
764
                    configs = [Config('app', 'mode', 'advanced')]
765
            else:
766
                configs = None
767

    
768
            if configs:
769
                self.saveAppConfigs(configs)
770

    
771
    '''
772
        @brief  load app style
773
        @author humkyung
774
        @date   2018.04.20
775
    '''
776
    def loadAppStyle(self):
777
        style = 'Fusion'
778

    
779
        path = os.path.join(os.getenv('USERPROFILE'), 'Digital PID')
780
        if not os.path.exists(path): os.makedirs(path)
781

    
782
        self.buildAppDatabase()
783
        try:
784
            appDatabaseFilePath = os.path.join(path, 'App.db')
785
            # Creates or opens a file called mydb with a SQLite3 DB
786
            conn = sqlite3.connect(appDatabaseFilePath)
787
            # Get a cursor object
788
            cursor = conn.cursor()
789

    
790
            sql = "select Value from Configuration where Section='App' and Key='Style'"
791
            cursor.execute(sql)
792
            rows = cursor.fetchall()
793
            style = rows[0][0] if 1 == len(rows) else 'Fusion'
794
        # Catch the exception
795
        except Exception as ex:
796
            # Roll back any change if something goes wrong
797
            conn.rollback()
798
            print('error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
799
                                                      sys.exc_info()[-1].tb_lineno))
800
        finally:
801
            # Close the db connection
802
            conn.close()
803

    
804
        return style
805

    
806
    '''
807
        @brief  load app styles and then return a list
808
        @author humkyung
809
        @date   2018.04.20
810
    '''
811
    def loadAppStyles(self):
812
        styles = []
813

    
814
        try:
815
            self.buildAppDatabase()
816

    
817
            path = os.path.join(os.getenv('USERPROFILE'), 'Digital PID')
818
            appDatabaseFilePath = os.path.join(path, 'App.db')
819

    
820
            # Creates or opens a file called mydb with a SQLite3 DB
821
            conn = sqlite3.connect(appDatabaseFilePath)
822
            # Get a cursor object
823
            cursor = conn.cursor()
824

    
825
            sql = 'select UID,Value from Styles'
826
            cursor.execute(sql)
827
            rows = cursor.fetchall()
828
            for row in rows: styles.append(row[1])
829
            if 0 == len(rows): rows.append('fusion')
830
        # Catch the exception
831
        except Exception as ex:
832
            # Roll back any change if something goes wrong
833
            conn.rollback()
834
            print('error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
835
                                                      sys.exc_info()[-1].tb_lineno))
836
        finally:
837
            # Close the db connection
838
            conn.close()
839

    
840
        return styles
841

    
842
    '''
843
        @brief  Set current Project
844
        @history    2018.06.27  Jeongwoo    If DB file is not, copy DB file from ProgramData
845
    '''
846
    def setCurrentProject(self, project):
847
        self.project = project
848
        project.make_sub_directories()
849
        try:
850
            # save size unit
851
            #self.saveConfigs([Config('Project', 'Unit', project.prj_unit)])
852

    
853
            if self.project.database.db_type == 'SQLite':
854
                # Creates or opens a file called mydb with a SQLite3 DB
855
                db_path = self.project.database.file_path
856

    
857
                if not os.path.isfile(db_path):
858
                    templatePath = self.getTemplateDbPath()
859
                    templateFile = QFile(templatePath)
860
                    templateFile.copy(db_path)
861

    
862
                try:
863
                    conn = self.project.database.connect()
864
                    with conn:
865
                        # Get a cursor object
866
                        cursor = conn.cursor()
867

    
868
                        fileNames = os.listdir(os.path.join(os.path.dirname(os.path.realpath(__file__)), 'Scripts'))
869
                        for fileName in fileNames:
870
                            if fileName.endswith(".sql") and ('SQLite_Project' == os.path.splitext(fileName)[0].split('.')[0]):
871
                                try:
872
                                    file = QFile(
873
                                        os.path.join(os.path.dirname(os.path.realpath(__file__)), 'Scripts', fileName))
874
                                    file.open(QFile.ReadOnly)
875
                                    sql = file.readAll()
876
                                    sql = str(sql, encoding='utf8')
877
                                    cursor.executescript(sql)
878
                                finally:
879
                                    file.close()
880
                        conn.commit()
881
                except Exception as ex:
882
                    print('error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
883
                                                              sys.exc_info()[-1].tb_lineno))
884
        # Catch the exception
885
        except Exception as ex:
886
            # Roll back any change if something goes wrong
887
            print('error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
888
                                                      sys.exc_info()[-1].tb_lineno))
889
        finally:
890
            pass
891

    
892
    '''
893
        @brief  Get current Project
894
    '''
895
    def getCurrentProject(self):
896
        return self.project
897

    
898
    '''
899
        @brief      return project database path
900
        @history    humkyung 2018.04.19 return Project.db in Program Data folder instead of PROJECT_DB_PATH variable
901
    '''
902
    def getPrjDatabasePath(self):
903
        path = os.path.join(os.getenv('USERPROFILE'), 'Digital PID')
904
        if not os.path.exists(path): os.makedirs(path)
905

    
906
        prjDatabaseFilePath = os.path.join(path, 'Project.db')
907
        try:
908
            # Creates or opens a file called mydb with a SQLite3 DB
909
            conn = sqlite3.connect(prjDatabaseFilePath)
910
            # Get a cursor object
911
            cursor = conn.cursor()
912

    
913
            filePath = os.path.join(os.path.dirname(os.path.realpath(__file__)), 'Scripts', 'Project.Projects.sql')
914
            try:
915
                file = QFile(filePath)
916
                file.open(QFile.ReadOnly)
917
                sql = file.readAll()
918
                sql = str(sql, encoding='utf8')
919
                cursor.executescript(sql)
920
            finally:
921
                file.close()
922
            conn.commit()
923
        # Catch the exception
924
        except Exception as ex:
925
            # Roll back any change if something goes wrong
926
            conn.rollback()
927
            print('error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
928
                                                      sys.exc_info()[-1].tb_lineno))
929
        finally:
930
            # Close the db connection
931
            conn.close()
932

    
933
        return prjDatabaseFilePath
934

    
935
    def getErrorItemSvgPath(self):
936
        '''
937
            @brief  return error item svg path
938
            @author euisung
939
            @date   2019.04.02
940
        '''
941
        return os.path.join(os.getenv('USERPROFILE'), 'Digital PID', 'Explode.svg')
942

    
943
    def updateTitleBlockProperties(self, titleBlockProps):
944
        '''
945
            @brief  update title block properties
946
            @author euisung
947
            @date   2018.11.09
948
        '''
949
        try:
950
            originTitleBlockProps = self.getTitleBlockProperties()
951
            deletedTitleBlockProps = []
952
            for originTitleBlockProp in originTitleBlockProps:
953
                for titleBlockProp in titleBlockProps:
954
                    # uid compare for determine delete props
955
                    if originTitleBlockProp[0] == titleBlockProp[0]:
956
                        break
957
                deletedTitleBlockProps.append(originTitleBlockProp[0])
958

    
959
            # Creates or opens a file called mydb with a SQLite3 DB
960
            conn = self.project.database.connect()
961
            with conn:
962
                try:
963
                    # Get a cursor object
964
                    cursor = conn.cursor()
965

    
966
                    for deletedTitleBlockProp in deletedTitleBlockProps:
967
                        sql = "delete from TitleBlockValues where TitleBlockProperties_UID='{}'".format(deletedTitleBlockProp)
968
                        cursor.execute(sql)
969
                        sql = "delete from TitleBlockProperties where UID='{}'".format(deletedTitleBlockProp)
970
                        cursor.execute(sql)
971

    
972
                    for titleBlockProp in titleBlockProps:
973
                        sql = self.project.database.to_sql("insert into [TitleBlockProperties]([UID], [NAME], [AREA], [TEXT]) values(?,?,?,?)")
974
                        param = (titleBlockProp[0], titleBlockProp[1], titleBlockProp[2], titleBlockProp[3])  # uid, name, area, text
975
                        cursor.execute(sql, param)
976
                    conn.commit()
977
                    # Catch the exception
978
                except Exception as ex:
979
                    # Roll back any change if something goes wrong
980
                    conn.rollback()
981
                    from App import App
982
                    from AppDocData import MessageType
983
                    message = 'error occurred({}) in {}:{}'.format(repr(ex), sys.exc_info()[-1].tb_frame.f_code.co_filename,
984
                                                                   sys.exc_info()[-1].tb_lineno)
985
                    App.mainWnd().addMessage.emit(MessageType.Error, message)
986
        # Catch the exception
987
        except Exception as ex:
988
            from App import App
989
            from AppDocData import MessageType
990
            message = 'error occurred({}) in {}:{}'.format(repr(ex), sys.exc_info()[-1].tb_frame.f_code.co_filename,
991
                                                           sys.exc_info()[-1].tb_lineno)
992
            App.mainWnd().addMessage.emit(MessageType.Error, message)
993

    
994
        self._titleBlockProperties = None
995

    
996
    def getTitleBlockProperties(self):
997
        """"return title block properties"""
998

    
999
        res = None
1000
        if self._titleBlockProperties is None:
1001
            self._titleBlockProperties = []
1002

    
1003
            with self.project.database.connect() as conn:
1004
                try:
1005
                    # Get a cursor object
1006
                    cursor = conn.cursor()
1007

    
1008
                    sql = "select UID, Name, AREA, [TEXT] from TitleBlockProperties"
1009
                    cursor.execute(sql)
1010
                    rows = cursor.fetchall()
1011
                    for row in rows:
1012
                        attr = []
1013
                        attr.append(row['UID'])  # uid
1014
                        attr.append(row['Name'])  # name
1015
                        attr.append(row['AREA'])  # area
1016
                        attr.append(row['TEXT'])  # text
1017
                        self._titleBlockProperties.append(attr)
1018

    
1019
                    res = self._titleBlockProperties
1020
                # Catch the exception
1021
                except Exception as ex:
1022
                    print('error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
1023
                                                              sys.exc_info()[-1].tb_lineno))
1024
        else:
1025
            res = self._titleBlockProperties
1026

    
1027
        return res
1028

    
1029
    def clearLineNoProperties(self):
1030
        self._lineNoProperties = None
1031
        self._lineNoPropertiesUID = {}
1032

    
1033
    def getLineProperties(self):
1034
        """return line no properties"""
1035
        from SymbolAttr import SymbolAttr
1036

    
1037
        res = None
1038
        if self._lineNoProperties is None:
1039
            self._lineNoProperties = []
1040

    
1041
            with self.project.database.connect() as conn:
1042
                try:
1043
                    # Get a cursor object
1044
                    cursor = conn.cursor()
1045

    
1046
                    sql = "select UID, Name, DisplayName, Type, LimitNumber, [index] from LineProperties " \
1047
                          "order by [index]"
1048
                    cursor.execute(sql)
1049
                    rows = cursor.fetchall()
1050
                    for row in rows:
1051
                        attr = SymbolAttr()
1052
                        attr.UID = row['UID']
1053
                        attr.Attribute = row['Name']
1054
                        attr.DisplayAttribute = row['DisplayName']
1055
                        attr.AttributeType = row['Type']
1056
                        attr.Length = row['LimitNumber']
1057
                        attr.IsProp = 5
1058
                        attr.Index = -1
1059
                        self._lineNoProperties.append(attr)
1060

    
1061
                    res = self._lineNoProperties
1062

    
1063
                    # update cache
1064
                    if res:
1065
                        for _prop in res:
1066
                            if str(_prop.UID) not in self._lineNoPropertiesUID:
1067
                                self._lineNoPropertiesUID[str(_prop.UID)] = [_prop]
1068
                # Catch the exception
1069
                except Exception as ex:
1070
                    print('error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
1071
                                                              sys.exc_info()[-1].tb_lineno))
1072
        else:
1073
            res = self._lineNoProperties
1074

    
1075
        return res
1076

    
1077
    def get_equipment_attributes(self):
1078
        """ return equipment attributes """
1079

    
1080
        from SymbolAttr import SymbolAttr
1081

    
1082
        res = None
1083
        if not hasattr(self, '_equipment_attributes'):
1084
            self._equipment_attributes = []
1085

    
1086
            with self.project.database.connect() as conn:
1087
                try:
1088
                    # Get a cursor object
1089
                    cursor = conn.cursor()
1090

    
1091
                    sql = "select distinct A.Attribute from SymbolAttribute A join SymbolType B on " \
1092
                          "A.SymbolType_UID=B.UID where B.Category in ('Equipment', 'Package')"#,'Equipment Components')"
1093
                    cursor.execute(sql)
1094
                    rows = cursor.fetchall()
1095
                    for row in rows:
1096
                        attr = SymbolAttr()
1097
                        attr.Attribute = row['Attribute']
1098
                        self._equipment_attributes.append(attr)
1099

    
1100
                    res = self._equipment_attributes
1101
                # Catch the exception
1102
                except Exception as ex:
1103
                    print('error occurred({}) in {}:{}'.format(repr(ex), sys.exc_info()[-1].tb_frame.f_code.co_filename,
1104
                                                               sys.exc_info()[-1].tb_lineno))
1105
        else:
1106
            res = self._equipment_attributes
1107

    
1108
        return res
1109

    
1110
    '''
1111
        @brief  return line properties
1112
        @author humkyung
1113
        @date   2018.04.09
1114
    '''
1115
    def getLinePropertiesByUID(self, UID):
1116
        from SymbolAttr import SymbolAttr
1117

    
1118
        res = []
1119
        if UID in self._lineNoPropertiesUID:
1120
            res = self._lineNoPropertiesUID[UID]
1121
            return res
1122

    
1123
        with self.project.database.connect() as conn:
1124
            try:
1125
                # Get a cursor object
1126
                cursor = conn.cursor()
1127

    
1128
                sql = f"select UID, Name, DisplayName, Type, LimitNumber, [index] from LineProperties where " \
1129
                      f"uid = '{UID}'"
1130
                cursor.execute(sql)
1131
                rows = cursor.fetchall()
1132
                for row in rows:
1133
                    attr = SymbolAttr()
1134
                    attr.UID = row['UID']
1135
                    attr.Attribute = row['Name']
1136
                    attr.DisplayAttribute = row['DisplayName']
1137
                    attr.AttributeType = row['Type']
1138
                    attr.Length = row['LimitNumber']
1139
                    attr.IsProp = 5
1140
                    attr.Index = -1
1141
                    res.append(attr)
1142
                self._lineNoPropertiesUID[UID] = res
1143
            # Catch the exception
1144
            except Exception as ex:
1145
                print('error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
1146
                                                          sys.exc_info()[-1].tb_lineno))
1147

    
1148
        return res
1149

    
1150
    '''
1151
        @brief  return line types 
1152
        @author humkyung
1153
        @date   2018.06.27
1154
    '''
1155
    def getLineTypes(self):
1156
        from LineTypeConditions import LineTypeConditions
1157

    
1158
        res = []
1159
        conn = self.project.database.connect()
1160
        with conn:
1161
            try:
1162
                cursor = conn.cursor()
1163
                sql = "select UID,Name,Type1,Conditions1,Type2,Conditions2 from LineTypes order by Name"
1164
                cursor.execute(sql)
1165
                rows = cursor.fetchall()
1166
                for row in rows:
1167
                    line_type = LineTypeConditions(row['UID'], row['Name'])
1168
                    line_type._conditions[0][0] = row['Type1']
1169
                    line_type._conditions[0][1] = row['Conditions1']
1170
                    line_type._conditions[1][0] = row['Type2']
1171
                    line_type._conditions[1][1] = row['Conditions2']
1172
                    res.append(line_type)
1173
            # Catch the exception
1174
            except Exception as ex:
1175
                print('error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
1176
                                                          sys.exc_info()[-1].tb_lineno))
1177

    
1178
        return res
1179

    
1180
    '''
1181
        @brief      Insert New Project Info
1182
        @author     Jeongwoo
1183
        @date       2018.04.06
1184
        @history    humkyung 2018.04.19 use getPrjDatabasePath function instead of PROJECT_DB_PATH variable
1185
    '''
1186
    def insertProjectInfo(self, desc, prj_unit, dir):
1187
        prjDatabaseFilePath = self.getPrjDatabasePath()
1188
        conn = sqlite3.connect(prjDatabaseFilePath)
1189
        with conn:
1190
            try:
1191
                folderName = dir.split('/')[-1]
1192
                if folderName:
1193
                    nowDate = datetime.now().strftime('%Y.%m.%d %H:%M')
1194
                    sql = "insert or replace into Projects(Name, [Desc], [Unit], Path, CreatedDate, UpdatedDate) values(?, ?, ?, ?, ?, ?)"
1195
                    param = (folderName, desc, prj_unit, dir, nowDate, nowDate)
1196

    
1197
                    cursor = conn.cursor()
1198
                    cursor.execute(sql, param)
1199
                    conn.commit()
1200
                else:
1201
                    print("Empty folder name")
1202
            except Exception as ex:
1203
                # Roll back any change if something goes wrong
1204
                conn.rollback()
1205
                print('error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
1206
                                                          sys.exc_info()[-1].tb_lineno))
1207

    
1208
    def removeProjectInfo(self, targetProject):
1209
        '''
1210
        @brief      Remove Project Info
1211
        @author     Euisung
1212
        @date       2019.01.28
1213
        '''
1214
        prjDatabaseFilePath = self.getPrjDatabasePath()
1215
        conn = sqlite3.connect(prjDatabaseFilePath)
1216
        with conn:
1217
            try:
1218
                sql = "delete from Projects where Id = '{}'".format(targetProject.id)
1219
                cur = conn.cursor()
1220
                cur.execute(sql)
1221
                conn.commit()
1222
            except Exception as ex:
1223
                # Roll back any change if something goes wrong
1224
                conn.rollback()
1225
                print('error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
1226
                                                          sys.exc_info()[-1].tb_lineno))
1227

    
1228
    '''
1229
        @brief      update project
1230
        @author     Jeongwoo
1231
        @date       2018.04.06
1232
        @history    humkyung 2018.04.19 use getPrjDatabasePath function instead of PROJECT_DB_PATH variable
1233
    '''
1234
    def updateProjectUpdatedDate(self, project):
1235
        prjDatabaseFilePath = self.getPrjDatabasePath()
1236
        conn = sqlite3.connect(prjDatabaseFilePath)
1237
        with conn:
1238
            try:
1239
                nowDate = datetime.now().strftime('%Y.%m.%d %H:%M')
1240
                sql = '''
1241
                    UPDATE Projects
1242
                    SET UpdatedDate = ?,[Desc]=?,[Unit]=? 
1243
                    WHERE Id = ?
1244
                '''
1245
                cur = conn.cursor()
1246
                cur.execute(sql, (nowDate, project.desc, project.prj_unit, project.getId()))
1247

    
1248
                if project.database.host and project.database.port:
1249
                    _host = project.database.host + ':' + project.database.port
1250
                else:
1251
                    _host = None
1252
                sql = 'insert or replace into DBSettings(Projects_UID, DBTypes_UID, Host, User, Password, FilePath) values(?,(select UID from DBTypes where Name=?),?,?,?,?)'
1253
                cur = conn.cursor()
1254
                cur.execute(sql, (
1255
                    project.getId(), project.database.db_type, _host, project.database.user,
1256
                    project.database.password, project.database.file_path))
1257
                conn.commit()
1258
            except Exception as ex:
1259
                # Roll back any change if something goes wrong
1260
                conn.rollback()
1261
                print('error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
1262
                                                          sys.exc_info()[-1].tb_lineno))
1263

    
1264
    '''
1265
        @brief  get project list from database
1266
        @history    humkyung 2018.04.18 add only project which's project exists
1267
    '''
1268
    def getProjectList(self):
1269
        from Project import Project
1270

    
1271
        projectList = []
1272

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

    
1295
        return projectList
1296

    
1297
    '''
1298
        @brief  get sliding window size
1299
        @author humkyung
1300
    '''
1301
    def getSlidingWindowSize(self):
1302
        res = [25, 20]
1303
        try:
1304
            configs = self.getConfigs('Sliding Window')
1305
            for config in configs:
1306
                if config.key == 'Width':
1307
                    res[0] = int(config.value)
1308
                elif config.key == 'Height':
1309
                    res[1] = int(config.value)
1310
        # Catch the exception
1311
        except Exception as ex:
1312
            print('error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
1313
                                                      sys.exc_info()[-1].tb_lineno))
1314

    
1315
        return res
1316

    
1317
    '''
1318
        @brief  get line no configuration
1319
        @author humkyung
1320
        @date   2018.04.16
1321
    '''
1322
    def getLineNoConfiguration(self):
1323
        res = None
1324

    
1325
        conn = self.project.database.connect()
1326
        with conn:
1327
            try:
1328
                # Get a cursor object
1329
                cursor = conn.cursor()
1330

    
1331
                delimiter = None
1332
                sql = "select * from configuration where section='Line No' and key='Delimiter"
1333
                cursor.execute(sql)
1334
                rows = cursor.fetchall()
1335
                if len(rows) == 1:
1336
                    delimiter = rows[0][2]
1337

    
1338
                if delimiter is not None:
1339
                    sql = "select * from configuration where section='Line No' and key='Configuration'"
1340
                    cursor.execute(sql)
1341
                    rows = cursor.fetchall()
1342
                    if len(rows) == 1:
1343
                        res = rows[0][2].split(delimiter)
1344
            # Catch the exception
1345
            except Exception as ex:
1346
                print('error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
1347
                                                          sys.exc_info()[-1].tb_lineno))
1348

    
1349
        return res
1350

    
1351
    '''
1352
        @brief  get area list
1353
        @author humkyung
1354
        @history    euisung     2018.11.20 (0,0),(0,0) process add
1355
    '''
1356
    def getAreaList(self, size=False):
1357
        from Area import Area
1358

    
1359
        if len(self._areas) == 0:
1360
            conn = self.project.database.connect()
1361
            with conn:
1362
                try:
1363
                    # Get a cursor object
1364
                    cursor = conn.cursor()
1365

    
1366
                    sql = "select * from configuration where section='Area'"
1367
                    cursor.execute(sql)
1368
                    rows = cursor.fetchall()
1369
                    for row in rows:
1370
                        name = row['Key']
1371
                        area = Area(name)
1372
                        area.parse(row['Value'])
1373
                        self._areas.append(area)
1374
                # Catch the exception
1375
                except Exception as ex:
1376
                    print('error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
1377
                                                              sys.exc_info()[-1].tb_lineno))
1378

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

    
1381
    '''
1382
        @brief  get area of given name
1383
        @author humkyung
1384
        @date   2018.04.07
1385
    '''
1386
    def getArea(self, name):
1387
        areas = self.getAreaList(size=True)
1388
        matches = [area for area in areas if area.name == name]
1389
        if 1 == len(matches) and matches[0].height is not 0 and matches[0].width is not 0:
1390
            return matches[0]
1391

    
1392
        return None
1393

    
1394
    def getConfigs(self, section, key=None):
1395
        """ get configurations from database """
1396
        res = []
1397

    
1398
        if self._configs is None:
1399
            self._configs = []
1400
            with self.project.database.connect() as conn:
1401
                try:
1402
                    # Get a cursor object
1403
                    cursor = conn.cursor()
1404

    
1405
                    sql = "select * from configuration"
1406

    
1407
                    cursor.execute(sql)
1408
                    rows = cursor.fetchall()
1409
                    for row in rows:
1410
                        self._configs.append(Config(row['Section'], row['Key'], row['Value']))
1411
                # Catch the exception
1412
                except Exception as ex:
1413
                    print('error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
1414
                                                              sys.exc_info()[-1].tb_lineno))
1415

    
1416
        if key is not None:
1417
            return [con for con in self._configs if con.section == section and con.key == key]
1418
        else:
1419
            return [con for con in self._configs if con.section == section]
1420

    
1421
    def getAppConfigs(self, section, key=None):
1422
        """get application configurations"""
1423

    
1424
        res = []
1425

    
1426
        # Creates or opens a file called mydb with a SQLite3 DB
1427
        dbPath = self.getAppDbPath()
1428
        with sqlite3.connect(dbPath) as conn:
1429
            try:
1430
                # Get a cursor object
1431
                cursor = conn.cursor()
1432

    
1433
                if key is not None:
1434
                    sql = "select * from configuration where section=? and key=?"
1435
                    param = (section, key)
1436
                else:
1437
                    sql = "select * from configuration where section=?"
1438
                    param = (section,)
1439

    
1440
                cursor.execute(sql, param)
1441
                rows = cursor.fetchall()
1442
                for row in rows:
1443
                    res.append(Config(row[0], row[1], row[2]))
1444
            # Catch the exception
1445
            except Exception as ex:
1446
                print('error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
1447
                                                          sys.exc_info()[-1].tb_lineno))
1448

    
1449
        return res
1450

    
1451
    '''
1452
        @brief      save configurations
1453
        @author     humkyung
1454
        @date       2018.04.16
1455
        @history    humkyung 2018.07.03 replace ' with " if value has '
1456
                    kyouho 2018.07.09 change query method
1457
    '''
1458
    def saveConfigs(self, configs):
1459
        from LineTypeConditions import LineTypeConditions
1460

    
1461
        with self.project.database.connect() as conn:
1462
            try:
1463
                # Get a cursor object
1464
                cursor = conn.cursor()
1465
                if self.project.database.db_type == 'SQLite':
1466
                    cursor.execute('begin')
1467

    
1468
                for config in configs:
1469
                    if type(config) is Config:
1470
                        value = config.value
1471
                        #if type(value) is str and "'" in value:
1472
                        #    value = value.replace("'", "''")
1473

    
1474
                        sql = self.project.database.to_sql(
1475
                            "insert into configuration(Section,[Key],Value) select ?,?,? where not exists(select 1 from configuration where Section=? and [Key]=?)")
1476
                        param = (config.section, config.key, str(value), config.section, config.key)
1477
                        cursor.execute(sql, param)
1478
                        sql = self.project.database.to_sql(
1479
                            "update configuration set Value=? where Section=? and [Key]=?")
1480
                        param = (str(value), config.section, config.key)
1481
                        cursor.execute(sql, param)
1482
                    elif hasattr(config, 'toSql'):
1483
                        sql = config.toSql()
1484
                        if type(sql) is list:
1485
                            for item in sql:
1486
                                if item is not None and 2 == len(item):
1487
                                    cursor.execute(self.project.database.to_sql(item[0]), item[1])
1488
                        else:
1489
                            if sql is not None and 2 == len(sql):
1490
                                cursor.execute(self.project.database.to_sql(sql[0]), sql[1])
1491
                self._configs = None  # reset config table
1492
                LineTypeConditions.CONDITIONS = None
1493

    
1494
                if self.project.database.db_type == 'SQLite':
1495
                    cursor.execute('commit')
1496
                else:
1497
                    conn.commit()
1498
            # Catch the exception
1499
            except Exception as ex:
1500
                # Roll back any change if something goes wrong
1501
                conn.rollback()
1502

    
1503
                from App import App
1504
                message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
1505
                                                              sys.exc_info()[-1].tb_lineno)
1506
                App.mainWnd().addMessage.emit(MessageType.Error, message)
1507

    
1508
    def saveAppConfigs(self, configs):
1509
        """save application configurations"""
1510

    
1511
        # Creates or opens a file called mydb with a SQLite3 DB
1512
        dbPath = self.getAppDbPath()
1513
        with sqlite3.connect(dbPath) as conn:
1514
            try:
1515
                # Get a cursor object
1516
                cursor = conn.cursor()
1517

    
1518
                for config in configs:
1519
                    value = config.value
1520
                    if type(value) is str and "'" in value:
1521
                        value = value.replace("'", "''")
1522

    
1523
                    sql = "insert or replace into configuration values(?,?,?)"
1524
                    param = (config.section, config.key, value)
1525

    
1526
                    cursor.execute(sql, param)
1527
                conn.commit()
1528
            # Catch the exception
1529
            except Exception as ex:
1530
                # Roll back any change if something goes wrong
1531
                conn.rollback()
1532
                print('error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
1533
                                                          sys.exc_info()[-1].tb_lineno))
1534

    
1535
    def updateProjectUnit(self, unit):
1536
        """save project configurations"""
1537

    
1538
        # Creates or opens a file called mydb with a SQLite3 DB
1539
        dbPath = self.getPrjDatabasePath()
1540
        with sqlite3.connect(dbPath) as conn:
1541
            try:
1542
                # Get a cursor object
1543
                cursor = conn.cursor()
1544

    
1545
                sql = "update Projects set [Unit]=? where [Id]=?"
1546
                param = (unit, self.project.getId())
1547

    
1548
                cursor.execute(sql, param)
1549
                conn.commit()
1550
            # Catch the exception
1551
            except Exception as ex:
1552
                # Roll back any change if something goes wrong
1553
                conn.rollback()
1554
                
1555
                from App import App
1556
                message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
1557
                                                              sys.exc_info()[-1].tb_lineno)
1558
                App.mainWnd().addMessage.emit(MessageType.Error, message)
1559

    
1560
    def deleteConfigs(self, section, key=None):
1561
        """
1562
        delete configurations by using section and key
1563
        :param section:
1564
        :param key:
1565
        :return: None
1566
        """
1567
        with self.project.database.connect() as conn:
1568
            try:
1569
                # Get a cursor object
1570
                cursor = conn.cursor()
1571

    
1572
                if key is not None:
1573
                    sql = "delete from configuration where section='{}' and [key]='{}'".format(section, key)
1574
                else:
1575
                    sql = "delete from configuration where section='{}'".format(section)
1576
                cursor.execute(sql)
1577

    
1578
                conn.commit()
1579
            # Catch the exception
1580
            except Exception as ex:
1581
                # Roll back any change if something goes wrong
1582
                conn.rollback()
1583

    
1584
                message = f'error occurred({ex}) in {sys.exc_info()[-1].tb_frame.f_code.co_filename}:' \
1585
                          f'{sys.exc_info()[-1].tb_lineno}'
1586
                print(message)
1587

    
1588
    def deleteAppConfigs(self, section, key=None):
1589
        """
1590
        @brief  delete application configurations
1591
        @author humkyung
1592
        @date   2018.11.01
1593
        """
1594

    
1595
        # Creates or opens a file called mydb with a SQLite3 DB
1596
        dbPath = self.getAppDbPath()
1597
        conn = sqlite3.connect(dbPath)
1598
        with conn:
1599
            try:
1600
                # Get a cursor object
1601
                cursor = conn.cursor()
1602

    
1603
                if key is not None:
1604
                    sql = "delete from configuration where section='{}' and key='{}'".format(section, key)
1605
                else:
1606
                    sql = "delete from configuration where section='{}'".format(section)
1607
                cursor.execute(sql)
1608

    
1609
                conn.commit()
1610
            # Catch the exception
1611
            except Exception as ex:
1612
                # Roll back any change if something goes wrong
1613
                conn.rollback()
1614
                print('error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
1615
                                                          sys.exc_info()[-1].tb_lineno))
1616

    
1617
    '''
1618
        @brief      set area list
1619
        @history    humkyung 2018.05.18 round area coordinate and dimension before saving
1620
        @history    euisung  2018.11.20 add self._area reset process
1621
    '''
1622
    def setAreaList(self, areas):
1623
        for area in areas:
1624
            matches = [x for x in self._areas if x.name == area.name]
1625
            if 1 == len(matches):
1626
                matches[0].x = area.x
1627
                matches[0].y = area.y
1628
                matches[0].width = area.width
1629
                matches[0].height = area.height
1630
            elif 0 == len(matches):
1631
                self._areas.append(area)
1632

    
1633
        # Creates or opens a file called mydb with a SQLite3 DB
1634
        conn = self.project.database.connect()
1635
        with conn:
1636
            try:
1637
                # Get a cursor object
1638
                cursor = conn.cursor()
1639

    
1640
                for area in self._areas:
1641
                    sql = "insert into configuration select 'Area','{}','({},{}),({},{})' where not exists(select 1 from configuration where Section='Area' and [Key]='{}')".format(
1642
                        area.name, round(area.x), round(area.y), round(area.width), round(area.height), area.name)
1643
                    cursor.execute(sql)
1644
                    sql = "update configuration set Value='({},{}),({},{})' where Section='Area' and [Key]='{}'".format(
1645
                        round(area.x), round(area.y), round(area.width), round(area.height), area.name)
1646
                    cursor.execute(sql)
1647
                conn.commit()
1648
            # Catch the exception
1649
            except Exception as ex:
1650
                # Roll back any change if something goes wrong
1651
                conn.rollback()
1652

    
1653
                from App import App
1654
                message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
1655
                                                              sys.exc_info()[-1].tb_lineno)
1656
                App.mainWnd().addMessage.emit(MessageType.Error, message)
1657
            finally:
1658
                # Close the db connection
1659
                self._areas = []
1660

    
1661
    def getSymbolNameList(self):
1662
        """ get symbol name list """
1663
        symbolNametList = []
1664

    
1665
        conn = self.project.database.connect()
1666
        with conn:
1667
            cursor = conn.cursor()
1668
            sql = 'SELECT * FROM SymbolName'
1669
            try:
1670
                cursor.execute(sql)
1671
                rows = cursor.fetchall()
1672
                for row in rows:
1673
                    symbolNametList.append(row['Name'])  # Name String
1674
            except Exception as ex:
1675
                print('error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
1676
                                                          sys.exc_info()[-1].tb_lineno))
1677

    
1678
        return symbolNametList
1679

    
1680
    '''
1681
        @brief      get symbol name list by symbol Type
1682
        @author     Jeongwoo
1683
        @date       18.04.06
1684
        @history    .
1685
    '''
1686
    def getSymbolNameListByType(self, type):
1687
        symbolNametList = []
1688
        if type in self._symbolNametList:
1689
            return self._symbolNametList[type]
1690

    
1691
        conn = self.project.database.connect()
1692
        with conn:
1693
            cursor = conn.cursor()
1694
            sql = ''
1695
            if type is not None:
1696
                sql = self.project.database.to_sql('SELECT * FROM SymbolName WHERE [Type]=?')
1697
                try:
1698
                    cursor.execute(sql, (type,))
1699
                    rows = cursor.fetchall()
1700
                    for row in rows:
1701
                        symbolNametList.append(row['Name'])  # Name String
1702
                    self._symbolNametList[type] = symbolNametList
1703
                except Exception as ex:
1704
                    print('error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
1705
                                                              sys.exc_info()[-1].tb_lineno))
1706

    
1707
        return symbolNametList
1708

    
1709
    '''
1710
        @brief  delete added symbol data
1711
    '''
1712
    def deleteSymbol(self, fileName):
1713
        ret = False
1714

    
1715
        conn = self.project.database.connect()
1716
        with conn:
1717
            try:
1718
                cursor = conn.cursor()
1719
                sql = self.project.database.to_sql("DELETE FROM Symbol WHERE name = ?")
1720
                try:
1721
                    cursor.execute(sql, (fileName,))
1722
                    conn.commit()
1723
                    ret = True
1724
                except Exception as ex:
1725
                    conn.rollback()
1726
                    from App import App
1727
                    message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
1728
                                                                sys.exc_info()[-1].tb_lineno)
1729
                    App.mainWnd().addMessage.emit(MessageType.Error, message)
1730
                    ret = False
1731
            finally:
1732
                self._symbolBase = {}
1733
                return (ret, fileName)
1734

    
1735
    def getDuplicatedAttrs(self, param):
1736
        """ get duplicated attributes """
1737

    
1738
        res = []
1739
        
1740
        with self.project.database.connect() as conn:
1741
            cursor = conn.cursor()
1742
            sql = self.project.database.to_sql(f"SELECT t.Value, c.UID, d.Name FROM "
1743
                                               f"(SELECT a.[Value] FROM Attributes a GROUP BY a.[value] HAVING COUNT(a.[value]) > 1) t "
1744
                                               f"INNER JOIN Attributes a ON a.Value=t.value "
1745
                                               f"INNER JOIN SymbolAttribute b ON a.SymbolAttribute_UID=b.UID "
1746
                                               f"INNER JOIN Components c ON a.Components_UID=c.UID "
1747
                                               f"INNER JOIN Drawings d ON c.Drawings_UID=d.UID "
1748
                                               f"WHERE b.Attribute=? AND t.value != '' AND t.value != 'None' AND t.value IS NOT null")
1749
            try:
1750
                cursor.execute(sql, (param,))
1751
                rows = cursor.fetchall()
1752
                for row in rows:
1753
                    res.append([row['Name'], row['UID'], row['Value']])
1754

    
1755
                res = sorted(res, key=lambda pram: param[2])
1756
                return res
1757

    
1758
            except Exception as ex:
1759
                from App import App
1760
                message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
1761
                                                              sys.exc_info()[-1].tb_lineno)
1762
                App.mainWnd().addMessage.emit(MessageType.Error, message)
1763

    
1764
    '''
1765
        @brief  get symbol name
1766
        @history    18.04.24    Jeongwoo    Add isExceptDetect Field
1767
    '''
1768
    def getSymbolByQuery(self, fieldName, param):
1769
        ret = None
1770

    
1771
        if fieldName in self._symbolBase:
1772
            if param in self._symbolBase[fieldName]:
1773
                ret = self._symbolBase[fieldName][param]
1774
                return ret
1775
        else:
1776
            self._symbolBase[fieldName] = {}
1777

    
1778
        with self.project.database.connect() as conn:
1779
            cursor = conn.cursor()
1780
            sql = self.project.database.to_sql(f"SELECT a.UID as UID,a.Name,b.Type,a.Threshold,a.MinMatchPoint,"
1781
                                               f"a.IsDetectOrigin,a.RotationCount,a.OCROption,a.IsContainChild,"
1782
                                               f"a.OriginalPoint,a.ConnectionPoint,a.BaseSymbol,a.AdditionalSymbol,"
1783
                                               f"a.IsExceptDetect,a.HasInstrumentLabel,a.flip,a.TextArea,b.UID as DB_UID,a.Type as [Desc] FROM "
1784
                                               f"Symbol a inner join SymbolType b on a.SymbolType_UID=b.UID WHERE "
1785
                                               f"a.{fieldName}=?")
1786
            try:
1787
                cursor.execute(sql, (param,))
1788
                rows = cursor.fetchall()
1789
                if rows is not None and len(rows) > 0:
1790
                    symbolTuple = rows[0]
1791
                    ret = symbol.SymbolBase(symbolTuple['Name'], symbolTuple['Type'], symbolTuple['Threshold']
1792
                                            , symbolTuple['MinMatchPoint'], symbolTuple['IsDetectOrigin'],
1793
                                            symbolTuple['RotationCount'], symbolTuple['OCROption'],
1794
                                            symbolTuple['IsContainChild'], symbolTuple['OriginalPoint'],
1795
                                            symbolTuple['ConnectionPoint'], symbolTuple['BaseSymbol'],
1796
                                            symbolTuple['AdditionalSymbol'], symbolTuple['IsExceptDetect'],
1797
                                            symbolTuple['HasInstrumentLabel'], symbolTuple['UID'],
1798
                                            iType=symbolTuple['DB_UID'], detectFlip=symbolTuple['flip'],
1799
                                            text_area=symbolTuple['TextArea'], desc=symbolTuple['Desc'])
1800
                    self._symbolBase[fieldName][param] = ret
1801
            except Exception as ex:
1802
                from App import App
1803
                message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
1804
                                                              sys.exc_info()[-1].tb_lineno)
1805
                App.mainWnd().addMessage.emit(MessageType.Error, message)
1806

    
1807
        return ret
1808

    
1809
    '''
1810
        @brief  get symbol name list
1811
        @history    18.04.24    Jeongwoo    Add isExceptDetect Field
1812
    '''
1813
    def getSymbolListByType(self, field_name=None, param=None):
1814
        ret = []
1815

    
1816
        with self.project.database.connect() as conn:
1817
            cursor = conn.cursor()
1818
            if field_name is not None and param is not None:
1819
                sql = """SELECT a.UID,a.Name,b.Type,a.Threshold,a.MinMatchPoint,a.IsDetectOrigin,a.RotationCount,
1820
                a.OCROption,a.IsContainChild,a.OriginalPoint,a.ConnectionPoint,a.BaseSymbol,a.AdditionalSymbol,a.Width,a.Height,
1821
                a.IsExceptDetect,a.HasInstrumentLabel,a.flip,a.TextArea,b.UID as DB_UID,a.Type as [Desc] FROM Symbol a 
1822
                inner join SymbolType b on a.SymbolType_UID=b.UID WHERE 
1823
                SymbolType_UID = (select UID from SymbolType where {}={})""".format(
1824
                    field_name, self.project.database.place_holder)
1825
            else:
1826
                sql = """SELECT a.UID,a.Name,b.Type,a.Threshold,a.MinMatchPoint,a.IsDetectOrigin,a.RotationCount, 
1827
                a.OCROption,a.IsContainChild,a.OriginalPoint,a.ConnectionPoint,a.BaseSymbol,a.AdditionalSymbol,a.Width,a.Height,
1828
                a.IsExceptDetect,a.HasInstrumentLabel,a.flip,a.TextArea,b.UID as DB_UID,a.Type as [Desc] FROM Symbol a 
1829
                inner join SymbolType b on a.SymbolType_UID=b.UID"""
1830
            try:
1831
                cursor.execute(sql, (param,)) if param is not None else cursor.execute(sql)
1832
                rows = cursor.fetchall()
1833
                if rows is not None and len(rows) > 0:
1834
                    for symbolTuple in rows:
1835
                        sym = symbol.SymbolBase(symbolTuple['Name'], symbolTuple['Type'], symbolTuple['Threshold'],
1836
                                                symbolTuple['MinMatchPoint'], symbolTuple['IsDetectOrigin'],
1837
                                                symbolTuple['RotationCount'], symbolTuple['OCROption'],
1838
                                                symbolTuple['IsContainChild'], symbolTuple['OriginalPoint'],
1839
                                                symbolTuple['ConnectionPoint'], symbolTuple['BaseSymbol'],
1840
                                                symbolTuple['AdditionalSymbol'], symbolTuple['IsExceptDetect'],
1841
                                                symbolTuple['HasInstrumentLabel'], symbolTuple['UID'],
1842
                                                iType=symbolTuple['DB_UID'],width=symbolTuple['Width'], height=symbolTuple['Height'],
1843
                                                detectFlip=symbolTuple['flip'], text_area=symbolTuple['TextArea'], desc=symbolTuple['Desc'])
1844
                        ret.append(sym)
1845

    
1846
                # update cache
1847
                if ret:
1848
                    if 'UID' not in self._symbolBase:
1849
                        self._symbolBase['UID'] = {}
1850
                    if 'name' not in self._symbolBase:
1851
                        self._symbolBase['name'] = {}
1852

    
1853
                    for _symbol in ret:
1854
                        if _symbol.uid not in self._symbolBase['UID']:
1855
                            self._symbolBase['UID'][_symbol.uid] = _symbol
1856
                        if _symbol.sName not in self._symbolBase['name']:
1857
                            self._symbolBase['name'][_symbol.sName] = _symbol
1858
            except Exception as ex:
1859
                from App import App
1860
                message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
1861
                                                              sys.exc_info()[-1].tb_lineno)
1862
                App.mainWnd().addMessage.emit(MessageType.Error, message)
1863

    
1864
        return ret
1865

    
1866
    '''
1867
        @brief      get NominalDiameter
1868
        @author     humkyung
1869
        @date       2018.04.20
1870
        @history    humkyung 2018.04.24 read MetricStr column and set size unit
1871
                    kyouho 2018.07.04 forCheckLineNumber get only inch or metric
1872
                    kyouho 2018.07.16 edit query order by code
1873
    '''
1874
    def getNomialPipeSizeData(self, forCheckLineNumber=False, orderStr="MetricStr"):
1875
        res = []
1876
        configs = self.getConfigs('Line No', 'Size Unit')
1877
        sizeUnit = configs[0].value if 1 == len(configs) else 'Metric'
1878

    
1879
        conn = self.project.database.connect()
1880
        with conn:
1881
            try:
1882
                # Get a cursor object
1883
                cursor = conn.cursor()
1884

    
1885
                sql = f"select UID,Code,Metric,Inch,InchStr,AllowableInchStr,MetricStr,AllowableMetricStr from " \
1886
                      f"NominalDiameter ORDER BY {orderStr} DESC"
1887
                cursor.execute(sql)
1888
                rows = cursor.fetchall()
1889
                for row in rows:
1890
                    pipeSize = NominalPipeSize(row['UID'], row['Code'], float(row['Metric']) if row['Metric'] else None,
1891
                                               float(row['Inch']) if row['Inch'] else None, row['InchStr'],
1892
                                               row['AllowableInchStr'], row['MetricStr'], row['AllowableMetricStr'])
1893
                    pipeSize.sizeUnit = sizeUnit
1894
                    if forCheckLineNumber:
1895
                        if sizeUnit == 'Inch' and pipeSize.inchStr:
1896
                            res.append(pipeSize.inchStr)
1897
                        elif sizeUnit == 'Metric' and pipeSize.metricStr:
1898
                            res.append(pipeSize.metricStr)
1899
                    else:
1900
                        res.append(pipeSize)
1901

    
1902
                if 'Inch' in sizeUnit:
1903
                    res = sorted(res, key=lambda param:len(param.inchStr), reverse=True)
1904
                else:
1905
                    res = sorted(res, key=lambda param:len(param.metricStr), reverse=True)
1906
            # Catch the exception
1907
            except Exception as ex:
1908
                from App import App
1909
                message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
1910
                                                              sys.exc_info()[-1].tb_lineno)
1911
                App.mainWnd().addMessage.emit(MessageType.Error, message)
1912

    
1913
        return res
1914

    
1915
    '''
1916
        @brief      insert NominalDiameter table
1917
        @author     kyouho
1918
        @date       2018.07.16
1919
    '''
1920
    def insertNomialPipeSize(self, pipeSizes):
1921
        conn = self.project.database.connect()
1922
        with conn:
1923
            try:
1924
                # Get a cursor object
1925
                cursor = conn.cursor()
1926
                for pipeSize in pipeSizes:
1927
                    sql = pipeSize.toSql()
1928
                    if type(sql) is list and len(sql) == 1:
1929
                        cursor.execute(self.project.database.to_sql(sql[0][0]), sql[0][1])
1930

    
1931
                conn.commit()
1932
            # Catch the exception
1933
            except Exception as ex:
1934
                # Roll back any change if something goes wrong
1935
                conn.rollback()
1936

    
1937
                from App import App
1938
                message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
1939
                                                              sys.exc_info()[-1].tb_lineno)
1940
                App.mainWnd().addMessage.emit(MessageType.Error, message)
1941

    
1942
    '''
1943
        @brief      delete NominalDiameter table
1944
        @author     kyouho
1945
        @date       2018.07.16
1946
    '''
1947
    def deleteNomialPipeSize(self):
1948
        conn = self.project.database.connect()
1949
        with conn:
1950
            cursor = conn.cursor()
1951
            sql = "DELETE FROM NominalDiameter"
1952
            try:
1953
                cursor.execute(sql)
1954
                conn.commit()
1955
            except Exception as ex:
1956
                conn.rollback()
1957
                print('error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
1958
                                                          sys.exc_info()[-1].tb_lineno))
1959

    
1960
    '''
1961
        @brief      convert inch to metric
1962
        @author     kyouho
1963
        @date       2018.07.09
1964
    '''
1965
    def convertInchToMetric(self, inch):
1966
        result = ''
1967
        conn = self.project.database.connect()
1968
        with conn:
1969
            try:
1970
                # Get a cursor object
1971
                cursor = conn.cursor()
1972

    
1973
                sql = "select MetricStr from NominalDiameter WHERE InchStr = ?"
1974
                param = (inch,)
1975
                cursor.execute(sql, param)
1976
                rows = cursor.fetchall()
1977

    
1978
                if rows:
1979
                    result = rows[0][0]
1980
                # Catch the exception
1981
            except Exception as ex:
1982
                print('error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
1983
                                                          sys.exc_info()[-1].tb_lineno))
1984

    
1985
        return result
1986

    
1987
    '''
1988
        @brief      get Color MaxUID
1989
        @author     kyouho
1990
        @date       2018.07.03
1991
    '''
1992
    def getMaxColorUID(self):
1993
        result = 0
1994

    
1995
        conn = self.project.database.connect()
1996
        with conn:
1997
            try:
1998
                # Get a cursor object
1999
                cursor = conn.cursor()
2000

    
2001
                sql = "select MAX(UID) from Colors"
2002
                cursor.execute(sql)
2003
                rows = cursor.fetchall()
2004

    
2005
                result = rows[0][0]
2006
                # Catch the exception
2007
            except Exception as ex:
2008
                print('error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
2009
                                                          sys.exc_info()[-1].tb_lineno))
2010

    
2011
        return result
2012

    
2013
    '''
2014
        @brief      insert Color property
2015
        @author     kyouho
2016
        @date       2018.07.09
2017
    '''
2018
    def setPropertyColor(self, _color):
2019
        conn = self.project.database.connect()
2020
        with conn:
2021
            try:
2022
                # Get a cursor object
2023
                cursor = conn.cursor()
2024
                sql = "INSERT INTO Colors(UID, RED, GREEN, BLUE, PROPERTY, VALUE) VALUES(?,?,?,?,?,?)"
2025
                param = (_color.index, _color.red, _color.green, _color.blue, _color._property, _color.value)
2026
                cursor.execute(sql, param)
2027
                conn.commit()
2028
            # Catch the exception
2029
            except Exception as ex:
2030
                # Roll back any change if something goes wrong
2031
                conn.rollback()
2032
                print('error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
2033
                                                          sys.exc_info()[-1].tb_lineno))
2034

    
2035
    '''
2036
        @brief      delete Color property
2037
        @author     kyouho
2038
        @date       2018.07.09
2039
    '''
2040
    def deletePropertyColor(self, property):
2041
        conn = self.project.database.connect()
2042
        with conn:
2043
            try:
2044
                # Get a cursor object
2045
                cursor = conn.cursor()
2046

    
2047
                sql = "DELETE FROM Colors WHERE PROPERTY = '{}'".format(property)
2048
                cursor.execute(sql)
2049
                conn.commit()
2050
                # Catch the exception
2051
            except Exception as ex:
2052
                # Roll back any change if something goes wrong
2053
                conn.rollback()
2054
                print('error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
2055
                                                          sys.exc_info()[-1].tb_lineno))
2056

    
2057
    '''
2058
        @brief      get Fluid Code
2059
        @author     kyouho
2060
        @date       2018.07.03
2061
        @history    kyouho 2018.07.04 kyouho 2018.07.04 forCheckLineNumber get only code
2062
    '''
2063
    def getFluidCodeData(self, forCheckLineNumber=False):
2064
        from FluidCodeData import FluidCodeData
2065
        result = []
2066

    
2067
        conn = self.project.database.connect()
2068
        with conn:
2069
            try:
2070
                # Get a cursor object
2071
                cursor = conn.cursor()
2072

    
2073
                sql = 'select uid, code, description from FluidCode order by length(code) DESC'
2074
                cursor.execute(sql)
2075
                rows = cursor.fetchall()
2076
                for row in rows:
2077
                    data = FluidCodeData(row[0], row[1], row[2])
2078
                    if forCheckLineNumber:
2079
                        result.append(data.code)
2080
                    else:
2081
                        result.append(data)
2082
                # Catch the exception
2083
            except Exception as ex:
2084
                print('error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
2085
                                                          sys.exc_info()[-1].tb_lineno))
2086

    
2087
        return result
2088

    
2089
    '''
2090
        @brief      get Symbol Attribute
2091
        @author     kyouho
2092
        @date       2018.07.18
2093
    '''
2094
    def checkAttribute(self, attr):
2095
        conn = self.project.database.connect()
2096
        with conn:
2097
            try:
2098
                # Get a cursor object
2099
                cursor = conn.cursor()
2100

    
2101
                sql = 'select UID from SymbolAttribute where UID = ?'
2102
                param = (attr,)
2103
                cursor.execute(sql, param)
2104
                rows = cursor.fetchall()
2105
                if len(rows):
2106
                    return True
2107
                else:
2108
                    return False
2109
                # Catch the exception
2110
            except Exception as ex:
2111
                print('error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
2112
                                                          sys.exc_info()[-1].tb_lineno))
2113

    
2114
        return False
2115

    
2116
    def read_drawing_shape(self, drawing):
2117
        """read drawing shape"""
2118

    
2119
        res = None
2120

    
2121
        with self.project.database.connect() as conn:
2122
            try:
2123
                # Get a cursor object
2124
                cursor = conn.cursor()
2125

    
2126
                sql = f"select Image from Drawings where UID='{drawing}'"
2127
                cursor.execute(sql)
2128
                records = cursor.fetchall()
2129
                for record in records:
2130
                    res = record[0]
2131
                    break
2132

    
2133
            # Catch the exception
2134
            except Exception as ex:
2135
                from App import App
2136
                # Roll back any change if something goes wrong
2137
                conn.rollback()
2138

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

    
2143
        return res
2144

    
2145
    def read_symbol_shape(self, symbol_name):
2146
        """read symbol shape(image and svg)"""
2147
        
2148
        res = (None, None)
2149

    
2150
        # need to test on mssql
2151
        return res
2152

    
2153
        with self.project.database.connect() as conn:
2154
            try:
2155
                # Get a cursor object
2156
                cursor = conn.cursor()
2157

    
2158
                sql = f"select Image, Svg from Symbol where Name='{symbol_name}'"
2159
                cursor.execute(sql)
2160
                records = cursor.fetchall()
2161
                for record in records:
2162
                    res = (record[0], record[1])
2163
                    break
2164

    
2165
            # Catch the exception
2166
            except Exception as ex:
2167
                from App import App
2168
                # Roll back any change if something goes wrong
2169
                conn.rollback()
2170

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

    
2175
        return res
2176

    
2177

    
2178
    def update_symbol_shape(self, symbol_name, image_file, svg_file, image_display_file):
2179
        """update symbol shape"""
2180

    
2181
        # need to test on mssql
2182
        return
2183

    
2184
        with self.project.database.connect() as conn:
2185
            try:
2186
                # Get a cursor object
2187
                cursor = conn.cursor()
2188

    
2189
                cols = []
2190
                params = []
2191

    
2192
                image_blob_data = None
2193
                if image_file and os.path.isfile(image_file):
2194
                    with open(image_file, 'rb') as file:
2195
                        image_blob_data = file.read()
2196
                    cols.append('Image=?')
2197
                    params.append(image_blob_data)
2198

    
2199
                svg_blob_data = None
2200
                if svg_file and os.path.isfile(svg_file):
2201
                    with open(svg_file, 'rb') as file:
2202
                        svg_blob_data = file.read()
2203
                    cols.append('Svg=?')
2204
                    params.append(svg_blob_data)
2205

    
2206
                image_display_blob_data = None
2207
                if image_file and image_display_file and os.path.isfile(image_display_file):
2208
                    with open(image_file, 'rb') as file:
2209
                        image_display_blob_data = file.read()
2210
                    cols.append('Image_display=?')
2211
                    params.append(image_display_blob_data)
2212

    
2213
                sql = f"update Symbol set {','.join(cols)} where Name='{symbol_name}'"
2214
                # Convert data into tuple format
2215
                cursor.execute(self.project.database.to_sql(sql), tuple(params))
2216
                conn.commit()
2217

    
2218
            # Catch the exception
2219
            except Exception as ex:
2220
                from App import App
2221
                # Roll back any change if something goes wrong
2222
                conn.rollback()
2223

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

    
2228
    def getReplaceTables(self):
2229
        ''' get replace(inst) code tables '''
2230

    
2231
        import uuid
2232
        from CodeTables import CodeTable
2233

    
2234
        with self.project.database.connect() as conn:
2235
            try:
2236
                result = []
2237

    
2238
                # Get a cursor object
2239
                cursor = conn.cursor()
2240

    
2241
                sql = self.project.database.to_sql('select UID, Name, Description from InstTables')
2242
                cursor.execute(sql)
2243
                rows = cursor.fetchall()
2244
                for row in rows:
2245
                    table = []
2246
                    table.append(uuid.UUID(row['UID']))
2247
                    table.append(row['Name'])
2248
                    table.append(row['Description'])
2249
                    table.append(CodeTable.instance('InstCodes', inst_table_uid=row['UID']))
2250
                    result.append(table)
2251
            # Catch the exception
2252
            except Exception as ex:
2253
                from App import App
2254
                message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
2255
                                                              sys.exc_info()[-1].tb_lineno)
2256
                App.mainWnd().addMessage.emit(MessageType.Error, message)
2257

    
2258
        return result
2259

    
2260
    def getCustomTables(self):
2261
        ''' get custom code tables '''
2262

    
2263
        import uuid
2264
        from CodeTables import CodeTable
2265

    
2266
        with self.project.database.connect() as conn:
2267
            try:
2268
                result = []
2269

    
2270
                # Get a cursor object
2271
                cursor = conn.cursor()
2272

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

    
2290
        return result
2291

    
2292
    def loadSymbolAttributeCodeTables(self):
2293
        ''' load symbol attribute code tables '''
2294

    
2295
        try:
2296
            types = self.getSymbolTypeList()
2297

    
2298
            for _type in types:
2299
                self.getSymbolAttribute(_type[2])
2300

    
2301
        except Exception as ex:
2302
            from App import App
2303
            message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
2304
                                                            sys.exc_info()[-1].tb_lineno)
2305
            App.mainWnd().addMessage.emit(MessageType.Error, message)
2306

    
2307
    '''
2308
        @brief      get Symbol Attribute
2309
        @author     kyouho
2310
        @date       2018.07.18
2311
        @history    humkyung 2018.10.13 load expression
2312
    '''
2313
    def getSymbolAttribute(self, _type):
2314
        import uuid
2315
        from SymbolAttr import SymbolAttr
2316
        from CodeTables import CodeTable
2317

    
2318
        result = []
2319

    
2320
        if self._attributeByType and _type in self._attributeByType:
2321
            new_attr_without_any_binding_data = []
2322
            for attr_old in self._attributeByType[_type]:
2323
                attr = SymbolAttr()
2324
                attr.UID = attr_old.UID
2325
                attr.Attribute = attr_old.Attribute
2326
                attr.DisplayAttribute = attr_old.DisplayAttribute
2327
                attr.AttributeType = attr_old.AttributeType
2328
                attr.AttrAt = attr_old.AttrAt
2329
                attr.Expression = attr_old.Expression
2330
                attr.Target = attr_old.Target
2331
                attr.IsProp = attr_old.IsProp
2332
                attr.Codes = attr_old.Codes
2333
                attr.Index = attr_old.Index
2334
                new_attr_without_any_binding_data.append(attr)
2335
            self._attributeByType[_type] = new_attr_without_any_binding_data
2336

    
2337
            return self._attributeByType[_type]
2338

    
2339
        with self.project.database.connect() as conn:
2340
            try:
2341
                # Get a cursor object
2342
                cursor = conn.cursor()
2343

    
2344
                sql = self.project.database.to_sql(
2345
                    'select a.UID, a.Attribute, a.DisplayAttribute, a.AttributeType, a.[AttrAt], a.[Expression], '
2346
                    'a.[index], a.[Target], a.[Property], a.[index] from SymbolAttribute a inner join SymbolType t '
2347
                    'on a.SymbolType_UID = t.UID and t.type = ? order by a.[index]')
2348
                param = (_type,)
2349
                cursor.execute(sql, param)
2350
                rows = cursor.fetchall()
2351
                for row in rows:
2352
                    attr = SymbolAttr()
2353
                    attr.UID = uuid.UUID(row['UID'].replace('\n', ""))
2354
                    attr.Attribute = row['Attribute']
2355
                    attr.DisplayAttribute = row['DisplayAttribute']
2356
                    attr.AttributeType = row['AttributeType']
2357
                    attr.AttrAt = row['AttrAt']
2358
                    attr.Expression = row['Expression']
2359
                    attr.Target = row['Target']
2360
                    attr.IsProp = row['Property']
2361
                    attr.Index = row['index']
2362
                    attr.Codes = CodeTable.instance('SymbolAttributeCodeTable', symbol_attribute_uid=row['UID'])
2363
                    result.append(attr)
2364
            # Catch the exception
2365
            except Exception as ex:
2366
                from App import App
2367
                message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
2368
                                                              sys.exc_info()[-1].tb_lineno)
2369
                App.mainWnd().addMessage.emit(MessageType.Error, message)
2370

    
2371
        self._attributeByType[_type] = result
2372
        return result
2373

    
2374
    '''
2375
        @brief      get Symbol Attribute by UID
2376
        @author     kyouho
2377
        @date       2018.08.17
2378
        @history    humkyung 2018.10.13 load expression
2379
    '''
2380
    def getSymbolAttributeByUID(self, UID):
2381
        from SymbolAttr import SymbolAttr
2382

    
2383
        res = None
2384

    
2385
        with self.project.database.connect() as conn:
2386
            try:
2387
                # Get a cursor object
2388
                cursor = conn.cursor()
2389

    
2390
                sql = f"select Attribute, DisplayAttribute, AttributeType, AttrAt, Expression, Target, Property, [index] from " \
2391
                      f"SymbolAttribute where uid = '{UID}'"
2392
                cursor.execute(sql)
2393
                rows = cursor.fetchall()
2394
                if len(rows):
2395
                    res = SymbolAttr()
2396
                    res.UID = UID
2397
                    res.Attribute = rows[0]['Attribute']
2398
                    res.DisplayAttribute = rows[0]['DisplayAttribute']
2399
                    res.AttributeType = rows[0]['AttributeType']
2400
                    res.AttrAt = rows[0]['AttrAt']
2401
                    res.Expression = rows[0]['Expression']
2402
                    res.Target = rows[0]['Target']
2403
                    res.IsProp = rows[0]['Property']
2404
                    res.Index = rows[0]['index']
2405
                # Catch the exception
2406
            except Exception as ex:
2407
                from App import App
2408
                message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
2409
                                                              sys.exc_info()[-1].tb_lineno)
2410
                App.mainWnd().addMessage.emit(MessageType.Error, message)
2411

    
2412
        return res
2413

    
2414
    '''
2415
        @brief      save symbol attributes
2416
        @author     humkyung
2417
        @date       2018.08.14
2418
        @history    humkyung 2018.10.13 save expression
2419
    '''
2420
    def saveSymbolAttributes(self, type, attrs, type_str):
2421
        from CodeTables import CodeTable
2422

    
2423
        with self.project.database.connect() as conn:
2424
            try:
2425
                # Get a cursor object
2426
                cursor = conn.cursor()
2427

    
2428
                # delete symbol attribute code table data
2429
                origin_attrs = self.getSymbolAttribute(type_str)
2430
                for origin_attr in origin_attrs:
2431
                    '''
2432
                    # delete symbol attribute code table data for deleted symbol attribute, and backup not edited attribute code table data
2433
                    remain = False
2434
                    for attr in attrs:
2435
                        if str(origin_attr.UID) == attr[0]:
2436
                            remain = True
2437
                            break
2438
                    if remain and attr[-1] and type(attr[-1][0][3]) is list: # this means not edited and need backup
2439
                        attr[-1] = self.getCodeTable('SymbolAttributeCodeTable', forCheckLineNumber=False, symbol_attribute_uid=origin_attr.UID)
2440
                    '''
2441
                    
2442
                    sql = "delete from SymbolAttributeCodeTable where SymbolAttribute_UID = '{}'".format(origin_attr.UID)
2443
                    cursor.execute(sql)
2444
                # up to here
2445

    
2446
                # update symbol attribute
2447
                sql = self.project.database.to_sql('delete from SymbolAttribute where SymbolType_UID = ?')
2448
                param = (type,)
2449
                cursor.execute(sql, param)
2450

    
2451
                for attr in attrs:
2452
                    sql = self.project.database.to_sql(
2453
                        'insert into SymbolAttribute(UID, SymbolType_UID, Attribute, DisplayAttribute, AttributeType, '
2454
                        'AttrAt, Expression, Target, [index], [Property]) values(?, ?, ?, ?, ?, ?, ?, ?, ?, ?)')
2455
                    attr.insert(1, type)
2456
                    cursor.execute(sql, tuple(attr[:-1]))
2457
                # up to here
2458

    
2459
                # update symbol attribute code table data
2460
                for attr in attrs:
2461
                    if attr[-1]:
2462
                        for code in attr[-1]:
2463
                            sql = self.project.database.to_sql( \
2464
                                "insert into SymbolAttributeCodeTable(UID, Code, Description, Allowables, "
2465
                                "SymbolAttribute_UID) VALUES(?,?,?,?,?)")
2466
                            param = (code[0], code[1], code[2], ','.join(code[3]), attr[0])
2467
                            cursor.execute(sql, param)
2468
                # up to here
2469

    
2470
                conn.commit()
2471

    
2472
                if hasattr(self, '_equipment_attributes'):
2473
                    del self._equipment_attributes
2474

    
2475
                if hasattr(self, '_valve_attributes'):
2476
                    del self._valve_attributes
2477

    
2478
                if hasattr(self, '_inst_attributes'):
2479
                    del self._inst_attributes
2480

    
2481
                if hasattr(self, '_note_attributes'):
2482
                    del self._note_attributes
2483
            # Catch the exception
2484
            except Exception as ex:
2485
                # Roll back any change if something goes wrong
2486
                conn.rollback()
2487

    
2488
                from App import App
2489
                message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
2490
                                                              sys.exc_info()[-1].tb_lineno)
2491
                App.mainWnd().addMessage.emit(MessageType.Error, message)
2492

    
2493
            self._attributeByType = {}
2494
            CodeTable.clearTables()
2495

    
2496
    def save_hmb_data(self, hmb_list: list):
2497
        import uuid
2498

    
2499
        app_doc_data = AppDocData.instance()
2500
        with app_doc_data.project.database.connect() as conn:
2501
            try:
2502
                cursor = conn.cursor()
2503
                sql = 'delete from HMB_VALUE'
2504
                cursor.execute(sql)
2505
                sql = 'delete from HMB_LIST'
2506
                cursor.execute(sql)
2507
                sql = 'delete from Stream_No'
2508
                cursor.execute(sql)
2509

    
2510
                list_uids = []
2511
                if hmb_list and hmb_list[0].datas:
2512
                    """save hmb data catalog""" 
2513
                    for data in hmb_list[0].datas[0]:
2514
                        sql = f"insert into HMB_LIST(UID, Name, Unit, [index], [Type]) values(?,?,?,?,?)"
2515
                        sql = self.project.database.to_sql(sql)
2516
                        list_uid = str(uuid.uuid4())
2517
                        params = (list_uid, data.name, data.unit, data.index, data.phase)
2518
                        list_uids.append(list_uid)
2519
                        cursor.execute(sql, params)
2520

    
2521
                for hmb in hmb_list:
2522
                    """stream no save"""
2523
                    sql = f'insert into Stream_No(UID, Stream_No, [From], [To]) values(?,?,?,?)'
2524
                    sql = self.project.database.to_sql(sql)
2525
                    hmb.uid = hmb.uid if hmb.uid else str(uuid.uuid4())
2526
                    params = (str(hmb.uid), hmb.stream_no, hmb.hfrom, hmb.hto)
2527
                    cursor.execute(sql, params)
2528

    
2529
                    """save hmb data value"""
2530
                    params = []
2531
                    sql = f"insert into HMB_Value(UID, HMB_LIST_UID, Stream_No_UID, Value, [Case]) values(?,?,?,?,?)"
2532
                    sql = self.project.database.to_sql(sql)
2533
                    for data_case in hmb.datas:
2534
                        index = 0
2535
                        for data in data_case:
2536
                            params.append((str(uuid.uuid4()), list_uids[index], hmb.uid, data.value, data.case))
2537
                            index = index + 1
2538
                    cursor.executemany(sql, tuple(params))
2539

    
2540
                conn.commit()
2541
                self._hmbData = None
2542
                        
2543
            except Exception as ex:
2544
                # Roll back any change if something goes wrong
2545
                conn.rollback()
2546

    
2547
                from App import App
2548
                message = f"error occurred({repr(ex)}) in {sys.exc_info()[-1].tb_frame.f_code.co_filename}:" \
2549
                          f"{sys.exc_info()[-1].tb_lineno}"
2550
                App.mainWnd().addMessage.emit(MessageType.Error, message)
2551

    
2552
    def get_hmb_data(self, file_path: str):
2553
        """get hmb data from pap database if file_path is given otherwise get hmb data from id2 database"""
2554

    
2555
        from HMBTable import HMBData
2556

    
2557
        if not file_path:
2558
            if self._hmbData is None:
2559
                app_doc_data = AppDocData.instance()
2560
                with app_doc_data.project.database.connect() as conn:
2561
                    try:
2562
                        cursor = conn.cursor()
2563
                        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 " \
2564
                                f"HMB_VALUE v " \
2565
                                f"INNER JOIN HMB_LIST r ON v.HMB_LIST_UID=r.UID " \
2566
                                f"INNER JOIN Stream_No s ON v.Stream_No_UID=s.UID " \
2567
                                f"ORDER BY s.stream_no"
2568
                        cursor.execute(sql)
2569
                        rows = cursor.fetchall()
2570

    
2571
                        hmbs = HMBData.from_row(rows)
2572
                        self._hmbData = hmbs
2573
                        return self._hmbData
2574
                    except Exception as ex:
2575
                        # Roll back any change if something goes wrong
2576
                        conn.rollback()
2577

    
2578
                        from App import App
2579
                        message = f"error occurred({repr(ex)}) in {sys.exc_info()[-1].tb_frame.f_code.co_filename}:" \
2580
                                f"{sys.exc_info()[-1].tb_lineno}"
2581
                        App.mainWnd().addMessage.emit(MessageType.Error, message)
2582
            else:
2583
                return self._hmbData
2584
        else:
2585
            with sqlite3.connect(file_path) as conn:
2586
                try:
2587
                    conn.row_factory = sqlite3.Row
2588
                    cursor = conn.cursor()
2589
                    sql = 'select * from HMB_condition'
2590
                    cursor.execute(sql)
2591
                    rows = cursor.fetchall()
2592
                    return rows
2593
                except Exception as ex:
2594
                    # Roll back any change if something goes wrong
2595
                    conn.rollback()
2596

    
2597
                    from App import App
2598
                    message = f"error occurred({repr(ex)}) in {sys.exc_info()[-1].tb_frame.f_code.co_filename}:" \
2599
                              f"{sys.exc_info()[-1].tb_lineno}"
2600
                    App.mainWnd().addMessage.emit(MessageType.Error, message)
2601

    
2602
        return None
2603

    
2604
    def get_hmb_attributes(self):
2605
        """get hmb attributes"""
2606
        from SymbolAttr import SymbolAttr
2607

    
2608
        attrs = []
2609
        with self.project.database.connect() as conn:
2610
            try:
2611
                # Get a cursor object
2612
                cursor = conn.cursor()
2613

    
2614
                sql = f"select * from SymbolAttribute where SymbolType_UID = " \
2615
                      f"(select UID from SymbolType where Type='HMB') order by [index]"
2616
                sql = self.project.database.to_sql(sql)
2617
                cursor.execute(sql)
2618
                rows = cursor.fetchall()
2619
                for row in rows:
2620
                    attr = SymbolAttr(row['UID'])
2621
                    attr.Attribute = row['Attribute']
2622
                    attr.DisplayAttribute = row['DisplayAttribute']
2623
                    attr.AttributeType = row['AttributeType']
2624
                    attr.AttrAt = row['AttrAt']
2625
                    attr.Expression = row['Expression']
2626
                    attr.Target = row['Target']
2627
                    attr.IsProp = row['Property']
2628
                    attr.Index = row['index']
2629

    
2630
                    attrs.append(attr)
2631

    
2632
            # Catch the exception
2633
            except Exception as ex:
2634
                # Roll back any change if something goes wrong
2635
                conn.rollback()
2636

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

    
2642
        return attrs
2643

    
2644
    def save_hmb_model(self, model: QStandardItemModel):
2645
        """ no more used """
2646
        """save hmb model to database"""
2647

    
2648
        with self.project.database.connect() as conn:
2649
            try:
2650
                # get a cursor object
2651
                cursor = conn.cursor()
2652

    
2653
                # delete hmb table
2654
                sql = 'delete from HMB'
2655
                sql = self.project.database.to_sql(sql)
2656
                cursor.execute(sql)
2657
                # up to here
2658

    
2659
                for row in range(model.rowCount()):
2660
                    params = []
2661
                    for col in range(model.columnCount()):
2662
                        data = model.data(model.index(row, col))
2663
                        params.append(data)
2664

    
2665
                    values = ['?' for col in range(model.columnCount())]
2666
                    sql = f"insert into HMB values({','.join(values)})"
2667
                    cursor.execute(sql, params)
2668

    
2669
                conn.commit()
2670
            except Exception as ex:
2671
                # Roll back any change if something goes wrong
2672
                conn.rollback()
2673

    
2674
                from App import App
2675
                message = f"error occurred({repr(ex)}) in {sys.exc_info()[-1].tb_frame.f_code.co_filename}:" \
2676
                          f"{sys.exc_info()[-1].tb_lineno}"
2677
                App.mainWnd().addMessage.emit(MessageType.Error, message)
2678

    
2679
    def save_hmb_attributes(self, attrs):
2680
        """save hmb attributes"""
2681
        from CodeTables import CodeTable
2682

    
2683
        with self.project.database.connect() as conn:
2684
            try:
2685
                # Get a cursor object
2686
                cursor = conn.cursor()
2687

    
2688
                # delete hmb attributes
2689
                sql = f"delete from SymbolAttribute where SymbolType_UID = (select UID from SymbolType where Type='HMB')"
2690
                sql = self.project.database.to_sql(sql)
2691
                cursor.execute(sql)
2692
                # up to here
2693

    
2694
                for idx, attr in enumerate(attrs):
2695
                    sql = self.project.database.to_sql(
2696
                        'insert into SymbolAttribute(UID, SymbolType_UID, Attribute, DisplayAttribute, AttributeType, '
2697
                        'AttrAt, Expression, Target, [index], [Property]) values(?, '
2698
                        '(select uid from SymbolType where Type=\'HMB\'), ?, ?, ?, ?, ?, ?, ?, ?)')
2699
                    params = (str(attr.UID), attr.Attribute, attr.Attribute, 'String', attr.AttrAt,
2700
                              attr.Expression if attr.Expression else None, attr.Target, idx, attr.IsProp)
2701

    
2702
                    cursor.execute(sql, params)
2703
                # up to here
2704

    
2705
                conn.commit()
2706

    
2707
            # Catch the exception
2708
            except Exception as ex:
2709
                # Roll back any change if something goes wrong
2710
                conn.rollback()
2711

    
2712
                from App import App
2713
                message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
2714
                                                               sys.exc_info()[-1].tb_lineno)
2715
                App.mainWnd().addMessage.emit(MessageType.Error, message)
2716

    
2717
    @staticmethod
2718
    def save_stream_line_data(stream_line_list: list):
2719
        """ save stream line from to """
2720
        import uuid
2721

    
2722
        app_doc_data = AppDocData.instance()
2723
        with app_doc_data.project.database.connect() as conn:
2724
            try:
2725
                cursor = conn.cursor()
2726
                """delete stream line which has stream number is given data"""
2727
                sql = "delete from HMB_From_To where Stream_No=?"
2728
                sql = app_doc_data.project.database.to_sql(sql)
2729
                params = (stream_line_list[0],)
2730
                cursor.execute(sql, params)
2731
                """up to here"""
2732

    
2733
                for stream_line in stream_line_list[1]:
2734
                    sql = f"insert into HMB_From_To(UID,[Drawing_UID],[From_Component_UID],[To_Component_UID],[Stream_No],[Case]) values" \
2735
                          f"(?,?,?,?,?,?)"
2736
                    sql = app_doc_data.project.database.to_sql(sql)
2737
                    params = (str(uuid.uuid4()), stream_line[0], stream_line[1], stream_line[2], stream_line[3], stream_line[4])
2738
                    cursor.execute(sql, params)
2739

    
2740
                conn.commit()
2741
            except Exception as ex:
2742
                # Roll back any change if something goes wrong
2743
                conn.rollback()
2744

    
2745
                from App import App
2746
                message = f"error occurred({repr(ex)}) in {sys.exc_info()[-1].tb_frame.f_code.co_filename}:" \
2747
                          f"{sys.exc_info()[-1].tb_lineno}"
2748
                App.mainWnd().addMessage.emit(MessageType.Error, message)
2749

    
2750
    def get_stream_line_list_data(self, drawing_names=None):
2751
        """ get stream line list data from """
2752
        with self.project.database.connect() as conn:
2753
            try:
2754
                # Get a cursor object
2755
                cursor = conn.cursor()
2756

    
2757
                if drawing_names is None:
2758
                    doc_names = self.activeDrawing.name
2759
                else:
2760
                    doc_names = "','".join(drawing_names)
2761

    
2762
                sql = f"select S.PnIDNumber, S.Tag_Seq_No, S.PipingMaterialsClass, S.InsulationPurpose, S.FluidCode, " \
2763
                      f"S.UnitNumber, S.NominalDiameter, S.[From], S.[To], S.Stream_No, S.[Case], S.[Index], D.Name from Stream_Line_List S " \
2764
                      f"join Drawings D on S.Drawing_UID=D.UID " \
2765
                      f"where S.Drawing_UID in (select UID from Drawings where Name in ('{doc_names}'))"
2766
                sql = self.project.database.to_sql(sql)
2767
                cursor.execute(sql)
2768
                rows = cursor.fetchall()
2769

    
2770
                datas = []
2771
                for row in rows:
2772
                    data = {}
2773
                    data['PnIDNumber'] = row['PnIDNumber']
2774
                    data['Tag Seq No'] = row['Tag_Seq_No']
2775
                    data['PipingMaterialsClass'] = row['PipingMaterialsClass']
2776
                    data['InsulationPurpose'] = row['InsulationPurpose']
2777
                    data['FluidCode'] = row['FluidCode']
2778
                    data['UnitNumber'] = row['UnitNumber']
2779
                    data['NominalDiameter'] = row['NominalDiameter']
2780
                    data['FROM'] = row['From']
2781
                    data['TO'] = row['To']
2782
                    data['Stream No'] = row['Stream_No']
2783
                    data['Case'] = row['Case'] if row['Case'] else ''
2784
                    data['index'] = row['Index']
2785
                    data['Drawing Name'] = row['Name']
2786
                    
2787
                    datas.append(data)
2788

    
2789
                return datas
2790

    
2791
            # Catch the exception
2792
            except Exception as ex:
2793
                # Roll back any change if something goes wrong
2794
                conn.rollback()
2795

    
2796
                from App import App
2797
                message = f"error occurred({repr(ex)}) in {sys.exc_info()[-1].tb_frame.f_code.co_filename}:" \
2798
                          f"{sys.exc_info()[-1].tb_lineno}"
2799
                App.mainWnd().addMessage.emit(MessageType.Error, message)
2800

    
2801
    def get_stream_from_to(self, stream_no: str = None, drawing_uid: str = None) -> list:
2802
        """ get stream lines related to hmb """
2803

    
2804
        with self.project.database.connect() as conn:
2805
            try:
2806
                # Get a cursor object
2807
                cursor = conn.cursor()
2808

    
2809
                if stream_no:
2810
                    sql = f"select h.Drawing_UID, h.From_Component_UID, h.To_Component_UID, d.Name, h.[Case] from HMB_From_To h " \
2811
                          f"inner join Drawings d on d.UID=h.Drawing_UID " \
2812
                          f"where Stream_No = ?"
2813
                    params = (stream_no,)
2814
                else:
2815
                    sql = f"select h.From_Component_UID, h.To_Component_UID, s.Stream_No, h.[Case] from HMB_From_To h " \
2816
                          f"inner join Stream_No s on s.Stream_No=h.Stream_No " \
2817
                          f"where Drawing_UID = ?"
2818
                    params = (drawing_uid,)
2819
                sql = self.project.database.to_sql(sql)
2820
                cursor.execute(sql, params)
2821
                return cursor.fetchall()
2822
            # Catch the exception
2823
            except Exception as ex:
2824
                # Roll back any change if something goes wrong
2825
                conn.rollback()
2826

    
2827
                from App import App
2828
                message = f"error occurred({repr(ex)}) in {sys.exc_info()[-1].tb_frame.f_code.co_filename}:" \
2829
                          f"{sys.exc_info()[-1].tb_lineno}"
2830
                App.mainWnd().addMessage.emit(MessageType.Error, message)
2831

    
2832

    
2833
    def saveCustomCodes(self, tables):
2834
        ''' save custom code tables and codes '''
2835

    
2836
        from CodeTables import CodeTable
2837

    
2838
        conn = self.project.database.connect()
2839
        with conn:
2840
            try:
2841
                # Get a cursor object
2842
                cursor = conn.cursor()
2843

    
2844
                # delete custom codes and tables
2845
                sql = "delete from CustomCodes"
2846
                cursor.execute(sql)
2847

    
2848
                sql = "delete from CustomTables"
2849
                cursor.execute(sql)
2850
                # up to here
2851

    
2852
                # update symbol attribute code table data
2853
                for table in tables:
2854
                    sql = self.project.database.to_sql("insert into CustomTables (UID, Name, Description) VALUES(?,?,?)")
2855
                    param = (table[0], table[1], table[2])
2856
                    cursor.execute(sql, param)
2857

    
2858
                    for code in table[3]:
2859
                        sql = self.project.database.to_sql( \
2860
                            "insert into CustomCodes(UID, Code, Description, Allowables, Table_UID) VALUES(?,?,?,?,?)")
2861
                        param = (code[0], code[1], code[2], ','.join(code[3]), table[0])
2862
                        cursor.execute(sql, param)
2863
                # up to here
2864

    
2865
                conn.commit()
2866

    
2867
            # Catch the exception
2868
            except Exception as ex:
2869
                # Roll back any change if something goes wrong
2870
                conn.rollback()
2871

    
2872
                from App import App
2873
                message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
2874
                                                              sys.exc_info()[-1].tb_lineno)
2875
                App.mainWnd().addMessage.emit(MessageType.Error, message)
2876

    
2877
            CodeTable.clearTables()
2878

    
2879
    def saveReplaceCodes(self, tables):
2880
        ''' save repalce(inst) code tables and codes '''
2881

    
2882
        from CodeTables import CodeTable
2883

    
2884
        conn = self.project.database.connect()
2885
        with conn:
2886
            try:
2887
                # Get a cursor object
2888
                cursor = conn.cursor()
2889

    
2890
                # delete custom codes and tables
2891
                sql = "delete from InstCodes"
2892
                cursor.execute(sql)
2893

    
2894
                sql = "delete from InstTables"
2895
                cursor.execute(sql)
2896
                # up to here
2897

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

    
2904
                    for code in table[3]:
2905
                        sql = self.project.database.to_sql( \
2906
                            "insert into InstCodes(UID, Code, Symbols, Attribute, NewCode, Expression, Priority, Table_UID) VALUES(?,?,?,?,?,?,?,?)")
2907
                        param = (code[0], ','.join(code[1]), ','.join(code[2]), ','.join(code[3]), code[4], code[5], code[6], table[0])
2908
                        cursor.execute(sql, param)
2909
                # up to here
2910

    
2911
                conn.commit()
2912

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

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

    
2923
            CodeTable.clearTables()
2924

    
2925
    '''
2926
        @brief      save symbol attributes
2927
        @author     humkyung
2928
        @date       2018.08.14
2929
    '''
2930
    def saveLineAttributes(self, attrs):
2931
        with self.project.database.connect() as conn:
2932
            try:
2933
                # Get a cursor object
2934
                cursor = conn.cursor()
2935

    
2936
                sql = 'delete from LineProperties'
2937
                cursor.execute(sql)
2938

    
2939
                for attr in attrs:
2940
                    sql = self.project.database.to_sql(
2941
                        'insert into LineProperties(UID, Name, DisplayName, Type, LimitNumber, [index]) values(?, ?, ?, ?, ?, ?)')
2942
                    cursor.execute(sql, tuple(attr))
2943

    
2944
                conn.commit()
2945

    
2946
                self._lineNoProperties = None
2947
                self._lineNoPropertiesUID = {}
2948
            # Catch the exception
2949
            except Exception as ex:
2950
                # Roll back any change if something goes wrong
2951
                conn.rollback()
2952

    
2953
                from App import App
2954
                message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
2955
                                                              sys.exc_info()[-1].tb_lineno)
2956
                App.mainWnd().addMessage.emit(MessageType.Error, message)
2957

    
2958
    '''
2959
        @brief      get symbol type id
2960
        @author     kyouho
2961
        @date       2018.08.17
2962
    '''
2963
    def getSymbolTypeId(self, symbolType):
2964
        result = []
2965

    
2966
        with self.project.database.connect() as conn:
2967
            try:
2968
                # Get a cursor object
2969
                cursor = conn.cursor()
2970

    
2971
                sql = self.project.database.to_sql('select UID from SymbolType where Type = ?')
2972
                param = (symbolType,)
2973
                cursor.execute(sql, param)
2974
                rows = cursor.fetchall()
2975

    
2976
                if len(rows):
2977
                    result = rows[0]['UID']
2978
                else:
2979
                    result = -1
2980
                # Catch the exception
2981
            except Exception as ex:
2982
                print('error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
2983
                                                          sys.exc_info()[-1].tb_lineno))
2984

    
2985
        return result
2986

    
2987
    '''
2988
        @brief      get Code Table Data
2989
        @author     kyouho
2990
        @date       2018.07.10
2991
    '''
2992
    def getCodeTable(self, property, forCheckLineNumber=False, symbol_attribute_uid=None, custom_table_uid=None, custom=False, \
2993
                                                    inst_table_uid=None, inst=False):
2994
        result = []
2995
        with self.project.database.connect() as conn:
2996
            try:
2997
                # Get a cursor object
2998
                cursor = conn.cursor()
2999

    
3000
                if property.upper().replace(' ', '') == "NOMINALDIAMETER" and forCheckLineNumber:
3001
                    cols = ['InchStr', 'MetricStr']
3002
                    sql = f"select {cols[0]}, {cols[1]} from [{property}] order by Metric ASC"
3003
                    cursor.execute(sql)
3004
                    rows = cursor.fetchall()
3005
                    for index in range(2):
3006
                        for row in rows:
3007
                            if row[cols[index]] != '' and result.count(row[cols[index]].replace("'", '"')) == 0:
3008
                                result.append(row[cols[index]].replace("'", '"'))
3009
                else:
3010
                    """
3011
                    sql = "select name from sqlite_master where type='table'"# AND name={}".format(property)
3012
                    cursor.execute(sql)
3013
                    rows = cursor.fetchall()
3014
                    if property.upper() in [name[0].upper() for name in rows]:
3015
                    """
3016
                    if not symbol_attribute_uid and not custom_table_uid and not custom and not inst_table_uid and not inst:
3017
                        sql = 'select uid, code, description, Allowables from [{}] order by code DESC'.format(property)
3018
                    elif symbol_attribute_uid and not custom_table_uid and not inst_table_uid and not inst:
3019
                        sql = "select uid, code, description, Allowables from [{}] where SymbolAttribute_UID='{}' " \
3020
                              "order by code DESC".format(property, symbol_attribute_uid)
3021
                    elif not symbol_attribute_uid and custom_table_uid and not inst_table_uid:
3022
                        sql = "select uid, code, description, Allowables from [{}] where Table_UID='{}' " \
3023
                              "order by code DESC".format(property, custom_table_uid)
3024
                    elif not symbol_attribute_uid and not custom_table_uid and inst_table_uid:
3025
                        sql = "select uid, code, symbols, attribute, newcode, expression, priority from [{}] where Table_UID='{}' " \
3026
                              "order by code DESC".format(property, inst_table_uid)
3027
                    elif custom:
3028
                        sql = "select uid, code, description, Allowables from CustomCodes \
3029
                                    where table_uid = (select uid from CustomTables where upper(name) like upper('{}'))".format(property)
3030
                    elif inst:
3031
                        sql = "select uid, code, symbols, attribute, newcode, expression, priority from InstCodes \
3032
                                    where table_uid = (select uid from InstTables where upper(name) like upper('{}'))".format(property)
3033
                    cursor.execute(sql)
3034
                    rows = cursor.fetchall()
3035
                    if not inst:
3036
                        for row in rows:
3037
                            if forCheckLineNumber:
3038
                                data = row['code']
3039
                            else:
3040
                                data = (row['uid'], row['code'], row['description'], row['Allowables'])
3041
                            result.append(data)
3042
                        # else:
3043
                        #    result = None
3044
                    else:
3045
                        for row in rows:
3046
                            data = (row['uid'], row['code'], row['symbols'], row['attribute'], row['newcode'], row['expression'], row['priority'])
3047
                            result.append(data)
3048
            # Catch the exception
3049
            except Exception as ex:
3050
                from App import App
3051
                message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
3052
                                                              sys.exc_info()[-1].tb_lineno)
3053
                App.mainWnd().addMessage.emit(MessageType.Error, message)
3054

    
3055
        return result
3056

    
3057
    def get_components(self, drawing):
3058
        """ get components in given drawing """
3059

    
3060
        with self.project.database.connect() as conn:
3061
            try:
3062
                # Get a cursor object
3063
                cursor = conn.cursor()
3064

    
3065
                sql = "select a.*,b.Name,b.SymbolType_UID,b.[Type],b.OriginalPoint,b.ConnectionPoint,b.BaseSymbol," \
3066
                      "b.AdditionalSymbol,b.HasInstrumentLabel,b.Flip as DetectFlip from Components a " \
3067
                      "join Symbol b on a.Symbol_UID=b.UID where a.Drawings_UID='{}'".format(drawing)
3068
                cursor.execute(sql)
3069
                return cursor.fetchall()
3070
                # Catch the exception
3071
            except Exception as ex:
3072
                from App import App
3073
                message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
3074
                                                              sys.exc_info()[-1].tb_lineno)
3075
                App.mainWnd().addMessage.emit(MessageType.Error, message)
3076

    
3077
    def check_runs(self):
3078
        """ check run item duplication """
3079

    
3080
        with self.project.database.connect() as conn:
3081
            try:
3082
                # Get a cursor object
3083
                cursor = conn.cursor()
3084

    
3085
                sql = "select [Components_UID], count([Components_UID]) as count from [PipeRunItems] " \
3086
                      "group by [Components_UID] having count([Components_UID]) > 1"
3087

    
3088
                cursor.execute(sql)
3089

    
3090
                rows = cursor.fetchall()
3091

    
3092
                items = []
3093
                if rows:
3094
                    for row in rows:
3095
                        sql = "select c.[UID], d.[Name] from [Components] c inner join [Drawings] d on c.Drawings_UID=d.[UID]" \
3096
                              "where c.[UID]='" + row["Components_UID"] + "'"
3097
                        cursor.execute(sql)
3098

    
3099
                        _rows = cursor.fetchall()
3100
                        if _rows:
3101
                            items = items + _rows
3102

    
3103
                return items
3104
                # Catch the exception
3105
            except Exception as ex:
3106
                from App import App
3107
                message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
3108
                                                              sys.exc_info()[-1].tb_lineno)
3109
                App.mainWnd().addMessage.emit(MessageType.Error, message)
3110

    
3111
    def get_opcs(self):
3112
        """ get opc in project """
3113
        configs = self.getConfigs('PSN', 'Symbols')
3114
        target = configs[0].value if configs else 'ALL'
3115

    
3116
        with self.project.database.connect() as conn:
3117
            try:
3118
                # Get a cursor object
3119
                cursor = conn.cursor()
3120

    
3121
                '''
3122
                if target == "ALL" or target == '':
3123
                    sql = "select (select Name from Drawings where UID=a.Drawings_UID) as Drawing," \
3124
                        "(select Value from Components where UID=a.Owner) as [Line No]," \
3125
                        "(select Name from Symbol where a.Symbol_UID=UID) as Symbol," \
3126
                        "(select stuff((select ',' + convert(NVARCHAR(10),[index]) from [Points] where Connected = a.UID for XML PAth('')),1,1,'')) as [Count]," \
3127
                        "UID as OPC from Components a " \
3128
                        "where Symbol_UID in (select UID from Symbol where SymbolType_UID in " \
3129
                        "(select UID from SymbolType where Type='Instrument OPC''s' or Type='Piping OPC''s'))"
3130
                else:
3131
                    sql = "select (select Name from Drawings where UID=a.Drawings_UID) as Drawing," \
3132
                        "(select Value from Components where UID=a.Owner) as [Line No]," \
3133
                        "(select Name from Symbol where a.Symbol_UID=UID) as Symbol," \
3134
                        "(select stuff((select ',' + convert(NVARCHAR(10),[index]) from [Points] where Connected = a.UID for XML PAth('')),1,1,'')) as [Count]," \
3135
                        "UID as OPC from Components a " \
3136
                        "where Symbol_UID in (" + target + ")"
3137
                '''
3138
                if target == "ALL" or target == '':
3139
                    sql = "select (select Name from Drawings where UID=a.Drawings_UID) as Drawing," \
3140
                        "(select Value from Components where UID=a.Owner) as [Line No]," \
3141
                        "(select Name from Symbol where a.Symbol_UID=UID) as Symbol," \
3142
                        "(select Count(1) from [Points] where Connected = a.UID) as [Count]," \
3143
                        "(select [Index] from [PipeRunItems] where Components_UID = a.UID) as [Index]," \
3144
                        "UID as OPC from Components a " \
3145
                        "where Symbol_UID in (select UID from Symbol where SymbolType_UID in " \
3146
                        "(select UID from SymbolType where Type='Instrument OPC''s' or Type='Piping OPC''s'))"
3147
                else:
3148
                    sql = "select (select Name from Drawings where UID=a.Drawings_UID) as Drawing," \
3149
                        "(select Value from Components where UID=a.Owner) as [Line No]," \
3150
                        "(select Name from Symbol where a.Symbol_UID=UID) as Symbol," \
3151
                        "(select Count(1) from [Points] where Connected = a.UID) as [Count]," \
3152
                        "(select [Index] from [PipeRunItems] where Components_UID = a.UID) as [Index]," \
3153
                        "UID as OPC from Components a " \
3154
                        "where Symbol_UID in (" + target + ")"
3155

    
3156
                cursor.execute(sql)
3157

    
3158
                rows = cursor.fetchall()
3159

    
3160
                opcs = []
3161
                if self.project.database.db_type == 'SQLite':
3162
                    for row in rows:
3163
                        #count = str(len(row["Count"].split(',')))
3164
                        opcs.append({ "Drawing":row["Drawing"], "Line No":row["Line No"], "Symbol":row["Symbol"], "Count":row["Count"], "OPC":row["OPC"], "Index": row["Index"]})
3165
                else:
3166
                    opcs = rows
3167

    
3168
                for opc in opcs:
3169
                    opc['Index'] = 0 if opc['Index'] == 1 else 1 # 0 : start with opc, 1 : end with opc
3170

    
3171
                return opcs
3172
                # Catch the exception
3173
            except Exception as ex:
3174
                from App import App
3175
                message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
3176
                                                              sys.exc_info()[-1].tb_lineno)
3177
                App.mainWnd().addMessage.emit(MessageType.Error, message)
3178

    
3179
    def get_opc_relations(self):
3180
        """ get opc relations """
3181
        conn = self.project.database.connect()
3182
        with conn:
3183
            try:
3184
                # Get a cursor object
3185
                cursor = conn.cursor()
3186

    
3187
                sql = "select (select Name from Drawings where UID=a.From_Drawings_UID) as From_Drawing,\
3188
                a.From_LineNo_UID as From_LineNo,\
3189
                a.From_OPC_UID,\
3190
                (select Name from Drawings where UID=a.To_Drawings_UID) as To_Drawing,\
3191
                a.To_LineNo_UID as To_LineNo,\
3192
                a.To_OPC_UID \
3193
                from OPCRelations a"
3194
                cursor.execute(sql)
3195
                return cursor.fetchall()
3196
                # Catch the exception
3197
            except Exception as ex:
3198
                from App import App
3199
                message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
3200
                                                              sys.exc_info()[-1].tb_lineno)
3201
                App.mainWnd().addMessage.emit(MessageType.Error, message)
3202

    
3203
    def save_opc_relations(self, opcs):
3204
        """ save opc relations """
3205
        conn = self.project.database.connect()
3206
        with conn:
3207
            try:
3208
                # Get a cursor object
3209
                cursor = conn.cursor()
3210
                sql = 'delete from OPCRelations'
3211
                cursor.execute(sql)
3212

    
3213
                for opc in opcs:
3214
                    sql = 'insert into OPCRelations(From_Drawings_UID,From_LineNo_UID,From_OPC_UID,To_Drawings_UID,To_LineNo_UID,To_OPC_UID) \
3215
                        values({},{},{},{},{},{})'.format(
3216
                        "(select UID from Drawings where Name='{}')".format(opc[0]),
3217
                        "'{}'".format(opc[1]) if opc[1] else 'null',
3218
                        "'{}'".format(opc[2]) if opc[2] else 'null',
3219
                        "(select UID from Drawings where Name='{}')".format(opc[3]) if opc[3] else 'null',
3220
                        "'{}'".format(opc[4]) if opc[4] else 'null',
3221
                        "'{}'".format(opc[5]) if opc[5] else 'null')
3222
                    cursor.execute(sql)
3223

    
3224
                conn.commit()
3225
            # Catch the exception
3226
            except Exception as ex:
3227
                conn.rollback()
3228

    
3229
                from App import App
3230
                message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
3231
                                                              sys.exc_info()[-1].tb_lineno)
3232
                App.mainWnd().addMessage.emit(MessageType.Error, message)
3233

    
3234
    def get_component_connectors(self, component):
3235
        """ get connectors of given component """
3236
        if self._connecterss and component in self._connecterss:
3237
            return self._connecterss[component]
3238

    
3239
        conn = self.project.database.connect()
3240
        with conn:
3241
            try:
3242
                # Get a cursor object
3243
                cursor = conn.cursor()
3244

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

    
3249
                pre = ''
3250
                rows = cursor.fetchall()
3251
                for row in rows:
3252
                    if pre != row['Components_UID']:
3253
                        if pre != '':
3254
                            self._connecterss[pre] = compo
3255
                        pre = row['Components_UID']
3256
                        compo = []
3257
                        compo.append(row)
3258
                        if row is rows[-1]:
3259
                            self._connecterss[row['Components_UID']] = compo
3260
                    else:
3261
                        compo.append(row)
3262
                        if row is rows[-1]:
3263
                            self._connecterss[row['Components_UID']] = compo
3264

    
3265
                return self._connecterss[component] if component in self._connecterss else []
3266
                # Catch the exception
3267
            except Exception as ex:
3268
                from App import App
3269
                message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
3270
                                                              sys.exc_info()[-1].tb_lineno)
3271
                App.mainWnd().addMessage.emit(MessageType.Error, message)
3272

    
3273
    def get_component_associations(self, component):
3274
        """ get associations of given component """
3275
        if self._associationss and component in self._associationss:
3276
            return self._associationss[component]
3277
        elif self._associationss:
3278
            return []
3279

    
3280
        conn = self.project.database.connect()
3281
        with conn:
3282
            try:
3283
                # Get a cursor object
3284
                cursor = conn.cursor()
3285

    
3286
                # sql = "select * from Associations where Components_UID='{}'".format(component)
3287
                sql = "select a.* from Associations a \
3288
                            join Components b on a.Components_UID=b.[UID] where Drawings_UID='{}' order by Components_UID".format(
3289
                    self.activeDrawing.UID)
3290
                cursor.execute(sql)
3291

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

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

    
3316
    def get_component_attributes(self, component):
3317
        """ get attributes of given component """
3318
        if self._attributess and component in self._attributess:
3319
            return self._attributess[component]
3320
        elif self._attributess:
3321
            return []
3322

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

    
3329
                sql = "select a.*, b.* from Attributes a \
3330
                            join SymbolAttribute b on a.SymbolAttribute_UID=b.UID \
3331
                            join Components c on a.Components_UID=c.UID \
3332
                        where Drawings_UID='{}' order by a.Components_UID, b.[index]".format(self.activeDrawing.UID)
3333
                cursor.execute(sql)
3334

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

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

    
3359
    def get_pipe_runs(self, component):
3360
        """ get line runs of given component """
3361
        conn = self.project.database.connect()
3362
        with conn:
3363
            try:
3364
                # Get a cursor object
3365
                cursor = conn.cursor()
3366

    
3367
                sql = "select * from PipeRuns where Owner='{}' order by [Index]".format(component)
3368
                cursor.execute(sql)
3369
                return cursor.fetchall()
3370
                # Catch the exception
3371
            except Exception as ex:
3372
                from App import App
3373
                message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
3374
                                                              sys.exc_info()[-1].tb_lineno)
3375
                App.mainWnd().addMessage.emit(MessageType.Error, message)
3376

    
3377
    def get_pipe_run_items(self, pipe_run):
3378
        """ get line run items of given pipe run """
3379
        conn = self.project.database.connect()
3380
        with conn:
3381
            try:
3382
                # Get a cursor object
3383
                cursor = conn.cursor()
3384

    
3385
                sql = "select * from PipeRunItems where PipeRuns_UID='{}' order by [Index]".format(pipe_run)
3386
                cursor.execute(sql)
3387
                return cursor.fetchall()
3388
                # Catch the exception
3389
            except Exception as ex:
3390
                from App import App
3391
                message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
3392
                                                              sys.exc_info()[-1].tb_lineno)
3393
                App.mainWnd().addMessage.emit(MessageType.Error, message)
3394

    
3395
    '''
3396
        @brief      get special item types from database
3397
        @author     humkyung
3398
        @date       2019.08.10
3399
    '''
3400
    def get_special_item_types(self):
3401
        conn = self.project.database.connect()
3402
        with conn:
3403
            try:
3404
                # Get a cursor object
3405
                cursor = conn.cursor()
3406

    
3407
                sql = 'select UID, Code, Type, Allowables from SpecialItemTypes order by Code DESC'
3408
                cursor.execute(sql)
3409
                return cursor.fetchall()
3410
                # Catch the exception
3411
            except Exception as ex:
3412
                from App import App
3413
                message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
3414
                                                              sys.exc_info()[-1].tb_lineno)
3415
                App.mainWnd().addMessage.emit(MessageType.Error, message)
3416

    
3417
    '''
3418
        @brief      save special item types
3419
        @author     humkyung
3420
        @date       2019.08.10
3421
    '''
3422
    def save_special_item_types(self, datas):
3423
        import uuid
3424

    
3425
        conn = self.project.database.connect()
3426
        with conn:
3427
            try:
3428
                # Get a cursor object
3429
                cursor = conn.cursor()
3430

    
3431
                for data in datas:
3432
                    uid, code, _type, allowables = data[0], data[1], data[2], data[3]
3433
                    if not uid:
3434
                        sql = self.project.database.to_sql(
3435
                            'insert into SpecialItemTypes(UID, Code, Type, Allowables) values(?, ?, ?, ?)')
3436
                        param = (str(uuid.uuid4()), data[1], data[2], data[3])
3437
                    elif uid == '-1':
3438
                        sql = self.project.database.to_sql('delete from SpecialItemTypes where uid=?')
3439
                        param = (data[-1],)
3440
                    else:
3441
                        sql = self.project.database.to_sql(
3442
                            'update SpecialItemTypes SET Code=?, Type=?, Allowables=? WHERE UID = ?')
3443
                        param = (data[1], data[2], data[3], data[0])
3444
                    cursor.execute(sql, param)
3445

    
3446
                conn.commit()
3447
            # Catch the exception
3448
            except Exception as ex:
3449
                # Roll back any change if something goes wrong
3450
                conn.rollback()
3451

    
3452
                from App import App
3453
                message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
3454
                                                              sys.exc_info()[-1].tb_lineno)
3455
                App.mainWnd().addMessage.emit(MessageType.Error, message)
3456

    
3457
    def get_special_items(self, drawings=None):
3458
        """ get special items from database """
3459
        result = []
3460

    
3461
        conn = self.project.database.connect()
3462
        with conn:
3463
            try:
3464
                # get a cursor object
3465
                cursor = conn.cursor()
3466

    
3467
                sql = 'select distinct (select Value from Components where UID=D.Owner) as "Line No",C.Code from Components A \
3468
                    left join Drawings B on A.Drawings_UID=B.UID \
3469
                    left join SpecialItemTypes C on A.SpecialItemTypes_UID=C.UID \
3470
                    left join Components D on A.Connected=D.UID \
3471
                    where A.SpecialItemTypes_UID is not null'
3472
                if drawings is not None:
3473
                    doc_names = "','".join(drawings)
3474
                    sql += f" and A.Drawings_UID in (select UID from Drawings where Name in ('{doc_names}'))"
3475
                sql += ' order by "Line No"'
3476
                cursor.execute(sql)
3477

    
3478
                return cursor.fetchall()
3479
            # catch the exception
3480
            except Exception as ex:
3481
                from App import App
3482
                message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
3483
                                                              sys.exc_info()[-1].tb_lineno)
3484
                App.mainWnd().addMessage.emit(MessageType.Error, message)
3485

    
3486
        return None
3487

    
3488
    '''
3489
        @brief      Set Common Code Data
3490
        @author     kyouho
3491
        @date       2018.07.12
3492
    '''
3493
    def saveCommonCodeData(self, tableName, datas):
3494
        import uuid
3495

    
3496
        conn = self.project.database.connect()
3497
        with conn:
3498
            try:
3499
                # Get a cursor object
3500
                cursor = conn.cursor()
3501

    
3502
                sql = self.project.database.to_sql('delete from {}'.format(tableName))
3503
                cursor.execute(sql)
3504

    
3505
                for data in datas:
3506
                    '''
3507
                    uid, code, description, allowables = data[0], data[1], data[2], data[3]
3508
                    if not uid:
3509
                        sql = self.project.database.to_sql(
3510
                            "insert into {}(UID, CODE, DESCRIPTION, ALLOWABLES) values(?, ?, ?, ?)".format(tableName))
3511
                        param = (str(uuid.uuid4()), data[1], data[2], data[3])
3512
                    elif uid == '-1':
3513
                        sql = self.project.database.to_sql('delete from {} where uid=?'.format(tableName))
3514
                        param = (data[-1],)
3515
                    else:
3516
                        sql = self.project.database.to_sql(
3517
                            "update {} SET CODE=?, DESCRIPTION=?, ALLOWABLES=? WHERE UID = ?".format(tableName))
3518
                        param = (data[1], data[2], data[3], data[0])
3519
                    cursor.execute(sql, param)
3520
                    '''
3521
                    if data[0]:
3522
                        uid = data[0]
3523
                    else:
3524
                        uid = str(uuid.uuid4())
3525
                    sql = self.project.database.to_sql(
3526
                        "insert into {}(UID, CODE, DESCRIPTION, ALLOWABLES) values(?, ?, ?, ?)".format(tableName))
3527
                    param = (uid, data[1], data[2], data[3])
3528
                    cursor.execute(sql, param)
3529

    
3530
                conn.commit()
3531
            # Catch the exception
3532
            except Exception as ex:
3533
                # Roll back any change if something goes wrong
3534
                conn.rollback()
3535

    
3536
                from App import App
3537
                message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
3538
                                                              sys.exc_info()[-1].tb_lineno)
3539
                App.mainWnd().addMessage.emit(MessageType.Error, message)
3540

    
3541
    def selectView(self):
3542
        """ get document name list """
3543
        result = []
3544

    
3545
        with self.project.database.connect() as conn:
3546
            try:
3547
                # Get a cursor object
3548
                cursor = conn.cursor()
3549

    
3550
                sql = "select * from T_PSN_VIEW"
3551
                cursor.execute(sql)
3552

    
3553
                rows = cursor.fetchall()
3554
                for row in rows:
3555
                    result.append(row['OID'])
3556

    
3557
                result.sort()
3558
            # Catch the exception
3559
            except Exception as ex:
3560
                print('error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
3561
                                                          sys.exc_info()[-1].tb_lineno))
3562

    
3563
        return result
3564

    
3565
    '''
3566
        @brief      Set Common Code Data
3567
        @author     kyouho
3568
        @date       2018.07.12
3569
    '''
3570
    def deleteCommonCodeData(self, datas):
3571
        try:
3572
            conn = self.project.database.connect()
3573
            with conn:
3574
                # Get a cursor object
3575
                cursor = conn.cursor()
3576

    
3577
                for data in datas:
3578
                    uid = data[0]
3579
                    tableName = data[1]
3580

    
3581
                    if uid:
3582
                        sql = "delete from {} where UID = ?".format(tableName)
3583
                        param = (uid,)
3584
                        cursor.execute(sql, param)
3585

    
3586
                    cursor.execute(sql, param)
3587

    
3588
                conn.commit()
3589

    
3590
        # Catch the exception
3591
        except Exception as ex:
3592
            # Roll back any change if something goes wrong
3593
            conn.rollback()
3594

    
3595
            from App import App
3596
            message = f"error occurred({repr(ex)}) in {sys.exc_info()[-1].tb_frame.f_code.co_filename}:" \
3597
                        f"{sys.exc_info()[-1].tb_lineno}"
3598
            App.mainWnd().addMessage.emit(MessageType.Error, message)
3599

    
3600
    '''
3601
        @brief      delete data list
3602
        @author     kyouho
3603
        @date       2018.08.16
3604
    '''
3605
    def deleteDataList(self, tableName, UID):
3606
        conn = self.project.database.connect()
3607
        with conn:
3608
            try:
3609
                # Get a cursor object
3610
                cursor = conn.cursor()
3611
                sql = 'delete from {} where UID = {}'.format(tableName, UID)
3612
                cursor.execute(sql)
3613
                conn.commit()
3614

    
3615
            # Catch the exception
3616
            except Exception as ex:
3617
                # Roll back any change if something goes wrong
3618
                conn.rollback()
3619

    
3620
                from App import App
3621
                message = f"error occurred({repr(ex)}) in {sys.exc_info()[-1].tb_frame.f_code.co_filename}:" \
3622
                          f"{sys.exc_info()[-1].tb_lineno}"
3623
                App.mainWnd().addMessage.emit(MessageType.Error, message)
3624

    
3625
    def get_document_name_list(self):
3626
        """ get document name list """
3627
        result = []
3628

    
3629
        with self.project.database.connect() as conn:
3630
            try:
3631
                # Get a cursor object
3632
                cursor = conn.cursor()
3633

    
3634
                sql = "select distinct B.Name as 'Drawing_Name' from Components A join Drawings B on " \
3635
                      "A.Drawings_UID=B.UID"
3636
                cursor.execute(sql)
3637

    
3638
                rows = cursor.fetchall()
3639
                for row in rows:
3640
                    result.append(row['Drawing_Name'])
3641

    
3642
                result.sort()
3643
            # Catch the exception
3644
            except Exception as ex:
3645
                print('error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
3646
                                                          sys.exc_info()[-1].tb_lineno))
3647

    
3648
        return result
3649

    
3650
    '''
3651
        @brief      get line documentName list
3652
        @author     kyouho
3653
        @date       2018.08.13
3654
    '''
3655
    def getLineDocumentNameList(self):
3656
        result = []
3657

    
3658
        conn = self.project.database.connect()
3659
        with conn:
3660
            try:
3661
                # Get a cursor object
3662
                cursor = conn.cursor()
3663

    
3664
                sql = 'select DISTINCT(PNID_NO) from LINE_DATA_LIST'
3665

    
3666
                cursor.execute(sql)
3667
                rows = cursor.fetchall()
3668
                for row in rows:
3669
                    result.append(row[0])
3670
            # Catch the exception
3671
            except Exception as ex:
3672
                print('error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
3673
                                                          sys.exc_info()[-1].tb_lineno))
3674

    
3675
        return result
3676

    
3677
    '''
3678
        @brief      get line data list
3679
        @author     kyouho
3680
        @date       2018.08.13
3681
    '''
3682
    def get_line_data_list(self, drawings=None):
3683
        result = []
3684

    
3685
        with self.project.database.connect() as conn:
3686
            try:
3687
                # Get a cursor object
3688
                cursor = conn.cursor()
3689

    
3690
                '''
3691
                sql = 'select A.UID,B.Name,A.Value as [Line No] from Components A left join Drawings B on A.Drawings_UID=B.UID'
3692
                if drawings is not None:
3693
                    doc_names = "','".join(drawings)
3694
                    sql += f" where A.Symbol_UID=1 and Drawings_UID in (select UID from Drawings where Name in ('{doc_names}'))"
3695
                cursor.execute(sql)
3696
                comps = [(row['UID'], row['Name'], row['Line No']) for row in cursor.fetchall()]
3697
                for comp in comps:
3698
                    sql = f"select b.Name,a.Value from LineNoAttributes a left join LineProperties b " \
3699
                          f"on a.LineProperties_UID=b.UID where a.Components_UID='{comp[0]}'"
3700
                    cursor.execute(sql)
3701
                    attrs = cursor.fetchall()
3702
                    data = []
3703
                    for attr in attrs:
3704
                        data.append([attr['Name'], attr['Value']])
3705
                    if data:
3706
                        data.insert(0, ['Drawing Name', comp[1]])
3707
                        data.insert(0, ['UID', comp[0]])
3708
                        data.insert(0, ['Line No', comp[2]])
3709
                        result.append(data)
3710
                '''
3711

    
3712
                sql = 'select A.UID,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 \
3713
                        left join LineNoAttributes C on A.[UID]=C.Components_UID left join LineProperties D on C.LineProperties_UID=D.UID'
3714
                if drawings is not None:
3715
                    doc_names = "','".join(drawings)
3716
                    sql += f" where A.Symbol_UID=1 and Drawings_UID in (select UID from Drawings where Name in ('{doc_names}'))"
3717
                cursor.execute(sql)
3718

    
3719
                comps = [[row['UID'], row['Name'], row['Line No'], row['AttrN'], row['AttrV']] for row in cursor.fetchall()]
3720
                lineNos = {}
3721

    
3722
                for comp in comps:
3723
                    if comp[0] not in lineNos:
3724
                        lineNos[comp[0]] = [['Line No', comp[2]], ['UID', comp[0]], ['Drawing Name', comp[1]]]
3725
                    lineNos[comp[0]].append([comp[3], comp[4]])
3726

    
3727
                result = list(lineNos.values())
3728

    
3729
            # catch the exception
3730
            except Exception as ex:
3731
                print('error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
3732
                                                          sys.exc_info()[-1].tb_lineno))
3733

    
3734
        return result
3735

    
3736
    def get_equipment_data_list(self, drawings=None):
3737
        """ get equipment data list """
3738

    
3739
        result = []
3740

    
3741
        with self.project.database.connect() as conn:
3742
            try:
3743
                # Get a cursor object
3744
                cursor = conn.cursor()
3745

    
3746
                sql = "select A.UID,B.NAME,C.SymbolType_UID,D.Type,C.NAME as symbol from Components A join Drawings B on A.Drawings_UID=B.UID\
3747
                        join Symbol C on A.Symbol_UID=C.UID\
3748
                        join SymbolType D on C.SymbolType_UID=D.UID\
3749
                        where (D.Category in ('Equipment') or A.Symbol_UID=7)"#,'Equipment Components')"
3750

    
3751
                if drawings is not None:
3752
                    doc_names = "','".join(drawings)
3753
                    sql += f" and A.Drawings_UID in (select UID from Drawings where Name in ('{doc_names}'))"
3754

    
3755
                cursor.execute(sql)
3756
                comps = [(row['UID'], row['NAME'], row['SymbolType_UID'], row['Type'], row['symbol']) for row in cursor.fetchall()]
3757
                for comp in comps:
3758
                    sql = f"select distinct B.Attribute,A.Value from Attributes A left join SymbolAttribute B on " \
3759
                          f"A.SymbolAttribute_UID=B.UID where A.Components_UID='{comp[0]}'"
3760
                    cursor.execute(sql)
3761
                    attrs = cursor.fetchall()
3762
                    data = []
3763
                    for attr in attrs:
3764
                        data.append([attr['Attribute'], attr['Value']])
3765
                    if data:
3766
                        data.insert(0, ['Type', comp[3]])
3767
                        data.insert(0, ['Drawing Name', comp[1]])
3768
                        data.insert(0, ['ITEM_NO', comp[4]])
3769
                        data.insert(0, ['UID', comp[0]])
3770
                        result.append(data)
3771

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

    
3777
        return result
3778

    
3779
    '''
3780
        @brief      set line data list
3781
        @author     kyouho
3782
        @date       2018.08.13
3783
    '''
3784
    def setLineDataList(self, dataLists):
3785
        conn = self.project.database.connect()
3786
        with conn:
3787
            try:
3788
                # Get a cursor object
3789
                cursor = conn.cursor()
3790

    
3791
                for data in dataLists:
3792
                    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(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"
3793
                    param = tuple(data)
3794
                    cursor.execute(sql, param)
3795

    
3796
                conn.commit()
3797

    
3798
            # Catch the exception
3799
            except Exception as ex:
3800
                # Roll back any change if something goes wrong
3801
                conn.rollback()
3802

    
3803
                from App import App
3804
                message = f"error occurred({repr(ex)}) in {sys.exc_info()[-1].tb_frame.f_code.co_filename}:" \
3805
                          f"{sys.exc_info()[-1].tb_lineno}"
3806
                App.mainWnd().addMessage.emit(MessageType.Error, message)
3807

    
3808
    '''
3809
        @brief      delete line data list
3810
        @author     kyouho
3811
        @date       2018.08.13
3812
    '''
3813
    def deleteLineDataList(self, removeUID):
3814
        conn = self.project.database.connect()
3815
        with conn:
3816
            try:
3817
                # Get a cursor object
3818
                cursor = conn.cursor()
3819

    
3820
                for uid in removeUID:
3821
                    sql = "delete from LINE_DATA_LIST where uid = '{}'".format(uid)
3822
                    cursor.execute(sql)
3823

    
3824
                conn.commit()
3825

    
3826
            # Catch the exception
3827
            except Exception as ex:
3828
                # Roll back any change if something goes wrong
3829
                conn.rollback()
3830

    
3831
                from App import App
3832
                message = f"error occurred({repr(ex)}) in {sys.exc_info()[-1].tb_frame.f_code.co_filename}:" \
3833
                          f"{sys.exc_info()[-1].tb_lineno}"
3834
                App.mainWnd().addMessage.emit(MessageType.Error, message)
3835

    
3836
    '''
3837
        @brief      delete line data list
3838
        @author     kyouho
3839
        @date       2018.08.13
3840
    '''
3841
    def deleteLineDataList_LineNo(self, removeUID):
3842
        conn = self.project.database.connect()
3843
        with conn:
3844
            try:
3845
                # Get a cursor object
3846
                cursor = conn.cursor()
3847

    
3848
                for uid in removeUID:
3849
                    sql = "delete from LINE_DATA_LIST where LINE_NO = ?"
3850
                    param = (uid,)
3851
                    cursor.execute(sql, param)
3852

    
3853
                conn.commit()
3854

    
3855
            # Catch the exception
3856
            except Exception as ex:
3857
                # Roll back any change if something goes wrong
3858
                conn.rollback()
3859

    
3860
                from App import App
3861
                message = f"error occurred({repr(ex)}) in {sys.exc_info()[-1].tb_frame.f_code.co_filename}:" \
3862
                          f"{sys.exc_info()[-1].tb_lineno}"
3863
                App.mainWnd().addMessage.emit(MessageType.Error, message)
3864

    
3865
    '''
3866
        @brief      delete equip data list
3867
        @author     kyouho
3868
        @date       2018.08.14
3869
    '''
3870
    def deleteEquipDataList(self, removeUID):
3871
        conn = self.project.database.connect()
3872
        with conn:
3873
            try:
3874
                # Get a cursor object
3875
                cursor = conn.cursor()
3876

    
3877
                for uid in removeUID:
3878
                    sql = "delete from EQUIPMENT_DATA_LIST where uid = '{}'".format(uid)
3879
                    cursor.execute(sql)
3880

    
3881
                conn.commit()
3882

    
3883
            # Catch the exception
3884
            except Exception as ex:
3885
                # Roll back any change if something goes wrong
3886
                conn.rollback()
3887

    
3888
                from App import App
3889
                message = f"error occurred({repr(ex)}) in {sys.exc_info()[-1].tb_frame.f_code.co_filename}:" \
3890
                          f"{sys.exc_info()[-1].tb_lineno}"
3891
                App.mainWnd().addMessage.emit(MessageType.Error, message)
3892

    
3893
    '''
3894
        @brief      delete inst data list
3895
        @author     kyouho
3896
        @date       2018.08.14
3897
    '''
3898
    def deleteInstDataList(self, removeUID):
3899
        conn = self.project.database.connect()
3900
        with conn:
3901
            try:
3902
                # Get a cursor object
3903
                cursor = conn.cursor()
3904

    
3905
                for uid in removeUID:
3906
                    sql = "delete from INSTRUMENT_DATA_LIST where uid = '{}'".format(uid)
3907
                    cursor.execute(sql)
3908

    
3909
                conn.commit()
3910

    
3911
            # Catch the exception
3912
            except Exception as ex:
3913
                # Roll back any change if something goes wrong
3914
                conn.rollback()
3915

    
3916
                from App import App
3917
                message = f"error occurred({repr(ex)}) in {sys.exc_info()[-1].tb_frame.f_code.co_filename}:" \
3918
                          f"{sys.exc_info()[-1].tb_lineno}"
3919
                App.mainWnd().addMessage.emit(MessageType.Error, message)
3920

    
3921
    '''
3922
        @brief      delete note data list
3923
        @author     kyouho
3924
        @date       2018.10.10
3925
    '''
3926
    def deleteNoteDataList(self, removeUID):
3927
        conn = self.project.database.connect()
3928
        with conn:
3929
            try:
3930
                # Get a cursor object
3931
                cursor = conn.cursor()
3932

    
3933
                for uid in removeUID:
3934
                    sql = "delete from NOTE_DATA_LIST where uid = '{}'".format(uid)
3935
                    cursor.execute(sql)
3936

    
3937
                conn.commit()
3938

    
3939
            # Catch the exception
3940
            except Exception as ex:
3941
                # Roll back any change if something goes wrong
3942
                conn.rollback()
3943

    
3944
                from App import App
3945
                message = f"error occurred({repr(ex)}) in {sys.exc_info()[-1].tb_frame.f_code.co_filename}:" \
3946
                          f"{sys.exc_info()[-1].tb_lineno}"
3947
                App.mainWnd().addMessage.emit(MessageType.Error, message)
3948

    
3949
    def get_valve_attributes(self):
3950
        """ return valve attributes """
3951

    
3952
        from SymbolAttr import SymbolAttr
3953

    
3954
        res = None
3955
        if not hasattr(self, '_valve_attributes'):
3956
            self._valve_attributes = []
3957

    
3958
            with self.project.database.connect() as conn:
3959
                try:
3960
                    # Get a cursor object
3961
                    cursor = conn.cursor()
3962

    
3963
                    sql = "select distinct A.Attribute from SymbolAttribute A join SymbolType B on " \
3964
                          "A.SymbolType_UID=B.UID where B.Category = 'Piping'"
3965
                    cursor.execute(sql)
3966
                    rows = cursor.fetchall()
3967
                    for row in rows:
3968
                        attr = SymbolAttr()
3969
                        attr.Attribute = row['Attribute']
3970
                        self._valve_attributes.append(attr)
3971

    
3972
                    res = self._valve_attributes
3973
                # Catch the exception
3974
                except Exception as ex:
3975
                    from App import App
3976
                    message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
3977
                                                                sys.exc_info()[-1].tb_lineno)
3978
                    App.mainWnd().addMessage.emit(MessageType.Error, message)
3979
        else:
3980
            res = self._valve_attributes
3981

    
3982
        return res
3983

    
3984
    def get_valve_data_list(self, drawings=None):
3985
        """get valve data list"""
3986

    
3987
        result = []
3988
        conn = self.project.database.connect()
3989
        with conn:
3990
            try:
3991
                # Get a cursor object
3992
                cursor = conn.cursor()
3993

    
3994
                sql = "select a.UID,D.Name,E.Name as 'Drawing Name',C.Attribute,B.Value,a.[Owner] from Components a " \
3995
                      "join Attributes B on a.UID=B.Components_UID " \
3996
                      "join SymbolAttribute C on B.SymbolAttribute_UID=C.UID " \
3997
                      "join Symbol D on a.Symbol_UID=D.UID " \
3998
                      "join Drawings E on a.Drawings_UID=E.UID " \
3999
                      "where a.Symbol_UID in (select UID from Symbol where SymbolType_UID in " \
4000
                      "(select UID from SymbolType where Category in ('Piping')))"
4001
                if drawings is not None:
4002
                    doc_names = "','".join(drawings)
4003
                    sql += f" and A.Drawings_UID in (select UID from Drawings where Name in ('{doc_names}'))"
4004

    
4005
                cursor.execute(sql)
4006
                rows = cursor.fetchall()
4007
                '''
4008
                for row in rows:
4009
                    matches = [res for res in result if res['UID'] == row['UID']]
4010
                    if matches:
4011
                        matches[0][row['Attribute']] = row['Value']
4012
                    else:
4013
                        data = {'UID': row['UID'], 'ITEM_NO': row['Name'], 'Drawing Name': row['Drawing Name'],
4014
                                'Owner': row['Owner'], row['Attribute']: row['Value']}
4015
                        result.append(data)
4016

4017
                '''
4018
                valves = {}
4019

    
4020
                for row in rows:
4021
                    if row['UID'] not in valves:
4022
                        valves[row['UID']] = {'UID': row['UID'], 'ITEM_NO': row['Name'], 'Drawing Name': row['Drawing Name'],
4023
                                'Owner': row['Owner']}
4024
                    valves[row['UID']][row['Attribute']] = row['Value']
4025

    
4026
                result = list(valves.values())
4027

    
4028
            # Catch the exception
4029
            except Exception as ex:
4030
                from App import App
4031
                message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
4032
                                                              sys.exc_info()[-1].tb_lineno)
4033
                App.mainWnd().addMessage.emit(MessageType.Error, message)
4034

    
4035
        return result
4036

    
4037
    def get_instrument_attributes(self):
4038
        """ return valve attributes """
4039

    
4040
        from SymbolAttr import SymbolAttr
4041

    
4042
        res = None
4043
        if not hasattr(self, '_inst_attributes'):
4044
            self._inst_attributes = []
4045

    
4046
            with self.project.database.connect() as conn:
4047
                try:
4048
                    # Get a cursor object
4049
                    cursor = conn.cursor()
4050

    
4051
                    sql = "select distinct A.Attribute from SymbolAttribute A join SymbolType B on " \
4052
                          "A.SymbolType_UID=B.UID where B.Category = 'Instrumentation'"
4053
                    cursor.execute(sql)
4054
                    rows = cursor.fetchall()
4055
                    for row in rows:
4056
                        attr = SymbolAttr()
4057
                        attr.Attribute = row['Attribute']
4058
                        self._inst_attributes.append(attr)
4059

    
4060
                    res = self._inst_attributes
4061
                # Catch the exception
4062
                except Exception as ex:
4063
                    from App import App
4064
                    message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
4065
                                                                sys.exc_info()[-1].tb_lineno)
4066
                    App.mainWnd().addMessage.emit(MessageType.Error, message)
4067
        else:
4068
            res = self._inst_attributes
4069

    
4070
        return res
4071

    
4072
    '''
4073
        @brief      get instrument data list
4074
        @author     kyouho
4075
        @date       2018.08.14
4076
    '''
4077
    def get_instrument_data_list(self, drawings=None):
4078
        result = []
4079
        conn = self.project.database.connect()
4080
        with conn:
4081
            try:
4082
                # Get a cursor object
4083
                cursor = conn.cursor()
4084

    
4085
                sql = "select a.UID,D.Name,E.Name as 'Drawing Name',C.Attribute,B.Value,a.Symbol_UID,a.[Owner] from Components a " \
4086
                      "join Attributes B on a.UID=B.Components_UID " \
4087
                      "join SymbolAttribute C on B.SymbolAttribute_UID=C.UID " \
4088
                      "join Symbol D on a.Symbol_UID=D.UID " \
4089
                      "join Drawings E on a.Drawings_UID=E.UID " \
4090
                      "where a.Symbol_UID in (select UID from Symbol where SymbolType_UID in " \
4091
                      "(select UID from SymbolType where Category in ('Instrumentation')))"
4092
                if drawings is not None:
4093
                    doc_names = "','".join(drawings)
4094
                    sql += f" and A.Drawings_UID in (select UID from Drawings where Name in ('{doc_names}'))"
4095

    
4096
                cursor.execute(sql)
4097
                rows = cursor.fetchall()
4098
                '''
4099
                for row in rows:
4100
                    matches = [res for res in result if res['UID'] == row['UID']]
4101
                    if matches:
4102
                        matches[0][row['Attribute']] = row['Value']
4103
                    else:
4104
                        data = {'UID': row['UID'], 'ITEM_NO': row['Name'], 'Drawing Name': row['Drawing Name'], 'Owner': row['Owner'], 
4105
                                'Symbol_UID': int(row['Symbol_UID']), row['Attribute']: row['Value']}
4106
                        result.append(data)
4107
                '''
4108
                insts = {}
4109

    
4110
                for row in rows:
4111
                    if row['UID'] not in insts:
4112
                        insts[row['UID']] = {'UID': row['UID'], 'ITEM_NO': row['Name'], 'Drawing Name': row['Drawing Name'], 'Owner': row['Owner'], 
4113
                                'Symbol_UID': int(row['Symbol_UID'])}
4114
                    insts[row['UID']][row['Attribute']] = row['Value']
4115

    
4116
                result = list(insts.values())
4117
            # Catch the exception
4118
            except Exception as ex:
4119
                from App import App
4120
                message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
4121
                                                              sys.exc_info()[-1].tb_lineno)
4122
                App.mainWnd().addMessage.emit(MessageType.Error, message)
4123

    
4124
        return result
4125

    
4126
    def get_note_attributes(self):
4127
        """ return note attributes """
4128

    
4129
        from SymbolAttr import SymbolAttr
4130

    
4131
        res = None
4132
        if not hasattr(self, '_note_attributes'):
4133
            self._note_attributes = []
4134

    
4135
            with self.project.database.connect() as conn:
4136
                try:
4137
                    # Get a cursor object
4138
                    cursor = conn.cursor()
4139

    
4140
                    sql = "select distinct A.Attribute from SymbolAttribute A join SymbolType B on " \
4141
                          "A.SymbolType_UID=B.UID where B.Category='General' and B.Type='Notes'"
4142
                    cursor.execute(sql)
4143
                    rows = cursor.fetchall()
4144
                    for row in rows:
4145
                        attr = SymbolAttr()
4146
                        attr.Attribute = row['Attribute']
4147
                        self._note_attributes.append(attr)
4148

    
4149
                    res = self._note_attributes
4150
                # Catch the exception
4151
                except Exception as ex:
4152
                    from App import App
4153
                    message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
4154
                                                                sys.exc_info()[-1].tb_lineno)
4155
                    App.mainWnd().addMessage.emit(MessageType.Error, message)
4156
        else:
4157
            res = self._note_attributes
4158

    
4159
        return res
4160

    
4161
    def get_note_data_list(self, drawings=None):
4162
        """ get note data list """
4163
        result = []
4164

    
4165
        conn = self.project.database.connect()
4166
        with conn:
4167
            try:
4168
                # Get a cursor object
4169
                cursor = conn.cursor()
4170

    
4171
                sql = "select a.UID,D.Name,E.Name as 'Drawing Name',C.Attribute,B.Value from Components a " \
4172
                      "join Attributes B on a.UID=B.Components_UID " \
4173
                      "join SymbolAttribute C on B.SymbolAttribute_UID=C.UID " \
4174
                      "join Symbol D on a.Symbol_UID=D.UID " \
4175
                      "join Drawings E on a.Drawings_UID=E.UID " \
4176
                      "where a.Symbol_UID in (select UID from Symbol where SymbolType_UID in " \
4177
                      "(select UID from SymbolType where Category='General' and Type='Notes'))"
4178
                if drawings is not None:
4179
                    doc_names = "','".join(drawings)
4180
                    sql += f" and A.Drawings_UID in (select UID from Drawings where Name in ('{doc_names}'))"
4181

    
4182
                cursor.execute(sql)
4183
                rows = cursor.fetchall()
4184
                for row in rows:
4185
                    matches = [res for res in result if res['UID'] == row['UID']]
4186
                    if matches:
4187
                        matches[0][row['Attribute']] = row['Value']
4188
                    else:
4189
                        data = {'UID': row['UID'], 'ITEM_NO': row['Name'], 'Drawing Name': row['Drawing Name'],
4190
                                row['Attribute']: row['Value']}
4191
                        result.append(data)
4192
            # Catch the exception
4193
            except Exception as ex:
4194
                from App import App
4195
                message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
4196
                                                              sys.exc_info()[-1].tb_lineno)
4197
                App.mainWnd().addMessage.emit(MessageType.Error, message)
4198

    
4199
        return result
4200

    
4201
    def clearAllDrawingDataFromDatabase(self):
4202
        """ clear all drawing data from database """
4203

    
4204
        sql = ''
4205

    
4206
        with self.project.database.connect() as conn:
4207
            try:
4208
                # Get a cursor object
4209
                cursor = conn.cursor()
4210

    
4211
                sql = "delete from LINE_DATA_LIST"
4212
                cursor.execute(sql)
4213
                sql = "delete from TitleBlockValues"
4214
                cursor.execute(sql)
4215
                sql = "delete from LineNoAttributes"
4216
                cursor.execute(sql)
4217
                sql = "delete from Attributes"
4218
                cursor.execute(sql)
4219
                sql = "delete from Associations"
4220
                cursor.execute(sql)
4221
                sql = "delete from Points"
4222
                cursor.execute(sql)
4223
                sql = "delete from PipeRunItems"
4224
                cursor.execute(sql)
4225
                sql = "delete from PipeRuns"
4226
                cursor.execute(sql)
4227
                sql = "delete from Components"
4228
                cursor.execute(sql)
4229
                sql = "delete from Stream_Line_List"
4230
                cursor.execute(sql)
4231
                sql = "delete from [Views]"
4232
                cursor.execute(sql)
4233
                sql = "delete from Drawings"
4234
                cursor.execute(sql)
4235

    
4236
                """
4237
                for drawing in drawings:
4238
                    sql = "delete from LINE_DATA_LIST where PNID_NO = '{}'".format(drawing.UID)
4239
                    cursor.execute(sql)
4240
                    sql = "delete from TitleBlockValues where Drawings_UID = '{}'".format(drawing.UID)
4241
                    cursor.execute(sql)
4242
                    sql = f"delete from LineNoAttributes where Components_UID in " \
4243
                                f"(select UID from Components where Drawings_UID='{drawing.UID}')"
4244
                    cursor.execute(sql)
4245
                    sql = f"delete from Attributes where Components_UID in " \
4246
                                f"(select UID from Components where Drawings_UID='{drawing.UID}')"
4247
                    cursor.execute(sql)
4248
                    sql = f"delete from Associations where Components_UID in " \
4249
                                f"(select UID from Components where Drawings_UID='{drawing.UID}')"
4250
                    cursor.execute(sql)
4251
                    sql = f"delete from Points where Components_UID in " \
4252
                                f"(select UID from Components where Drawings_UID='{drawing.UID}')"
4253
                    cursor.execute(sql)
4254
                    sql = f"delete from PipeRunItems where PipeRuns_UID in " \
4255
                                f"(select UID from PipeRuns where Drawings_UID='{drawing.UID}')"
4256
                    cursor.execute(sql)
4257
                    sql = f"delete from PipeRuns where Drawings_UID='{drawing.UID}'"
4258
                    cursor.execute(sql)
4259
                    sql = "delete from Components where Drawings_UID='{}'".format(drawing.UID)
4260
                    cursor.execute(sql)
4261
                    sql = "delete from Stream_Line_List where Drawing_UID='{}'".format(drawing.UID)
4262
                    cursor.execute(sql)
4263
                    sql = "delete from [Views] where Drawings_UID='{}'".format(drawing.UID)
4264
                    cursor.execute(sql)
4265
                    sql = "delete from Drawings where [UID]='{}'".format(drawing.UID)
4266
                    cursor.execute(sql)
4267

4268
                    # multi table delete not support in mssql
4269
                    ''' 
4270
                    sql = f"delete LINE_DATA_LIST, TitleBlockValues, LineNoAttributes, Attributes, Associations, Points, PipeRunItems, PipeRuns, Components, Stream_Line_List, [Views], Drawings " \
4271
                            f"from LINE_DATA_LIST a " \
4272
                            f"join TitleBlockValues b on a.PNID_NO = b.Drawings_UID " \
4273
                            f"join LineNoAttributes c on b.Drawings_UID = c.Drawings_UID " \
4274
                            f"join Attributes d on c.Drawings_UID = d.Drawings_UID " \
4275
                            f"join Associations e on d.Drawings_UID = e.Drawings_UID " \
4276
                            f"join Points f on e.Drawings_UID = f.Drawings_UID " \
4277
                            f"join PipeRunItems g on f.Drawings_UID = g.Drawings_UID " \
4278
                            f"join PipeRuns h on g.Drawings_UID = h.Drawings_UID " \
4279
                            f"join Components i on h.Drawings_UID = i.Drawings_UID " \
4280
                            f"join Stream_Line_List j on i.Drawings_UID = j.Drawing_UID " \
4281
                            f"join [Views] k on j.Drawing_UID = k.Drawings_UID " \
4282
                            f"join Drawings l on k.Drawings_UID = l.[UID] " \
4283
                            f"where l.[uid] = '{drawing.UID}'"
4284
                    cursor.execute(sql)
4285
                    '''
4286
                """
4287

    
4288
                if self.project.database.db_type == 'SQLite':
4289
                    cursor.execute('commit')
4290
                else:
4291
                    conn.commit()
4292

    
4293
                # Catch the exception
4294
            except Exception as ex:
4295
                # Roll back any change if something goes wrong
4296
                conn.rollback()
4297

    
4298
                from App import App
4299
                message = 'error occurred({}\\n{}) in {}:{}'.format(repr(ex), sql,
4300
                                                                    sys.exc_info()[-1].tb_frame.f_code.co_filename,
4301
                                                                    sys.exc_info()[-1].tb_lineno)
4302
                App.mainWnd().addMessage.emit(MessageType.Error, message)
4303

    
4304
    def checkDatabaseCascade(self):
4305
        if self.project.database.db_type == 'SQLite':
4306
            return True
4307
        
4308
        #configs = self.getConfigs('Database', 'Cascade')
4309
        #if 1 == len(configs):
4310
        #    return True
4311
        
4312
        with self.project.database.connect() as conn:
4313
            try:
4314
                # Get a cursor object
4315
                cursor = conn.cursor()
4316
                sql = "select * from INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS where DELETE_RULE ='CASCADE'"
4317
                cursor.execute(sql)
4318
                rows = cursor.fetchall()
4319
                if rows:
4320
                    return True
4321
                else:
4322
                    return False
4323

    
4324
            # Catch the exception
4325
            except Exception as ex:
4326
                from App import App
4327
                message = f"error occurred({repr(ex)}) in {sys.exc_info()[-1].tb_frame.f_code.co_filename}:" \
4328
                          f"{sys.exc_info()[-1].tb_lineno}"
4329
                App.mainWnd().addMessage.emit(MessageType.Error, message)
4330
        
4331
        return False
4332

    
4333
    def setDatabaseCascade(self):
4334
        # temp not finished
4335
        with self.project.database.connect() as conn:
4336
            try:
4337
                # Get a cursor object
4338
                cursor = conn.cursor()
4339
                sql = "select * from INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS "
4340
                cursor.execute(sql)
4341
                rows = cursor.fetchall()
4342
                if rows:
4343
                    return True
4344
                else:
4345
                    return False
4346

    
4347
            # Catch the exception
4348
            except Exception as ex:
4349
                # Roll back any change if something goes wrong
4350
                conn.rollback()
4351

    
4352
                from App import App
4353
                message = 'error occurred({}\\n{}) in {}:{}'.format(repr(ex), sql,
4354
                                                                    sys.exc_info()[-1].tb_frame.f_code.co_filename,
4355
                                                                    sys.exc_info()[-1].tb_lineno)
4356
                App.mainWnd().addMessage.emit(MessageType.Error, message)
4357

    
4358

    
4359
    def saveToDatabase(self, items, rect: QRectF, show_progress=None):
4360
        """ save given items to database """
4361
        import uuid
4362

    
4363
        # delete all datas of current drawing
4364
        drawing_name = self.activeDrawing.name
4365
        drawing_uid = self.activeDrawing.UID
4366
        sql = ''
4367

    
4368
        isCascade = self.checkDatabaseCascade()
4369

    
4370
        queries = {'first': [], 'second': []}
4371
        for item in items:
4372
            if hasattr(item, 'toSql_return_separately'):
4373
                sql, sqlLater = item.toSql_return_separately()
4374
                queries['first'].append(sql)
4375
                queries['second'].append(sqlLater)
4376
            else:
4377
                queries['first'].append(item.toSql())
4378

    
4379
        """
4380
        # Drawing Cascade test
4381
        if self.project.database.db_type != 'SQLite':
4382
            ''' update drawing's modified time for MSSQL '''
4383
            drawings = self.getDrawings()
4384
            drawing = [drawing for drawing in drawings if self.imgName == os.path.splitext(drawing.name)[0]]
4385
            if drawing[0]:
4386
                drawing[0].datetime = datetime.now().strftime('%Y-%m-%d %H:%M:%S')
4387

4388
            ''' hmb backup '''
4389
            #from_to = self.get_stream_from_to(drawing_uid = self.activeDrawing.UID)
4390
        """
4391

    
4392
        with self.project.database.connect() as conn:
4393
            try:
4394
                # Get a cursor object
4395
                cursor = conn.cursor()
4396
                if self.project.database.db_type == 'SQLite':
4397
                    #import timeit
4398
                    #_start = timeit.default_timer()
4399
                    cursor.execute('begin')
4400

    
4401
                    sql = "delete from LINE_DATA_LIST where PNID_NO = '{}'".format(drawing_name)
4402
                    cursor.execute(sql)
4403

    
4404
                    sql = "delete from TitleBlockValues where Drawings_UID = '{}'".format(drawing_uid)
4405
                    cursor.execute(sql)
4406

    
4407
                    # delete LineNoAttributes
4408
                    sql = f"delete from LineNoAttributes where Components_UID in " \
4409
                        f"(select UID from Components where Drawings_UID='{drawing_uid}')"
4410
                    cursor.execute(sql)
4411

    
4412
                    # delete Attributes
4413
                    sql = f"delete from Attributes where Components_UID in " \
4414
                        f"(select UID from Components where Drawings_UID='{drawing_uid}')"
4415
                    cursor.execute(sql)
4416

    
4417
                    # delete Associations
4418
                    sql = f"delete from Associations where Components_UID in " \
4419
                        f"(select UID from Components where Drawings_UID='{drawing_uid}')"
4420
                    cursor.execute(sql)
4421

    
4422
                    # delete Points
4423
                    sql = f"delete from Points where Components_UID in " \
4424
                        f"(select UID from Components where Drawings_UID='{drawing_uid}')"
4425
                    cursor.execute(sql)
4426

    
4427
                    # delete PipeRunItems
4428
                    sql = f"delete from PipeRunItems where PipeRuns_UID in " \
4429
                        f"(select UID from PipeRuns where Drawings_UID='{drawing_uid}')"
4430
                    cursor.execute(sql)
4431

    
4432
                    # delete PipeRuns
4433
                    sql = f"delete from PipeRuns where Drawings_UID='{drawing_uid}'"
4434
                    cursor.execute(sql)
4435

    
4436
                    # delete Components 
4437
                    sql = "delete from Components where Drawings_UID='{}'".format(drawing_uid)
4438
                    cursor.execute(sql)
4439

    
4440
                    # delete Stream Line List
4441
                    sql = "delete from Stream_Line_List where Drawing_UID='{}'".format(drawing_uid)
4442
                    cursor.execute(sql)
4443
                    #_stop = timeit.default_timer()
4444
                    #seconds = _stop - _start
4445
                    #print(seconds)
4446
                else:
4447
                    #import timeit
4448
                    #_start = timeit.default_timer()
4449
                    if not isCascade:
4450
                        sql = f"delete from LINE_DATA_LIST where PNID_NO = '{drawing_name}'" \
4451
                            f"delete from TitleBlockValues where Drawings_UID = '{drawing_uid}'" \
4452
                            f"delete from LineNoAttributes where Components_UID in " \
4453
                            f"(select UID from Components where Drawings_UID='{drawing_uid}')" \
4454
                            f"delete from Attributes where Components_UID in " \
4455
                            f"(select UID from Components where Drawings_UID='{drawing_uid}')" \
4456
                            f"delete from Associations where Components_UID in " \
4457
                            f"(select UID from Components where Drawings_UID='{drawing_uid}')" \
4458
                            f"delete from Points where Components_UID in " \
4459
                            f"(select UID from Components where Drawings_UID='{drawing_uid}')" \
4460
                            f"delete from PipeRunItems where PipeRuns_UID in " \
4461
                            f"(select UID from PipeRuns where Drawings_UID='{drawing_uid}')" \
4462
                            f"delete from PipeRuns where Drawings_UID='{drawing_uid}'" \
4463
                            f"delete from Components where Drawings_UID='{drawing_uid}'" \
4464
                            f"delete from Stream_Line_List where Drawing_UID='{drawing_uid}'"
4465
                        cursor.execute(sql)
4466
                        #_stop = timeit.default_timer()
4467
                        #seconds = _stop - _start
4468
                        #print(seconds)
4469
                    else:
4470
                        sql = f"delete from LINE_DATA_LIST where PNID_NO = '{drawing_name}'" \
4471
                            f"delete from TitleBlockValues where Drawings_UID = '{drawing_uid}'" \
4472
                            f"delete from Components where Drawings_UID='{drawing_uid}'" \
4473
                            f"delete from Stream_Line_List where Drawing_UID='{drawing_uid}'"
4474
                        cursor.execute(sql)
4475

    
4476
                        '''
4477
                        sql = f"delete from Drawings where [UID] = '{drawing_uid}'"
4478
                        cursor.execute(sql)
4479

4480
                        sql = self.project.database.to_sql(
4481
                            'insert into Drawings(UID, [NAME], [DATETIME], [OCCUPIED], [Image]) values(?, ?, ?, ?, ?)')
4482
                        param = tuple([str(drawing[0].UID), drawing[0].name, drawing[0].datetime, os.environ['COMPUTERNAME'], None])
4483
                        cursor.execute(sql, param)
4484
                        _stop = timeit.default_timer()
4485
                        seconds = _stop - _start
4486
                        print(seconds)
4487
                        '''
4488
                
4489
                progress = 0
4490
                length = len(queries['first']) + len(queries['second'])
4491
                for sql in queries['first']:
4492
                    if type(sql) is list:
4493
                        for item in sql:
4494
                            if item is not None and 2 == len(item):
4495
                                cursor.executemany(self.project.database.to_sql(item[0]), item[1])
4496
                    else:
4497
                        if sql is not None and 2 == len(sql):
4498
                            cursor.executemany(self.project.database.to_sql(sql[0]), sql[1])
4499

    
4500
                    if show_progress:
4501
                        show_progress.emit(int((progress / length)*100))
4502
                    progress += 1
4503

    
4504
                for sql in queries['second']:
4505
                    if type(sql) is list:
4506
                        for item in sql:
4507
                            if item is not None and 2 == len(item):
4508
                                cursor.executemany(self.project.database.to_sql(item[0]), item[1])
4509
                    else:
4510
                        if sql is not None and 2 == len(sql):
4511
                            cursor.executemany(self.project.database.to_sql(sql[0]), sql[1])
4512

    
4513
                    if show_progress:
4514
                        show_progress.emit(int((progress / length)*100))
4515
                    progress += 1
4516

    
4517
                # save Stream No Line List
4518
                index = 1
4519
                for model_data in self._streamLineListModelDatas:
4520
                    sql = f"insert into Stream_Line_List (UID, Drawing_UID, PnIDNumber, Tag_Seq_No, PipingMaterialsClass, InsulationPurpose, FluidCode, " \
4521
                          f"UnitNumber, NominalDiameter, [From], [To], Stream_No, [Case], [Index]) values(?,?,?,?,?,?,?,?,?,?,?,?,?,?)"
4522
                    sql = self.project.database.to_sql(sql)
4523
                    params = (str(uuid.uuid4()), drawing_uid, model_data['PnIDNumber'], model_data['Tag Seq No'], model_data['PipingMaterialsClass'], model_data['InsulationPurpose'], \
4524
                              model_data['FluidCode'], model_data['UnitNumber'], model_data['NominalDiameter'], model_data['FROM'], model_data['TO'], model_data['Stream No'], model_data['Case'], index)
4525
                    cursor.execute(sql, params)
4526
                    index += 1
4527

    
4528
                if show_progress:
4529
                    show_progress.emit(99)
4530

    
4531
                if self.project.database.db_type == 'SQLite':
4532
                    cursor.execute('commit')
4533
                else:
4534
                    conn.commit()
4535
            # Catch the exception
4536
            except Exception as ex:
4537
                # Roll back any change if something goes wrong
4538
                conn.rollback()
4539

    
4540
                from App import App
4541
                message = 'error occurred({}\\n{}) in {}:{}'.format(repr(ex), sql,
4542
                                                                    sys.exc_info()[-1].tb_frame.f_code.co_filename,
4543
                                                                    sys.exc_info()[-1].tb_lineno)
4544
                App.mainWnd().addMessage.emit(MessageType.Error, message)
4545

    
4546
        if rect:
4547
            self.activeDrawing.view_rect = rect
4548
            self.update_view_region(self.activeDrawing)
4549

    
4550
    def update_view_region(self, drawing):
4551
        """update view region"""
4552
        with self.project.database.connect() as conn:
4553
            try:
4554
                # Get a cursor object
4555
                cursor = conn.cursor()
4556

    
4557
                # check if there is view region
4558
                sql = f"select Drawings_UID from Views where Drawings_UID=?"
4559
                params = (drawing.UID,)
4560
                cursor.execute(self.project.database.to_sql(sql), params)
4561
                rows = cursor.fetchall()
4562
                if rows:
4563
                    sql = f"update Views set X=?,Y=?,Width=?,Height=? where Drawings_UID=?"
4564
                    params = (drawing.view_rect.x(), drawing.view_rect.y(),
4565
                              drawing.view_rect.width(), drawing.view_rect.height(), drawing.UID)
4566
                else:
4567
                    sql = f"insert into Views(Drawings_UID,X,Y,Width,Height) values(?,?,?,?,?)"
4568
                    params = (drawing.UID, drawing.view_rect.x(), drawing.view_rect.y(),
4569
                              drawing.view_rect.width(), drawing.view_rect.height())
4570

    
4571
                sql = self.project.database.to_sql(sql)
4572
                cursor.execute(sql, params)
4573
                conn.commit()
4574
            # Catch the exception
4575
            except Exception as ex:
4576

    
4577
                from App import App
4578
                message = 'error occurred({}\\n{}) in {}:{}'.format(repr(ex), sql,
4579
                                                                    sys.exc_info()[-1].tb_frame.f_code.co_filename,
4580
                                                                    sys.exc_info()[-1].tb_lineno)
4581
                App.mainWnd().addMessage.emit(MessageType.Error, message)
4582

    
4583
    '''
4584
        @brief      set equipment data list
4585
        @author     humkyung
4586
        @date       2018.05.03
4587
    '''
4588
    def setEquipmentDataList(self, dataList):
4589
        conn = self.project.database.connect()
4590
        with conn:
4591
            try:
4592
                # Get a cursor object
4593
                cursor = conn.cursor()
4594

    
4595
                for data in dataList:
4596
                    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(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"
4597
                    param = tuple(data)
4598
                    cursor.execute(self.project.database.to_sql(sql), param)
4599
                conn.commit()
4600
            # Catch the exception
4601
            except Exception as ex:
4602
                # Roll back any change if something goes wrong
4603
                conn.rollback()
4604

    
4605
                from App import App
4606
                message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
4607
                                                              sys.exc_info()[-1].tb_lineno)
4608
                App.mainWnd().addMessage.emit(MessageType.Error, message)
4609

    
4610
    '''
4611
        @brief      set instrumnet data list
4612
        @author     kyoyho
4613
        @date       2018.08.14
4614
    '''
4615
    def setInstrumentDataList(self, dataList):
4616
        conn = self.project.database.connect()
4617
        with conn:
4618
            try:
4619
                # Get a cursor object
4620
                cursor = conn.cursor()
4621

    
4622
                for data in dataList:
4623
                    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(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"
4624
                    param = tuple(data)
4625
                    cursor.execute(sql, param)
4626
                conn.commit()
4627

    
4628
            # Catch the exception
4629
            except Exception as ex:
4630
                # Roll back any change if something goes wrong
4631
                conn.rollback()
4632

    
4633
                from App import App
4634
                message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
4635
                                                              sys.exc_info()[-1].tb_lineno)
4636
                App.mainWnd().addMessage.emit(MessageType.Error, message)
4637

    
4638
    def getDrawings(self):
4639
        """ get drawings """
4640
        from Drawing import Drawing
4641

    
4642
        res = []
4643

    
4644
        with self.project.database.connect() as conn:
4645
            try:
4646
                cursor = conn.cursor()
4647
                if self.project.database.db_type == 'SQLite':
4648
                    sql = 'select UID, [NAME], [DATETIME], IFNULL(B.[X], 0) as X, IFNULL(B.[Y], 0) as Y, ' \
4649
                          'IFNULL(B.[Width], 0) as Width, IFNULL(B.[Height], 0) as Height from Drawings A ' \
4650
                          'left join Views B on A.UID = B.Drawings_UID'
4651
                else:
4652
                    sql = 'select UID, [NAME], [DATETIME], ISNULL(B.[X], 0) as X, ISNULL(B.[Y], 0) as Y, ' \
4653
                          'ISNULL(B.[Width], 0) as Width, ISNULL(B.[Height], 0) as Height from Drawings A ' \
4654
                          'left join Views B on A.UID = B.Drawings_UID'
4655

    
4656
                cursor.execute(self.project.database.to_sql(sql))
4657
                for row in cursor.fetchall():
4658
                    rect = QRectF(float(row['X']), float(row['Y']), float(row['Width']), float(row['Height']))
4659
                    res.append(Drawing(row['UID'], row['NAME'], row['DATETIME'], rect))
4660
            # Catch the exception
4661
            except Exception as ex:
4662
                from App import App
4663
                message = 'error occurred({}) in {}:{}'.format(repr(ex), sys.exc_info()[-1].tb_frame.f_code.co_filename,
4664
                                                              sys.exc_info()[-1].tb_lineno)
4665
                App.mainWnd().addMessage.emit(MessageType.Error, message)
4666

    
4667
        return res
4668

    
4669
    def saveDrawings(self, drawings):
4670
        """save given drawings"""
4671

    
4672
        import uuid
4673

    
4674
        if not drawings:
4675
            return
4676

    
4677
        with self.project.database.connect() as conn:
4678
            try:
4679
                # Get a cursor object
4680
                cursor = conn.cursor()
4681
                if self.project.database.db_type == 'SQLite':
4682
                    cursor.execute('begin')
4683

    
4684
                for drawing in drawings:
4685
                    if drawing.UID is None:
4686
                        # get image data
4687
                        image_blob_data = None
4688
                        #file_path = os.path.join(self.project.getDrawingFilePath(), drawing.name)
4689
                        #if drawing.name and os.path.isfile(file_path):
4690
                        #    with open(file_path.encode('utf-8'), 'rb') as file:
4691
                        #        image_blob_data = file.read()
4692
                        # up to here
4693

    
4694
                        sql = self.project.database.to_sql(
4695
                            'insert into Drawings(UID, [NAME], [DATETIME], [Image]) values(?, ?, ?, ?)')
4696
                        param = tuple([str(uuid.uuid4()), drawing.name, '', image_blob_data])
4697
                        drawing.UID = param[0]
4698
                    else:
4699
                        sql = self.project.database.to_sql("update Drawings set [NAME]=?,[DATETIME]=? where UID=?")
4700
                        param = (drawing.name, drawing.datetime, str(drawing.UID))
4701
                        #param = (drawing.name, drawing.datetime, image_blob_data, str(drawing.UID))
4702

    
4703
                    cursor.execute(sql, param)
4704

    
4705
                if self.project.database.db_type == 'SQLite':
4706
                    cursor.execute('commit')
4707
                else:
4708
                    conn.commit()
4709
            # Catch the exception
4710
            except Exception as ex:
4711
                # Roll back any change if something goes wrong
4712
                conn.rollback()
4713

    
4714
                from App import App
4715
                message = 'error occurred({}) in {}:{}'.format(repr(ex), sys.exc_info()[-1].tb_frame.f_code.co_filename,
4716
                                                              sys.exc_info()[-1].tb_lineno)
4717
                App.mainWnd().addMessage.emit(MessageType.Error, message)
4718

    
4719
    '''
4720
        @brief  get IsOriginDetect ComboBox Items
4721
    '''
4722
    def getIsOriginDetectComboBoxItems(self):
4723
        return [("원본 도면", 0), ("텍스트 제거 도면", 1)]
4724

    
4725
    '''
4726
        @brief  get IsOriginDetect ComboBox Items
4727
    '''
4728
    def getOcrOptionComboBoxItems(self):
4729
        return [("OCR 미적용", 0), ("일반 심볼", 1), ("Instrument 계통", 2)]
4730

    
4731
    '''
4732
        @brief      Return Symbol Type Items
4733
        @author     Jeongwoo
4734
        @date       18.04.20
4735
        @history    18.05.08    Jeongwoo type index changed
4736
    '''
4737
    def getSymbolTypeList(self):
4738
        symbolTypeList = []
4739

    
4740
        with self.project.database.connect() as conn:
4741
            cursor = conn.cursor()
4742
            sql = 'SELECT * FROM SymbolType ORDER BY Type ASC'
4743
            try:
4744
                cursor.execute(sql)
4745
                rows = cursor.fetchall()
4746
                for row in rows:
4747
                    symbolTypeList.append((row['UID'], row['Category'], row['Type']))  # UID, category, type
4748
            except Exception as ex:
4749
                from App import App
4750
                message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
4751
                                                              sys.exc_info()[-1].tb_lineno)
4752
                App.mainWnd().addMessage.emit(MessageType.Error, message)
4753

    
4754
        return symbolTypeList
4755

    
4756
    def getSymbolCategoryByType(self, type: str):
4757
        """get symbol category by using symbol type"""
4758
        category = None
4759
        if type in self._symbolType:
4760
            return self._symbolType[type]
4761

    
4762
        with self.project.database.connect() as conn:
4763
            try:
4764
                cursor = conn.cursor()
4765
                sql = self.project.database.to_sql('SELECT Category FROM SymbolType WHERE [Type] = ?')
4766
                cursor.execute(sql, (type,))
4767
                rows = cursor.fetchall()
4768
                if rows is not None and len(rows) > 0:
4769
                    category = rows[0]['Category']
4770
                    self._symbolType[type] = category
4771
            except Exception as ex:
4772
                print('error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
4773
                                                          sys.exc_info()[-1].tb_lineno))
4774

    
4775
        return category
4776

    
4777
    '''
4778
        @brief      Check Symbol Type is included in 'Equipment' Category
4779
        @author     Jeongwoo
4780
        @date       2018.05.09
4781
    '''
4782
    def isEquipmentType(self, type):
4783
        category = self.getSymbolCategoryByType(type)
4784
        return category is not None and category == 'Equipment'
4785

    
4786
    '''
4787
        @brief      Return Symbol Type Items with "None"
4788
        @author     Jeongwoo
4789
        @date       18.04.06
4790
        @history    Seperate SymbolTypeList and "None"
4791
    '''
4792
    def getSymbolTypeComboBoxItems(self):
4793
        symbolTypeList = [symbol_type for symbol_type in self.getSymbolTypeList() if symbol_type[1]]
4794
        symbolTypeList.insert(0, ('None', 'None', 'None'))
4795

    
4796
        return symbolTypeList
4797

    
4798
    '''
4799
        @brief  get Base Symbol ComboBox Items
4800
    '''
4801
    def getBaseSymbolComboBoxItems(self, type=None):
4802
        bsymbolNameList = self.getSymbolNameListByType(type)
4803
        bsymbolNameList = bsymbolNameList.copy()
4804
        bsymbolNameList.sort()
4805
        bsymbolNameList.insert(0, "None")
4806
        return bsymbolNameList
4807

    
4808
    '''
4809
        @brief  get Additional Symbol ComboBox Items
4810
    '''
4811
    def getAdditionalSymbolComboBoxItems(self):
4812
        asymbolNameList = self.getSymbolNameList()
4813
        asymbolNameList.sort()
4814
        asymbolNameList.insert(0, "None")
4815
        return asymbolNameList
4816

    
4817
    '''
4818
        @brief  get Additional Symbol's default direction ComboBox Items
4819
    '''
4820
    def getDefaultSymbolDirectionComboBoxItems(self):
4821
        return [("UP", 0), ("DOWN", 2), ("LEFT", 3), ("RIGHT", 1)]
4822

    
4823
    '''
4824
        @brief  getter of activeDrawing
4825
        @author humkyung
4826
        @date   2018.07.07
4827
    '''
4828
    @property
4829
    def activeDrawing(self):
4830
        return self._activeDrawing
4831

    
4832
    '''
4833
        @brief  setter of activeDrawing
4834
        @author humkyung
4835
        @date   2018.07.07
4836
    '''
4837
    @activeDrawing.setter
4838
    def activeDrawing(self, value):
4839
        if self._activeDrawing:
4840
            del self._activeDrawing
4841

    
4842
        self._activeDrawing = value
4843

    
4844
    def getColNames(self, table):
4845
        """ return column names of given table and attribute names if tabe is VALVE_DATA_LIST or EQUIPMET_DATA_LIST """
4846
        res = None
4847

    
4848
        conn = self.project.database.connect()
4849
        with conn:
4850
            try:
4851
                cursor = conn.cursor()
4852
                cursor.execute('select * from {}'.format(table))
4853
                res = [col_name[0] for col_name in cursor.description]
4854

    
4855
                if table == 'EQUIPMET_DATA_LIST' or table == 'VALVE_DATA_LIST':
4856
                    sql = 'select distinct c.Attribute from {} a left join Attributes b on a.uid=b.Components_UID ' \
4857
                          'left join SymbolAttribute c on b.SymbolAttribute_UID=c.UID where c.Attribute is not NULL'.format(
4858
                        table)
4859
                    cursor.execute(sql)
4860
                    rows = cursor.fetchall()
4861
                    for row in rows:
4862
                        res.append(row['Attribute'])
4863
            # Catch the exception
4864
            except Exception as ex:
4865
                print('error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
4866
                                                          sys.exc_info()[-1].tb_lineno))
4867

    
4868
        return res
4869

    
4870

    
4871
    def get_ext_apps(self):
4872
        """get external application information from App.db"""
4873

    
4874
        path = os.path.join(os.getenv('USERPROFILE'), 'Digital PID')
4875
        app_database_path = os.path.join(path, 'App.db')
4876
        with sqlite3.connect(app_database_path) as conn:
4877
            try:
4878
                conn.row_factory = sqlite3.Row
4879
                cursor = conn.cursor()
4880
                sql = 'select * from ExtApps'
4881
                cursor.execute(sql)
4882
                rows = cursor.fetchall()
4883
                return rows
4884
            except Exception as ex:
4885
                # Roll back any change if something goes wrong
4886
                conn.rollback()
4887

    
4888
                from App import App
4889
                message = f"error occurred({repr(ex)}) in {sys.exc_info()[-1].tb_frame.f_code.co_filename}:" \
4890
                          f"{sys.exc_info()[-1].tb_lineno}"
4891
                App.mainWnd().addMessage.emit(MessageType.Error, message)
4892

    
4893
        return None
4894

    
4895
    def set_ext_apps(self, model:QStandardItemModel) -> None:
4896
        """ save ext apps to database """
4897

    
4898
        path = os.path.join(os.getenv('USERPROFILE'), 'Digital PID')
4899
        app_database_path = os.path.join(path, 'App.db')
4900
        with sqlite3.connect(app_database_path) as conn:
4901
            try:
4902
                # Get a cursor object
4903
                cursor = conn.cursor()
4904

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

    
4909
                for row in range(model.rowCount()):
4910
                    param = (model.item(row, 0).text(), model.item(row, 1).text(), model.item(row, 2).text())
4911

    
4912
                    sql = "insert into ExtApps([Name], Executable, Argument) select ?,?,? where not exists" \
4913
                          "(select [Name] from ExtApps where [Name]=?)"
4914
                    cursor.execute(sql, (param[0], param[1], param[2], param[0]))
4915

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

    
4919
                conn.commit()
4920
            # Catch the exception
4921
            except Exception as ex:
4922
                conn.rollback()
4923

    
4924
                from App import App
4925
                message = f'error occurred({ex}) in {sys.exc_info()[-1].tb_frame.f_code.co_filename}:' \
4926
                          f'{sys.exc_info()[-1].tb_lineno}'
4927
                App.mainWnd().addMessage.emit(MessageType.Error, message)
4928

    
4929
        return None
4930

    
4931
    '''
4932
        @brief  getter of OCRData
4933
        @author humkyung
4934
        @date   2018.11.19
4935
    '''
4936
    @property
4937
    def OCRData(self):
4938
        if self._OCRData is None:
4939
            configs = self.getConfigs('Text Recognition', 'OCR Data')
4940
            self._OCRData = configs[0].value if 1 == len(configs) else 'eng'
4941

    
4942
        return self._OCRData
4943

    
4944
    '''
4945
        @brief  setter of OCRData
4946
        @author humkyung
4947
        @date   2018.11.19
4948
    '''
4949
    @OCRData.setter
4950
    def OCRData(self, value):
4951
        self._OCRData = value
4952

    
4953

    
4954
if __name__ == '__main__':
4955
    from AppDocData import AppDocData
4956

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