프로젝트

일반

사용자정보

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

hytos / DTI_PID / DTI_PID / SymbolAttrEditorDialog.py @ 8aece8c1

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

1
# coding: utf-8
2
"""
3
This is SymbolAttrEditor module
4
"""
5
import os
6
import sys
7
import re
8
from PyQt5.QtCore import *
9
from PyQt5.QtGui import *
10
from PyQt5.QtWidgets import *
11
import sqlite3
12
from AppDocData import AppDocData
13
from AppDocData import Config
14
from TableWidgetEx import QTableWidgetEx
15
from SymbolSvgItem import SymbolSvgItem
16

    
17
import SymbolAttrEditor_UI
18

    
19

    
20
class AttributeDelegate(QStyledItemDelegate):
21
    def createEditor(self, parent, option, index):
22
        editor = super(AttributeDelegate, self).createEditor(parent, option, index)
23
        if index.column() == 1:
24
            editor = QLineEdit(parent)
25
            validator = QRegExpValidator(QRegExp('^[A-Za-z0-9-_ ]+$'), parent)
26
            editor.setValidator(validator)
27
        elif index.column() == 4:
28
            editor = QLineEdit(parent)
29
            validator = QRegExpValidator(QRegExp('^(\\d+|)$'), parent)
30
            editor.setValidator(validator)
31
        #elif index.column() == 5:
32
        #    combobox = self.parent().cellWidget(index.row(), 3)
33
        #    if combobox:
34
        #        if combobox.currentText() == 'HMB':
35
        #            app_doc_data = AppDocData.instance()
36
        #            attrs = app_doc_data.get_hmb_attributes()
37
        #            editor = QComboBox(parent)
38
        #            editor.addItems([attr.Attribute for attr in attrs])
39

    
40
        return editor
41

    
42

    
43
class QSymbolAttrEditorDialog(QDialog):
44
    """ This is symbol attribute editor dialog class """
45

    
46
    SYMBOL_ATTR_DATA_TYPES = {'Symbol Item': -1, 'Size Text Item': -1, 'Text Item': -1, 'Tag No': -1,
47
                              'Line Item': -1, 'Comp Item': -1, 'EQ Item': -1, 'Int': 1,
48
                              'String': 1, 'Combined': 1, 'HMB': 1, 'Reference': 1} # 'Valve Oper Code': -1, 
49
    LINE_NO_ATTR_TYPES = ['Code Table', 'Int', 'String', 'Symbol']
50

    
51
    def __init__(self, parent, symbolType = None):
52
        QDialog.__init__(self, parent)
53

    
54
        self.ui = SymbolAttrEditor_UI.Ui_SymbolAttrEditorDialog()
55
        self.ui.setupUi(self)
56
        self.ui.buttonBox.button(QDialogButtonBox.Ok).setIcon(QIcon(':/newPrefix/OK.svg'))
57
        self.ui.buttonBox.button(QDialogButtonBox.Cancel).setIcon(QIcon(':/newPrefix/Remove.svg'))
58

    
59
        self._symbolType = symbolType
60
        if symbolType is not None:
61
            self.ui.labelLineNo.setVisible(False)
62
            self.currentTypeId = 0
63
            # insert QTableWidgetEx
64
            self.ui.tableWidgetAttr = QTableWidgetEx(self.ui.groupBox)
65
            self.ui.tableWidgetAttr.setColumnCount(8)
66
            self.ui.tableWidgetAttr.setObjectName("tableWidgetAttr")
67
            self.ui.tableWidgetAttr.setRowCount(0)
68
            self.ui.tableWidgetAttr.verticalHeader().setVisible(False)
69
            self.ui.horizontalLayout_2.addWidget(self.ui.tableWidgetAttr)
70
            delegate = AttributeDelegate(self.ui.tableWidgetAttr)
71
            self.ui.tableWidgetAttr.setItemDelegate(delegate)
72
            # up to here
73
            # combobox logic
74
            self.settingComboBoxSymbolType(symbolType[2])
75
            self.ui.comboBoxSymbolType.currentTextChanged.connect(self.changeSymbolType)
76
            self.ui.comboBoxSymbolType.setEnabled(False)
77
            # up to here
78
            self.ui.pushButtonAddAttr.clicked.connect(self.onAddAttr)
79
            self.ui.pushButtonDelAttr.clicked.connect(self.onDelAttr)
80
            self.ui.tableWidgetAttr.setHorizontalHeaderLabels(['UID', 'Name', 'Display Name', 'Type', 'Attr At',
81
                                                               'Expression', 'Target', 'Code Table'])
82
            self.ui.tableWidgetAttr.horizontalHeaderItem(1).setSizeHint(QSize(25, 25))
83
            self.ui.tableWidgetAttr.setColumnWidth(3, 130)
84
            self.ui.tableWidgetAttr.hideColumn(0)
85

    
86
            self.ui.tableWidgetAttr.cellDoubleClicked.connect(self.cell_double_clicked)
87
        else:
88
            self.ui.comboBoxSymbolType.setVisible(False)
89
            # insert QTableWidgetEx
90
            self.ui.tableWidgetAttr = QTableWidgetEx(self.ui.groupBox)
91
            self.ui.tableWidgetAttr.setColumnCount(5)
92
            self.ui.tableWidgetAttr.setObjectName("tableWidgetAttr")
93
            self.ui.tableWidgetAttr.setRowCount(0)
94
            self.ui.tableWidgetAttr.verticalHeader().setVisible(False)
95
            self.ui.horizontalLayout_2.addWidget(self.ui.tableWidgetAttr)
96
            # up to here
97
            self.ui.tableWidgetAttr.setHorizontalHeaderLabels(['UID', 'Name', 'Display Name', 'Type', 'Length',
98
                                                               'Expression'])
99
            self.ui.tableWidgetAttr.horizontalHeaderItem(1).setSizeHint(QSize(25, 25))
100
            self.ui.tableWidgetAttr.hideColumn(0)
101

    
102
            self.settingLineNoAttributeTable()
103

    
104
            self.ui.pushButtonAddAttr.clicked.connect(self.onAddLineNoAttr)
105
            self.ui.pushButtonDelAttr.clicked.connect(self.onDelLineNoAttr)
106

    
107
    def changeType(self, text):
108
        """ make combobox for hmb type """
109
        from ItemDataExportDialog import QItemDataExportDialog
110

    
111
        row = self.ui.tableWidgetAttr.indexAt(self.sender().pos()).row()
112
        #col = self.ui.tableWidgetAttr.indexAt(self.sender().pos()).column()
113

    
114
        if text == 'HMB':
115
            hmb = QComboBox()
116
            names = ['']
117
            QItemDataExportDialog.add_hmb_header(names)
118
            hmb.addItems(names)
119
            hmb.currentTextChanged.connect(self.changeHMB)
120
            self.ui.tableWidgetAttr.takeItem(row, 1)
121
            self.ui.tableWidgetAttr.setCellWidget(row, 1, hmb)
122
        else:
123
            if self.ui.tableWidgetAttr.cellWidget(row, 1):
124
                self.ui.tableWidgetAttr.removeCellWidget(row, 1)
125
                self.ui.tableWidgetAttr.setItem(row, 1, QTableWidgetItem())
126

    
127
    def changeHMB(self, text):
128
        row = self.ui.tableWidgetAttr.indexAt(self.sender().pos()).row()
129
        #col = self.ui.tableWidgetAttr.indexAt(self.sender().pos()).column()
130

    
131
        item = QTableWidgetItem('HMB ' + text)
132
        self.ui.tableWidgetAttr.takeItem(row, 2)
133
        self.ui.tableWidgetAttr.setItem(row, 2, item)
134

    
135
    def cell_double_clicked(self, row, column):
136
        if self._symbolType is None or not (column is 6 or column is 7): return
137
        if hasattr(self.ui.tableWidgetAttr.item(row, 0), 'tag') and \
138
                self.ui.tableWidgetAttr.item(row, 0).data(Qt.UserRole).IsProp == 2: return
139

    
140
        from SymbolAttrTargetDialog import SymbolAttrTargetDialog
141
        from SymbolAttrCodeTableDialog import SymbolAttrCodeTableDialog
142
        from App import App
143

    
144
        try:
145
            # code table setting
146
            if column == 7:
147
                dialog = SymbolAttrCodeTableDialog(self, str(self.ui.tableWidgetAttr.item(row, 0).data(Qt.UserRole).UID),
148
                                                   tableDatas=self.ui.tableWidgetAttr.item(row, 7).data(Qt.UserRole))
149
                (isAccept, code_data) = dialog.showDialog()
150

    
151
                if isAccept:
152
                    self.ui.tableWidgetAttr.item(row, 7).setData(Qt.UserRole, code_data)
153

    
154
                graphicsView = App.mainWnd().graphicsView
155
                if dialog.code_area:
156
                    if dialog.code_area.scene():
157
                        graphicsView.scene().removeItem(dialog.code_area)
158
                if dialog.desc_area:
159
                    if dialog.desc_area.scene():
160
                        graphicsView.scene().removeItem(dialog.desc_area)
161
                graphicsView.useDefaultCommand()
162
            # target setting
163
            elif column == 6:
164
                symbolType = self.ui.comboBoxSymbolType.currentText()
165

    
166
                dialog = SymbolAttrTargetDialog(self, symbolType, self.ui.tableWidgetAttr.item(row, 6).data(Qt.UserRole))
167
                (isAccept, target) = dialog.showDialog()
168

    
169
                if isAccept:
170
                    self.ui.tableWidgetAttr.item(row, 6).setData(Qt.UserRole, target)
171
                    if target == 'ALL':
172
                        self.ui.tableWidgetAttr.item(row, 6).setText('ALL')
173
                    else:
174
                        self.ui.tableWidgetAttr.item(row, 6).setText('...')
175

    
176
        except Exception as ex:
177
            from App import App
178
            from AppDocData import MessageType
179

    
180
            message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
181
                                                           sys.exc_info()[-1].tb_lineno)
182
            App.mainWnd().addMessage.emit(MessageType.Error, message)
183

    
184
    '''
185
        @brief      setting combobox symbolType
186
        @author     kyouho
187
        @date       2018.08.16
188
    '''
189
    def settingComboBoxSymbolType(self, selectedType):
190
        docData = AppDocData.instance()
191
        comboBox = self.ui.comboBoxSymbolType
192

    
193
        symbolTypes = docData.getSymbolTypeList()
194
        for type in symbolTypes:
195
            comboBox.addItem(type[2])
196

    
197
        result = comboBox.findText(selectedType)
198
        if result != -1:
199
            comboBox.setCurrentIndex(result)
200

    
201
        self.changeSymbolType()
202

    
203
    '''
204
        @brief      combobox symbolType change logic
205
        @author     kyouho
206
        @date       2018.08.16
207
    '''
208
    def changeSymbolType(self):
209
        self._symbolType = self.ui.comboBoxSymbolType.currentText()
210
        self.ui.tableWidgetAttr.setRowCount(0)
211
        self.load_data(self._symbolType)
212

    
213
    def load_data(self, symbolType):
214
        """load data from database"""
215
        from ItemDataExportDialog import QItemDataExportDialog
216

    
217
        try:
218
            app_doc_data = AppDocData.instance()
219

    
220
            self.currentTypeId = app_doc_data.getSymbolTypeId(symbolType)
221

    
222
            attrs = app_doc_data.getSymbolAttribute(symbolType)
223
            self.ui.tableWidgetAttr.setRowCount(len(attrs))
224

    
225
            row = 0
226
            for attr in attrs:
227
                item = QTableWidgetItem(str(attr.UID))  # UID
228
                item.setData(Qt.UserRole, attr)
229
                self.ui.tableWidgetAttr.setItem(row, 0, item)
230
                
231
                item = QTableWidgetItem(attr.DisplayAttribute)  # Display Name
232
                self.ui.tableWidgetAttr.setItem(row, 2, item)
233

    
234
                attrTypeComboBox = QComboBox()
235
                for key, value in QSymbolAttrEditorDialog.SYMBOL_ATTR_DATA_TYPES.items():
236
                    attrTypeComboBox.addItem(key)
237

    
238
                if attr.IsProp and attr.IsProp >= 3:  # Type
239
                    attrTypeComboBox.setEnabled(False)
240
                if attr.AttributeType in [type for type, _ in QSymbolAttrEditorDialog.SYMBOL_ATTR_DATA_TYPES.items()]:
241
                    self.ui.tableWidgetAttr.setCellWidget(row, 3, attrTypeComboBox)
242
                    result = attrTypeComboBox.findText(attr.AttributeType)
243
                    attrTypeComboBox.setCurrentIndex(result)
244
                else:
245
                    if attr.IsProp >= 3:
246
                        item = QTableWidgetItem(attr.AttributeType)
247
                        item.setFlags(Qt.ItemIsEnabled)
248
                    self.ui.tableWidgetAttr.setItem(row, 3, item)
249
                attrTypeComboBox.currentTextChanged.connect(self.changeType)
250

    
251
                if attr.AttributeType != 'HMB':
252
                    item = QTableWidgetItem(attr.Attribute)  # Name
253
                    if attr.IsProp and attr.IsProp >= 2:
254
                        item.setFlags(Qt.ItemIsEnabled)
255
                        item.setBackground(Qt.lightGray)
256
                    self.ui.tableWidgetAttr.setItem(row, 1, item)
257
                else:
258
                    hmb = QComboBox()
259
                    names = ['', 'PHASE']
260
                    QItemDataExportDialog.add_hmb_header(names)
261
                    hmb.addItems(names)
262
                    self.ui.tableWidgetAttr.setCellWidget(row, 1, hmb)
263
                    result = hmb.findText(attr.Attribute)
264
                    if result:
265
                        hmb.setCurrentIndex(result)
266
                    hmb.currentTextChanged.connect(self.changeHMB)
267

    
268
                item = QTableWidgetItem(str(attr.AttrAt))  # Attribute At
269
                if attr.IsProp and attr.IsProp >= 2:
270
                    item.setFlags(Qt.ItemIsEnabled)
271
                self.ui.tableWidgetAttr.setItem(row, 4, item)
272

    
273
                item = QTableWidgetItem(attr.Expression)  # Expression
274
                if attr.IsProp and attr.IsProp >= 2:
275
                    item.setFlags(Qt.ItemIsEnabled)
276
                self.ui.tableWidgetAttr.setItem(row, 5, item)
277

    
278
                item = QTableWidgetItem('ALL') if attr.Target == 'ALL' or attr.Target is None else QTableWidgetItem('...')
279
                item.setData(Qt.UserRole, attr.Target)
280
                item.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
281
                item.setFlags(Qt.ItemIsEnabled)
282
                self.ui.tableWidgetAttr.setItem(row, 6, item)
283

    
284
                item = QTableWidgetItem('...')
285
                item.setData(Qt.UserRole, attr.Codes.values)
286
                item.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
287
                item.setFlags(Qt.ItemIsEnabled)
288
                self.ui.tableWidgetAttr.setItem(row, 7, item)
289

    
290
                row = row + 1
291
        except Exception as ex:
292
            from App import App
293
            from AppDocData import MessageType
294

    
295
            message = f"error occurred({repr(ex)}) in {sys.exc_info()[-1].tb_frame.f_code.co_filename}:" \
296
                      f"{sys.exc_info()[-1].tb_lineno}"
297
            App.mainWnd().addMessage.emit(MessageType.Error, message)
298

    
299
    def save_data(self):
300
        """save symbol attributes"""
301

    
302
        try:
303
            app_doc_data = AppDocData.instance()
304

    
305
            attrs = []
306
            table = self.ui.tableWidgetAttr
307

    
308
            for index in range(table.rowCount()):
309
                attr = []
310
                attr.append(table.item(index, 0).text() if table.item(index, 0) else '')
311

    
312
                attr_name = table.item(index, 1).text() if table.item(index, 1) else \
313
                                (table.cellWidget(index, 1).currentText() if table.cellWidget(index, 1) else '')
314
                attr.append(attr_name)
315

    
316
                attr_display_name = table.item(index, 2).text() if table.item(index, 2) else attr_name
317
                attr.append(attr_display_name)
318

    
319
                if not attr_name or not attr_display_name:
320
                    QMessageBox.information(self, 'Information', f"'Name' must be set")
321
                    return False
322

    
323
                attr_data_type = table.cellWidget(index, 3).currentText() if table.cellWidget(index, 3) else \
324
                    table.item(index, 3).text()
325
                attr.append(attr_data_type)
326

    
327
                attr_at = table.item(index, 4).text() if table.item(index, 4) else ''
328
                if attr_data_type in [items[0] for items in QSymbolAttrEditorDialog.SYMBOL_ATTR_DATA_TYPES.items() if items[1] == -1] and not attr_at:
329
                    QMessageBox.information(self, 'Information', f"'Attr At' must be set for {attr_data_type}")
330
                    return False
331

    
332
                attr.append(attr_at)  # Attribute At
333

    
334
                attr.append(table.item(index, 5).text() if table.item(index, 5) else '')  # Expression
335
                attr.append(table.item(index, 6).data(Qt.UserRole) if table.item(index, 6).data(Qt.UserRole) is not None else 'ALL')  # Target
336
                attr.append(index)
337
                attr.append(table.item(index, 0).data(Qt.UserRole).IsProp) if table.item(index, 0).data(Qt.UserRole) else \
338
                    attr.append(0)
339
                attr.append(table.item(index, 7).data(Qt.UserRole))   # code table
340
                attrs.append(attr)
341

    
342
            app_doc_data.saveSymbolAttributes(self.currentTypeId, attrs, self._symbolType)
343
            return True
344
        except Exception as ex:
345
            from App import App
346
            from AppDocData import MessageType
347

    
348
            message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
349
                                                           sys.exc_info()[-1].tb_lineno)
350
            App.mainWnd().addMessage.emit(MessageType.Error, message)
351

    
352
        return False
353

    
354
    '''
355
        @brief  add a attribute
356
        @author humkyung
357
        @date   2018.08.13
358
    '''
359
    def onAddAttr(self):
360
        import uuid
361
        from SymbolAttr import SymbolAttr
362

    
363
        rows = self.ui.tableWidgetAttr.rowCount()
364
        self.ui.tableWidgetAttr.setRowCount(rows + 1)
365

    
366
        attrTypeComboBox = QComboBox()
367
        for key, value in QSymbolAttrEditorDialog.SYMBOL_ATTR_DATA_TYPES.items():
368
            attrTypeComboBox.addItem(key)
369
        self.ui.tableWidgetAttr.setCellWidget(rows, 3, attrTypeComboBox)
370
        attrTypeComboBox.currentTextChanged.connect(self.changeType)
371

    
372
        item = QTableWidgetItem('ALL')
373
        item.setData(Qt.UserRole, 'ALL')
374
        item.setTextAlignment(Qt.AlignHCenter)
375
        item.setFlags(Qt.ItemIsEnabled)
376
        self.ui.tableWidgetAttr.setItem(rows, 6, item)
377

    
378
        item = QTableWidgetItem('...')
379
        item.setData(Qt.UserRole, [])
380
        item.setTextAlignment(Qt.AlignHCenter)
381
        item.setFlags(Qt.ItemIsEnabled)
382
        self.ui.tableWidgetAttr.setItem(rows, 7, item)
383

    
384
        attr = SymbolAttr()
385
        item = QTableWidgetItem(str(attr.UID))
386
        item.setData(Qt.UserRole, attr)
387
        #item.tag = attr
388
        self.ui.tableWidgetAttr.setItem(rows, 0, item)
389

    
390
    '''
391
        @brief  delete selected attribute 
392
        @author humkyung
393
        @date   2018.08.13
394
    '''
395
    def onDelAttr(self):
396
        model = self.ui.tableWidgetAttr.model()
397
        row = self.ui.tableWidgetAttr.currentRow()
398

    
399
        if row != -1 and not (hasattr(self.ui.tableWidgetAttr.item(row, 0), 'tag') and
400
                              self.ui.tableWidgetAttr.item(row, 0).data(Qt.UserRole).IsProp == 2):
401
            model.removeRow(row)
402

    
403
    '''
404
        @brief      save attributes
405
        @author     humkyung
406
        @date       2018.08.13
407
    '''
408
    def accept(self):
409
        if self._symbolType is not None:
410
            if not self.save_data():
411
                return
412
        else:
413
            self.saveLineAttrData()
414

    
415
        QDialog.accept(self)
416

    
417
    '''
418
        @brief  setting attribute table line no
419
        @author kyoyho
420
        @date   2018.08.21
421
    '''
422
    def settingLineNoAttributeTable(self):
423
        table = self.ui.tableWidgetAttr
424
        docData = AppDocData.instance()
425
        attrs = docData.getLineProperties()
426

    
427
        table.setRowCount(len(attrs))
428

    
429
        row = 0
430
        for attr in attrs:
431
            item = QTableWidgetItem(attr.UID if attr.UID is not None else '')
432
            self.ui.tableWidgetAttr.setItem(row, 0, item)
433
            item = QTableWidgetItem(attr.Attribute if attr.Attribute is not None else '')
434
            # item.setFlags(Qt.ItemIsEnabled)
435
            self.ui.tableWidgetAttr.setItem(row, 1, item)
436
            item = QTableWidgetItem(attr.DisplayAttribute if attr.DisplayAttribute is not None else '')
437
            self.ui.tableWidgetAttr.setItem(row, 2, item)
438

    
439
            attrTypeComboBox = QComboBox()
440
            for _type in QSymbolAttrEditorDialog.LINE_NO_ATTR_TYPES:
441
                attrTypeComboBox.addItem(_type)
442
            self.ui.tableWidgetAttr.setCellWidget(row, 3, attrTypeComboBox)
443
            result = attrTypeComboBox.findText(attr.AttributeType if attr.DisplayAttribute is not None else '')
444
            attrTypeComboBox.setCurrentIndex(result)
445

    
446
            item = QTableWidgetItem(str(attr.Length) if attr.Length is not None else '')
447
            self.ui.tableWidgetAttr.setItem(row, 4, item)
448

    
449
            item = QTableWidgetItem(str(attr.Expression) if attr.Expression is not None else '')
450
            self.ui.tableWidgetAttr.setItem(row, 5, item)
451

    
452
            row = row + 1
453

    
454
    '''
455
        @brief  add attribute 
456
        @author kyoyho
457
        @date   2018.08.21
458
    '''
459
    def onAddLineNoAttr(self):
460
        rows = self.ui.tableWidgetAttr.rowCount()
461
        self.ui.tableWidgetAttr.setRowCount(rows + 1)
462

    
463
        attrTypeComboBox = QComboBox()
464
        for _type in QSymbolAttrEditorDialog.LINE_NO_ATTR_TYPES:
465
            attrTypeComboBox.addItem(_type)
466
        self.ui.tableWidgetAttr.setCellWidget(rows, 3, attrTypeComboBox)
467

    
468
        import uuid
469
        self.ui.tableWidgetAttr.setItem(rows, 0, QTableWidgetItem(str(uuid.uuid4())))
470

    
471
    '''
472
        @brief  delete selected attribute 
473
        @author kyoyho
474
        @date   2018.08.21
475
    '''
476
    def onDelLineNoAttr(self):
477
        model = self.ui.tableWidgetAttr.model()
478
        row = self.ui.tableWidgetAttr.currentRow()
479

    
480
        if row != -1:
481
            model.removeRow(row)
482

    
483
    '''
484
        @brief      Check Number
485
        @author     kyouho
486
        @date       2018.08.20
487
    '''
488
    def isNumber(self, num):
489
        p = re.compile('(^[0-9]+$)')
490
        result = p.match(num)
491

    
492
        if result:
493
            return True
494
        else:
495
            return False
496

    
497
    '''
498
        @brief      save data
499
        @author     kyouho
500
        @date       2018.08.21
501
    '''
502
    def saveLineAttrData(self):
503
        appDocData = AppDocData.instance()
504

    
505
        attrs = []
506
        table = self.ui.tableWidgetAttr
507

    
508
        for index in range(table.rowCount()):
509
            attr = []
510
            attr.append(table.item(index, 0).text() if table.item(index, 0) is not None else '')
511
            attr.append(table.item(index, 1).text() if table.item(index, 1) is not None else '')
512
            attr.append(table.item(index, 2).text() if table.item(index, 2) is not None else '')
513
            attr.append(
514
                table.cellWidget(index, 3).currentText() if table.cellWidget(index, 3).currentIndex() >= 0 else '')
515
            attr.append(int(table.item(index, 4).text()) if table.item(index, 4) is not None and self.isNumber(
516
                table.item(index, 4).text()) else None)
517
            attr.append(index)
518
            attrs.append(attr)
519

    
520
        appDocData.saveLineAttributes(attrs)
클립보드 이미지 추가 (최대 크기: 500 MB)