프로젝트

일반

사용자정보

통계
| 개정판:

hytos / DTI_PID / DTI_PID / CodeTableDialog.py @ d9a0fe64

이력 | 보기 | 이력해설 | 다운로드 (37 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]))  # Description
318
                table.setItem(row, 3, QTableWidgetItem(tableData[3] if type(tableData[3]) is str else ','.join(tableData[3])))  # Allowables
319
                row += 1
320
        except Exception as ex:
321
            from App import App
322

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

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

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

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

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

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

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

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

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

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

    
397
        import io
398
        import csv
399

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

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

    
418
        import io
419
        import csv
420

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

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

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

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

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

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

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

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

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

    
496
            table = self.findTableWidget(tabText)
497

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

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

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

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

    
540
            count = codes.count(editCode)
541

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

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

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

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

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

    
567
            self.currentCode[tabText] = res
568

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

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

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

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

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

    
608

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

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

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

    
622
        QApplication.setOverrideCursor(Qt.WaitCursor)
623

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

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

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

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

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

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

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

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

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

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

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

    
716
                        pipe_sizes.append(pipe_size)
717

    
718
                    row_index += 1
719

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

    
732
                    row_index += 1
733

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

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

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

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

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

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

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

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

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

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

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

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

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

    
807
        QDialog.accept(self)
808

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

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

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

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

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

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

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

    
853
            from NominalPipeSize import NominalPipeSize
854

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

    
868
            docData.insertNomialPipeSize(pipeSizes)
869

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

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