프로젝트

일반

사용자정보

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

hytos / DTI_PID / DTI_PID / AppDocData.py @ 0a77ad35

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

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

    
4
import sys
5
import os
6
import sqlite3
7
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
        self.section = section
30
        self.key = key
31
        self.value = value
32

    
33
    '''
34
        @brief  return size value string
35
        @author humkyung
36
        @date   2018.04.24
37
    '''
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

    
47

    
48
class Color:
49
    def __init__(self, index, red, green, blue):
50
        self.index = index
51
        self.red = red
52
        self.green = green
53
        self.blue = blue
54

    
55

    
56
'''
57
    @brief      MessageType
58
    @author     humkyung 
59
    @date       2018.07.31
60
'''
61

    
62

    
63
class MessageType(Enum):
64
    Normal = 1
65
    Error = 2
66
    Check = 3
67

    
68

    
69
class AppDocData(SingletonInstance):
70
    DATABASE = 'ITI_PID.db'
71

    
72
    def __init__(self):
73
        from DisplayColors import DisplayColors
74

    
75
        self._imgFilePath = None
76
        self.imgName = None
77
        self._OCRData = None
78
        self._imgSrc = None
79

    
80
        self._areas = []
81
        self._colors = None
82
        self._lineNoProperties = None
83
        self._lineTypes = None
84
        self._lineTypeConfigs = None
85
        self._activeDrawing = None
86
        self._hmbTable = None
87
        self._titleBlockProperties = None
88
        self.needReOpening = None
89

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

    
101
        # caches
102
        self._configs = None
103
        self._symbolBase = {}
104
        self._symbolType = {}
105
        self._lineNoPropertiesUID = {}
106
        self._attributeByType = {}
107

    
108
        # for load drawing data from database
109
        self._connecterss = {}
110
        self._associationss = {}
111
        self._attributess = {}
112

    
113
    def clearTempDBData(self):
114
        self._connecterss = {}
115
        self._associationss = {}
116
        self._attributess = {}
117

    
118
    def clearItemList(self, trim):
119
        '''
120
            @brief      clear item list
121
            @author     euisung
122
            @date       2018.11.28
123
        '''
124
        self.equipments.clear()
125
        self.symbols.clear()
126
        self.lineNos.clear()
127
        self.texts.clear()
128
        self.unknowns.clear()
129
        self.allItems.clear()
130
        self.lineIndicators.clear()
131
        if trim:
132
            self.tracerLineNos.clear()
133
            self.lines.clear()
134

    
135
    '''
136
        @brief      clear
137
        @author     humkyung
138
        @date       2018.09.06
139
    '''
140

    
141
    def clear(self):
142
        if self.activeDrawing and self.activeDrawing.UID:
143
            self.clear_occupying_drawing(self.activeDrawing.UID)
144

    
145
        self._imgFilePath = None
146
        self.imgName = None
147
        self._imgSrc = None
148

    
149
        self._areas.clear()
150
        self.equipments.clear()
151
        self.lineNos.clear()
152
        self.lines.clear()
153
        self.texts.clear()
154
        self.symbols.clear()
155
        self.unknowns.clear()
156
        self.allItems.clear()
157
        self.tracerLineNos.clear()
158
        self.lineIndicators.clear()
159
        self._colors = None
160
        self._lineNoProperties = None
161
        self._lineTypeConfigs = None
162
        self._activeDrawing = None
163
        self._hmbTable = None
164
        self._titleBlockProperties = None
165

    
166
        self._configs = None
167
        self._symbolBase = {}
168
        self._symbolType = {}
169
        self._lineNoPropertiesUID = {}
170
        self._attributeByType = {}
171

    
172
        self._connecterss = {}
173
        self._associationss = {}
174
        self._attributess = {}
175

    
176
    def clear_occupying_drawing(self, drawing):
177
        """ clear drawing access """
178
        conn = self.project.database.connect()
179
        with conn:
180
            try:
181
                # Get a cursor object
182
                cursor = conn.cursor()
183
                if drawing:
184
                    sql = "UPDATE Drawings SET [OCCUPIED]=null WHERE [OCCUPIED]='{}' and UID='{}'".format(os.environ['COMPUTERNAME'], drawing)
185
                else:
186
                    sql = "UPDATE Drawings SET [OCCUPIED]=null"
187
                cursor.execute(sql)
188

    
189
                conn.commit()
190
            # Catch the exception
191
            except Exception as ex:
192
                conn.rollback()
193

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

    
198
    def set_occupying_drawing(self, drawing) -> str:
199
        """ set drawing access return true if success"""
200
        with self.project.database.connect() as conn:
201
            try:
202
                # Get a cursor object
203
                cursor = conn.cursor()
204
                sql = f"select OCCUPIED from Drawings where [UID]='{drawing}'"
205
                cursor.execute(sql)
206

    
207
                rows = cursor.fetchall()
208
                if not rows[0]['OCCUPIED'] or rows[0]['OCCUPIED'] == os.environ['COMPUTERNAME']:
209
                    sql = f"UPDATE Drawings SET [OCCUPIED]='{os.environ['COMPUTERNAME']}' WHERE UID='{drawing}'"
210
                    cursor.execute(sql)
211
                    conn.commit()
212
                    return None
213
                else:
214
                    return rows[0]['OCCUPIED']
215

    
216
            # Catch the exception
217
            except Exception as ex:
218
                conn.rollback()
219

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

    
224
                return None
225

    
226
    '''
227
        @brief      Get drawing file list
228
        @author     euisung
229
        @date       2018.09.28
230
    '''
231

    
232
    def getDrawingFileList(self):
233
        """ get drawing files which's extension is .png or jpg from drawing folder """
234
        drawingFileList = []
235

    
236
        try:
237
            project = AppDocData.instance().getCurrentProject()
238
            path = project.getDrawingFilePath()
239
            drawingFileList = [f for f in os.listdir(path) if os.path.isfile(os.path.join(path, f)) and
240
                               (os.path.splitext(f)[1].upper() == '.PNG' or os.path.splitext(f)[1].upper() == '.JPG' or
241
                                os.path.splitext(f)[1].upper() == '.JPEG')]
242
            drawingFileList.sort()
243
        except Exception as ex:
244
            print('error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
245
                                                      sys.exc_info()[-1].tb_lineno))
246

    
247
        return drawingFileList
248

    
249
    '''
250
        @brief      Get Training file list
251
        @author     euisung
252
        @date       2018.10.16
253
    '''
254

    
255
    def getTrainingFileList(self):
256
        try:
257
            project = AppDocData.instance().getCurrentProject()
258
            path = project.getTrainingFilePath()
259
            trainingFileList = os.listdir(path)
260
            trainingFileList.sort()
261
        except Exception as ex:
262
            from App import App
263
            message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
264
                                                          sys.exc_info()[-1].tb_lineno)
265
            App.mainWnd().addMessage.emit(MessageType.Error, message)
266

    
267
        return trainingFileList
268

    
269
    def getTrainingSymbolFileList(self):
270
        """  Get Symbol Training file list """
271
        try:
272
            project = AppDocData.instance().getCurrentProject()
273
            path = project.getTrainingSymbolFilePath()
274
            symbolTrainingFileList = os.listdir(path)
275
            symbolTrainingFileList.sort()
276
        except Exception as ex:
277
            from App import App
278
            message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
279
                                                          sys.exc_info()[-1].tb_lineno)
280
            App.mainWnd().addMessage.emit(MessageType.Error, message)
281

    
282
        return symbolTrainingFileList
283

    
284
    '''
285
        @brief      Get DB file path in ProgramData
286
        @author     Jeongwoo
287
        @date       2018.06.27
288
        @history    2018.06.29  Jeongwoo    Change method to get template db path
289
    '''
290

    
291
    def getTemplateDbPath(self):
292
        path = os.path.join(os.getenv('ALLUSERSPROFILE'), 'Digital PID')
293
        templateDbPath = os.path.join(path, 'Template.db')
294
        return templateDbPath
295

    
296
    def get_template_symbol_library_path(self):
297
        """return template symbol library path"""
298

    
299
        path = os.path.join(os.getenv('ALLUSERSPROFILE'), 'Digital PID')
300
        return os.path.join(path, 'SymbolLibrary.syl')
301

    
302
    def getAppDbPath(self):
303
        """
304
        @brief      Get application DB file path in ProgramData
305
        @author     humkyung
306
        @date       2018.10.01
307
        """
308

    
309
        path = os.path.join(os.getenv('ALLUSERSPROFILE'), 'Digital PID')
310
        app_database = os.path.join(path, 'App.db')
311
        return app_database
312

    
313
    '''
314
        @brief  getter of colors 
315
        @author humkyung
316
        @date   2018.06.18
317
    '''
318

    
319
    @property
320
    def colors(self):
321
        import random
322

    
323
        if self._colors is None or self._colors == []:
324
            self._colors = []
325
            with self.project.database.connect() as conn:
326
                try:
327
                    cursor = conn.cursor()
328
                    sql = 'SELECT UID,RED,GREEN,BLUE FROM Colors'
329
                    cursor.execute(sql)
330
                    rows = cursor.fetchall()
331
                    for row in rows:
332
                        self._colors.append(Color(row['UID'], row['RED'], row['GREEN'], row['BLUE']))
333
                # Catch the exception
334
                except Exception as ex:
335
                    from App import App
336
                    message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
337
                                                                  sys.exc_info()[-1].tb_lineno)
338
                    App.mainWnd().addMessage.emit(MessageType.Error, message)
339

    
340
        return self._colors.pop(random.randrange(0, len(self._colors)))
341

    
342
    '''
343
        @brief  setter of colors
344
        @author humkyung
345
        @date   2018.06.18
346
    '''
347

    
348
    @colors.setter
349
    def colors(self, value):
350
        self._colors = value
351

    
352
    '''
353
        @brief      set image file path
354
        @author     humkyung
355
        @date       2018.07.30
356
    '''
357

    
358
    def setImgFilePath(self, path):
359
        self._imgFilePath = path
360
        self.imgName = os.path.splitext(os.path.basename(self._imgFilePath))[0]
361

    
362
    @staticmethod
363
    def my_imread(file_path):
364
        """ read a file which's name contains unicode string : ref http://devdoftech.co.kr:82/redmine/issues/631 """
365
        import numpy as np
366
        import cv2
367

    
368
        _bytes = None
369
        with open(file_path.encode('utf-8'), 'rb') as stream:
370
            _bytes = bytearray(stream.read())
371

    
372
        numpyArray = np.asarray(_bytes, dtype=np.uint8)
373
        res = cv2.imdecode(numpyArray, cv2.IMREAD_UNCHANGED)
374
        return res
375

    
376
    @property
377
    def imgSrc(self):
378
        """return the image of active drawing"""
379

    
380
        if self.activeDrawing:
381
            return self.activeDrawing.image
382

    
383
        return None
384

    
385
    @imgSrc.setter
386
    def imgSrc(self, value):
387
        """set the image of active drawing with given value"""
388

    
389
        if self.activeDrawing:
390
            self.activeDrawing.image = value
391

    
392
    '''
393
        @brief  getter of line type configs
394
        @author humkyung
395
        @date   2018.06.28
396
    '''
397

    
398
    @property
399
    def lineTypeConfigs(self):
400
        from PyQt5.QtCore import Qt
401

    
402
        if self._lineTypeConfigs is None:
403
            self._lineTypeConfigs = []
404

    
405
            styleMap = [('SolidLine', Qt.SolidLine), ('DashLine', Qt.DashLine), ('DotLine', Qt.DotLine),
406
                        ('DashDotLine', Qt.DashDotLine),
407
                        ('DashDotDotLine', Qt.DashDotDotLine), ('CustomDashLine', Qt.CustomDashLine)]
408

    
409
            configs = self.getConfigs('LineTypes')
410
            for config in configs:
411
                color, width, _style, transparent = config.value.split(',')
412
                matches = [param for param in styleMap if param[0] == _style]
413
                style = matches[0][1] if matches else Qt.SolidLine
414
                self._lineTypeConfigs.append((config.key, color, int(width), style, float(transparent)))
415

    
416
        return self._lineTypeConfigs
417

    
418
    '''
419
        @brief  setter of line type configs
420
        @author humkyung
421
        @date   2018.06.28
422
    '''
423

    
424
    @lineTypeConfigs.setter
425
    def lineTypeConfigs(self, value):
426
        self._lineTypeConfigs = value
427

    
428
    @property
429
    def drain_size(self):
430
        """ getter of drain_size """
431
        if not hasattr(self, '_drain_size') or not self._drain_size:
432
            configs = self.getConfigs('Drain Size Rule', 'Size')
433
            self._drain_size = configs[0].value if configs else '1"'
434

    
435
        return self._drain_size
436

    
437
    @drain_size.setter
438
    def drain_size(self, value):
439
        """ setter of drain_size """
440
        self._drain_size = value
441

    
442
    '''
443
        @brief      getter of hmb table
444
        @author     humkyung
445
        @date       2018.07.16
446
    '''
447

    
448
    @property
449
    def hmbTable(self):
450
        from HMBTable import HMBTable
451

    
452
        if self._hmbTable is None:
453
            self._hmbTable = HMBTable()
454
            self._hmbTable.load_data()
455

    
456
        return self._hmbTable
457

    
458
    '''
459
        @brief      setter of hmb table
460
        @author     humkyung
461
        @date       2018.07.16
462
    '''
463

    
464
    @hmbTable.setter
465
    def hmbTable(self, value):
466
        self._hmbTable = value
467

    
468
    '''
469
        @brief  get line type config of given line type
470
        @author humkyung
471
        @date   2018.06.28
472
    '''
473

    
474
    def getLineTypeConfig(self, lineType):
475
        from PyQt5.QtCore import Qt
476

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

    
480
    def getCurrentPidSource(self):
481
        return self.activeDrawing.currentPidSource
482

    
483
    '''
484
        @brief      Check if exist file name or not
485
        @author     Jeongwoo
486
        @date       2018.05.03
487
    '''
488

    
489
    def isExistFileName(self, name):
490
        rows = None
491
        with self.project.database.connect() as conn:
492
            try:
493
                cursor = conn.cursor()
494
                sql = "SELECT * FROM Symbol WHERE name = '" + name + "'"
495
                cursor.execute(sql)
496
                rows = cursor.fetchall()
497
            # Catch the exception
498
            except Exception as ex:
499
                # Roll back any change if something goes wrong
500
                conn.rollback()
501
                print('error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
502
                                                          sys.exc_info()[-1].tb_lineno))
503
            finally:
504
                if rows is not None and len(rows) > 0:
505
                    return True
506
                else:
507
                    return False
508

    
509
    '''
510
        @brief      Insert new symbol into Symbol Table, Moved from SG_DbHelper
511
        @author     Jeongwoo
512
        @date       2018.05.03
513
    '''
514

    
515
    def insertSymbol(self, symbol):
516
        isAdded = False
517
        with self.project.database.connect() as conn:
518
            try:
519
                sql = self.project.database.to_sql("""
520
                    INSERT INTO Symbol(name, SymbolType_UID, threshold, minMatchPoint, isDetectOrigin, rotationCount, ocrOption, isContainChild, originalPoint, connectionPoint, baseSymbol, additionalSymbol, isExceptDetect, hasInstrumentLabel, width, height, flip, TextArea) 
521
                    VALUES(?, (select UID from SymbolType where Type=?), ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?);
522
                """)
523

    
524
                cursor = conn.cursor()
525
                query = (symbol.getName(), symbol.getType(), symbol.getThreshold()
526
                         , symbol.getMinMatchCount(), symbol.getIsDetectOnOrigin(), symbol.getRotationCount()
527
                         , symbol.getOcrOption(), symbol.getIsContainChild()
528
                         , symbol.getOriginalPoint(), symbol.getConnectionPoint()
529
                         , symbol.getBaseSymbol(), symbol.getAdditionalSymbol(), symbol.getIsExceptDetect(),
530
                         symbol.getHasInstrumentLabel()
531
                         , symbol.width, symbol.height, symbol.detectFlip, symbol.text_area_str)
532
                cursor.execute(sql, query)
533
                conn.commit()
534
                isAdded = True
535
            # Catch the exception
536
            except Exception as ex:
537
                # Roll back any change if something goes wrong
538
                conn.rollback()
539

    
540
                from App import App
541
                message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
542
                                                              sys.exc_info()[-1].tb_lineno)
543
                App.mainWnd().addMessage.emit(MessageType.Error, message)
544
            finally:
545
                return (isAdded, symbol.getType(), symbol.getName(), symbol.getPath())
546

    
547
    '''
548
        @brief      Update symbol in Symbol Table, Moved from SG_DbHelper
549
        @author     Jeongwoo
550
        @date       2018.05.03
551
    '''
552

    
553
    def updateSymbol(self, symbol):
554
        isUpdated = False
555

    
556
        with self.project.database.connect() as conn:
557
            try:
558
                sql = self.project.database.to_sql("""
559
                    UPDATE Symbol
560
                    SET
561
                        name = ?, SymbolType_UID=(select UID from SymbolType where Type=?), threshold=?, 
562
                        minMatchPoint=?, isDetectOrigin=?, rotationCount=?, ocrOption=?, isContainChild=?, 
563
                        originalPoint=?, connectionPoint=?, baseSymbol=?, additionalSymbol=?, isExceptDetect=?, 
564
                        hasInstrumentLabel=?, width=?, height=?, flip=?, TextArea=? WHERE uid = ?
565
                """)
566

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

    
583
                from App import App
584
                message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
585
                                                              sys.exc_info()[-1].tb_lineno)
586
                App.mainWnd().addMessage.emit(MessageType.Error, message)
587
            finally:
588
                self._symbolBase = {}
589
                return (isUpdated, symbol.getType(), symbol.getName(), symbol.getPath())
590

    
591
    def getSymbolPreset(self):
592
        """ get symbol preset """
593
        presets = []
594
        with self.project.database.connect() as conn:
595
            try:
596
                cursor = conn.cursor()
597
                sql = 'SELECT [UID], [Find], [Target], [Action], [Condition] FROM SymbolPreset'
598
                cursor.execute(sql)
599
                rows = cursor.fetchall()
600
                for row in rows:
601
                    presets.append([row['Find'], row['Target'], row['Action'], row['Condition']])
602
            # Catch the exception
603
            except Exception as ex:
604
                from App import App
605
                message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
606
                                                                sys.exc_info()[-1].tb_lineno)
607
                App.mainWnd().addMessage.emit(MessageType.Error, message)
608

    
609
                return []
610

    
611
        return presets
612

    
613
    def saveSymbolPreset(self, presets):
614
        """ save symbol preset """
615
        import uuid
616

    
617
        conn = self.project.database.connect()
618
        with conn:
619
            try:
620
                # Get a cursor object
621
                cursor = conn.cursor()
622

    
623
                sql = "delete from SymbolPreset"
624
                cursor.execute(sql)
625

    
626
                for preset in presets:
627
                    sql = self.project.database.to_sql("insert into [SymbolPreset]([UID], [Find], [Target], [Action], [Condition]) values(?,?,?,?,?)")
628
                    param = (str(uuid.uuid4()), preset[0], preset[1], preset[2], preset[3])
629
                    cursor.execute(sql, param)
630
                conn.commit()
631

    
632
            except Exception as ex:
633
                # Roll back any change if something goes wrong
634
                conn.rollback()
635
                from App import App
636
                from AppDocData import MessageType
637
                message = 'error occurred({}) in {}:{}'.format(repr(ex), sys.exc_info()[-1].tb_frame.f_code.co_filename,
638
                                                                sys.exc_info()[-1].tb_lineno)
639
                App.mainWnd().addMessage.emit(MessageType.Error, message)
640
        
641

    
642
    def getTargetSymbolList(self, all=False):
643
        """get symbol list to be detected except isExceptDetect field is unset"""
644
        targetSymbolList = []
645

    
646
        with self.project.database.connect() as conn:
647
            cursor = conn.cursor()
648
            if not all:
649
                sql = """SELECT a.UID,a.Name,b.Type,a.Threshold,a.MinMatchPoint,a.IsDetectOrigin,a.RotationCount,
650
                a.OCROption,a.IsContainChild,a.OriginalPoint,a.ConnectionPoint,a.BaseSymbol,a.AdditionalSymbol,a.Width,a.Height,
651
                a.IsExceptDetect,a.HasInstrumentLabel,a.flip,a.TextArea,b.UID as DB_UID FROM Symbol a inner join SymbolType b on 
652
                a.SymbolType_UID=b.UID WHERE a.IsExceptDetect = 0 order by width * height desc"""
653
            else:
654
                sql = """SELECT a.UID,a.Name,b.Type,a.Threshold,a.MinMatchPoint,a.IsDetectOrigin,a.RotationCount,
655
                a.OCROption,a.IsContainChild,a.OriginalPoint,a.ConnectionPoint,a.BaseSymbol,a.AdditionalSymbol,a.Width,a.Height,
656
                a.IsExceptDetect,a.HasInstrumentLabel,a.flip,a.TextArea,b.UID as DB_UID FROM Symbol a inner join SymbolType b on 
657
                a.SymbolType_UID=b.UID order by width * height desc"""
658
            try:
659
                cursor.execute(sql)
660
                rows = cursor.fetchall()
661
                for row in rows:
662
                    sym = symbol.SymbolBase(row['Name'], row['Type'], row['Threshold'],
663
                                                row['MinMatchPoint'], row['IsDetectOrigin'],
664
                                                row['RotationCount'], row['OCROption'],
665
                                                row['IsContainChild'], row['OriginalPoint'],
666
                                                row['ConnectionPoint'], row['BaseSymbol'],
667
                                                row['AdditionalSymbol'], row['IsExceptDetect'],
668
                                                row['HasInstrumentLabel'], row['UID'],
669
                                                iType=row['DB_UID'], width=row['Width'], height=row['Height'],
670
                                                detectFlip=row['flip'], text_area=row['TextArea'])
671
                    targetSymbolList.append(sym)
672
            except Exception as ex:
673
                print('error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
674
                                                          sys.exc_info()[-1].tb_lineno))
675

    
676
        return targetSymbolList
677

    
678
    def get_favorite_libraries(self):
679
        res = []
680

    
681
        with self.project.database.connect() as conn:
682
            cursor = conn.cursor()
683
            sql = f"select UID,Symbol_UID from Libraries where [User]='{os.environ['COMPUTERNAME'].upper()}'"
684
            try:
685
                cursor.execute(sql)
686
                return cursor.fetchall()
687
            except Exception as ex:
688
                print('error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
689
                                                          sys.exc_info()[-1].tb_lineno))
690

    
691
        return None
692

    
693
    def buildAppDatabase(self):
694
        """build application database"""
695
        path = os.path.join(os.getenv('ALLUSERSPROFILE'), 'Digital PID')
696
        appDatabaseFilePath = os.path.join(path, 'App.db')
697

    
698
        # Creates or opens a file called mydb with a SQLite3 DB
699
        with sqlite3.connect(appDatabaseFilePath) as conn:
700
            try:
701
                # Get a cursor object
702
                cursor = conn.cursor()
703

    
704
                sqlFiles = ['App.Configuration.sql', 'App.Styles.sql']
705
                for sqlFile in sqlFiles:
706
                    filePath = os.path.join(os.path.dirname(os.path.realpath(__file__)), 'Scripts', sqlFile)
707
                    try:
708
                        file = QFile(filePath)
709
                        file.open(QFile.ReadOnly)
710
                        sql = file.readAll()
711
                        sql = str(sql, encoding='utf8')
712
                        cursor.executescript(sql)
713
                    finally:
714
                        file.close()
715
                conn.commit()
716
            # Catch the exception
717
            except Exception as ex:
718
                # Roll back any change if something goes wrong
719
                conn.rollback()
720
                print('error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
721
                                                          sys.exc_info()[-1].tb_lineno))
722

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

    
726
        configs = self.getAppConfigs('app', 'expiration')
727
        if not configs:
728
            configs = self.getAppConfigs('app', 'license')
729
            if configs and 'DOFTECH' in configs[0].value:
730
                self.deleteAppConfigs('app', 'mode')
731
                configs = None
732
            else:
733
                configs = [Config('app', 'mode', 'advanced')]
734
        else:
735
            configs = None
736

    
737
        if configs:
738
            self.saveAppConfigs(configs)
739

    
740
    '''
741
        @brief  load app style
742
        @author humkyung
743
        @date   2018.04.20
744
    '''
745

    
746
    def loadAppStyle(self):
747
        style = 'Fusion'
748

    
749
        path = os.path.join(os.getenv('ALLUSERSPROFILE'), 'Digital PID')
750
        if not os.path.exists(path): os.makedirs(path)
751

    
752
        self.buildAppDatabase()
753
        try:
754
            appDatabaseFilePath = os.path.join(path, 'App.db')
755
            # Creates or opens a file called mydb with a SQLite3 DB
756
            conn = sqlite3.connect(appDatabaseFilePath)
757
            # Get a cursor object
758
            cursor = conn.cursor()
759

    
760
            sql = "select Value from Configuration where Section='App' and Key='Style'"
761
            cursor.execute(sql)
762
            rows = cursor.fetchall()
763
            style = rows[0][0] if 1 == len(rows) else 'Fusion'
764
        # Catch the exception
765
        except Exception as ex:
766
            # Roll back any change if something goes wrong
767
            conn.rollback()
768
            print('error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
769
                                                      sys.exc_info()[-1].tb_lineno))
770
        finally:
771
            # Close the db connection
772
            conn.close()
773

    
774
        return style
775

    
776
    '''
777
        @brief  load app styles and then return a list
778
        @author humkyung
779
        @date   2018.04.20
780
    '''
781

    
782
    def loadAppStyles(self):
783
        styles = []
784

    
785
        try:
786
            self.buildAppDatabase()
787

    
788
            path = os.path.join(os.getenv('ALLUSERSPROFILE'), 'Digital PID')
789
            appDatabaseFilePath = os.path.join(path, 'App.db')
790

    
791
            # Creates or opens a file called mydb with a SQLite3 DB
792
            conn = sqlite3.connect(appDatabaseFilePath)
793
            # Get a cursor object
794
            cursor = conn.cursor()
795

    
796
            sql = 'select UID,Value from Styles'
797
            cursor.execute(sql)
798
            rows = cursor.fetchall()
799
            for row in rows: styles.append(row[1])
800
            if 0 == len(rows): rows.append('fusion')
801
        # Catch the exception
802
        except Exception as ex:
803
            # Roll back any change if something goes wrong
804
            conn.rollback()
805
            print('error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
806
                                                      sys.exc_info()[-1].tb_lineno))
807
        finally:
808
            # Close the db connection
809
            conn.close()
810

    
811
        return styles
812

    
813
    '''
814
        @brief  Set current Project
815
        @history    2018.06.27  Jeongwoo    If DB file is not, copy DB file from ProgramData
816
    '''
817

    
818
    def setCurrentProject(self, project):
819
        self.project = project
820
        project.make_sub_directories()
821
        try:
822
            # save size unit
823
            #self.saveConfigs([Config('Project', 'Unit', project.prj_unit)])
824

    
825
            if self.project.database.db_type == 'SQLite':
826
                # Creates or opens a file called mydb with a SQLite3 DB
827
                db_path = self.project.database.file_path
828

    
829
                if not os.path.isfile(db_path):
830
                    templatePath = self.getTemplateDbPath()
831
                    templateFile = QFile(templatePath)
832
                    templateFile.copy(db_path)
833

    
834
                try:
835
                    conn = self.project.database.connect()
836
                    with conn:
837
                        # Get a cursor object
838
                        cursor = conn.cursor()
839

    
840
                        fileNames = os.listdir(os.path.join(os.path.dirname(os.path.realpath(__file__)), 'Scripts'))
841
                        for fileName in fileNames:
842
                            if fileName.endswith(".sql") and ('SQLite_Project' == os.path.splitext(fileName)[0].split('.')[0]):
843
                                try:
844
                                    file = QFile(
845
                                        os.path.join(os.path.dirname(os.path.realpath(__file__)), 'Scripts', fileName))
846
                                    file.open(QFile.ReadOnly)
847
                                    sql = file.readAll()
848
                                    sql = str(sql, encoding='utf8')
849
                                    cursor.executescript(sql)
850
                                finally:
851
                                    file.close()
852
                        conn.commit()
853
                except Exception as ex:
854
                    print('error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
855
                                                              sys.exc_info()[-1].tb_lineno))
856
        # Catch the exception
857
        except Exception as ex:
858
            # Roll back any change if something goes wrong
859
            print('error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
860
                                                      sys.exc_info()[-1].tb_lineno))
861
        finally:
862
            pass
863

    
864
    '''
865
        @brief  Get current Project
866
    '''
867

    
868
    def getCurrentProject(self):
869
        return self.project
870

    
871
    '''
872
        @brief      return project database path
873
        @history    humkyung 2018.04.19 return Project.db in Program Data folder instead of PROJECT_DB_PATH variable
874
    '''
875

    
876
    def getPrjDatabasePath(self):
877
        path = os.path.join(os.getenv('ALLUSERSPROFILE'), 'Digital PID')
878
        if not os.path.exists(path): os.makedirs(path)
879

    
880
        prjDatabaseFilePath = os.path.join(path, 'Project.db')
881
        try:
882
            # Creates or opens a file called mydb with a SQLite3 DB
883
            conn = sqlite3.connect(prjDatabaseFilePath)
884
            # Get a cursor object
885
            cursor = conn.cursor()
886

    
887
            filePath = os.path.join(os.path.dirname(os.path.realpath(__file__)), 'Scripts', 'Project.Projects.sql')
888
            try:
889
                file = QFile(filePath)
890
                file.open(QFile.ReadOnly)
891
                sql = file.readAll()
892
                sql = str(sql, encoding='utf8')
893
                cursor.executescript(sql)
894
            finally:
895
                file.close()
896
            conn.commit()
897
        # Catch the exception
898
        except Exception as ex:
899
            # Roll back any change if something goes wrong
900
            conn.rollback()
901
            print('error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
902
                                                      sys.exc_info()[-1].tb_lineno))
903
        finally:
904
            # Close the db connection
905
            conn.close()
906

    
907
        return prjDatabaseFilePath
908

    
909
    def getErrorItemSvgPath(self):
910
        '''
911
            @brief  return error item svg path
912
            @author euisung
913
            @date   2019.04.02
914
        '''
915
        return os.path.join(os.getenv('ALLUSERSPROFILE'), 'Digital PID', 'Explode.svg')
916

    
917
    def updateTitleBlockProperties(self, titleBlockProps):
918
        '''
919
            @brief  update title block properties
920
            @author euisung
921
            @date   2018.11.09
922
        '''
923
        try:
924
            originTitleBlockProps = self.getTitleBlockProperties()
925
            deletedTitleBlockProps = []
926
            for originTitleBlockProp in originTitleBlockProps:
927
                for titleBlockProp in titleBlockProps:
928
                    # uid compare for determine delete props
929
                    if originTitleBlockProp[0] == titleBlockProp[0]:
930
                        break
931
                deletedTitleBlockProps.append(originTitleBlockProp[0])
932

    
933
            # Creates or opens a file called mydb with a SQLite3 DB
934
            conn = self.project.database.connect()
935
            with conn:
936
                try:
937
                    # Get a cursor object
938
                    cursor = conn.cursor()
939

    
940
                    for deletedTitleBlockProp in deletedTitleBlockProps:
941
                        sql = "delete from TitleBlockValues where TitleBlockProperties_UID='{}'".format(deletedTitleBlockProp)
942
                        cursor.execute(sql)
943
                        sql = "delete from TitleBlockProperties where UID='{}'".format(deletedTitleBlockProp)
944
                        cursor.execute(sql)
945

    
946
                    for titleBlockProp in titleBlockProps:
947
                        sql = self.project.database.to_sql("insert into [TitleBlockProperties]([UID], [NAME], [AREA], [TEXT]) values(?,?,?,?)")
948
                        param = (titleBlockProp[0], titleBlockProp[1], titleBlockProp[2], titleBlockProp[3])  # uid, name, area, text
949
                        cursor.execute(sql, param)
950
                    conn.commit()
951
                    # Catch the exception
952
                except Exception as ex:
953
                    # Roll back any change if something goes wrong
954
                    conn.rollback()
955
                    from App import App
956
                    from AppDocData import MessageType
957
                    message = 'error occurred({}) in {}:{}'.format(repr(ex), sys.exc_info()[-1].tb_frame.f_code.co_filename,
958
                                                                   sys.exc_info()[-1].tb_lineno)
959
                    App.mainWnd().addMessage.emit(MessageType.Error, message)
960
        # Catch the exception
961
        except Exception as ex:
962
            from App import App
963
            from AppDocData import MessageType
964
            message = 'error occurred({}) in {}:{}'.format(repr(ex), sys.exc_info()[-1].tb_frame.f_code.co_filename,
965
                                                           sys.exc_info()[-1].tb_lineno)
966
            App.mainWnd().addMessage.emit(MessageType.Error, message)
967

    
968
        self._titleBlockProperties = None
969

    
970
    def getTitleBlockProperties(self):
971
        """"return title block properties"""
972

    
973
        res = None
974
        if self._titleBlockProperties is None:
975
            self._titleBlockProperties = []
976

    
977
            with self.project.database.connect() as conn:
978
                try:
979
                    # Get a cursor object
980
                    cursor = conn.cursor()
981

    
982
                    sql = "select UID, Name, AREA, [TEXT] from TitleBlockProperties"
983
                    cursor.execute(sql)
984
                    rows = cursor.fetchall()
985
                    for row in rows:
986
                        attr = []
987
                        attr.append(row['UID'])  # uid
988
                        attr.append(row['Name'])  # name
989
                        attr.append(row['AREA'])  # area
990
                        attr.append(row['TEXT'])  # text
991
                        self._titleBlockProperties.append(attr)
992

    
993
                    res = self._titleBlockProperties
994
                # Catch the exception
995
                except Exception as ex:
996
                    print('error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
997
                                                              sys.exc_info()[-1].tb_lineno))
998
        else:
999
            res = self._titleBlockProperties
1000

    
1001
        return res
1002

    
1003
    def clearLineNoProperties(self):
1004
        self._lineNoProperties = None
1005
        self._lineNoPropertiesUID = {}
1006

    
1007
    def getLineProperties(self):
1008
        """return line no properties"""
1009
        from SymbolAttr import SymbolAttr
1010

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

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

    
1020
                    sql = "select UID, Name, DisplayName, Type, LimitNumber, [index] from LineProperties " \
1021
                          "order by [index]"
1022
                    cursor.execute(sql)
1023
                    rows = cursor.fetchall()
1024
                    for row in rows:
1025
                        attr = SymbolAttr()
1026
                        attr.UID = row['UID']
1027
                        attr.Attribute = row['Name']
1028
                        attr.DisplayAttribute = row['DisplayName']
1029
                        attr.AttributeType = row['Type']
1030
                        attr.Length = row['LimitNumber']
1031
                        attr.IsProp = 5
1032
                        self._lineNoProperties.append(attr)
1033

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

    
1042
        return res
1043

    
1044
    def get_equipment_attributes(self):
1045
        """ return equipment attributes """
1046

    
1047
        from SymbolAttr import SymbolAttr
1048

    
1049
        res = None
1050
        if not hasattr(self, '_equipment_attributes'):
1051
            self._equipment_attributes = []
1052

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

    
1058
                    sql = "select distinct A.Attribute from SymbolAttribute A join SymbolType B on " \
1059
                          "A.SymbolType_UID=B.UID where B.Category in ('Equipment')"#,'Equipment Components')"
1060
                    cursor.execute(sql)
1061
                    rows = cursor.fetchall()
1062
                    for row in rows:
1063
                        attr = SymbolAttr()
1064
                        attr.Attribute = row['Attribute']
1065
                        self._equipment_attributes.append(attr)
1066

    
1067
                    res = self._equipment_attributes
1068
                # Catch the exception
1069
                except Exception as ex:
1070
                    print('error occurred({}) in {}:{}'.format(repr(ex), sys.exc_info()[-1].tb_frame.f_code.co_filename,
1071
                                                               sys.exc_info()[-1].tb_lineno))
1072
        else:
1073
            res = self._equipment_attributes
1074

    
1075
        return res
1076

    
1077
    '''
1078
        @brief  return line properties
1079
        @author humkyung
1080
        @date   2018.04.09
1081
    '''
1082

    
1083
    def getLinePropertiesByUID(self, UID):
1084
        from SymbolAttr import SymbolAttr
1085

    
1086
        res = []
1087
        if UID in self._lineNoPropertiesUID:
1088
            res = self._lineNoPropertiesUID[UID]
1089
            return res
1090

    
1091
        with self.project.database.connect() as conn:
1092
            try:
1093
                # Get a cursor object
1094
                cursor = conn.cursor()
1095

    
1096
                sql = f"select UID, Name, DisplayName, Type, LimitNumber, [index] from LineProperties where " \
1097
                      f"uid = '{UID}'"
1098
                cursor.execute(sql)
1099
                rows = cursor.fetchall()
1100
                for row in rows:
1101
                    attr = SymbolAttr()
1102
                    attr.UID = row['UID']
1103
                    attr.Attribute = row['Name']
1104
                    attr.DisplayAttribute = row['DisplayName']
1105
                    attr.AttributeType = row['Type']
1106
                    attr.Length = row['LimitNumber']
1107
                    attr.IsProp = 5
1108
                    res.append(attr)
1109
                self._lineNoPropertiesUID[UID] = res
1110
            # Catch the exception
1111
            except Exception as ex:
1112
                print('error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
1113
                                                          sys.exc_info()[-1].tb_lineno))
1114

    
1115
        return res
1116

    
1117
    '''
1118
        @brief  return line types 
1119
        @author humkyung
1120
        @date   2018.06.27
1121
    '''
1122

    
1123
    def getLineTypes(self):
1124
        from LineTypeConditions import LineTypeConditions
1125

    
1126
        res = []
1127
        conn = self.project.database.connect()
1128
        with conn:
1129
            try:
1130
                cursor = conn.cursor() if self.project.database.db_type == 'SQLite' else conn.cursor(as_dict=True)
1131
                sql = "select UID,Name,Type1,Conditions1,Type2,Conditions2 from LineTypes order by Name"
1132
                cursor.execute(sql)
1133
                rows = cursor.fetchall()
1134
                for row in rows:
1135
                    line_type = LineTypeConditions(row['UID'], row['Name'])
1136
                    line_type._conditions[0][0] = row['Type1']
1137
                    line_type._conditions[0][1] = row['Conditions1']
1138
                    line_type._conditions[1][0] = row['Type2']
1139
                    line_type._conditions[1][1] = row['Conditions2']
1140
                    res.append(line_type)
1141
            # Catch the exception
1142
            except Exception as ex:
1143
                print('error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
1144
                                                          sys.exc_info()[-1].tb_lineno))
1145

    
1146
        return res
1147

    
1148
    '''
1149
        @brief      Insert New Project Info
1150
        @author     Jeongwoo
1151
        @date       2018.04.06
1152
        @history    humkyung 2018.04.19 use getPrjDatabasePath function instead of PROJECT_DB_PATH variable
1153
    '''
1154

    
1155
    def insertProjectInfo(self, desc, prj_unit, dir):
1156
        prjDatabaseFilePath = self.getPrjDatabasePath()
1157
        conn = sqlite3.connect(prjDatabaseFilePath)
1158
        with conn:
1159
            try:
1160
                folderName = dir.split('/')[-1]
1161
                if folderName:
1162
                    nowDate = datetime.datetime.now().strftime('%Y.%m.%d %H:%M')
1163
                    sql = "insert or replace into Projects(Name, [Desc], [Unit], Path, CreatedDate, UpdatedDate) values(?, ?, ?, ?, ?, ?)"
1164
                    param = (folderName, desc, prj_unit, dir, nowDate, nowDate)
1165

    
1166
                    cursor = conn.cursor()
1167
                    cursor.execute(sql, param)
1168
                    conn.commit()
1169
                else:
1170
                    print("Empty folder name")
1171
            except Exception as ex:
1172
                # Roll back any change if something goes wrong
1173
                conn.rollback()
1174
                print('error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
1175
                                                          sys.exc_info()[-1].tb_lineno))
1176

    
1177
    def removeProjectInfo(self, targetProject):
1178
        '''
1179
        @brief      Remove Project Info
1180
        @author     Euisung
1181
        @date       2019.01.28
1182
        '''
1183
        prjDatabaseFilePath = self.getPrjDatabasePath()
1184
        conn = sqlite3.connect(prjDatabaseFilePath)
1185
        with conn:
1186
            try:
1187
                sql = "delete from Projects where Id = '{}'".format(targetProject.id)
1188
                cur = conn.cursor()
1189
                cur.execute(sql)
1190
                conn.commit()
1191
            except Exception as ex:
1192
                # Roll back any change if something goes wrong
1193
                conn.rollback()
1194
                print('error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
1195
                                                          sys.exc_info()[-1].tb_lineno))
1196

    
1197
    '''
1198
        @brief      update project
1199
        @author     Jeongwoo
1200
        @date       2018.04.06
1201
        @history    humkyung 2018.04.19 use getPrjDatabasePath function instead of PROJECT_DB_PATH variable
1202
    '''
1203

    
1204
    def updateProjectUpdatedDate(self, project):
1205
        prjDatabaseFilePath = self.getPrjDatabasePath()
1206
        conn = sqlite3.connect(prjDatabaseFilePath)
1207
        with conn:
1208
            try:
1209
                nowDate = datetime.datetime.now().strftime('%Y.%m.%d %H:%M')
1210
                sql = '''
1211
                    UPDATE Projects
1212
                    SET UpdatedDate = ?,[Desc]=?,[Unit]=? 
1213
                    WHERE Id = ?
1214
                '''
1215
                cur = conn.cursor()
1216
                cur.execute(sql, (nowDate, project.desc, project.prj_unit, project.getId()))
1217

    
1218
                sql = 'insert or replace into DBSettings(Projects_UID, DBTypes_UID, Host, User, Password, FilePath) values(?,(select UID from DBTypes where Name=?),?,?,?,?)'
1219
                cur = conn.cursor()
1220
                cur.execute(sql, (
1221
                    project.getId(), project.database.db_type, project.database.host, project.database.user,
1222
                    project.database.password, project.database.file_path))
1223
                conn.commit()
1224
            except Exception as ex:
1225
                # Roll back any change if something goes wrong
1226
                conn.rollback()
1227
                print('error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
1228
                                                          sys.exc_info()[-1].tb_lineno))
1229

    
1230
    '''
1231
        @brief  get project list from database
1232
        @history    humkyung 2018.04.18 add only project which's project exists
1233
    '''
1234

    
1235
    def getProjectList(self):
1236
        from Project import Project
1237

    
1238
        projectList = []
1239

    
1240
        conn = sqlite3.connect(self.getPrjDatabasePath())
1241
        with conn:
1242
            conn.row_factory = sqlite3.Row
1243
            cursor = conn.cursor()
1244
            sql = "select a.Id,a.Name,a.[Desc],a.[Unit],a.Path,a.CreatedDate,a.UpdatedDate,\
1245
                (select \
1246
                CASE \
1247
                WHEN b.DBTypes_UID is NULL THEN 'SQLite' \
1248
                ELSE (select Name from DBTypes where UID=b.DBTypes_UID) \
1249
                END \
1250
                ) DBType,b.Host,b.User,b.Password \
1251
                from projects a left join dbsettings b on a.Id=b.Projects_UID order by strftime(a.UpdatedDate) desc"
1252
            try:
1253
                cursor.execute(sql)
1254
                rows = cursor.fetchall()
1255
                for row in rows:
1256
                    if os.path.isdir(row['Path']):  # check if folder exists
1257
                        projectList.append(Project(row))
1258
            except Exception as ex:
1259
                print('error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
1260
                                                          sys.exc_info()[-1].tb_lineno))
1261

    
1262
        return projectList
1263

    
1264
    '''
1265
        @brief  get sliding window size
1266
        @author humkyung
1267
    '''
1268

    
1269
    def getSlidingWindowSize(self):
1270
        res = [25, 20]
1271
        try:
1272
            configs = self.getConfigs('Sliding Window')
1273
            for config in configs:
1274
                if config.key == 'Width':
1275
                    res[0] = int(config.value)
1276
                elif config.key == 'Height':
1277
                    res[1] = int(config.value)
1278
        # Catch the exception
1279
        except Exception as ex:
1280
            print('error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
1281
                                                      sys.exc_info()[-1].tb_lineno))
1282

    
1283
        return res
1284

    
1285
    '''
1286
        @brief  get line no configuration
1287
        @author humkyung
1288
        @date   2018.04.16
1289
    '''
1290

    
1291
    def getLineNoConfiguration(self):
1292
        res = None
1293

    
1294
        conn = self.project.database.connect()
1295
        with conn:
1296
            try:
1297
                # Get a cursor object
1298
                cursor = conn.cursor()
1299

    
1300
                delimiter = None
1301
                sql = "select * from configuration where section='Line No' and key='Delimiter"
1302
                cursor.execute(sql)
1303
                rows = cursor.fetchall()
1304
                if len(rows) == 1:
1305
                    delimiter = rows[0][2]
1306

    
1307
                if delimiter is not None:
1308
                    sql = "select * from configuration where section='Line No' and key='Configuration'"
1309
                    cursor.execute(sql)
1310
                    rows = cursor.fetchall()
1311
                    if len(rows) == 1:
1312
                        res = rows[0][2].split(delimiter)
1313
            # Catch the exception
1314
            except Exception as ex:
1315
                print('error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
1316
                                                          sys.exc_info()[-1].tb_lineno))
1317

    
1318
        return res
1319

    
1320
    '''
1321
        @brief  get area list
1322
        @author humkyung
1323
        @history    euisung     2018.11.20 (0,0),(0,0) process add
1324
    '''
1325

    
1326
    def getAreaList(self):
1327
        from Area import Area
1328

    
1329
        if len(self._areas) == 0:
1330
            conn = self.project.database.connect()
1331
            with conn:
1332
                try:
1333
                    # Get a cursor object
1334
                    cursor = conn.cursor()
1335

    
1336
                    sql = "select * from configuration where section='Area'"
1337
                    cursor.execute(sql)
1338
                    rows = cursor.fetchall()
1339
                    for row in rows:
1340
                        name = row['Key']
1341
                        area = Area(name)
1342
                        area.parse(row['Value'])
1343
                        self._areas.append(area)
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 self._areas
1350

    
1351
    '''
1352
        @brief  get area of given name
1353
        @author humkyung
1354
        @date   2018.04.07
1355
    '''
1356

    
1357
    def getArea(self, name):
1358
        areas = self.getAreaList()
1359
        matches = [area for area in areas if area.name == name]
1360
        if 1 == len(matches) and matches[0].height is not 0 and matches[0].width is not 0:
1361
            return matches[0]
1362

    
1363
        return None
1364

    
1365
    def getConfigs(self, section, key=None):
1366
        """ get configurations from database """
1367
        res = []
1368

    
1369
        if self._configs is None:
1370
            self._configs = []
1371
            with self.project.database.connect() as conn:
1372
                try:
1373
                    # Get a cursor object
1374
                    cursor = conn.cursor()
1375

    
1376
                    sql = "select * from configuration"
1377

    
1378
                    cursor.execute(sql)
1379
                    rows = cursor.fetchall()
1380
                    for row in rows:
1381
                        self._configs.append(Config(row['Section'], row['Key'], row['Value']))
1382
                # Catch the exception
1383
                except Exception as ex:
1384
                    print('error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
1385
                                                              sys.exc_info()[-1].tb_lineno))
1386

    
1387
        if key is not None:
1388
            return [con for con in self._configs if con.section == section and con.key == key]
1389
        else:
1390
            return [con for con in self._configs if con.section == section]
1391

    
1392
        return res
1393

    
1394
    def getAppConfigs(self, section, key=None):
1395
        """get application configurations"""
1396

    
1397
        res = []
1398

    
1399
        # Creates or opens a file called mydb with a SQLite3 DB
1400
        dbPath = self.getAppDbPath()
1401
        with sqlite3.connect(dbPath) as conn:
1402
            try:
1403
                # Get a cursor object
1404
                cursor = conn.cursor()
1405

    
1406
                if key is not None:
1407
                    sql = "select * from configuration where section=? and key=?"
1408
                    param = (section, key)
1409
                else:
1410
                    sql = "select * from configuration where section=?"
1411
                    param = (section,)
1412

    
1413
                cursor.execute(sql, param)
1414
                rows = cursor.fetchall()
1415
                for row in rows:
1416
                    res.append(Config(row[0], row[1], row[2]))
1417
            # Catch the exception
1418
            except Exception as ex:
1419
                print('error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
1420
                                                          sys.exc_info()[-1].tb_lineno))
1421

    
1422
        return res
1423

    
1424
    '''
1425
        @brief      save configurations
1426
        @author     humkyung
1427
        @date       2018.04.16
1428
        @history    humkyung 2018.07.03 replace ' with " if value has '
1429
                    kyouho 2018.07.09 change query method
1430
    '''
1431

    
1432
    def saveConfigs(self, configs):
1433
        with self.project.database.connect() as conn:
1434
            try:
1435
                # Get a cursor object
1436
                cursor = conn.cursor()
1437
                if self.project.database.db_type == 'SQLite':
1438
                    cursor.execute('begin')
1439

    
1440
                for config in configs:
1441
                    if type(config) is Config:
1442
                        value = config.value
1443
                        if type(value) is str and "'" in value:
1444
                            value = value.replace("'", "''")
1445

    
1446
                        sql = self.project.database.to_sql(
1447
                            "insert into configuration(Section,[Key],Value) select ?,?,? where not exists(select 1 from configuration where Section=? and [Key]=?)")
1448
                        param = (config.section, config.key, str(value), config.section, config.key)
1449
                        cursor.execute(sql, param)
1450
                        sql = self.project.database.to_sql(
1451
                            "update configuration set Value=? where Section=? and [Key]=?")
1452
                        param = (str(value), config.section, config.key)
1453
                        cursor.execute(sql, param)
1454
                    elif hasattr(config, 'toSql'):
1455
                        sql = config.toSql()
1456
                        if type(sql) is list:
1457
                            for item in sql:
1458
                                if item is not None and 2 == len(item):
1459
                                    cursor.execute(self.project.database.to_sql(item[0]), item[1])
1460
                        else:
1461
                            if sql is not None and 2 == len(sql):
1462
                                cursor.execute(self.project.database.to_sql(sql[0]), sql[1])
1463
                self._configs = None  # reset config table
1464

    
1465
                if self.project.database.db_type == 'SQLite':
1466
                    cursor.execute('commit')
1467
                else:
1468
                    conn.commit()
1469
            # Catch the exception
1470
            except Exception as ex:
1471
                # Roll back any change if something goes wrong
1472
                conn.rollback()
1473

    
1474
                from App import App
1475
                message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
1476
                                                              sys.exc_info()[-1].tb_lineno)
1477
                App.mainWnd().addMessage.emit(MessageType.Error, message)
1478

    
1479
    def saveAppConfigs(self, configs):
1480
        """save application configurations"""
1481

    
1482
        # Creates or opens a file called mydb with a SQLite3 DB
1483
        dbPath = self.getAppDbPath()
1484
        with sqlite3.connect(dbPath) as conn:
1485
            try:
1486
                # Get a cursor object
1487
                cursor = conn.cursor()
1488

    
1489
                for config in configs:
1490
                    value = config.value
1491
                    if type(value) is str and "'" in value:
1492
                        value = value.replace("'", "''")
1493

    
1494
                    sql = "insert or replace into configuration values(?,?,?)"
1495
                    param = (config.section, config.key, value)
1496

    
1497
                    cursor.execute(sql, param)
1498
                conn.commit()
1499
            # Catch the exception
1500
            except Exception as ex:
1501
                # Roll back any change if something goes wrong
1502
                conn.rollback()
1503
                print('error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
1504
                                                          sys.exc_info()[-1].tb_lineno))
1505

    
1506
    def updateProjectUnit(self, unit):
1507
        """save project configurations"""
1508

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

    
1516
                sql = "update Projects set [Unit]=? where [Id]=?"
1517
                param = (unit, self.project.getId())
1518

    
1519
                cursor.execute(sql, param)
1520
                conn.commit()
1521
            # Catch the exception
1522
            except Exception as ex:
1523
                # Roll back any change if something goes wrong
1524
                conn.rollback()
1525
                
1526
                from App import App
1527
                message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
1528
                                                              sys.exc_info()[-1].tb_lineno)
1529
                App.mainWnd().addMessage.emit(MessageType.Error, message)
1530

    
1531
    '''
1532
        @brief  delete configurations
1533
        @author humkyung
1534
        @date   2018.06.29
1535
    '''
1536
    def deleteConfigs(self, section, key=None):
1537
        conn = self.project.database.connect()
1538
        with conn:
1539
            try:
1540
                # Get a cursor object
1541
                cursor = conn.cursor()
1542

    
1543
                if key is not None:
1544
                    sql = "delete from configuration where section='{}' and key='{}'".format(section, key)
1545
                else:
1546
                    sql = "delete from configuration where section='{}'".format(section)
1547
                cursor.execute(sql)
1548

    
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
                print('error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
1555
                                                          sys.exc_info()[-1].tb_lineno))
1556

    
1557
    def deleteAppConfigs(self, section, key=None):
1558
        """
1559
        @brief  delete application configurations
1560
        @author humkyung
1561
        @date   2018.11.01
1562
        """
1563

    
1564
        # Creates or opens a file called mydb with a SQLite3 DB
1565
        dbPath = self.getAppDbPath()
1566
        conn = sqlite3.connect(dbPath)
1567
        with 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
                print('error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
1584
                                                          sys.exc_info()[-1].tb_lineno))
1585

    
1586
    '''
1587
        @brief      set area list
1588
        @history    humkyung 2018.05.18 round area coordinate and dimension before saving
1589
        @history    euisung  2018.11.20 add self._area reset process
1590
    '''
1591

    
1592
    def setAreaList(self, areas):
1593
        for area in areas:
1594
            matches = [x for x in self._areas if x.name == area.name]
1595
            if 1 == len(matches):
1596
                matches[0].x = area.x
1597
                matches[0].y = area.y
1598
                matches[0].width = area.width
1599
                matches[0].height = area.height
1600
            elif 0 == len(matches):
1601
                self._areas.append(area)
1602

    
1603
        # Creates or opens a file called mydb with a SQLite3 DB
1604
        conn = self.project.database.connect()
1605
        with conn:
1606
            try:
1607
                # Get a cursor object
1608
                cursor = conn.cursor()
1609

    
1610
                for area in self._areas:
1611
                    sql = "insert into configuration select 'Area','{}','({},{}),({},{})' where not exists(select 1 from configuration where Section='Area' and [Key]='{}')".format(
1612
                        area.name, round(area.x), round(area.y), round(area.width), round(area.height), area.name)
1613
                    cursor.execute(sql)
1614
                    sql = "update configuration set Value='({},{}),({},{})' where Section='Area' and [Key]='{}'".format(
1615
                        round(area.x), round(area.y), round(area.width), round(area.height), area.name)
1616
                    cursor.execute(sql)
1617
                conn.commit()
1618
            # Catch the exception
1619
            except Exception as ex:
1620
                # Roll back any change if something goes wrong
1621
                conn.rollback()
1622

    
1623
                from App import App
1624
                message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
1625
                                                              sys.exc_info()[-1].tb_lineno)
1626
                App.mainWnd().addMessage.emit(MessageType.Error, message)
1627
            finally:
1628
                # Close the db connection
1629
                self._areas = []
1630

    
1631
    def getSymbolNameList(self):
1632
        """ get symbol name list """
1633
        symbolNametList = []
1634

    
1635
        conn = self.project.database.connect()
1636
        with conn:
1637
            cursor = conn.cursor()
1638
            sql = 'SELECT * FROM SymbolName'
1639
            try:
1640
                cursor.execute(sql)
1641
                rows = cursor.fetchall()
1642
                for row in rows:
1643
                    symbolNametList.append(row['Name'])  # Name String
1644
            except Exception as ex:
1645
                print('error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
1646
                                                          sys.exc_info()[-1].tb_lineno))
1647

    
1648
        return symbolNametList
1649

    
1650
    '''
1651
        @brief      get symbol name list by symbol Type
1652
        @author     Jeongwoo
1653
        @date       18.04.06
1654
        @history    .
1655
    '''
1656

    
1657
    def getSymbolNameListByType(self, type):
1658
        symbolNametList = []
1659

    
1660
        conn = self.project.database.connect()
1661
        with conn:
1662
            cursor = conn.cursor()
1663
            sql = ''
1664
            if type is not None:
1665
                sql = self.project.database.to_sql('SELECT * FROM SymbolName WHERE [Type]=?')
1666
                try:
1667
                    cursor.execute(sql, (type,))
1668
                    rows = cursor.fetchall()
1669
                    for row in rows:
1670
                        symbolNametList.append(row['Name'])  # Name String
1671
                except Exception as ex:
1672
                    print('error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
1673
                                                              sys.exc_info()[-1].tb_lineno))
1674

    
1675
        return symbolNametList
1676

    
1677
    '''
1678
        @brief  delete added symbol data
1679
    '''
1680

    
1681
    def deleteSymbol(self, fileName):
1682
        ret = False
1683

    
1684
        conn = self.project.database.connect()
1685
        with conn:
1686
            try:
1687
                cursor = conn.cursor()
1688
                sql = self.project.database.to_sql("DELETE FROM Symbol WHERE name = ?")
1689
                try:
1690
                    cursor.execute(sql, (fileName,))
1691
                    conn.commit()
1692
                    ret = True
1693
                except Exception as ex:
1694
                    conn.rollback()
1695
                    print('error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
1696
                                                              sys.exc_info()[-1].tb_lineno))
1697
                    ret = False
1698
            finally:
1699
                self._symbolBase = {}
1700
                return (ret, fileName)
1701

    
1702
    '''
1703
        @brief  get symbol name
1704
        @history    18.04.24    Jeongwoo    Add isExceptDetect Field
1705
    '''
1706

    
1707
    def getSymbolByQuery(self, fieldName, param):
1708
        ret = None
1709

    
1710
        if fieldName in self._symbolBase:
1711
            if param in self._symbolBase[fieldName]:
1712
                ret = self._symbolBase[fieldName][param]
1713
                return ret
1714
        else:
1715
            self._symbolBase[fieldName] = {}
1716

    
1717
        with self.project.database.connect() as conn:
1718
            cursor = conn.cursor()
1719
            sql = self.project.database.to_sql(f"SELECT a.UID as UID,a.Name,b.Type,a.Threshold,a.MinMatchPoint,"
1720
                                               f"a.IsDetectOrigin,a.RotationCount,a.OCROption,a.IsContainChild,"
1721
                                               f"a.OriginalPoint,a.ConnectionPoint,a.BaseSymbol,a.AdditionalSymbol,"
1722
                                               f"a.IsExceptDetect,a.HasInstrumentLabel,a.flip,a.TextArea,b.UID as DB_UID FROM "
1723
                                               f"Symbol a inner join SymbolType b on a.SymbolType_UID=b.UID WHERE "
1724
                                               f"a.{fieldName}=?")
1725
            try:
1726
                cursor.execute(sql, (param,))
1727
                rows = cursor.fetchall()
1728
                if rows is not None and len(rows) > 0:
1729
                    symbolTuple = rows[0]
1730
                    ret = symbol.SymbolBase(symbolTuple['Name'], symbolTuple['Type'], symbolTuple['Threshold']
1731
                                            , symbolTuple['MinMatchPoint'], symbolTuple['IsDetectOrigin'],
1732
                                            symbolTuple['RotationCount'], symbolTuple['OCROption'],
1733
                                            symbolTuple['IsContainChild'], symbolTuple['OriginalPoint'],
1734
                                            symbolTuple['ConnectionPoint'], symbolTuple['BaseSymbol'],
1735
                                            symbolTuple['AdditionalSymbol'], symbolTuple['IsExceptDetect'],
1736
                                            symbolTuple['HasInstrumentLabel'], symbolTuple['UID'],
1737
                                            iType=symbolTuple['DB_UID'], detectFlip=symbolTuple['flip'],
1738
                                            text_area=symbolTuple['TextArea'])
1739
                    self._symbolBase[fieldName][param] = ret
1740
            except Exception as ex:
1741
                print('error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
1742
                                                          sys.exc_info()[-1].tb_lineno))
1743

    
1744
        return ret
1745

    
1746
    '''
1747
        @brief  get symbol name list
1748
        @history    18.04.24    Jeongwoo    Add isExceptDetect Field
1749
    '''
1750

    
1751
    def getSymbolListByType(self, field_name=None, param=None):
1752
        ret = []
1753

    
1754
        with self.project.database.connect() as conn:
1755
            cursor = conn.cursor()
1756
            if field_name is not None and param is not None:
1757
                sql = """SELECT a.UID,a.Name,b.Type,a.Threshold,a.MinMatchPoint,a.IsDetectOrigin,a.RotationCount,
1758
                a.OCROption,a.IsContainChild,a.OriginalPoint,a.ConnectionPoint,a.BaseSymbol,a.AdditionalSymbol,
1759
                a.IsExceptDetect,a.HasInstrumentLabel,a.flip,a.TextArea,b.UID as DB_UID FROM Symbol a 
1760
                inner join SymbolType b on a.SymbolType_UID=b.UID WHERE 
1761
                SymbolType_UID = (select UID from SymbolType where {}={})""".format(
1762
                    field_name, self.project.database.place_holder)
1763
            else:
1764
                sql = """SELECT a.UID,a.Name,b.Type,a.Threshold,a.MinMatchPoint,a.IsDetectOrigin,a.RotationCount, 
1765
                a.OCROption,a.IsContainChild,a.OriginalPoint,a.ConnectionPoint,a.BaseSymbol,a.AdditionalSymbol,
1766
                a.IsExceptDetect,a.HasInstrumentLabel,a.flip FROM Symbol a 
1767
                inner join SymbolType b on a.SymbolType_UID=b.UID"""
1768
            try:
1769
                cursor.execute(sql, (param,)) if param is not None else cursor.execute(sql)
1770
                rows = cursor.fetchall()
1771
                if rows is not None and len(rows) > 0:
1772
                    for symbolTuple in rows:
1773
                        sym = symbol.SymbolBase(symbolTuple['Name'], symbolTuple['Type'], symbolTuple['Threshold'],
1774
                                                symbolTuple['MinMatchPoint'], symbolTuple['IsDetectOrigin'],
1775
                                                symbolTuple['RotationCount'], symbolTuple['OCROption'],
1776
                                                symbolTuple['IsContainChild'], symbolTuple['OriginalPoint'],
1777
                                                symbolTuple['ConnectionPoint'], symbolTuple['BaseSymbol'],
1778
                                                symbolTuple['AdditionalSymbol'], symbolTuple['IsExceptDetect'],
1779
                                                symbolTuple['HasInstrumentLabel'], symbolTuple['UID'],
1780
                                                iType=symbolTuple['DB_UID'],
1781
                                                detectFlip=symbolTuple['flip'], text_area=symbolTuple['TextArea'])
1782
                        ret.append(sym)
1783
            except Exception as ex:
1784
                print('error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
1785
                                                          sys.exc_info()[-1].tb_lineno))
1786

    
1787
        return ret
1788

    
1789
    '''
1790
        @brief      get NominalDiameter
1791
        @author     humkyung
1792
        @date       2018.04.20
1793
        @history    humkyung 2018.04.24 read MetricStr column and set size unit
1794
                    kyouho 2018.07.04 forCheckLineNumber get only inch or metric
1795
                    kyouho 2018.07.16 edit query order by code
1796
    '''
1797

    
1798
    def getNomialPipeSizeData(self, forCheckLineNumber=False, orderStr="MetricStr"):
1799
        res = []
1800
        configs = self.getConfigs('Line No', 'Size Unit')
1801
        sizeUnit = configs[0].value if 1 == len(configs) else 'Metric'
1802

    
1803
        conn = self.project.database.connect()
1804
        with conn:
1805
            try:
1806
                # Get a cursor object
1807
                cursor = conn.cursor()
1808

    
1809
                sql = f"select UID,Code,Metric,Inch,InchStr,AllowableInchStr,MetricStr,AllowableMetricStr from " \
1810
                      f"NominalDiameter ORDER BY {orderStr} DESC"
1811
                cursor.execute(sql)
1812
                rows = cursor.fetchall()
1813
                for row in rows:
1814
                    pipeSize = NominalPipeSize(row['UID'], row['Code'], float(row['Metric']) if row['Metric'] else None,
1815
                                               float(row['Inch']) if row['Inch'] else None, row['InchStr'],
1816
                                               row['AllowableInchStr'], row['MetricStr'], row['AllowableMetricStr'])
1817
                    pipeSize.sizeUnit = sizeUnit
1818
                    if forCheckLineNumber:
1819
                        if sizeUnit == 'Inch' and pipeSize.inchStr:
1820
                            res.append(pipeSize.inchStr)
1821
                        elif sizeUnit == 'Metric' and pipeSize.metricStr:
1822
                            res.append(pipeSize.metricStr)
1823
                    else:
1824
                        res.append(pipeSize)
1825

    
1826
                if 'Inch' in sizeUnit:
1827
                    res = sorted(res, key=lambda param:len(param.inchStr), reverse=True)
1828
                else:
1829
                    res = sorted(res, key=lambda param:len(param.metricStr), reverse=True)
1830
            # Catch the exception
1831
            except Exception as ex:
1832
                from App import App
1833
                message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
1834
                                                              sys.exc_info()[-1].tb_lineno)
1835
                App.mainWnd().addMessage.emit(MessageType.Error, message)
1836

    
1837
        return res
1838

    
1839
    '''
1840
        @brief      insert NominalDiameter table
1841
        @author     kyouho
1842
        @date       2018.07.16
1843
    '''
1844

    
1845
    def insertNomialPipeSize(self, pipeSizes):
1846
        conn = self.project.database.connect()
1847
        with conn:
1848
            try:
1849
                # Get a cursor object
1850
                cursor = conn.cursor()
1851
                for pipeSize in pipeSizes:
1852
                    sql = pipeSize.toSql()
1853
                    if type(sql) is list and len(sql) == 1:
1854
                        cursor.execute(self.project.database.to_sql(sql[0][0]), sql[0][1])
1855

    
1856
                conn.commit()
1857
            # Catch the exception
1858
            except Exception as ex:
1859
                # Roll back any change if something goes wrong
1860
                conn.rollback()
1861

    
1862
                from App import App
1863
                message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
1864
                                                              sys.exc_info()[-1].tb_lineno)
1865
                App.mainWnd().addMessage.emit(MessageType.Error, message)
1866

    
1867
    '''
1868
        @brief      delete NominalDiameter table
1869
        @author     kyouho
1870
        @date       2018.07.16
1871
    '''
1872

    
1873
    def deleteNomialPipeSize(self):
1874
        conn = self.project.database.connect()
1875
        with conn:
1876
            cursor = conn.cursor()
1877
            sql = "DELETE FROM NominalDiameter"
1878
            try:
1879
                cursor.execute(sql)
1880
                conn.commit()
1881
            except Exception as ex:
1882
                conn.rollback()
1883
                print('error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
1884
                                                          sys.exc_info()[-1].tb_lineno))
1885

    
1886
    '''
1887
        @brief      convert inch to metric
1888
        @author     kyouho
1889
        @date       2018.07.09
1890
    '''
1891

    
1892
    def convertInchToMetric(self, inch):
1893
        result = ''
1894
        conn = self.project.database.connect()
1895
        with conn:
1896
            try:
1897
                # Get a cursor object
1898
                cursor = conn.cursor()
1899

    
1900
                sql = "select MetricStr from NominalDiameter WHERE InchStr = ?"
1901
                param = (inch,)
1902
                cursor.execute(sql, param)
1903
                rows = cursor.fetchall()
1904

    
1905
                if rows:
1906
                    result = rows[0][0]
1907
                # Catch the exception
1908
            except Exception as ex:
1909
                print('error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
1910
                                                          sys.exc_info()[-1].tb_lineno))
1911

    
1912
        return result
1913

    
1914
    '''
1915
        @brief      get Color MaxUID
1916
        @author     kyouho
1917
        @date       2018.07.03
1918
    '''
1919

    
1920
    def getMaxColorUID(self):
1921
        result = 0
1922

    
1923
        conn = self.project.database.connect()
1924
        with conn:
1925
            try:
1926
                # Get a cursor object
1927
                cursor = conn.cursor()
1928

    
1929
                sql = "select MAX(UID) from Colors"
1930
                cursor.execute(sql)
1931
                rows = cursor.fetchall()
1932

    
1933
                result = rows[0][0]
1934
                # Catch the exception
1935
            except Exception as ex:
1936
                print('error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
1937
                                                          sys.exc_info()[-1].tb_lineno))
1938

    
1939
        return result
1940

    
1941
    '''
1942
        @brief      insert Color property
1943
        @author     kyouho
1944
        @date       2018.07.09
1945
    '''
1946

    
1947
    def setPropertyColor(self, _color):
1948
        conn = self.project.database.connect()
1949
        with conn:
1950
            try:
1951
                # Get a cursor object
1952
                cursor = conn.cursor()
1953
                sql = "INSERT INTO Colors(UID, RED, GREEN, BLUE, PROPERTY, VALUE) VALUES(?,?,?,?,?,?)"
1954
                param = (_color.index, _color.red, _color.green, _color.blue, _color._property, _color.value)
1955
                cursor.execute(sql, param)
1956
                conn.commit()
1957
            # Catch the exception
1958
            except Exception as ex:
1959
                # Roll back any change if something goes wrong
1960
                conn.rollback()
1961
                print('error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
1962
                                                          sys.exc_info()[-1].tb_lineno))
1963

    
1964
    '''
1965
        @brief      delete Color property
1966
        @author     kyouho
1967
        @date       2018.07.09
1968
    '''
1969

    
1970
    def deletePropertyColor(self, property):
1971
        conn = self.project.database.connect()
1972
        with conn:
1973
            try:
1974
                # Get a cursor object
1975
                cursor = conn.cursor()
1976

    
1977
                sql = "DELETE FROM Colors WHERE PROPERTY = '{}'".format(property)
1978
                cursor.execute(sql)
1979
                conn.commit()
1980
                # Catch the exception
1981
            except Exception as ex:
1982
                # Roll back any change if something goes wrong
1983
                conn.rollback()
1984
                print('error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
1985
                                                          sys.exc_info()[-1].tb_lineno))
1986

    
1987
    '''
1988
        @brief      get Fluid Code
1989
        @author     kyouho
1990
        @date       2018.07.03
1991
        @history    kyouho 2018.07.04 kyouho 2018.07.04 forCheckLineNumber get only code
1992
    '''
1993

    
1994
    def getFluidCodeData(self, forCheckLineNumber=False):
1995
        from FluidCodeData import FluidCodeData
1996
        result = []
1997

    
1998
        conn = self.project.database.connect()
1999
        with conn:
2000
            try:
2001
                # Get a cursor object
2002
                cursor = conn.cursor()
2003

    
2004
                sql = 'select uid, code, description from FluidCode order by length(code) DESC'
2005
                cursor.execute(sql)
2006
                rows = cursor.fetchall()
2007
                for row in rows:
2008
                    data = FluidCodeData(row[0], row[1], row[2])
2009
                    if forCheckLineNumber:
2010
                        result.append(data.code)
2011
                    else:
2012
                        result.append(data)
2013
                # Catch the exception
2014
            except Exception as ex:
2015
                print('error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
2016
                                                          sys.exc_info()[-1].tb_lineno))
2017

    
2018
        return result
2019

    
2020
    '''
2021
        @brief      get Symbol Attribute
2022
        @author     kyouho
2023
        @date       2018.07.18
2024
    '''
2025

    
2026
    def checkAttribute(self, attr):
2027
        conn = self.project.database.connect()
2028
        with conn:
2029
            try:
2030
                # Get a cursor object
2031
                cursor = conn.cursor()
2032

    
2033
                sql = 'select UID from SymbolAttribute where UID = ?'
2034
                param = (attr,)
2035
                cursor.execute(sql, param)
2036
                rows = cursor.fetchall()
2037
                if len(rows):
2038
                    return True
2039
                else:
2040
                    return False
2041
                # Catch the exception
2042
            except Exception as ex:
2043
                print('error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
2044
                                                          sys.exc_info()[-1].tb_lineno))
2045

    
2046
        return False
2047

    
2048
    def read_drawing_shape(self, drawing):
2049
        """read drawing shape"""
2050

    
2051
        res = None
2052

    
2053
        with self.project.database.connect() as conn:
2054
            try:
2055
                # Get a cursor object
2056
                cursor = conn.cursor()
2057

    
2058
                sql = f"select Image from Drawings where UID='{drawing}'"
2059
                cursor.execute(sql)
2060
                records = cursor.fetchall()
2061
                for record in records:
2062
                    res = record[0]
2063
                    break
2064

    
2065
            # Catch the exception
2066
            except Exception as ex:
2067
                from App import App
2068
                # Roll back any change if something goes wrong
2069
                conn.rollback()
2070

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

    
2075
        return res
2076

    
2077
    def read_symbol_shape(self, symbol_name):
2078
        """read symbol shape(image and svg)"""
2079

    
2080
        
2081
        res = (None, None)
2082

    
2083
        # need to test on mssql
2084
        return res
2085

    
2086
        with self.project.database.connect() as conn:
2087
            try:
2088
                # Get a cursor object
2089
                cursor = conn.cursor()
2090

    
2091
                sql = f"select Image, Svg from Symbol where Name='{symbol_name}'"
2092
                cursor.execute(sql)
2093
                records = cursor.fetchall()
2094
                for record in records:
2095
                    res = (record[0], record[1])
2096
                    break
2097

    
2098
            # Catch the exception
2099
            except Exception as ex:
2100
                from App import App
2101
                # Roll back any change if something goes wrong
2102
                conn.rollback()
2103

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

    
2108
        return res
2109

    
2110

    
2111
    def update_symbol_shape(self, symbol_name, image_file, svg_file, image_display_file):
2112
        """update symbol shape"""
2113

    
2114
        # need to test on mssql
2115
        return
2116

    
2117
        with self.project.database.connect() as conn:
2118
            try:
2119
                # Get a cursor object
2120
                cursor = conn.cursor()
2121

    
2122
                cols = []
2123
                params = []
2124

    
2125
                image_blob_data = None
2126
                if image_file and os.path.isfile(image_file):
2127
                    with open(image_file, 'rb') as file:
2128
                        image_blob_data = file.read()
2129
                    cols.append('Image=?')
2130
                    params.append(image_blob_data)
2131

    
2132
                svg_blob_data = None
2133
                if svg_file and os.path.isfile(svg_file):
2134
                    with open(svg_file, 'rb') as file:
2135
                        svg_blob_data = file.read()
2136
                    cols.append('Svg=?')
2137
                    params.append(svg_blob_data)
2138

    
2139
                image_display_blob_data = None
2140
                if image_file and image_display_file and os.path.isfile(image_display_file):
2141
                    with open(image_file, 'rb') as file:
2142
                        image_display_blob_data = file.read()
2143
                    cols.append('Image_display=?')
2144
                    params.append(image_display_blob_data)
2145

    
2146
                sql = f"update Symbol set {','.join(cols)} where Name='{symbol_name}'"
2147
                # Convert data into tuple format
2148
                cursor.execute(self.project.database.to_sql(sql), tuple(params))
2149
                conn.commit()
2150

    
2151
            # Catch the exception
2152
            except Exception as ex:
2153
                from App import App
2154
                # Roll back any change if something goes wrong
2155
                conn.rollback()
2156

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

    
2161
    def getReplaceTables(self):
2162
        ''' get replace(inst) code tables '''
2163

    
2164
        import uuid
2165
        from CodeTables import CodeTable
2166

    
2167
        with self.project.database.connect() as conn:
2168
            try:
2169
                result = []
2170

    
2171
                # Get a cursor object
2172
                cursor = conn.cursor()
2173

    
2174
                sql = self.project.database.to_sql('select UID, Name, Description from InstTables')
2175
                cursor.execute(sql)
2176
                rows = cursor.fetchall()
2177
                for row in rows:
2178
                    table = []
2179
                    table.append(uuid.UUID(row['UID']))
2180
                    table.append(row['Name'])
2181
                    table.append(row['Description'])
2182
                    table.append(CodeTable.instance('InstCodes', inst_table_uid=row['UID']))
2183
                    result.append(table)
2184
            # Catch the exception
2185
            except Exception as ex:
2186
                from App import App
2187
                message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
2188
                                                              sys.exc_info()[-1].tb_lineno)
2189
                App.mainWnd().addMessage.emit(MessageType.Error, message)
2190

    
2191
        return result
2192

    
2193
    def getCustomTables(self):
2194
        ''' get custom code tables '''
2195

    
2196
        import uuid
2197
        from CodeTables import CodeTable
2198

    
2199
        with self.project.database.connect() as conn:
2200
            try:
2201
                result = []
2202

    
2203
                # Get a cursor object
2204
                cursor = conn.cursor()
2205

    
2206
                sql = self.project.database.to_sql('select UID, Name, Description from CustomTables')
2207
                cursor.execute(sql)
2208
                rows = cursor.fetchall()
2209
                for row in rows:
2210
                    table = []
2211
                    table.append(uuid.UUID(row['UID']))
2212
                    table.append(row['Name'])
2213
                    table.append(row['Description'])
2214
                    table.append(CodeTable.instance('CustomCodes', custom_table_uid=row['UID']))
2215
                    result.append(table)
2216
            # Catch the exception
2217
            except Exception as ex:
2218
                from App import App
2219
                message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
2220
                                                              sys.exc_info()[-1].tb_lineno)
2221
                App.mainWnd().addMessage.emit(MessageType.Error, message)
2222

    
2223
        return result
2224

    
2225
    '''
2226
        @brief      get Symbol Attribute
2227
        @author     kyouho
2228
        @date       2018.07.18
2229
        @history    humkyung 2018.10.13 load expression
2230
    '''
2231
    def getSymbolAttribute(self, _type):
2232
        import uuid
2233
        from SymbolAttr import SymbolAttr
2234
        from CodeTables import CodeTable
2235

    
2236
        result = []
2237

    
2238
        if self._attributeByType and _type in self._attributeByType:
2239
            new_attr_without_any_binding_data = []
2240
            for attr_old in self._attributeByType[_type]:
2241
                attr = SymbolAttr()
2242
                attr.UID = attr_old.UID
2243
                attr.Attribute = attr_old.Attribute
2244
                attr.DisplayAttribute = attr_old.DisplayAttribute
2245
                attr.AttributeType = attr_old.AttributeType
2246
                attr.AttrAt = attr_old.AttrAt
2247
                attr.Expression = attr_old.Expression
2248
                attr.Target = attr_old.Target
2249
                attr.IsProp = attr_old.IsProp
2250
                attr.Codes = attr_old.Codes
2251
                new_attr_without_any_binding_data.append(attr)
2252
            self._attributeByType[_type] = new_attr_without_any_binding_data
2253

    
2254
            return self._attributeByType[_type]
2255

    
2256
        with self.project.database.connect() as conn:
2257
            try:
2258
                # Get a cursor object
2259
                cursor = conn.cursor()
2260

    
2261
                sql = self.project.database.to_sql(
2262
                    'select a.UID, a.Attribute, a.DisplayAttribute, a.AttributeType, a.[AttrAt], a.[Expression], '
2263
                    'a.[index], a.[Target], a.[Property] from SymbolAttribute a inner join SymbolType t '
2264
                    'on a.SymbolType_UID = t.UID and t.type = ? order by a.[index]')
2265
                param = (_type,)
2266
                cursor.execute(sql, param)
2267
                rows = cursor.fetchall()
2268
                for row in rows:
2269
                    attr = SymbolAttr()
2270
                    attr.UID = uuid.UUID(row['UID'])
2271
                    attr.Attribute = row['Attribute']
2272
                    attr.DisplayAttribute = row['DisplayAttribute']
2273
                    attr.AttributeType = row['AttributeType']
2274
                    attr.AttrAt = row['AttrAt']
2275
                    attr.Expression = row['Expression']
2276
                    attr.Target = row['Target']
2277
                    attr.IsProp = row['Property']
2278
                    attr.Codes = CodeTable.instance('SymbolAttributeCodeTable', symbol_attribute_uid=row['UID'])
2279
                    result.append(attr)
2280
            # Catch the exception
2281
            except Exception as ex:
2282
                from App import App
2283
                message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
2284
                                                              sys.exc_info()[-1].tb_lineno)
2285
                App.mainWnd().addMessage.emit(MessageType.Error, message)
2286

    
2287
        self._attributeByType[_type] = result
2288
        return result
2289

    
2290
    '''
2291
        @brief      get Symbol Attribute by UID
2292
        @author     kyouho
2293
        @date       2018.08.17
2294
        @history    humkyung 2018.10.13 load expression
2295
    '''
2296

    
2297
    def getSymbolAttributeByUID(self, UID):
2298
        from SymbolAttr import SymbolAttr
2299

    
2300
        res = None
2301

    
2302
        with self.project.database.connect() as conn:
2303
            try:
2304
                # Get a cursor object
2305
                cursor = conn.cursor()
2306

    
2307
                sql = f"select Attribute, DisplayAttribute, AttributeType, AttrAt, Expression, Target, Property from " \
2308
                      f"SymbolAttribute where uid = '{UID}'"
2309
                cursor.execute(sql)
2310
                rows = cursor.fetchall()
2311
                if len(rows):
2312
                    res = SymbolAttr()
2313
                    res.UID = UID
2314
                    res.Attribute = rows[0]['Attribute']
2315
                    res.DisplayAttribute = rows[0]['DisplayAttribute']
2316
                    res.AttributeType = rows[0]['AttributeType']
2317
                    res.AttrAt = rows[0]['AttrAt']
2318
                    res.Expression = rows[0]['Expression']
2319
                    res.Target = rows[0]['Target']
2320
                    res.IsProp = rows[0]['Property']
2321
                # Catch the exception
2322
            except Exception as ex:
2323
                from App import App
2324
                message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
2325
                                                              sys.exc_info()[-1].tb_lineno)
2326
                App.mainWnd().addMessage.emit(MessageType.Error, message)
2327

    
2328
        return res
2329

    
2330
    '''
2331
        @brief      save symbol attributes
2332
        @author     humkyung
2333
        @date       2018.08.14
2334
        @history    humkyung 2018.10.13 save expression
2335
    '''
2336
    def saveSymbolAttributes(self, type, attrs, type_str):
2337
        from CodeTables import CodeTable
2338

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

    
2344
                # delete symbol attribute code table data
2345
                origin_attrs = self.getSymbolAttribute(type_str)
2346
                for origin_attr in origin_attrs:
2347
                    '''
2348
                    # delete symbol attribute code table data for deleted symbol attribute, and backup not edited attribute code table data
2349
                    remain = False
2350
                    for attr in attrs:
2351
                        if str(origin_attr.UID) == attr[0]:
2352
                            remain = True
2353
                            break
2354
                    if remain and attr[-1] and type(attr[-1][0][3]) is list: # this means not edited and need backup
2355
                        attr[-1] = self.getCodeTable('SymbolAttributeCodeTable', forCheckLineNumber=False, symbol_attribute_uid=origin_attr.UID)
2356
                    '''
2357
                    
2358
                    sql = "delete from SymbolAttributeCodeTable where SymbolAttribute_UID = '{}'".format(origin_attr.UID)
2359
                    cursor.execute(sql)
2360
                # up to here
2361

    
2362
                # update symbol attribute
2363
                sql = self.project.database.to_sql('delete from SymbolAttribute where SymbolType_UID = ?')
2364
                param = (type,)
2365
                cursor.execute(sql, param)
2366

    
2367
                for attr in attrs:
2368
                    sql = self.project.database.to_sql(
2369
                        'insert into SymbolAttribute(UID, SymbolType_UID, Attribute, DisplayAttribute, AttributeType, '
2370
                        'AttrAt, Expression, Target, [index], [Property]) values(?, ?, ?, ?, ?, ?, ?, ?, ?, ?)')
2371
                    attr.insert(1, type)
2372
                    cursor.execute(sql, tuple(attr[:-1]))
2373
                # up to here
2374

    
2375
                # update symbol attribute code table data
2376
                for attr in attrs:
2377
                    if attr[-1]:
2378
                        for code in attr[-1]:
2379
                            sql = self.project.database.to_sql( \
2380
                                "insert into SymbolAttributeCodeTable(UID, Code, Description, Allowables, "
2381
                                "SymbolAttribute_UID) VALUES(?,?,?,?,?)")
2382
                            param = (code[0], code[1], code[2], ','.join(code[3]), attr[0])
2383
                            cursor.execute(sql, param)
2384
                # up to here
2385

    
2386
                conn.commit()
2387

    
2388
                if hasattr(self, '_equipment_attributes'):
2389
                    del self._equipment_attributes
2390

    
2391
                if hasattr(self, '_valve_attributes'):
2392
                    del self._valve_attributes
2393

    
2394
                if hasattr(self, '_inst_attributes'):
2395
                    del self._inst_attributes
2396

    
2397
                if hasattr(self, '_note_attributes'):
2398
                    del self._note_attributes
2399
            # Catch the exception
2400
            except Exception as ex:
2401
                # Roll back any change if something goes wrong
2402
                conn.rollback()
2403

    
2404
                from App import App
2405
                message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
2406
                                                              sys.exc_info()[-1].tb_lineno)
2407
                App.mainWnd().addMessage.emit(MessageType.Error, message)
2408

    
2409
            self._attributeByType = {}
2410
            CodeTable.clearTables()
2411

    
2412
    def get_hmb_attributes(self):
2413
        """get hmb attributes"""
2414
        from SymbolAttr import SymbolAttr
2415

    
2416
        attrs = []
2417
        with self.project.database.connect() as conn:
2418
            try:
2419
                # Get a cursor object
2420
                cursor = conn.cursor()
2421

    
2422
                sql = f"select * from SymbolAttribute where SymbolType_UID = " \
2423
                      f"(select UID from SymbolType where Type='HMB') order by [index]"
2424
                sql = self.project.database.to_sql(sql)
2425
                cursor.execute(sql)
2426
                rows = cursor.fetchall()
2427
                for row in rows:
2428
                    attr = SymbolAttr(row['UID'])
2429
                    attr.Attribute = row['Attribute']
2430
                    attr.DisplayAttribute = row['DisplayAttribute']
2431
                    attr.AttributeType = row['AttributeType']
2432
                    attr.AttrAt = row['AttrAt']
2433
                    attr.Expression = row['Expression']
2434
                    attr.Target = row['Target']
2435
                    attr.IsProp = row['Property']
2436

    
2437
                    attrs.append(attr)
2438

    
2439
            # Catch the exception
2440
            except Exception as ex:
2441
                # Roll back any change if something goes wrong
2442
                conn.rollback()
2443

    
2444
                from App import App
2445
                message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
2446
                                                               sys.exc_info()[-1].tb_lineno)
2447
                App.mainWnd().addMessage.emit(MessageType.Error, message)
2448

    
2449
        return attrs
2450

    
2451
    def save_hmb_attributes(self, attrs):
2452
        """save hmb attributes"""
2453
        from CodeTables import CodeTable
2454

    
2455
        with self.project.database.connect() as conn:
2456
            try:
2457
                # Get a cursor object
2458
                cursor = conn.cursor()
2459

    
2460
                # delete hmb attributes
2461
                sql = f"delete from SymbolAttribute where SymbolType_UID = (select UID from SymbolType where Type='HMB')"
2462
                sql = self.project.database.to_sql(sql)
2463
                cursor.execute(sql)
2464
                # up to here
2465

    
2466
                for idx, attr in enumerate(attrs):
2467
                    sql = self.project.database.to_sql(
2468
                        'insert into SymbolAttribute(UID, SymbolType_UID, Attribute, DisplayAttribute, AttributeType, '
2469
                        'AttrAt, Expression, Target, [index], [Property]) values(?, '
2470
                        '(select uid from SymbolType where Type=\'HMB\'), ?, ?, ?, ?, ?, ?, ?, ?)')
2471
                    params = (str(attr.UID), attr.Attribute, attr.Attribute, 'String', attr.AttrAt,
2472
                              attr.Expression if attr.Expression else None, attr.Target, idx, attr.IsProp)
2473

    
2474
                    cursor.execute(sql, params)
2475
                # up to here
2476

    
2477
                conn.commit()
2478

    
2479
            # Catch the exception
2480
            except Exception as ex:
2481
                # Roll back any change if something goes wrong
2482
                conn.rollback()
2483

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

    
2489

    
2490
    def saveCustomCodes(self, tables):
2491
        ''' save custom code tables and codes '''
2492

    
2493
        from CodeTables import CodeTable
2494

    
2495
        conn = self.project.database.connect()
2496
        with conn:
2497
            try:
2498
                # Get a cursor object
2499
                cursor = conn.cursor()
2500

    
2501
                # delete custom codes and tables
2502
                sql = "delete from CustomCodes"
2503
                cursor.execute(sql)
2504

    
2505
                sql = "delete from CustomTables"
2506
                cursor.execute(sql)
2507
                # up to here
2508

    
2509
                # update symbol attribute code table data
2510
                for table in tables:
2511
                    sql = self.project.database.to_sql("insert into CustomTables (UID, Name, Description) VALUES(?,?,?)")
2512
                    param = (table[0], table[1], table[2])
2513
                    cursor.execute(sql, param)
2514

    
2515
                    for code in table[3]:
2516
                        sql = self.project.database.to_sql( \
2517
                            "insert into CustomCodes(UID, Code, Description, Allowables, Table_UID) VALUES(?,?,?,?,?)")
2518
                        param = (code[0], code[1], code[2], ','.join(code[3]), table[0])
2519
                        cursor.execute(sql, param)
2520
                # up to here
2521

    
2522
                conn.commit()
2523

    
2524
            # Catch the exception
2525
            except Exception as ex:
2526
                # Roll back any change if something goes wrong
2527
                conn.rollback()
2528

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

    
2534
            CodeTable.clearTables()
2535

    
2536
    def saveReplaceCodes(self, tables):
2537
        ''' save repalce(inst) code tables and codes '''
2538

    
2539
        from CodeTables import CodeTable
2540

    
2541
        conn = self.project.database.connect()
2542
        with conn:
2543
            try:
2544
                # Get a cursor object
2545
                cursor = conn.cursor()
2546

    
2547
                # delete custom codes and tables
2548
                sql = "delete from InstCodes"
2549
                cursor.execute(sql)
2550

    
2551
                sql = "delete from InstTables"
2552
                cursor.execute(sql)
2553
                # up to here
2554

    
2555
                # update symbol attribute code table data
2556
                for table in tables:
2557
                    sql = self.project.database.to_sql("insert into InstTables (UID, Name, Description) VALUES(?,?,?)")
2558
                    param = (table[0], table[1], table[2])
2559
                    cursor.execute(sql, param)
2560

    
2561
                    for code in table[3]:
2562
                        sql = self.project.database.to_sql( \
2563
                            "insert into CustomCodes(UID, Code, Symbols, New Code, Table_UID) VALUES(?,?,?,?,?)")
2564
                        param = (code[0], code[1], ','.join(code[2]), code[3], table[0])
2565
                        cursor.execute(sql, param)
2566
                # up to here
2567

    
2568
                conn.commit()
2569

    
2570
            # Catch the exception
2571
            except Exception as ex:
2572
                # Roll back any change if something goes wrong
2573
                conn.rollback()
2574

    
2575
                from App import App
2576
                message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
2577
                                                              sys.exc_info()[-1].tb_lineno)
2578
                App.mainWnd().addMessage.emit(MessageType.Error, message)
2579

    
2580
            CodeTable.clearTables()
2581

    
2582
    '''
2583
        @brief      save symbol attributes
2584
        @author     humkyung
2585
        @date       2018.08.14
2586
    '''
2587
    def saveLineAttributes(self, attrs):
2588
        with self.project.database.connect() as conn:
2589
            try:
2590
                # Get a cursor object
2591
                cursor = conn.cursor()
2592

    
2593
                sql = 'delete from LineProperties'
2594
                cursor.execute(sql)
2595

    
2596
                for attr in attrs:
2597
                    sql = self.project.database.to_sql(
2598
                        'insert into LineProperties(UID, Name, DisplayName, Type, LimitNumber, [index]) values(?, ?, ?, ?, ?, ?)')
2599
                    cursor.execute(sql, tuple(attr))
2600

    
2601
                conn.commit()
2602

    
2603
                self._lineNoProperties = None
2604
                self._lineNoPropertiesUID = {}
2605
            # Catch the exception
2606
            except Exception as ex:
2607
                # Roll back any change if something goes wrong
2608
                conn.rollback()
2609

    
2610
                from App import App
2611
                message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
2612
                                                              sys.exc_info()[-1].tb_lineno)
2613
                App.mainWnd().addMessage.emit(MessageType.Error, message)
2614

    
2615
    '''
2616
        @brief      get symbol type id
2617
        @author     kyouho
2618
        @date       2018.08.17
2619
    '''
2620

    
2621
    def getSymbolTypeId(self, symbolType):
2622
        result = []
2623

    
2624
        with self.project.database.connect() as conn:
2625
            try:
2626
                # Get a cursor object
2627
                cursor = conn.cursor()
2628

    
2629
                sql = self.project.database.to_sql('select UID from SymbolType where Type = ?')
2630
                param = (symbolType,)
2631
                cursor.execute(sql, param)
2632
                rows = cursor.fetchall()
2633

    
2634
                if len(rows):
2635
                    result = rows[0]['UID']
2636
                else:
2637
                    result = -1
2638
                # Catch the exception
2639
            except Exception as ex:
2640
                print('error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
2641
                                                          sys.exc_info()[-1].tb_lineno))
2642

    
2643
        return result
2644

    
2645
    '''
2646
        @brief      get Code Table Data
2647
        @author     kyouho
2648
        @date       2018.07.10
2649
    '''
2650

    
2651
    def getCodeTable(self, property, forCheckLineNumber=False, symbol_attribute_uid=None, custom_table_uid=None, custom=False, \
2652
                                                    inst_table_uid=None, inst=False):
2653
        result = []
2654
        with self.project.database.connect() as conn:
2655
            try:
2656
                # Get a cursor object
2657
                cursor = conn.cursor()
2658

    
2659
                if property.upper().replace(' ', '') == "NOMINALDIAMETER" and forCheckLineNumber:
2660
                    cols = ['InchStr', 'MetricStr']
2661
                    sql = f"select {cols[0]}, {cols[1]} from [{property}] order by Metric ASC"
2662
                    cursor.execute(sql)
2663
                    rows = cursor.fetchall()
2664
                    for index in range(2):
2665
                        for row in rows:
2666
                            if row[cols[index]] != '' and result.count(row[cols[index]].replace("'", '"')) == 0:
2667
                                result.append(row[cols[index]].replace("'", '"'))
2668
                else:
2669
                    """
2670
                    sql = "select name from sqlite_master where type='table'"# AND name={}".format(property)
2671
                    cursor.execute(sql)
2672
                    rows = cursor.fetchall()
2673
                    if property.upper() in [name[0].upper() for name in rows]:
2674
                    """
2675
                    if not symbol_attribute_uid and not custom_table_uid and not custom and not inst_table_uid:
2676
                        sql = 'select uid, code, description, Allowables from [{}] order by code DESC'.format(property)
2677
                    elif symbol_attribute_uid and not custom_table_uid and not inst_table_uid:
2678
                        sql = "select uid, code, description, Allowables from [{}] where SymbolAttribute_UID='{}' " \
2679
                              "order by code DESC".format(property, symbol_attribute_uid)
2680
                    elif not symbol_attribute_uid and custom_table_uid and not inst_table_uid:
2681
                        sql = "select uid, code, description, Allowables from [{}] where Table_UID='{}' " \
2682
                              "order by code DESC".format(property, custom_table_uid)
2683
                    elif not symbol_attribute_uid and not custom_table_uid and inst_table_uid:
2684
                        sql = "select uid, code, symbol, newcode from [{}] where Table_UID='{}' " \
2685
                              "order by code DESC".format(property, inst_table_uid)
2686
                    elif custom:
2687
                        sql = "select uid, code, description, Allowables from CustomCodes \
2688
                                    where table_uid = (select uid from CustomTables where upper(name) like upper('{}'))".format(property)
2689
                    elif isnt:
2690
                        sql = "select uid, code, description, Allowables from InstCodes \
2691
                                    where table_uid = (select uid from InstTables where upper(name) like upper('{}'))".format(property)
2692
                    cursor.execute(sql)
2693
                    rows = cursor.fetchall()
2694
                    if not isnt:
2695
                        for row in rows:
2696
                            if forCheckLineNumber:
2697
                                data = row['code']
2698
                            else:
2699
                                data = (row['uid'], row['code'], row['description'], row['Allowables'])
2700
                            result.append(data)
2701
                        # else:
2702
                        #    result = None
2703
                    else:
2704
                        for row in rows:
2705
                            data = (row['uid'], row['code'], row['symbol'], row['newcode'])
2706
                            result.append(data)
2707
            # Catch the exception
2708
            except Exception as ex:
2709
                from App import App
2710
                message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
2711
                                                              sys.exc_info()[-1].tb_lineno)
2712
                App.mainWnd().addMessage.emit(MessageType.Error, message)
2713

    
2714
        return result
2715

    
2716
    def get_components(self, drawing):
2717
        """ get components in given drawing """
2718

    
2719
        with self.project.database.connect() as conn:
2720
            try:
2721
                # Get a cursor object
2722
                cursor = conn.cursor() if self.project.database.db_type == 'SQLite' else conn.cursor(as_dict=True)
2723

    
2724
                sql = "select a.*,b.Name,b.SymbolType_UID,b.[Type],b.OriginalPoint,b.ConnectionPoint,b.BaseSymbol," \
2725
                      "b.AdditionalSymbol,b.HasInstrumentLabel,b.Flip as DetectFlip from Components a " \
2726
                      "join Symbol b on a.Symbol_UID=b.UID where a.Drawings_UID='{}'".format(drawing)
2727
                cursor.execute(sql)
2728
                return cursor.fetchall()
2729
                # Catch the exception
2730
            except Exception as ex:
2731
                from App import App
2732
                message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
2733
                                                              sys.exc_info()[-1].tb_lineno)
2734
                App.mainWnd().addMessage.emit(MessageType.Error, message)
2735

    
2736
    def get_opcs(self):
2737
        """ get opc in project """
2738
        with self.project.database.connect() as conn:
2739
            try:
2740
                # Get a cursor object
2741
                cursor = conn.cursor() if self.project.database.db_type == 'SQLite' else conn.cursor(as_dict=True)
2742

    
2743
                sql = "select (select Name from Drawings where UID=a.Drawings_UID) as Drawing," \
2744
                      "(select Value from Components where UID=a.Owner) as [Line No]," \
2745
                      "UID as OPC from Components a " \
2746
                      "where Symbol_UID in (select UID from Symbol where SymbolType_UID in " \
2747
                      "(select UID from SymbolType where Type='Instrument OPC''s' or Type='Piping OPC''s'))"
2748
                cursor.execute(sql)
2749
                return cursor.fetchall()
2750
                # Catch the exception
2751
            except Exception as ex:
2752
                from App import App
2753
                message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
2754
                                                              sys.exc_info()[-1].tb_lineno)
2755
                App.mainWnd().addMessage.emit(MessageType.Error, message)
2756

    
2757
    def get_opc_relations(self):
2758
        """ get opc relations """
2759
        conn = self.project.database.connect()
2760
        with conn:
2761
            try:
2762
                # Get a cursor object
2763
                cursor = conn.cursor() if self.project.database.db_type == 'SQLite' else conn.cursor(as_dict=True)
2764

    
2765
                sql = "select (select Name from Drawings where UID=a.From_Drawings_UID) as From_Drawing,\
2766
                a.From_LineNo_UID as From_LineNo,\
2767
                a.From_OPC_UID,\
2768
                (select Name from Drawings where UID=a.To_Drawings_UID) as To_Drawing,\
2769
                a.To_LineNo_UID as To_LineNo,\
2770
                a.To_OPC_UID \
2771
                from OPCRelations a"
2772
                cursor.execute(sql)
2773
                return cursor.fetchall()
2774
                # Catch the exception
2775
            except Exception as ex:
2776
                from App import App
2777
                message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
2778
                                                              sys.exc_info()[-1].tb_lineno)
2779
                App.mainWnd().addMessage.emit(MessageType.Error, message)
2780

    
2781
    def save_opc_relations(self, opcs):
2782
        """ save opc relations """
2783
        conn = self.project.database.connect()
2784
        with conn:
2785
            try:
2786
                # Get a cursor object
2787
                cursor = conn.cursor()
2788
                sql = 'delete from OPCRelations'
2789
                cursor.execute(sql)
2790

    
2791
                for opc in opcs:
2792
                    sql = 'insert into OPCRelations(From_Drawings_UID,From_LineNo_UID,From_OPC_UID,To_Drawings_UID,To_LineNo_UID,To_OPC_UID) \
2793
                        values({},{},{},{},{},{})'.format(
2794
                        "(select UID from Drawings where Name='{}')".format(opc[0]),
2795
                        "'{}'".format(opc[1]) if opc[1] else 'null',
2796
                        "'{}'".format(opc[2]) if opc[2] else 'null',
2797
                        "(select UID from Drawings where Name='{}')".format(opc[3]) if opc[3] else 'null',
2798
                        "'{}'".format(opc[4]) if opc[4] else 'null',
2799
                        "'{}'".format(opc[5]) if opc[5] else 'null')
2800
                    cursor.execute(sql)
2801

    
2802
                conn.commit()
2803
            # Catch the exception
2804
            except Exception as ex:
2805
                conn.rollback()
2806

    
2807
                from App import App
2808
                message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
2809
                                                              sys.exc_info()[-1].tb_lineno)
2810
                App.mainWnd().addMessage.emit(MessageType.Error, message)
2811

    
2812
    def get_component_connectors(self, component):
2813
        """ get connectors of given component """
2814
        if self._connecterss and component in self._connecterss:
2815
            return self._connecterss[component]
2816

    
2817
        conn = self.project.database.connect()
2818
        with conn:
2819
            try:
2820
                # Get a cursor object
2821
                cursor = conn.cursor() if self.project.database.db_type == 'SQLite' else conn.cursor(as_dict=True)
2822

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

    
2827
                pre = ''
2828
                rows = cursor.fetchall()
2829
                for row in rows:
2830
                    if pre != row['Components_UID']:
2831
                        if pre != '':
2832
                            self._connecterss[pre] = compo
2833
                        pre = row['Components_UID']
2834
                        compo = []
2835
                        compo.append(row)
2836
                        if row is rows[-1]:
2837
                            self._connecterss[row['Components_UID']] = compo
2838
                    else:
2839
                        compo.append(row)
2840
                        if row is rows[-1]:
2841
                            self._connecterss[row['Components_UID']] = compo
2842

    
2843
                return self._connecterss[component] if component in self._connecterss else []
2844
                # Catch the exception
2845
            except Exception as ex:
2846
                from App import App
2847
                message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
2848
                                                              sys.exc_info()[-1].tb_lineno)
2849
                App.mainWnd().addMessage.emit(MessageType.Error, message)
2850

    
2851
    def get_component_associations(self, component):
2852
        """ get associations of given component """
2853
        if self._associationss and component in self._associationss:
2854
            return self._associationss[component]
2855
        elif self._associationss:
2856
            return []
2857

    
2858
        conn = self.project.database.connect()
2859
        with conn:
2860
            try:
2861
                # Get a cursor object
2862
                cursor = conn.cursor() if self.project.database.db_type == 'SQLite' else conn.cursor(as_dict=True)
2863

    
2864
                # sql = "select * from Associations where Components_UID='{}'".format(component)
2865
                sql = "select a.* from Associations a \
2866
                            join Components b on a.Components_UID=b.[UID] where Drawings_UID='{}' order by Components_UID".format(
2867
                    self.activeDrawing.UID)
2868
                cursor.execute(sql)
2869

    
2870
                pre = ''
2871
                rows = cursor.fetchall()
2872
                for row in rows:
2873
                    if pre != row['Components_UID']:
2874
                        if pre != '':
2875
                            self._associationss[pre] = compo
2876
                        pre = row['Components_UID']
2877
                        compo = []
2878
                        compo.append(row)
2879
                        if row is rows[-1]:
2880
                            self._associationss[row['Components_UID']] = compo
2881
                    else:
2882
                        compo.append(row)
2883
                        if row is rows[-1]:
2884
                            self._associationss[row['Components_UID']] = compo
2885

    
2886
                return self._associationss[component] if component in self._associationss else []
2887
                # Catch the exception
2888
            except Exception as ex:
2889
                from App import App
2890
                message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
2891
                                                              sys.exc_info()[-1].tb_lineno)
2892
                App.mainWnd().addMessage.emit(MessageType.Error, message)
2893

    
2894
    def get_component_attributes(self, component):
2895
        """ get attributes of given component """
2896
        if self._attributess and component in self._attributess:
2897
            return self._attributess[component]
2898
        elif self._attributess:
2899
            return []
2900

    
2901
        conn = self.project.database.connect()
2902
        with conn:
2903
            try:
2904
                # Get a cursor object
2905
                cursor = conn.cursor() if self.project.database.db_type == 'SQLite' else conn.cursor(as_dict=True)
2906

    
2907
                sql = "select a.*, b.* from Attributes a \
2908
                            join SymbolAttribute b on a.SymbolAttribute_UID=b.UID \
2909
                            join Components c on a.Components_UID=c.UID \
2910
                        where Drawings_UID='{}' order by a.Components_UID, b.[index]".format(self.activeDrawing.UID)
2911
                cursor.execute(sql)
2912

    
2913
                pre = ''
2914
                rows = cursor.fetchall()
2915
                for row in rows:
2916
                    if pre != row['Components_UID']:
2917
                        if pre != '':
2918
                            self._attributess[pre] = compo
2919
                        pre = row['Components_UID']
2920
                        compo = []
2921
                        compo.append(row)
2922
                        if row is rows[-1]:
2923
                            self._attributess[row['Components_UID']] = compo
2924
                    else:
2925
                        compo.append(row)
2926
                        if row is rows[-1]:
2927
                            self._attributess[row['Components_UID']] = compo
2928

    
2929
                return self._attributess[component] if component in self._attributess else []
2930
                # Catch the exception
2931
            except Exception as ex:
2932
                from App import App
2933
                message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
2934
                                                              sys.exc_info()[-1].tb_lineno)
2935
                App.mainWnd().addMessage.emit(MessageType.Error, message)
2936

    
2937
    def get_pipe_runs(self, component):
2938
        """ get line runs of given component """
2939
        conn = self.project.database.connect()
2940
        with conn:
2941
            try:
2942
                # Get a cursor object
2943
                cursor = conn.cursor() if self.project.database.db_type == 'SQLite' else conn.cursor(as_dict=True)
2944

    
2945
                sql = "select * from PipeRuns where Owner='{}' order by [Index]".format(component)
2946
                cursor.execute(sql)
2947
                return cursor.fetchall()
2948
                # Catch the exception
2949
            except Exception as ex:
2950
                from App import App
2951
                message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
2952
                                                              sys.exc_info()[-1].tb_lineno)
2953
                App.mainWnd().addMessage.emit(MessageType.Error, message)
2954

    
2955
    def get_pipe_run_items(self, pipe_run):
2956
        """ get line run items of given pipe run """
2957
        conn = self.project.database.connect()
2958
        with conn:
2959
            try:
2960
                # Get a cursor object
2961
                cursor = conn.cursor() if self.project.database.db_type == 'SQLite' else conn.cursor(as_dict=True)
2962

    
2963
                sql = "select * from PipeRunItems where PipeRuns_UID='{}' order by [Index]".format(pipe_run)
2964
                cursor.execute(sql)
2965
                return cursor.fetchall()
2966
                # Catch the exception
2967
            except Exception as ex:
2968
                from App import App
2969
                message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
2970
                                                              sys.exc_info()[-1].tb_lineno)
2971
                App.mainWnd().addMessage.emit(MessageType.Error, message)
2972

    
2973
    '''
2974
        @brief      get special item types from database
2975
        @author     humkyung
2976
        @date       2019.08.10
2977
    '''
2978

    
2979
    def get_special_item_types(self):
2980
        conn = self.project.database.connect()
2981
        with conn:
2982
            try:
2983
                # Get a cursor object
2984
                cursor = conn.cursor() if self.project.database.db_type == 'SQLite' else conn.cursor(as_dict=True)
2985

    
2986
                sql = 'select UID, Code, Type, Allowables from SpecialItemTypes order by Code DESC'
2987
                cursor.execute(sql)
2988
                return cursor.fetchall()
2989
                # Catch the exception
2990
            except Exception as ex:
2991
                from App import App
2992
                message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
2993
                                                              sys.exc_info()[-1].tb_lineno)
2994
                App.mainWnd().addMessage.emit(MessageType.Error, message)
2995

    
2996
    '''
2997
        @brief      save special item types
2998
        @author     humkyung
2999
        @date       2019.08.10
3000
    '''
3001

    
3002
    def save_special_item_types(self, datas):
3003
        import uuid
3004

    
3005
        conn = self.project.database.connect()
3006
        with conn:
3007
            try:
3008
                # Get a cursor object
3009
                cursor = conn.cursor()
3010

    
3011
                for data in datas:
3012
                    uid, code, _type, allowables = data[0], data[1], data[2], data[3]
3013
                    if not uid:
3014
                        sql = self.project.database.to_sql(
3015
                            'insert into SpecialItemTypes(UID, Code, Type, Allowables) values(?, ?, ?, ?)')
3016
                        param = (str(uuid.uuid4()), data[1], data[2], data[3])
3017
                    elif uid == '-1':
3018
                        sql = self.project.database.to_sql('delete from SpecialItemTypes where uid=?')
3019
                        param = (data[-1],)
3020
                    else:
3021
                        sql = self.project.database.to_sql(
3022
                            'update SpecialItemTypes SET Code=?, Type=?, Allowables=? WHERE UID = ?')
3023
                        param = (data[1], data[2], data[3], data[0])
3024
                    cursor.execute(sql, param)
3025

    
3026
                conn.commit()
3027
            # Catch the exception
3028
            except Exception as ex:
3029
                # Roll back any change if something goes wrong
3030
                conn.rollback()
3031

    
3032
                from App import App
3033
                message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
3034
                                                              sys.exc_info()[-1].tb_lineno)
3035
                App.mainWnd().addMessage.emit(MessageType.Error, message)
3036

    
3037
    def get_special_items(self, drawings=None):
3038
        """ get special items from database """
3039
        result = []
3040

    
3041
        conn = self.project.database.connect()
3042
        with conn:
3043
            try:
3044
                # get a cursor object
3045
                cursor = conn.cursor()
3046

    
3047
                sql = 'select distinct (select Value from Components where UID=D.Owner) as "Line No",C.Code from Components A \
3048
                    left join Drawings B on A.Drawings_UID=B.UID \
3049
                    left join SpecialItemTypes C on A.SpecialItemTypes_UID=C.UID \
3050
                    left join Components D on A.Connected=D.UID \
3051
                    where A.SpecialItemTypes_UID is not null'
3052
                if drawings is not None:
3053
                    doc_names = "','".join(drawings)
3054
                    sql += f" and A.Drawings_UID in (select UID from Drawings where Name in ('{doc_names}'))"
3055
                sql += ' order by "Line No"'
3056
                cursor.execute(sql)
3057

    
3058
                return cursor.fetchall()
3059
            # catch the exception
3060
            except Exception as ex:
3061
                from App import App
3062
                message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
3063
                                                              sys.exc_info()[-1].tb_lineno)
3064
                App.mainWnd().addMessage.emit(MessageType.Error, message)
3065

    
3066
        return None
3067

    
3068
    '''
3069
        @brief      Set Common Code Data
3070
        @author     kyouho
3071
        @date       2018.07.12
3072
    '''
3073
    def saveCommonCodeData(self, tableName, datas):
3074
        import uuid
3075

    
3076
        conn = self.project.database.connect()
3077
        with conn:
3078
            try:
3079
                # Get a cursor object
3080
                cursor = conn.cursor()
3081

    
3082
                sql = self.project.database.to_sql('delete from {}'.format(tableName))
3083
                cursor.execute(sql)
3084

    
3085
                for data in datas:
3086
                    '''
3087
                    uid, code, description, allowables = data[0], data[1], data[2], data[3]
3088
                    if not uid:
3089
                        sql = self.project.database.to_sql(
3090
                            "insert into {}(UID, CODE, DESCRIPTION, ALLOWABLES) values(?, ?, ?, ?)".format(tableName))
3091
                        param = (str(uuid.uuid4()), data[1], data[2], data[3])
3092
                    elif uid == '-1':
3093
                        sql = self.project.database.to_sql('delete from {} where uid=?'.format(tableName))
3094
                        param = (data[-1],)
3095
                    else:
3096
                        sql = self.project.database.to_sql(
3097
                            "update {} SET CODE=?, DESCRIPTION=?, ALLOWABLES=? WHERE UID = ?".format(tableName))
3098
                        param = (data[1], data[2], data[3], data[0])
3099
                    cursor.execute(sql, param)
3100
                    '''
3101
                    if data[0]:
3102
                        uid = data[0]
3103
                    else:
3104
                        uid = str(uuid.uuid4())
3105
                    sql = self.project.database.to_sql(
3106
                        "insert into {}(UID, CODE, DESCRIPTION, ALLOWABLES) values(?, ?, ?, ?)".format(tableName))
3107
                    param = (uid, data[1], data[2], data[3])
3108
                    cursor.execute(sql, param)
3109

    
3110
                conn.commit()
3111
            # Catch the exception
3112
            except Exception as ex:
3113
                # Roll back any change if something goes wrong
3114
                conn.rollback()
3115

    
3116
                from App import App
3117
                message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
3118
                                                              sys.exc_info()[-1].tb_lineno)
3119
                App.mainWnd().addMessage.emit(MessageType.Error, message)
3120

    
3121
    '''
3122
        @brief      Set Common Code Data
3123
        @author     kyouho
3124
        @date       2018.07.12
3125
    '''
3126

    
3127
    def deleteCommonCodeData(self, datas):
3128
        try:
3129
            conn = self.project.database.connect()
3130
            with conn:
3131
                # Get a cursor object
3132
                cursor = conn.cursor()
3133

    
3134
                for data in datas:
3135
                    uid = data[0]
3136
                    tableName = data[1]
3137

    
3138
                    if uid:
3139
                        sql = "delete from {} where UID = ?".format(tableName)
3140
                        param = (uid,)
3141
                        cursor.execute(sql, param)
3142

    
3143
                    cursor.execute(sql, param)
3144

    
3145
                conn.commit()
3146

    
3147
        # Catch the exception
3148
        except Exception as ex:
3149
            # Roll back any change if something goes wrong
3150
            conn.rollback()
3151
            print('error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
3152
                                                      sys.exc_info()[-1].tb_lineno))
3153

    
3154
    '''
3155
        @brief      delete data list
3156
        @author     kyouho
3157
        @date       2018.08.16
3158
    '''
3159

    
3160
    def deleteDataList(self, tableName, UID):
3161
        conn = self.project.database.connect()
3162
        with conn:
3163
            try:
3164
                # Get a cursor object
3165
                cursor = conn.cursor()
3166
                sql = 'delete from {} where UID = {}'.format(tableName, UID)
3167
                cursor.execute(sql)
3168
                conn.commit()
3169

    
3170
            # Catch the exception
3171
            except Exception as ex:
3172
                # Roll back any change if something goes wrong
3173
                conn.rollback()
3174
                print('error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
3175
                                                          sys.exc_info()[-1].tb_lineno))
3176

    
3177
    def get_document_name_list(self):
3178
        """ get document name list """
3179
        result = []
3180

    
3181
        with self.project.database.connect() as conn:
3182
            try:
3183
                # Get a cursor object
3184
                cursor = conn.cursor()
3185

    
3186
                sql = "select distinct B.Name as 'Drawing_Name' from Components A join Drawings B on " \
3187
                      "A.Drawings_UID=B.UID"
3188
                cursor.execute(sql)
3189

    
3190
                rows = cursor.fetchall()
3191
                for row in rows:
3192
                    result.append(row['Drawing_Name'])
3193

    
3194
                result.sort()
3195
            # Catch the exception
3196
            except Exception as ex:
3197
                print('error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
3198
                                                          sys.exc_info()[-1].tb_lineno))
3199

    
3200
        return result
3201

    
3202
    '''
3203
        @brief      get line documentName list
3204
        @author     kyouho
3205
        @date       2018.08.13
3206
    '''
3207

    
3208
    def getLineDocumentNameList(self):
3209
        result = []
3210

    
3211
        conn = self.project.database.connect()
3212
        with conn:
3213
            try:
3214
                # Get a cursor object
3215
                cursor = conn.cursor()
3216

    
3217
                sql = 'select DISTINCT(PNID_NO) from LINE_DATA_LIST'
3218

    
3219
                cursor.execute(sql)
3220
                rows = cursor.fetchall()
3221
                for row in rows:
3222
                    result.append(row[0])
3223
            # Catch the exception
3224
            except Exception as ex:
3225
                print('error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
3226
                                                          sys.exc_info()[-1].tb_lineno))
3227

    
3228
        return result
3229

    
3230
    '''
3231
        @brief      get line data list
3232
        @author     kyouho
3233
        @date       2018.08.13
3234
    '''
3235

    
3236
    def get_line_data_list(self, drawings=None):
3237
        result = []
3238

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

    
3244
                sql = 'select A.UID,B.Name from Components A left join Drawings B on A.Drawings_UID=B.UID'
3245
                if drawings is not None:
3246
                    doc_names = "','".join(drawings)
3247
                    sql += f" where Drawings_UID in (select UID from Drawings where Name in ('{doc_names}'))"
3248
                cursor.execute(sql)
3249
                comps = [(row['UID'], row['Name']) for row in cursor.fetchall()]
3250
                for comp in comps:
3251
                    sql = f"select b.Name,a.Value from LineNoAttributes a left join LineProperties b " \
3252
                          f"on a.LineProperties_UID=b.UID where a.Components_UID='{comp[0]}'"
3253
                    cursor.execute(sql)
3254
                    attrs = cursor.fetchall()
3255
                    data = []
3256
                    for attr in attrs:
3257
                        data.append([attr['Name'], attr['Value']])
3258
                    if data:
3259
                        data.insert(0, ['Drawing Name', comp[1]])
3260
                        data.insert(0, ['UID', comp[0]])
3261
                        result.append(data)
3262

    
3263
            # catch the exception
3264
            except Exception as ex:
3265
                print('error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
3266
                                                          sys.exc_info()[-1].tb_lineno))
3267

    
3268
        return result
3269

    
3270
    def get_equipment_data_list(self, drawings=None):
3271
        """ get equipment data list """
3272

    
3273
        result = []
3274

    
3275
        with self.project.database.connect() as conn:
3276
            try:
3277
                # Get a cursor object
3278
                cursor = conn.cursor()
3279

    
3280
                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\
3281
                        join Symbol C on A.Symbol_UID=C.UID\
3282
                        join SymbolType D on C.SymbolType_UID=D.UID\
3283
                        where D.Category in ('Equipment')"#,'Equipment Components')"
3284

    
3285
                if drawings is not None:
3286
                    doc_names = "','".join(drawings)
3287
                    sql += f" and A.Drawings_UID in (select UID from Drawings where Name in ('{doc_names}'))"
3288

    
3289
                cursor.execute(sql)
3290
                comps = [(row['UID'], row['NAME'], row['SymbolType_UID'], row['Type'], row['symbol']) for row in cursor.fetchall()]
3291
                for comp in comps:
3292
                    sql = f"select distinct B.Attribute,A.Value from Attributes A left join SymbolAttribute B on " \
3293
                          f"A.SymbolAttribute_UID=B.UID where A.Components_UID='{comp[0]}'"
3294
                    cursor.execute(sql)
3295
                    attrs = cursor.fetchall()
3296
                    data = []
3297
                    for attr in attrs:
3298
                        data.append([attr['Attribute'], attr['Value']])
3299
                    if data:
3300
                        data.insert(0, ['Type', comp[3]])
3301
                        data.insert(0, ['Drawing Name', comp[1]])
3302
                        data.insert(0, ['ITEM_NO', comp[4]])
3303
                        data.insert(0, ['UID', comp[0]])
3304
                        result.append(data)
3305

    
3306
            # catch the exception
3307
            except Exception as ex:
3308
                print('error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
3309
                                                           sys.exc_info()[-1].tb_lineno))
3310

    
3311
        return result
3312

    
3313
    '''
3314
        @brief      set line data list
3315
        @author     kyouho
3316
        @date       2018.08.13
3317
    '''
3318

    
3319
    def setLineDataList(self, dataLists):
3320
        conn = self.project.database.connect()
3321
        with conn:
3322
            try:
3323
                # Get a cursor object
3324
                cursor = conn.cursor()
3325

    
3326
                for data in dataLists:
3327
                    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(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"
3328
                    param = tuple(data)
3329
                    cursor.execute(sql, param)
3330

    
3331
                conn.commit()
3332

    
3333
            # Catch the exception
3334
            except Exception as ex:
3335
                # Roll back any change if something goes wrong
3336
                conn.rollback()
3337
                print('error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
3338
                                                          sys.exc_info()[-1].tb_lineno))
3339

    
3340
    '''
3341
        @brief      delete line data list
3342
        @author     kyouho
3343
        @date       2018.08.13
3344
    '''
3345
    def deleteLineDataList(self, removeUID):
3346
        conn = self.project.database.connect()
3347
        with conn:
3348
            try:
3349
                # Get a cursor object
3350
                cursor = conn.cursor()
3351

    
3352
                for uid in removeUID:
3353
                    sql = "delete from LINE_DATA_LIST where uid = '{}'".format(uid)
3354
                    cursor.execute(sql)
3355

    
3356
                conn.commit()
3357

    
3358
            # Catch the exception
3359
            except Exception as ex:
3360
                # Roll back any change if something goes wrong
3361
                conn.rollback()
3362
                print('error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
3363
                                                          sys.exc_info()[-1].tb_lineno))
3364

    
3365
    '''
3366
        @brief      delete line data list
3367
        @author     kyouho
3368
        @date       2018.08.13
3369
    '''
3370

    
3371
    def deleteLineDataList_LineNo(self, removeUID):
3372
        conn = self.project.database.connect()
3373
        with conn:
3374
            try:
3375
                # Get a cursor object
3376
                cursor = conn.cursor()
3377

    
3378
                for uid in removeUID:
3379
                    sql = "delete from LINE_DATA_LIST where LINE_NO = ?"
3380
                    param = (uid,)
3381
                    cursor.execute(sql, param)
3382

    
3383
                conn.commit()
3384

    
3385
            # Catch the exception
3386
            except Exception as ex:
3387
                # Roll back any change if something goes wrong
3388
                conn.rollback()
3389
                print('error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
3390
                                                          sys.exc_info()[-1].tb_lineno))
3391

    
3392
    '''
3393
        @brief      delete equip data list
3394
        @author     kyouho
3395
        @date       2018.08.14
3396
    '''
3397

    
3398
    def deleteEquipDataList(self, removeUID):
3399
        conn = self.project.database.connect()
3400
        with conn:
3401
            try:
3402
                # Get a cursor object
3403
                cursor = conn.cursor()
3404

    
3405
                for uid in removeUID:
3406
                    sql = "delete from EQUIPMENT_DATA_LIST where uid = '{}'".format(uid)
3407
                    cursor.execute(sql)
3408

    
3409
                conn.commit()
3410

    
3411
            # Catch the exception
3412
            except Exception as ex:
3413
                # Roll back any change if something goes wrong
3414
                conn.rollback()
3415
                print('error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
3416
                                                          sys.exc_info()[-1].tb_lineno))
3417

    
3418
    '''
3419
        @brief      delete inst data list
3420
        @author     kyouho
3421
        @date       2018.08.14
3422
    '''
3423

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

    
3431
                for uid in removeUID:
3432
                    sql = "delete from INSTRUMENT_DATA_LIST where uid = '{}'".format(uid)
3433
                    cursor.execute(sql)
3434

    
3435
                conn.commit()
3436

    
3437
            # Catch the exception
3438
            except Exception as ex:
3439
                # Roll back any change if something goes wrong
3440
                conn.rollback()
3441
                print('error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
3442
                                                          sys.exc_info()[-1].tb_lineno))
3443

    
3444
    '''
3445
        @brief      delete note data list
3446
        @author     kyouho
3447
        @date       2018.10.10
3448
    '''
3449

    
3450
    def deleteNoteDataList(self, removeUID):
3451
        conn = self.project.database.connect()
3452
        with conn:
3453
            try:
3454
                # Get a cursor object
3455
                cursor = conn.cursor()
3456

    
3457
                for uid in removeUID:
3458
                    sql = "delete from NOTE_DATA_LIST where uid = '{}'".format(uid)
3459
                    cursor.execute(sql)
3460

    
3461
                conn.commit()
3462

    
3463
            # Catch the exception
3464
            except Exception as ex:
3465
                # Roll back any change if something goes wrong
3466
                conn.rollback()
3467
                print('error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
3468
                                                          sys.exc_info()[-1].tb_lineno))
3469

    
3470
    def get_valve_attributes(self):
3471
        """ return valve attributes """
3472

    
3473
        from SymbolAttr import SymbolAttr
3474

    
3475
        res = None
3476
        if not hasattr(self, '_valve_attributes'):
3477
            self._valve_attributes = []
3478

    
3479
            with self.project.database.connect() as conn:
3480
                try:
3481
                    # Get a cursor object
3482
                    cursor = conn.cursor()
3483

    
3484
                    sql = "select distinct A.Attribute from SymbolAttribute A join SymbolType B on " \
3485
                          "A.SymbolType_UID=B.UID where B.Category = 'Piping'"
3486
                    cursor.execute(sql)
3487
                    rows = cursor.fetchall()
3488
                    for row in rows:
3489
                        attr = SymbolAttr()
3490
                        attr.Attribute = row['Attribute']
3491
                        self._valve_attributes.append(attr)
3492

    
3493
                    res = self._valve_attributes
3494
                # Catch the exception
3495
                except Exception as ex:
3496
                    print('error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
3497
                                                               sys.exc_info()[-1].tb_lineno))
3498
        else:
3499
            res = self._valve_attributes
3500

    
3501
        return res
3502

    
3503
    def get_valve_data_list(self, drawings=None):
3504
        """get valve data list"""
3505

    
3506
        result = []
3507
        conn = self.project.database.connect()
3508
        with conn:
3509
            try:
3510
                # Get a cursor object
3511
                cursor = conn.cursor() if self.project.database.db_type == 'SQLite' else conn.cursor(as_dict=True)
3512

    
3513
                sql = "select a.UID,D.Name,E.Name as 'Drawing Name',C.Attribute,B.Value from Components a " \
3514
                      "join Attributes B on a.UID=B.Components_UID " \
3515
                      "join SymbolAttribute C on B.SymbolAttribute_UID=C.UID " \
3516
                      "join Symbol D on a.Symbol_UID=D.UID " \
3517
                      "join Drawings E on a.Drawings_UID=E.UID " \
3518
                      "where a.Symbol_UID in (select UID from Symbol where SymbolType_UID in " \
3519
                      "(select UID from SymbolType where Category in ('Piping')))"
3520
                if drawings is not None:
3521
                    doc_names = "','".join(drawings)
3522
                    sql += f" and A.Drawings_UID in (select UID from Drawings where Name in ('{doc_names}'))"
3523

    
3524
                cursor.execute(sql)
3525
                rows = cursor.fetchall()
3526
                for row in rows:
3527
                    matches = [res for res in result if res['UID'] == row['UID']]
3528
                    if matches:
3529
                        matches[0][row['Attribute']] = row['Value']
3530
                    else:
3531
                        data = {'UID': row['UID'], 'ITEM_NO': row['Name'], 'Drawing Name': row['Drawing Name'],
3532
                                row['Attribute']: row['Value']}
3533
                        result.append(data)
3534

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

    
3542
        return result
3543

    
3544
    def get_instrument_attributes(self):
3545
        """ return valve attributes """
3546

    
3547
        from SymbolAttr import SymbolAttr
3548

    
3549
        res = None
3550
        if not hasattr(self, '_inst_attributes'):
3551
            self._inst_attributes = []
3552

    
3553
            with self.project.database.connect() as conn:
3554
                try:
3555
                    # Get a cursor object
3556
                    cursor = conn.cursor()
3557

    
3558
                    sql = "select distinct A.Attribute from SymbolAttribute A join SymbolType B on " \
3559
                          "A.SymbolType_UID=B.UID where B.Category = 'Instrumentation'"
3560
                    cursor.execute(sql)
3561
                    rows = cursor.fetchall()
3562
                    for row in rows:
3563
                        attr = SymbolAttr()
3564
                        attr.Attribute = row['Attribute']
3565
                        self._inst_attributes.append(attr)
3566

    
3567
                    res = self._inst_attributes
3568
                # Catch the exception
3569
                except Exception as ex:
3570
                    print('error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
3571
                                                               sys.exc_info()[-1].tb_lineno))
3572
        else:
3573
            res = self._inst_attributes
3574

    
3575
        return res
3576

    
3577
    '''
3578
        @brief      get instrument data list
3579
        @author     kyouho
3580
        @date       2018.08.14
3581
    '''
3582

    
3583
    def get_instrument_data_list(self, drawings=None):
3584
        result = []
3585
        conn = self.project.database.connect()
3586
        with conn:
3587
            try:
3588
                # Get a cursor object
3589
                cursor = conn.cursor() if self.project.database.db_type == 'SQLite' else conn.cursor(as_dict=True)
3590

    
3591
                sql = "select a.UID,D.Name,E.Name as 'Drawing Name',C.Attribute,B.Value from Components a " \
3592
                      "join Attributes B on a.UID=B.Components_UID " \
3593
                      "join SymbolAttribute C on B.SymbolAttribute_UID=C.UID " \
3594
                      "join Symbol D on a.Symbol_UID=D.UID " \
3595
                      "join Drawings E on a.Drawings_UID=E.UID " \
3596
                      "where a.Symbol_UID in (select UID from Symbol where SymbolType_UID in " \
3597
                      "(select UID from SymbolType where Category in ('Instrumentation')))"
3598
                if drawings is not None:
3599
                    doc_names = "','".join(drawings)
3600
                    sql += f" and A.Drawings_UID in (select UID from Drawings where Name in ('{doc_names}'))"
3601

    
3602
                cursor.execute(sql)
3603
                rows = cursor.fetchall()
3604
                for row in rows:
3605
                    matches = [res for res in result if res['UID'] == row['UID']]
3606
                    if matches:
3607
                        matches[0][row['Attribute']] = row['Value']
3608
                    else:
3609
                        data = {'UID': row['UID'], 'ITEM_NO': row['Name'], 'Drawing Name': row['Drawing Name'],
3610
                                row['Attribute']: row['Value']}
3611
                        result.append(data)
3612
            # Catch the exception
3613
            except Exception as ex:
3614
                from App import App
3615
                message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
3616
                                                              sys.exc_info()[-1].tb_lineno)
3617
                App.mainWnd().addMessage.emit(MessageType.Error, message)
3618

    
3619
        return result
3620

    
3621
    def get_note_attributes(self):
3622
        """ return note attributes """
3623

    
3624
        from SymbolAttr import SymbolAttr
3625

    
3626
        res = None
3627
        if not hasattr(self, '_note_attributes'):
3628
            self._note_attributes = []
3629

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

    
3635
                    sql = "select distinct A.Attribute from SymbolAttribute A join SymbolType B on " \
3636
                          "A.SymbolType_UID=B.UID where B.Category='General' and B.Type='Notes'"
3637
                    cursor.execute(sql)
3638
                    rows = cursor.fetchall()
3639
                    for row in rows:
3640
                        attr = SymbolAttr()
3641
                        attr.Attribute = row['Attribute']
3642
                        self._note_attributes.append(attr)
3643

    
3644
                    res = self._note_attributes
3645
                # Catch the exception
3646
                except Exception as ex:
3647
                    print('error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
3648
                                                               sys.exc_info()[-1].tb_lineno))
3649
        else:
3650
            res = self._note_attributes
3651

    
3652
        return res
3653

    
3654
    def get_note_data_list(self, drawings=None):
3655
        """ get note data list """
3656
        result = []
3657

    
3658
        conn = self.project.database.connect()
3659
        with conn:
3660
            try:
3661
                # Get a cursor object
3662
                cursor = conn.cursor() if self.project.database.db_type == 'SQLite' else conn.cursor(as_dict=True)
3663

    
3664
                sql = "select a.UID,D.Name,E.Name as 'Drawing Name',C.Attribute,B.Value from Components a " \
3665
                      "join Attributes B on a.UID=B.Components_UID " \
3666
                      "join SymbolAttribute C on B.SymbolAttribute_UID=C.UID " \
3667
                      "join Symbol D on a.Symbol_UID=D.UID " \
3668
                      "join Drawings E on a.Drawings_UID=E.UID " \
3669
                      "where a.Symbol_UID in (select UID from Symbol where SymbolType_UID in " \
3670
                      "(select UID from SymbolType where Category='General' and Type='Notes'))"
3671
                if drawings is not None:
3672
                    doc_names = "','".join(drawings)
3673
                    sql += f" and A.Drawings_UID in (select UID from Drawings where Name in ('{doc_names}'))"
3674

    
3675
                cursor.execute(sql)
3676
                rows = cursor.fetchall()
3677
                for row in rows:
3678
                    matches = [res for res in result if res['UID'] == row['UID']]
3679
                    if matches:
3680
                        matches[0][row['Attribute']] = row['Value']
3681
                    else:
3682
                        data = {'UID': row['UID'], 'ITEM_NO': row['Name'], 'Drawing Name': row['Drawing Name'],
3683
                                row['Attribute']: row['Value']}
3684
                        result.append(data)
3685
            # Catch the exception
3686
            except Exception as ex:
3687
                from App import App
3688
                message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
3689
                                                              sys.exc_info()[-1].tb_lineno)
3690
                App.mainWnd().addMessage.emit(MessageType.Error, message)
3691

    
3692
        return result
3693

    
3694
    def saveToDatabase(self, items, show_progress=None):
3695
        """ save given items to database """
3696
        # delete all datas of current drawing
3697
        drawing_name = self.activeDrawing.name
3698
        drawing_uid = self.activeDrawing.UID
3699

    
3700
        queries = {'first':[], 'second':[]}
3701
        for item in items:
3702
            if hasattr(item, 'toSql_return_separately'):
3703
                sql, sqlLater = item.toSql_return_separately()
3704
                queries['first'].append(sql)
3705
                queries['second'].append(sqlLater)
3706
            else:
3707
                queries['first'].append(item.toSql())
3708

    
3709
        with self.project.database.connect() as conn:
3710
            try:
3711
                # Get a cursor object
3712
                cursor = conn.cursor()
3713
                if self.project.database.db_type == 'SQLite':
3714
                    cursor.execute('begin')
3715

    
3716
                sql = "delete from LINE_DATA_LIST where PNID_NO = '{}'".format(drawing_name)
3717
                cursor.execute(sql)
3718
                sql = "delete from TitleBlockValues where Drawings_UID = '{}'".format(drawing_uid)
3719
                cursor.execute(sql)
3720

    
3721
                # delete LineNoAttributes
3722
                sql = f"delete from LineNoAttributes where Components_UID in " \
3723
                      f"(select UID from Components where Drawings_UID='{drawing_uid}')"
3724
                cursor.execute(sql)
3725

    
3726
                # delete Attributes
3727
                sql = f"delete from Attributes where Components_UID in " \
3728
                      f"(select UID from Components where Drawings_UID='{drawing_uid}')"
3729
                cursor.execute(sql)
3730

    
3731
                # delete Associations
3732
                sql = f"delete from Associations where Components_UID in " \
3733
                      f"(select UID from Components where Drawings_UID='{drawing_uid}')"
3734
                cursor.execute(sql)
3735

    
3736
                # delete Points
3737
                sql = f"delete from Points where Components_UID in " \
3738
                      f"(select UID from Components where Drawings_UID='{drawing_uid}')"
3739
                cursor.execute(sql)
3740

    
3741
                # delete PipeRunItems
3742
                sql = f"delete from PipeRunItems where PipeRuns_UID in " \
3743
                      f"(select UID from PipeRuns where Drawings_UID='{drawing_uid}')"
3744
                cursor.execute(sql)
3745

    
3746
                # delete PipeRuns
3747
                sql = f"delete from PipeRuns where Drawings_UID='{drawing_uid}'"
3748
                cursor.execute(sql)
3749

    
3750
                # delete Components 
3751
                sql = "delete from Components where Drawings_UID='{}'".format(drawing_uid)
3752
                cursor.execute(sql)
3753

    
3754
                progress = 0
3755
                length = len(queries['first']) + len(queries['second'])
3756
                for sql in queries['first']:
3757
                    if type(sql) is list:
3758
                        for item in sql:
3759
                            if item is not None and 2 == len(item):
3760
                                cursor.executemany(self.project.database.to_sql(item[0]), item[1])
3761
                    else:
3762
                        if sql is not None and 2 == len(sql):
3763
                            cursor.executemany(self.project.database.to_sql(sql[0]), sql[1])
3764

    
3765
                    if show_progress:
3766
                        show_progress.emit(int((progress / length)*100))
3767
                    progress += 1
3768

    
3769
                for sql in queries['second']:
3770
                    if type(sql) is list:
3771
                        for item in sql:
3772
                            if item is not None and 2 == len(item):
3773
                                cursor.executemany(self.project.database.to_sql(item[0]), item[1])
3774
                    else:
3775
                        if sql is not None and 2 == len(sql):
3776
                            cursor.executemany(self.project.database.to_sql(sql[0]), sql[1])
3777

    
3778
                    if show_progress:
3779
                        show_progress.emit(int((progress / length)*100))
3780
                    progress += 1
3781

    
3782
                if show_progress:
3783
                    show_progress.emit(99)
3784

    
3785
                if self.project.database.db_type == 'SQLite':
3786
                    cursor.execute('commit')
3787
                else:
3788
                    conn.commit()
3789
            # Catch the exception
3790
            except Exception as ex:
3791
                # Roll back any change if something goes wrong
3792
                conn.rollback()
3793

    
3794
                from App import App
3795
                message = 'error occurred({}\\n{}) in {}:{}'.format(repr(ex), sql,
3796
                                                                    sys.exc_info()[-1].tb_frame.f_code.co_filename,
3797
                                                                    sys.exc_info()[-1].tb_lineno)
3798
                App.mainWnd().addMessage.emit(MessageType.Error, message)
3799

    
3800
    '''
3801
        @brief      set equipment data list
3802
        @author     humkyung
3803
        @date       2018.05.03
3804
    '''
3805

    
3806
    def setEquipmentDataList(self, dataList):
3807
        conn = self.project.database.connect()
3808
        with conn:
3809
            try:
3810
                # Get a cursor object
3811
                cursor = conn.cursor()
3812

    
3813
                for data in dataList:
3814
                    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(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"
3815
                    param = tuple(data)
3816
                    cursor.execute(self.project.database.to_sql(sql), param)
3817
                conn.commit()
3818
            # Catch the exception
3819
            except Exception as ex:
3820
                # Roll back any change if something goes wrong
3821
                conn.rollback()
3822

    
3823
                from App import App
3824
                message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
3825
                                                              sys.exc_info()[-1].tb_lineno)
3826
                App.mainWnd().addMessage.emit(MessageType.Error, message)
3827

    
3828
    '''
3829
        @brief      set instrumnet data list
3830
        @author     kyoyho
3831
        @date       2018.08.14
3832
    '''
3833

    
3834
    def setInstrumentDataList(self, dataList):
3835
        conn = self.project.database.connect()
3836
        with conn:
3837
            try:
3838
                # Get a cursor object
3839
                cursor = conn.cursor()
3840

    
3841
                for data in dataList:
3842
                    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(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"
3843
                    param = tuple(data)
3844
                    cursor.execute(sql, param)
3845
                conn.commit()
3846

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

    
3852
                from App import App
3853
                message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
3854
                                                              sys.exc_info()[-1].tb_lineno)
3855
                App.mainWnd().addMessage.emit(MessageType.Error, message)
3856

    
3857
    def getDrawings(self):
3858
        """ get drawings """
3859
        from Drawing import Drawing
3860

    
3861
        res = []
3862

    
3863
        with self.project.database.connect() as conn:
3864
            try:
3865
                cursor = conn.cursor() if self.project.database.db_type == 'SQLite' else conn.cursor(as_dict=True)
3866
                sql = 'select UID,[NAME],[DATETIME] from Drawings'
3867
                cursor.execute(sql)
3868
                for row in cursor.fetchall():
3869
                    res.append(Drawing(row['UID'], row['NAME'], row['DATETIME']))
3870
            # Catch the exception
3871
            except Exception as ex:
3872
                from App import App
3873
                message = 'error occurred({}) in {}:{}'.format(repr(ex), sys.exc_info()[-1].tb_frame.f_code.co_filename,
3874
                                                              sys.exc_info()[-1].tb_lineno)
3875
                App.mainWnd().addMessage.emit(MessageType.Error, message)
3876

    
3877
        return res
3878

    
3879
    def saveDrawings(self, drawings):
3880
        """save given drawings"""
3881

    
3882
        import uuid
3883

    
3884
        with self.project.database.connect() as conn:
3885
            try:
3886
                # Get a cursor object
3887
                cursor = conn.cursor() if self.project.database.db_type == 'SQLite' else conn.cursor(as_dict=True)
3888
                if self.project.database.db_type == 'SQLite':
3889
                    cursor.execute('begin')
3890

    
3891
                for drawing in drawings:
3892
                    if drawing.UID is None:
3893
                        # get image data
3894
                        image_blob_data = None
3895
                        #file_path = os.path.join(self.project.getDrawingFilePath(), drawing.name)
3896
                        #if drawing.name and os.path.isfile(file_path):
3897
                        #    with open(file_path.encode('utf-8'), 'rb') as file:
3898
                        #        image_blob_data = file.read()
3899
                        # up to here
3900

    
3901
                        sql = self.project.database.to_sql(
3902
                            'insert into Drawings(UID, [NAME], [DATETIME], [Image]) values(?, ?, ?, ?)')
3903
                        param = tuple([str(uuid.uuid4()), drawing.name, '', image_blob_data])
3904
                        drawing.UID = param[0]
3905
                    else:
3906
                        sql = self.project.database.to_sql("update Drawings set [NAME]=?,[DATETIME]=? where UID=?")
3907
                        param = (drawing.name, drawing.datetime, str(drawing.UID))
3908
                        #param = (drawing.name, drawing.datetime, image_blob_data, str(drawing.UID))
3909

    
3910
                    cursor.execute(sql, param)
3911

    
3912
                if self.project.database.db_type == 'SQLite':
3913
                    cursor.execute('commit')
3914
                else:
3915
                    conn.commit()
3916
            # Catch the exception
3917
            except Exception as ex:
3918
                # Roll back any change if something goes wrong
3919
                conn.rollback()
3920

    
3921
                from App import App
3922
                message = 'error occurred({}) in {}:{}'.format(repr(ex), sys.exc_info()[-1].tb_frame.f_code.co_filename,
3923
                                                              sys.exc_info()[-1].tb_lineno)
3924
                App.mainWnd().addMessage.emit(MessageType.Error, message)
3925

    
3926
    '''
3927
        @brief  get IsOriginDetect ComboBox Items
3928
    '''
3929

    
3930
    def getIsOriginDetectComboBoxItems(self):
3931
        return [("원본 도면", 0), ("텍스트 제거 도면", 1)]
3932

    
3933
    '''
3934
        @brief  get IsOriginDetect ComboBox Items
3935
    '''
3936

    
3937
    def getOcrOptionComboBoxItems(self):
3938
        return [("OCR 미적용", 0), ("일반 심볼", 1), ("Instrument 계통", 2)]
3939

    
3940
    '''
3941
        @brief      Return Symbol Type Items
3942
        @author     Jeongwoo
3943
        @date       18.04.20
3944
        @history    18.05.08    Jeongwoo type index changed
3945
    '''
3946

    
3947
    def getSymbolTypeList(self):
3948
        symbolTypeList = []
3949

    
3950
        with self.project.database.connect() as conn:
3951
            cursor = conn.cursor()
3952
            sql = 'SELECT * FROM SymbolType ORDER BY Type ASC'
3953
            try:
3954
                cursor.execute(sql)
3955
                rows = cursor.fetchall()
3956
                for row in rows:
3957
                    symbolTypeList.append((row['UID'], row['Category'], row['Type']))  # UID, category, type
3958
            except Exception as ex:
3959
                from App import App
3960
                message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
3961
                                                              sys.exc_info()[-1].tb_lineno)
3962
                App.mainWnd().addMessage.emit(MessageType.Error, message)
3963

    
3964
        return symbolTypeList
3965

    
3966
    '''
3967
        @brief      Get Symbol Category by Symbol Type
3968
        @author     Jeongwoo
3969
        @date       2018.05.09
3970
    '''
3971

    
3972
    def getSymbolCategoryByType(self, type):
3973
        category = None
3974
        if type in self._symbolType:
3975
            return self._symbolType[type]
3976

    
3977
        with self.project.database.connect() as conn:
3978
            try:
3979
                cursor = conn.cursor()
3980
                sql = self.project.database.to_sql('SELECT Category FROM SymbolType WHERE [Type] = ?')
3981
                cursor.execute(sql, (type,))
3982
                rows = cursor.fetchall()
3983
                if rows is not None and len(rows) > 0:
3984
                    category = rows[0]['Category']
3985
                    self._symbolType[type] = category
3986
            except Exception as ex:
3987
                print('error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
3988
                                                          sys.exc_info()[-1].tb_lineno))
3989

    
3990
        return category
3991

    
3992
    '''
3993
        @brief      Check Symbol Type is included in 'Equipment' Category
3994
        @author     Jeongwoo
3995
        @date       2018.05.09
3996
    '''
3997

    
3998
    def isEquipmentType(self, type):
3999
        category = self.getSymbolCategoryByType(type)
4000
        return category is not None and category == 'Equipment'
4001

    
4002
    '''
4003
        @brief      Return Symbol Type Items with "None"
4004
        @author     Jeongwoo
4005
        @date       18.04.06
4006
        @history    Seperate SymbolTypeList and "None"
4007
    '''
4008

    
4009
    def getSymbolTypeComboBoxItems(self):
4010
        symbolTypeList = [symbol_type for symbol_type in self.getSymbolTypeList() if symbol_type[1]]
4011
        symbolTypeList.insert(0, ('None', 'None', 'None'))
4012

    
4013
        return symbolTypeList
4014

    
4015
    '''
4016
        @brief  get Base Symbol ComboBox Items
4017
    '''
4018

    
4019
    def getBaseSymbolComboBoxItems(self, type=None):
4020
        bsymbolNameList = self.getSymbolNameListByType(type)
4021
        bsymbolNameList.sort()
4022
        bsymbolNameList.insert(0, "None")
4023
        return bsymbolNameList
4024

    
4025
    '''
4026
        @brief  get Additional Symbol ComboBox Items
4027
    '''
4028

    
4029
    def getAdditionalSymbolComboBoxItems(self):
4030
        asymbolNameList = self.getSymbolNameList()
4031
        asymbolNameList.sort()
4032
        asymbolNameList.insert(0, "None")
4033
        return asymbolNameList
4034

    
4035
    '''
4036
        @brief  get Additional Symbol's default direction ComboBox Items
4037
    '''
4038

    
4039
    def getDefaultSymbolDirectionComboBoxItems(self):
4040
        return [("UP", 0), ("DOWN", 2), ("LEFT", 3), ("RIGHT", 1)]
4041

    
4042
    '''
4043
        @brief  getter of activeDrawing
4044
        @author humkyung
4045
        @date   2018.07.07
4046
    '''
4047

    
4048
    @property
4049
    def activeDrawing(self):
4050
        return self._activeDrawing
4051

    
4052
    '''
4053
        @brief  setter of activeDrawing
4054
        @author humkyung
4055
        @date   2018.07.07
4056
    '''
4057

    
4058
    @activeDrawing.setter
4059
    def activeDrawing(self, value):
4060
        if self._activeDrawing:
4061
            del self._activeDrawing
4062

    
4063
        self._activeDrawing = value
4064

    
4065
    def getColNames(self, table):
4066
        """ return column names of given table and attribute names if tabe is VALVE_DATA_LIST or EQUIPMET_DATA_LIST """
4067
        res = None
4068

    
4069
        conn = self.project.database.connect()
4070
        with conn:
4071
            try:
4072
                cursor = conn.cursor()
4073
                cursor.execute('select * from {}'.format(table))
4074
                res = [col_name[0] for col_name in cursor.description]
4075

    
4076
                if table == 'EQUIPMET_DATA_LIST' or table == 'VALVE_DATA_LIST':
4077
                    sql = 'select distinct c.Attribute from {} a left join Attributes b on a.uid=b.Components_UID ' \
4078
                          'left join SymbolAttribute c on b.SymbolAttribute_UID=c.UID where c.Attribute is not NULL'.format(
4079
                        table)
4080
                    cursor.execute(sql)
4081
                    rows = cursor.fetchall()
4082
                    for row in rows:
4083
                        res.append(row['Attribute'])
4084
            # Catch the exception
4085
            except Exception as ex:
4086
                print('error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
4087
                                                          sys.exc_info()[-1].tb_lineno))
4088

    
4089
        return res
4090

    
4091
    '''
4092
        @brief  getter of OCRData
4093
        @author humkyung
4094
        @date   2018.11.19
4095
    '''
4096

    
4097
    @property
4098
    def OCRData(self):
4099
        if self._OCRData is None:
4100
            configs = self.getConfigs('Text Recognition', 'OCR Data')
4101
            self._OCRData = configs[0].value if 1 == len(configs) else 'eng'
4102

    
4103
        return self._OCRData
4104

    
4105
    '''
4106
        @brief  setter of OCRData
4107
        @author humkyung
4108
        @date   2018.11.19
4109
    '''
4110

    
4111
    @OCRData.setter
4112
    def OCRData(self, value):
4113
        self._OCRData = value
4114

    
4115

    
4116
if __name__ == '__main__':
4117
    from AppDocData import AppDocData
4118

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