프로젝트

일반

사용자정보

통계
| 개정판:

hytos / DTI_PID / DTI_PID / CodeTableDialog.py @ 7e2d59db

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

1
# coding: utf-8
2
"""
3
    This is code table dialog module
4
"""
5
import os
6
import sys, io
7
from PyQt5.QtCore import *
8
from PyQt5.QtGui import *
9
from PyQt5.QtWidgets import *
10
from AppDocData import AppDocData, MessageType
11
from App import App
12
from openpyxl import *
13
from openpyxl.styles import *
14

    
15
from PIL import Image
16
import tesseract_ocr_module as TOCR
17
import numpy as np
18

    
19
import CodeTable_UI
20
import FenceCommand
21
from GraphicsBoundingBoxItem import QGraphicsBoundingBoxItem
22

    
23
class QCodeTableDialog(QDialog):
24
    """ This code table dialog class """
25

    
26
    CODE_TABLES = (
27
    'Nominal Diameter', 'Fluid Code', 'Insulation Purpose', 'PnID Number', 'Piping Materials Class', 'Unit Number',
28
    'ValveOperCodes', 'EqpTagNames', 'ReservedWords', 'Dictionary')
29

    
30
    def __init__(self, parent, child_dialog=''):
31
        QDialog.__init__(self, parent)
32

    
33
        self.currentCode = {}
34

    
35
        self.code_area = None
36
        self.desc_area = None
37

    
38
        self.child_dialog = child_dialog
39
        if not child_dialog:
40
            self.ui = CodeTable_UI.Ui_CodeTableDialog()
41
            self.ui.setupUi(self)
42

    
43
            self.ui.spinBoxHeight.setValue(50)
44

    
45
            self.ui.tableWidgetNominalDiameter.setSortingEnabled(True)
46
            self.ui.tableWidgetFluidCode.setSortingEnabled(True)
47
            self.ui.tableWidgetInsulationPurpose.setSortingEnabled(True)
48
            self.ui.tableWidgetPnIDNumber.setSortingEnabled(True)
49
            self.ui.tableWidgetPipingMaterialsClass.setSortingEnabled(True)
50
            self.ui.tableWidgetUnitNumber.setSortingEnabled(True)
51
            self.ui.tableWidgetValveOperCodes.setSortingEnabled(True)
52
            self.ui.tableWidgetEqpTagNames.setSortingEnabled(True)
53
            self.ui.tableWidgetReservedWords.setSortingEnabled(True)
54

    
55
            # DB Table명 기준으로 작성
56
            for table in QCodeTableDialog.CODE_TABLES:
57
                self.settingTable(table)
58

    
59
            # connect signals
60
            self.ui.pushButtonImport.clicked.connect(self.import_code_table)
61
            self.ui.pushButtonExport.clicked.connect(self.export_code_table)
62
            self.ui.pushButtonRead.clicked.connect(self.read_from_legend)
63

    
64
        self.graphicsView = App.mainWnd().graphicsView
65
        self.fence_cmd = FenceCommand.FenceCommand(self.graphicsView)
66
        self.fence_cmd.onSuccess.connect(self.onAreaCreated)
67

    
68
    def getTabText(self):
69
        """ get current tab name text """
70
        if not self.child_dialog:
71
            _tabWidget = self.ui.tabWidget
72
            currentTabIndex = _tabWidget.currentIndex()
73
            tabText = self.replaceText(_tabWidget.tabText(currentTabIndex))
74
        else:
75
            tabText = self.child_dialog
76
        return tabText
77

    
78
    def read_from_legend(self):
79
        """ read code data from legend drawing """
80
        if self.ui.pushButtonRead.text() == 'Read from Legend':
81
            self.graphicsView.command = self.fence_cmd
82
            self.ui.pushButtonRead.setText('Draw Code Area')
83
        elif self.ui.pushButtonRead.text() == 'Read' and self.code_area and self.code_area.scene() and self.desc_area and self.desc_area.scene():
84
            # read ocr
85
            code_rect = self.code_area.sceneBoundingRect()
86
            desc_rect = self.desc_area.sceneBoundingRect()
87
            code_img = self.graphicsView.image().copy(code_rect.x(), code_rect.y(), code_rect.width(), code_rect.height())
88
            desc_img = self.graphicsView.image().copy(desc_rect.x(), desc_rect.y(), desc_rect.width(), desc_rect.height())
89
            code_texts = self.detectText(code_img, code_rect)
90
            desc_texts = self.detectText(desc_img, desc_rect)
91

    
92
            # check validate
93
            for code_text in code_texts:
94
                code_text.desc = []
95

    
96
            if desc_texts:
97
                for desc_index in reversed(range(len(desc_texts))):
98
                    for code_index in range(len(code_texts)):
99
                        if abs(desc_texts[desc_index].center[1] - code_texts[code_index].center[1]) < round(self.ui.spinBoxHeight.value() / 2):
100
                            code_texts[code_index].desc.append(desc_texts[desc_index])
101
                            desc_texts.pop(desc_index)
102
                            break
103

    
104
                for desc_index in reversed(range(len(desc_texts))):
105
                    min_distance = sys.maxsize
106
                    min_code = None
107
                    for code_index in range(len(code_texts)):
108
                        distance = desc_texts[desc_index].center[1] - code_texts[code_index].center[1]
109
                        if distance > 0 and distance < min_distance:
110
                            min_distance = distance
111
                            min_code = code_texts[code_index]
112

    
113
                    if min_code:
114
                        min_code.desc.append(desc_texts[desc_index])
115
                        desc_texts.pop(desc_index)
116
                    
117

    
118
                #QMessageBox.warning(self, self.tr('Notice'), self.tr('Please check text area.'))
119
                #return  
120

    
121
            desc_texts = []
122
            for code_text in code_texts:
123
                desc = ' '.join([desc.getText() for desc in sorted(code_text.desc, key=lambda desc: desc.center[1])])
124
                desc_texts.append(desc)
125

    
126
            # fill table
127
            tabText = self.getTabText()
128

    
129
            if tabText == 'NominalDiameter':
130
                return
131
            table = self.findTableWidget(tabText)
132

    
133
            table.cellChanged.disconnect(self.cellValueChanged)
134
            
135
            past_count = table.rowCount()
136
            for row_index in range(past_count):
137
                for code_index in reversed(range(len(code_texts))):
138
                    if table.isRowHidden(row_index): continue
139
                    if table.item(row_index, 1) and table.item(row_index, 1).text() == code_texts[code_index].getText():
140
                        table.setItem(row_index, 2, QTableWidgetItem(desc_texts[code_index]))
141
                        code_texts.pop(code_index)
142
                        desc_texts.pop(code_index)
143
                        break
144
            table.setRowCount(past_count + len(code_texts))
145
            for code_index in range(len(code_texts)):
146
                table.setItem(past_count + code_index - 1, 0, QTableWidgetItem(''))
147
                table.setItem(past_count + code_index - 1, 1, QTableWidgetItem(code_texts[code_index].getText()))
148
                table.setItem(past_count + code_index - 1, 2, QTableWidgetItem(desc_texts[code_index]))
149

    
150
            last_empty_row = table.rowCount()
151
            table.setItem(last_empty_row - 1, 0, QTableWidgetItem(''))
152
            table.setItem(last_empty_row - 1, 1, QTableWidgetItem(''))
153
            table.setItem(last_empty_row - 1, 2, QTableWidgetItem(''))
154

    
155
            table.cellChanged.connect(self.cellValueChanged)
156

    
157
            if self.code_area:
158
                if self.code_area.scene():
159
                    self.graphicsView.scene.removeItem(self.code_area)
160
                self.code_area = None
161
            if self.desc_area:
162
                if self.desc_area.scene():
163
                    self.graphicsView.scene.removeItem(self.desc_area)
164
                self.desc_area = None
165
            self.ui.pushButtonRead.setText('Read from Legend')
166
        else:
167
            if self.code_area:
168
                if self.code_area.scene():
169
                    self.graphicsView.scene.removeItem(self.code_area)
170
                self.code_area = None
171
            if self.desc_area:
172
                if self.desc_area.scene():
173
                    self.graphicsView.scene.removeItem(self.desc_area)
174
                self.desc_area = None
175
            self.ui.pushButtonRead.setText('Read from Legend')
176

    
177
    def onAreaCreated(self, x, y , width, height):
178
        import uuid
179
        THICKNESS = 5
180

    
181
        if self.ui.pushButtonRead.text() == 'Draw Code Area':
182
            item = QGraphicsBoundingBoxItem(x, y, width, height)
183
            item.setPen(QPen(Qt.red, THICKNESS, Qt.SolidLine))
184
            self.graphicsView.scene.addItem(item)
185
            self.code_area = item
186
            self.ui.pushButtonRead.setText('Draw Description Area')
187
        elif self.ui.pushButtonRead.text() == 'Draw Description Area' and self.code_area and self.code_area.scene():
188
            item = QGraphicsBoundingBoxItem(x, y, width, height)
189
            item.setPen(QPen(Qt.blue, THICKNESS, Qt.SolidLine))
190
            self.graphicsView.scene.addItem(item)
191
            self.desc_area = item
192
            self.ui.pushButtonRead.setText('Read')
193
            self.graphicsView.command = None
194

    
195
    def detectText(self, image, rect):
196
        """ detect text from image, come from OcrResultDialog and modified """
197
        try:
198
            buffer = QBuffer()
199
            buffer.open(QBuffer.ReadWrite)
200
            image.save(buffer, "PNG")
201
            pyImage = Image.open(io.BytesIO(buffer.data()))
202
            img = np.array(pyImage)
203
            
204
            docData = AppDocData.instance()
205
            configs = docData.getConfigs('Text Recognition', 'OCR Data')
206
            ocr_data = configs[0].value if 1 == len(configs) else 'eng'
207

    
208
            whiteCharList = docData.getConfigs('Text Recognition', 'White Character List')
209
            if len(whiteCharList) is 0:
210
                textInfoList = TOCR.getTextInfo(img, (round(rect.x()), round(rect.y())), 0, language=ocr_data)
211
            else:
212
                textInfoList = TOCR.getTextInfo(img, (round(rect.x()), round(rect.y())), 0, language=ocr_data, conf = whiteCharList[0].value)
213

    
214
            if textInfoList is not None and len(textInfoList) > 0:
215
                return textInfoList
216
        except Exception as ex:
217
            from App import App 
218
            message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename, sys.exc_info()[-1].tb_lineno)
219
            App.mainWnd().addMessage.emit(MessageType.Error, message)
220

    
221
    '''
222
        @brief      Setting Table
223
        @author     kyouho
224
        @date       2018.07.10
225
    '''
226

    
227
    def settingTable(self, tableName, symbol_attribute_uid=None, tableDatas=None):
228
        try:
229
            tableName = self.replaceText(tableName)
230
            docData = AppDocData.instance()
231
            table = self.findTableWidget(tableName)
232
            if table: table.horizontalHeader().setStretchLastSection(True)
233
            if tableName == "NominalDiameter":
234
                tableDatas = docData.getNomialPipeSizeData()
235
            elif tableName == "SymbolAttributeCodeTable":
236
                if tableDatas is None:
237
                    tableDatas = docData.getCodeTable(tableName, forCheckLineNumber=False, symbol_attribute_uid=symbol_attribute_uid)
238
                else:
239
                    pass
240
            else:
241
                tableDatas = docData.getCodeTable(tableName)
242

    
243
            if tableName == "NominalDiameter":
244
                self.fill_nominal_pipe_sizes(tableDatas)
245

    
246
                table.cellChanged.connect(self.cellValueChanged)
247
                self.checkRowAndAddRow(tableName, table)
248
            else:
249
                table.setColumnCount(4)
250
                table.setHorizontalHeaderLabels(['UID', 'Code', 'Desc.', 'Allowables'])
251
                table.hideColumn(0)
252

    
253
                self.fill_codes(table, tableDatas)
254

    
255
                table.horizontalHeaderItem(1).setSizeHint(QSize(30, 30))
256
                table.cellChanged.connect(self.cellValueChanged)
257
                self.checkRowAndAddRow(tableName, table)
258
                self.setCurrentCode(table, tableName)
259
        except Exception as ex:
260
            print('error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
261
                                                       sys.exc_info()[-1].tb_lineno))
262

    
263
    '''
264
        @brief      Insert row NominalPipeSzie Tablewidget
265
        @author     kyouho
266
        @date       2018.07.10
267
    '''
268

    
269
    def fill_nominal_pipe_sizes(self, pipeSizes):
270
        try:
271
            self.ui.tableWidgetNominalDiameter.setColumnCount(8)
272
            self.ui.tableWidgetNominalDiameter.setHorizontalHeaderLabels(
273
                ['UID', 'Code', 'Metric', 'Inch', 'InchStr', 'Inch Allowables', 'MetricStr', 'Metric Allowables'])
274
            self.ui.tableWidgetNominalDiameter.hideColumn(0)
275
            self.ui.tableWidgetNominalDiameter.setRowCount(len(pipeSizes))
276
            row = 0
277
            for pipeSize in pipeSizes:
278
                item = QTableWidgetItem(pipeSize.uid)
279
                item.setData(Qt.UserRole, pipeSize)
280
                self.ui.tableWidgetNominalDiameter.setItem(row, 0, item)
281
                self.ui.tableWidgetNominalDiameter.setItem(row, 1, QTableWidgetItem(pipeSize.code))
282
                self.ui.tableWidgetNominalDiameter.setItem(row, 2, QTableWidgetItem(
283
                    '' if pipeSize.metric is None else str(pipeSize.metric)))
284
                self.ui.tableWidgetNominalDiameter.setItem(row, 3, QTableWidgetItem(
285
                    '' if pipeSize.inch is None else str(pipeSize.inch)))
286
                self.ui.tableWidgetNominalDiameter.setItem(row, 4, QTableWidgetItem(
287
                    '' if pipeSize.inchStr is None else pipeSize.inchStr))
288
                self.ui.tableWidgetNominalDiameter.setItem(row, 5, QTableWidgetItem(
289
                    '' if pipeSize.allowable_inch_str is None else pipeSize.allowable_inch_str))
290
                self.ui.tableWidgetNominalDiameter.setItem(row, 6, QTableWidgetItem(
291
                    '' if pipeSize.metricStr is None else pipeSize.metricStr))
292
                self.ui.tableWidgetNominalDiameter.setItem(row, 7, QTableWidgetItem(
293
                    '' if pipeSize.allowable_metric_str is None else pipeSize.allowable_metric_str))
294
                row += 1
295

    
296
            self.ui.tableWidgetNominalDiameter.horizontalHeaderItem(0).setSizeHint(QSize(30, 30))
297
        except Exception as ex:
298
            from App import App
299

    
300
            message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
301
                                                           sys.exc_info()[-1].tb_lineno)
302
            App.mainWnd().addMessage.emit(MessageType.Error, message)
303

    
304
    '''
305
        @brief      Insert row Common Tablewidget
306
        @author     kyouho
307
        @date       2018.07.10
308
    '''
309

    
310
    def fill_codes(self, table, tableDatas):
311
        try:
312
            table.setRowCount(len(tableDatas))
313
            row = 0
314
            for tableData in tableDatas:
315
                table.setItem(row, 0, QTableWidgetItem(tableData[0]))  # UID
316
                table.setItem(row, 1, QTableWidgetItem(tableData[1]))  # Name
317
                table.setItem(row, 2, QTableWidgetItem(tableData[2] if tableData[2] else ''))  # Description
318
                table.setItem(row, 3, QTableWidgetItem((tableData[3] if type(tableData[3]) is str else ','.join(tableData[3])) \
319
                                                                            if tableData[3] else ''))  # Allowables
320
                row += 1
321
        except Exception as ex:
322
            from App import App
323

    
324
            message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
325
                                                           sys.exc_info()[-1].tb_lineno)
326
            App.mainWnd().addMessage.emit(MessageType.Error, message)
327

    
328
    '''
329
        @brief      Find TableWidget with Name
330
        @author     kyouhokyouho
331
        @date       2018.07.10
332
    '''
333

    
334
    def findTableWidget(self, tableName):
335
        tableName = self.replaceText(tableName)
336
        return self.findChild(QTableWidget, 'tableWidget' + tableName)
337

    
338
    '''
339
        @brief      key press event
340
        @author     kyouho
341
        @date       2018.07.10
342
    '''
343

    
344
    def keyPressEvent(self, e):
345
        try:
346
            if e.key() == Qt.Key_Delete:
347
                tabText = self.getTabText()
348
                
349
                table = self.findTableWidget(tabText)
350
                if table:
351
                    selectedIndexes = table.selectedIndexes()
352
                    selectedRows = [item.row() for item in selectedIndexes]
353
                    model = table.model()
354

    
355
                    rowsIndex = []
356
                    for row in selectedRows:
357
                        rowsIndex.append(row)
358

    
359
                    # 중복 제거
360
                    rowsIndex = list(set(rowsIndex))
361
                    rowsIndex.reverse()
362

    
363
                    if tabText != "NominalDiameter":
364
                        for row in rowsIndex:
365
                            table.hideRow(row)
366
                            """
367
                            uid = table.item(row, 0).text()
368
                            self.removeUID[uid] = tabText
369
                            model.removeRow(row)
370
                            """
371

    
372
                        self.checkRowAndAddRow(tabText, table)
373
            elif (e.key() == Qt.Key_C) and (e.modifiers() & Qt.ControlModifier):
374
                tabText = self.getTabText()
375
                
376
                table = self.findTableWidget(tabText)
377
                if table:
378
                    self.copy_selection(table)
379
            elif (e.key() == Qt.Key_V) and (e.modifiers() & Qt.ControlModifier):
380
                tabText = self.getTabText()
381
                '''
382
                table = self.findTableWidget(tabText)
383
                tab = self.ui.tabWidget.widget(self.ui.tabWidget.currentIndex())
384
                table = tab.findChild(QTableWidget)
385
                '''
386
                table = self.findTableWidget(tabText)
387
                if table:
388
                    self.paste_selection(table)
389
        except Exception as ex:
390
            from App import App
391
            message = 'error occurred({}) in {}:{}'.format(repr(ex), sys.exc_info()[-1].tb_frame.f_code.co_filename,
392
                                                           sys.exc_info()[-1].tb_lineno)
393
            App.mainWnd().addMessage.emit(MessageType.Error, message)
394

    
395
    def copy_selection(self, table_widget):
396
        """copy selected text to clipboard"""
397

    
398
        import io
399
        import csv
400

    
401
        selection = table_widget.selectedIndexes()
402
        if selection:
403
            rows = sorted(index.row() for index in selection)
404
            columns = sorted(index.column() for index in selection)
405
            rowcount = rows[-1] - rows[0] + 1
406
            colcount = columns[-1] - columns[0] + 1
407
            table = [[''] * colcount for _ in range(rowcount)]
408
            for index in selection:
409
                row = index.row() - rows[0]
410
                column = index.column() - columns[0]
411
                table[row][column] = index.data()
412
            stream = io.StringIO()
413
            csv.writer(stream, delimiter='\t').writerows(table)
414
            QApplication.clipboard().setText(stream.getvalue())
415

    
416
    def paste_selection(self, table_widget):
417
        """paste text of clipboard to table widget"""
418

    
419
        import io
420
        import csv
421

    
422
        selection = table_widget.selectedIndexes()
423
        if selection:
424
            model = table_widget.model()
425

    
426
            buffer = QApplication.clipboard().text()
427
            rows = sorted(index.row() for index in selection)
428
            columns = sorted(index.column() for index in selection)
429
            reader = csv.reader(io.StringIO(buffer), delimiter='\t')
430
            if len(rows) == 1 and len(columns) == 1:
431
                for i, line in enumerate(reader):
432
                    for j, cell in enumerate(line):
433
                        model.setData(model.index(rows[0] + i, columns[0] + j), cell)
434
            else:
435
                arr = [[cell for cell in row] for row in reader]
436
                for index in selection:
437
                    row = index.row() - rows[0]
438
                    column = index.column() - columns[0]
439
                    model.setData(model.index(index.row(), index.column()), arr[row][column])
440

    
441
    '''
442
        @brief      Add new row
443
        @author     kyouho
444
        @date       2018.07.10
445
    '''
446

    
447
    def checkRowAndAddRow(self, tableName, table):
448
        try:
449
            rowCount = table.rowCount()
450
            result = True
451
            if tableName != "NominalDiameter":
452
                for row in range(rowCount):
453
                    if table.isRowHidden(row): continue
454
                    code = table.item(row, 1).text()
455
                    if not code:
456
                        result = False
457
                if result:
458
                    table.cellChanged.disconnect(self.cellValueChanged)
459
                    table.setRowCount(rowCount + 1)
460
                    table.setItem(rowCount, 0, QTableWidgetItem(''))
461
                    table.setItem(rowCount, 1, QTableWidgetItem(''))
462
                    table.setItem(rowCount, 2, QTableWidgetItem(''))
463
                    table.setItem(rowCount, 3, QTableWidgetItem(''))
464
                    table.cellChanged.connect(self.cellValueChanged)
465
            else:
466
                columnCount = table.columnCount()
467

    
468
                for row in range(rowCount):
469
                    if not result:
470
                        break
471
                    for columnIndex in range(columnCount):
472
                        if not table.item(row, columnIndex).text():
473
                            result = False
474
                            break
475

    
476
                if result:
477
                    table.setRowCount(rowCount + 1)
478
                    table.cellChanged.disconnect(self.cellValueChanged)
479
                    for columnIndex in range(columnCount):
480
                        table.setItem(rowCount, columnIndex, QTableWidgetItem(''))
481
                    table.cellChanged.connect(self.cellValueChanged)
482

    
483
        except Exception as ex:
484
            print('error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
485
                                                       sys.exc_info()[-1].tb_lineno))
486

    
487
    '''
488
        @brief      cellValueChange event
489
        @author     kyouho
490
        @date       2018.07.10
491
    '''
492

    
493
    def cellValueChanged(self, row, column):
494
        try:
495
            tabText = self.getTabText()
496

    
497
            table = self.findTableWidget(tabText)
498

    
499
            if tabText != "NominalDiameter":
500
                item = table.item(row, 1)
501
                code = item.text()
502
                if column == 1:
503
                    result = self.isExistCode(table, code)
504
                    if result:
505
                        self.checkRowAndAddRow(tabText, table)
506
                        self.setCurrentCode(table, tabText)
507
                    else:
508
                        QMessageBox.warning(self, self.tr('Notice'),
509
                                            self.tr('The same code already exists in the table.'))
510
                        table.cellChanged.disconnect(self.cellValueChanged)
511
                        item.setText(self.currentCode[tabText][row])
512
                        table.cellChanged.connect(self.cellValueChanged)
513
                elif column == 2:
514
                    table.resizeColumnToContents(2)
515
                else:
516
                    table.resizeColumnToContents(3)
517
            else:
518
                self.checkRowAndAddRow(tabText, table)
519
        except Exception as ex:
520
            print('error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
521
                                                       sys.exc_info()[-1].tb_lineno))
522

    
523
    '''
524
        @brief      Check Duplicate Code 
525
        @author     kyouho
526
        @date       2018.07.10
527
    '''
528

    
529
    def isExistCode(self, table, editCode):
530
        try:
531
            if not editCode:
532
                return False
533

    
534
            rowCount = table.rowCount()
535
            codes = []
536
            for row in range(rowCount):
537
                if table.isRowHidden(row): continue
538
                code = table.item(row, 1).text()
539
                codes.append(code)
540

    
541
            count = codes.count(editCode)
542

    
543
            if count >= 2:
544
                return False
545
            else:
546
                return True
547

    
548
        except Exception as ex:
549
            print('error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
550
                                                       sys.exc_info()[-1].tb_lineno))
551

    
552
    '''
553
        @brief      save current Code (self.currentCode)
554
        @author     kyouho
555
        @date       2018.07.10
556
    '''
557

    
558
    def setCurrentCode(self, table, tabText):
559
        try:
560
            self.currentCode[tabText] = {}
561
            rowCount = table.rowCount()
562

    
563
            res = {}
564
            for row in range(rowCount):
565
                code = table.item(row, 1).text()
566
                res[row] = code
567

    
568
            self.currentCode[tabText] = res
569

    
570
        except Exception as ex:
571
            print('error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
572
                                                       sys.exc_info()[-1].tb_lineno))
573

    
574
    '''
575
        @brief      replaceTextForCodeTable
576
        @author     kyouho
577
        @date       2018.07.12
578
    '''
579

    
580
    def replaceText(self, text):
581
        return text.replace(' ', '').replace('&&', 'n')
582

    
583
    def import_code_table(self):
584
        """import code table excel file"""
585

    
586
        options = QFileDialog.Options()
587
        options |= QFileDialog.DontUseNativeDialog
588
        file_name, _ = QFileDialog.getOpenFileName(self, "Import code table", os.getcwd(), "xlsx files(*.xlsx)",
589
                                                   options=options)
590
        if file_name:
591
            QApplication.setOverrideCursor(Qt.WaitCursor)
592
            try:
593
                app_doc_data = AppDocData.instance()
594
                book = load_workbook(file_name)
595
                for sheet in book.worksheets:
596
                    matches = [index for index in range(self.ui.tabWidget.count())
597
                               if sheet.title == self.ui.tabWidget.tabText(index)]
598
                    if matches:
599
                        table = self.ui.tabWidget.widget(matches[0]).findChild(QTableWidget)
600
                        self.fill_table_with_sheet(sheet, table)
601
            except Exception as ex:
602
                from App import App
603
                message = 'error occurred({}) in {}:{}'.format(repr(ex), sys.exc_info()[-1].tb_frame.f_code.co_filename,
604
                                                               sys.exc_info()[-1].tb_lineno)
605
                App.mainWnd().addMessage.emit(MessageType.Error, message)
606
            finally:
607
                QApplication.restoreOverrideCursor()
608

    
609

    
610
    def export_code_table(self):
611
        """export code table to excel file"""
612

    
613
        app_doc_data = AppDocData.instance()
614
        project = app_doc_data.getCurrentProject()
615

    
616
        options = QFileDialog.Options()
617
        options |= QFileDialog.DontUseNativeDialog
618
        file_name, _ = QFileDialog.getSaveFileName(self, "Export code table", project.path, "xlsx files(*.xlsx)",
619
                                                   options=options)
620
        if not file_name:
621
            return
622

    
623
        QApplication.setOverrideCursor(Qt.WaitCursor)
624

    
625
        try:
626
            wb = Workbook()
627
            wb.active.title = self.tr(self.ui.tabWidget.tabText(0))
628
            for index in range(1, self.ui.tabWidget.count()):
629
                wb.create_sheet(self.tr(self.ui.tabWidget.tabText(index)))
630

    
631
            for index in range(self.ui.tabWidget.count()):
632
                tab = self.ui.tabWidget.widget(index)
633
                table = tab.findChild(QTableWidget)
634
                if table:
635
                    sheet = wb.worksheets[index]
636
                    self.set_sheet_header(table, sheet)
637
                    self.fill_sheet_with_table(table, sheet)
638
                    self.auto_resize_columns(sheet)
639

    
640
            file_name, ext = os.path.splitext(file_name)
641
            save_file_name = file_name + ext if ext.upper() == '.XLSX' else file_name + '.xlsx'
642
            wb.save(save_file_name)
643

    
644
            QMessageBox.about(self, self.tr("Information"), self.tr('Successfully saved.'))
645

    
646
            os.startfile(save_file_name)
647
        except Exception as ex:
648
            from App import App
649
            from AppDocData import MessageType
650

    
651
            message = 'error occurred({}) in {}:{}'.format(repr(ex), sys.exc_info()[-1].tb_frame.f_code.co_filename,
652
                                                           sys.exc_info()[-1].tb_lineno)
653
            App.mainWnd().addMessage.emit(MessageType.Error, message)
654
        finally:
655
            QApplication.restoreOverrideCursor()
656

    
657
    def set_sheet_header(self, table, sheet):
658
        """ set list header """
659

    
660
        try:
661
            thin = Side(border_style='thin', color='000000')
662
            border = Border(left=thin, right=thin, top=thin, bottom=thin)
663
            _col = 1
664
            for col in range(table.columnCount()):
665
                logical_index = table.horizontalHeader().logicalIndex(col)
666
                col_name = table.horizontalHeaderItem(logical_index).text()
667
                sheet.cell(1, _col, col_name)
668
                sheet.cell(row=1, column=_col).alignment = Alignment(horizontal='center', vertical='center',
669
                                                                     wrapText=True)
670
                sheet.cell(row=1, column=_col).fill = PatternFill(patternType='solid', fill_type='solid',
671
                                                                  fgColor=Color('8DB4E2'))
672
                sheet.cell(row=1, column=_col).border = border
673
                _col += 1
674
        except Exception as ex:
675
            from App import App
676
            from AppDocData import MessageType
677

    
678
            message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
679
                                                           sys.exc_info()[-1].tb_lineno)
680
            App.mainWnd().addMessage.emit(MessageType.Error, message)
681

    
682
    def fill_table_with_sheet(self, sheet, table):
683
        """fill table with sheet"""
684
        from NominalPipeSize import NominalPipeSize
685

    
686
        try:
687
            row_index = 0
688
            headers = {}
689
            if sheet.title == 'Nominal Diameter':
690
                pipe_sizes = []
691
                for row in sheet.rows:
692
                    if row_index == 0:
693
                        for col in range(sheet.max_column):
694
                            value = row[col].value
695
                            headers[col] = value
696
                    else:
697
                        pipe_size = NominalPipeSize(None, None, None, None, None, None, None, None)
698
                        for col in range(sheet.max_column):
699
                            value = row[col].value
700
                            if 'UID' == headers[col]:
701
                                pipe_size.uid = value
702
                            elif 'Code' == headers[col]:
703
                                pipe_size.code = value
704
                            elif 'Metric' == headers[col]:
705
                                pipe_size.metric = value
706
                            elif 'Inch' == headers[col]:
707
                                pipe_size.inch = value
708
                            elif 'InchStr' == headers[col]:
709
                                pipe_size.inchStr = value
710
                            elif 'Inch Allowables' == headers[col]:
711
                                pipe_size.allowable_inch_str = value
712
                            elif 'MetricStr' == headers[col]:
713
                                pipe_size.metricStr = value
714
                            elif 'Metric Allowables' == headers[col]:
715
                                pipe_size.allowable_metric_str = value
716

    
717
                        pipe_sizes.append(pipe_size)
718

    
719
                    row_index += 1
720

    
721
                self.fill_nominal_pipe_sizes(pipe_sizes)
722
            else:
723
                codes = []
724
                for row in sheet.rows:
725
                    if row_index == 0:
726
                        for col in range(sheet.max_column):
727
                            value = row[col].value
728
                            headers[col] = value
729
                    else:
730
                        code = [row[col].value for col in range(sheet.max_column)]
731
                        codes.append(code)
732

    
733
                    row_index += 1
734

    
735
                self.fill_codes(table, codes)
736
        except Exception as ex:
737
            from App import App
738
            from AppDocData import MessageType
739

    
740
            message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
741
                                                           sys.exc_info()[-1].tb_lineno)
742
            App.mainWnd().addMessage.emit(MessageType.Error, message)
743

    
744
    def fill_sheet_with_table(self, table, sheet):
745
        """fill sheet with table"""
746

    
747
        try:
748
            thin = Side(border_style='thin', color='000000')
749
            border = Border(left=thin, right=thin, top=thin, bottom=thin)
750

    
751
            for col in range(table.columnCount()):
752
                for row in range(table.rowCount()):
753
                    try:
754
                        text = str(table.item(row, col).text())
755
                        sheet.cell(row + 2, col + 1, text)
756
                        sheet.cell(row=row + 2, column=col + 1).border = border
757
                    except AttributeError:
758
                        pass
759
        except Exception as ex:
760
            from App import App
761
            from AppDocData import MessageType
762

    
763
            message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
764
                                                           sys.exc_info()[-1].tb_lineno)
765
            App.mainWnd().addMessage.emit(MessageType.Error, message)
766

    
767
    def auto_resize_columns(self, sheet):
768
        """ auto resize columns with contents """
769

    
770
        from openpyxl.utils import get_column_letter
771
        try:
772
            for col in sheet.columns:
773
                max_length = 0
774
                column = col[0].column  # Get the column name
775
                for cell in col:
776
                    try:  # Necessary to avoid error on empty cells
777
                        if len(str(cell.value)) > max_length:
778
                            max_length = len(cell.value)
779
                    except:
780
                        pass
781

    
782
                adjusted_width = (max_length + 2) * 1.2
783
                sheet.column_dimensions[
784
                    get_column_letter(column) if type(column) is int else column].width = adjusted_width
785
        except Exception as ex:
786
            from App import App
787
            from AppDocData import MessageType
788

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

    
793
    '''
794
        @brief      save codes
795
        @author     kyouho
796
        @date       2018.07.12
797
    '''
798

    
799
    def accept(self):
800
        from CodeTables import CodeTable
801
        for table in QCodeTableDialog.CODE_TABLES:
802
            if table != 'Nominal Diameter':
803
                self.saveCommonCodeData(table)
804

    
805
        self.saveNomialPipeSize()
806
        CodeTable.clearTables()
807

    
808
        QDialog.accept(self)
809

    
810
    '''
811
        @brief      save common code data
812
        @author     kyouho
813
        @date       2018.07.12
814
    '''
815

    
816
    def saveCommonCodeData(self, tableName):
817
        datas = []
818
        try:
819
            tableName = self.replaceText(tableName)
820
            table = self.findTableWidget(tableName)
821
            rowCount = table.rowCount()
822
            for row in range(rowCount):
823
                if table.isRowHidden(row):
824
                    uid, code, description, allowables = '-1', table.item(row, 1).text(), '', table.item(row, 0).text()
825
                elif table.item(row, 0):
826
                    uid = table.item(row, 0).text()
827
                    code = table.item(row, 1).text()
828
                    description = table.item(row, 2).text() if table.item(row, 2) is not None else ''
829
                    allowables = table.item(row, 3).text() if table.item(row, 3) is not None else ''
830

    
831
                if code:
832
                    datas.append((uid, code, description, allowables))
833

    
834
            docData = AppDocData.instance()
835
            docData.saveCommonCodeData(tableName.replace(' ', ''), datas)
836
        except Exception as ex:
837
            from App import App
838

    
839
            message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
840
                                                           sys.exc_info()[-1].tb_lineno)
841
            App.mainWnd().addMessage.emit(MessageType.Error, message)
842

    
843
    '''
844
        @brief      save common code data
845
        @author     kyouho
846
        @date       2018.07.16
847
    '''
848

    
849
    def saveNomialPipeSize(self):
850
        pipeSizes = []
851
        try:
852
            docData = AppDocData.instance()
853

    
854
            from NominalPipeSize import NominalPipeSize
855

    
856
            table = self.ui.tableWidgetNominalDiameter
857
            rowCount = table.rowCount()
858
            for row in range(rowCount):
859
                pipe_size = table.item(row, 0).data(Qt.UserRole)
860
                pipe_size.code = table.item(row, 1).text()
861
                pipe_size.metric = float(table.item(row, 2).text()) if table.item(row, 2).text() != '' else None
862
                pipe_size.inch = float(table.item(row, 3).text()) if table.item(row, 3).text() != '' else None
863
                pipe_size.inchStr = table.item(row, 4).text()
864
                pipe_size.allowable_inch_str = table.item(row, 5).text()
865
                pipe_size.metricStr = table.item(row, 6).text()
866
                pipe_size.allowable_metric_str = table.item(row, 7).text()
867
                pipeSizes.append(pipe_size)
868

    
869
            docData.insertNomialPipeSize(pipeSizes)
870

    
871
        except Exception as ex:
872
            from App import App
873

    
874
            message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
875
                                                           sys.exc_info()[-1].tb_lineno)
876
            App.mainWnd().addMessage.emit(MessageType.Error, message)
클립보드 이미지 추가 (최대 크기: 500 MB)