프로젝트

일반

사용자정보

통계
| 개정판:

hytos / DTI_PID / DTI_PID / XmlGenerator.py @ 8018a77a

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

1
# coding: utf-8
2
""" This is xml generator module """
3

    
4
from xml.etree.ElementTree import Element, SubElement, dump, ElementTree, parse
5
import symbol
6
import SymbolBase
7
import TextInfo as ti
8
import math
9
import os
10
import sys
11
from AppDocData import AppDocData
12

    
13
ROOT_NODE_NAME = "DWG"
14
ROOT_DWGNAME_NODE_NAME = "DWGNAME"
15
ROOT_SIZE_NODE_NAME = "SIZE"
16

    
17
SYMBOL_LIST_NODE_NAME = "SYMBOLS"
18
TEXT_INFO_LIST_NODE_NAME = "TEXTINFOS"
19
IMG_LINE_LIST_NODE_NAME = "IMGLINES"
20
NOTE_TEXT_INFO_LIST_NOTE_NAME = "NOTES"
21

    
22
SCATEGORY_NODE_NAME = "SYMBOL"
23

    
24
SNAME_NODE_NAME = "NAME"
25

    
26
STYPE_NOTE_NAME = "TYPE"
27

    
28
SCLASS_NODE_NAME = "CLASS"
29

    
30
SITEM_NODE_NAME = "ITEM"
31

    
32
SSUB_TEXT = "TEXT"
33
SSUB_ORIGINAL_POINT = "ORIGINALPOINT"
34
SSUB_CONNECTION_POINT = "CONNECTIONPOINT"
35
SSUB_PARENT = "PARENT"
36
SSUB_CHILD = "CHILD"
37
SSUB_ANGLE = "ANGLE"
38
SSUB_START_POINT = "STARTPOINT"
39
SSUB_SIZE = "SIZE"
40

    
41
LINE_NO_LIST_NODE_NAME = "LINE_NOS"
42

    
43
TEXT_INFO_NODE_NAME = "TEXTINFO"
44
TTEXT_NODE_NAME = "TEXT"
45
TTEXT_X_NODE_NAME = "X"
46
TTEXT_Y_NODE_NAME = "Y"
47
TTEXT_WIDTH_NODE_NAME = "WIDTH"
48
TTEXT_HEIGHT_NODE_NAME = "HEIGHT"
49
TTEXT_ANGLE_NODE_NAME = "ANGLE"
50

    
51
IMG_LINE_NODE_NAME = "IMGLINE"
52
ISP_NODE_NAME = "START"
53
IEP_NODE_NAME = "END"
54

    
55
NOTE_TEXT_INFO_NOTE_NAME = "NOTE"
56
TNOTE_TEXT_NODE_NAME = "TEXT"
57
TNOTE_TEXT_X_NODE_NAME = "X"
58
TNOTE_TEXT_Y_NODE_NAME = "Y"
59
TNOTE_TEXT_WIDTH_NODE_NAME = "WIDTH"
60
TNOTE_TEXT_HEIGHT_NODE_NAME = "HEIGHT"
61
TNOTE_TEXT_ANGLE_NODE_NAME = "ANGLE"
62

    
63
LINE_INFOS_NODE_NAME = "LINEINFOS"
64
LLINE_INFO_NODE_NAME = "LINEINFO"
65
LLINE_UUID = "UUID"
66
LLINE_START_POINT_NODE_NAME = "STARTPOINT"
67
LLINE_END_POINT_NODE_NAME = "ENDPOINT"
68

    
69
LINE_NOS_NODE_NAME = "LINENOS"
70
TRIM_LINE_NOS_NODE_NAME = "TRIMLINENOS"
71

    
72
UNKNOWNS_NODE_NAME = "UNKNOWNS"
73
VENDOR_NODE_NAME = "VENDORS"
74
# END_BREAK = "END_BREAKS"
75

    
76
'''
77
    @brief  
78
    @author 
79
    @date   
80
    @history    2018.05.25  Jeongwoo    Remove parameter 'imgLineList'
81
'''
82

    
83

    
84
def writeXml(pidName, pidWidth, pidHeight, searchedSymbolList, textInfoList, noteTextInfoList):
85
    path = os.path.join(AppDocData.instance().getCurrentProject().getTempPath(), pidName + '.xml')
86
    try:
87
        xmlData = generateXml(pidName, pidWidth, pidHeight, searchedSymbolList, textInfoList, noteTextInfoList)
88
        ElementTree(xmlData).write(path)
89
    except Exception as ex:
90
        from App import App
91
        from AppDocData import MessageType
92

    
93
        message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
94
                                                       sys.exc_info()[-1].tb_lineno)
95
        print(message)
96
        App.mainWnd().addMessage.emit(MessageType.Error, message)
97

    
98
    return path
99

    
100

    
101
'''
102
    @brief  write output xml
103
    @author humkyung
104
    @date   2018.04.23
105
'''
106

    
107

    
108
def writeOutputXml(pidName, pidWidth, pidHeight):
109
    try:
110
        path = os.path.join(AppDocData.instance().getCurrentProject().getOutputPath(), pidName + '.xml')
111

    
112
        xmlData = generateOutputXml(pidName, pidWidth, pidHeight)
113
        ElementTree(xmlData).write(path)
114
    except Exception as ex:
115
        from App import App
116
        from AppDocData import MessageType
117

    
118
        message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
119
                                                       sys.exc_info()[-1].tb_lineno)
120
        print(message)
121
        App.mainWnd().addMessage.emit(MessageType.Error, message)
122

    
123
    return path
124

    
125

    
126
'''
127
    @brief      generate output xml for converter
128
    @author     humkyung
129
    @date       2018.04.23
130
    @history    humkyung 2018.05.02 write equipment node
131
                humkyung 2018.05.10 write orphan lines
132
                humkyung 2018.05.16 remove code to write orphan lines and symbols
133
                humkyung 2018.09.06 write text to xml
134
'''
135

    
136

    
137
def generateOutputXml(pidName, pidWidth, pidHeight):
138
    appDocData = AppDocData.instance()
139

    
140
    try:
141
        xml = Element(ROOT_NODE_NAME)  # Root Node
142
        SubElement(xml, ROOT_DWGNAME_NODE_NAME).text = pidName
143
        SubElement(xml, ROOT_SIZE_NODE_NAME).text = str(pidWidth) + "," + str(pidHeight)
144
        SubElement(xml, 'UNIT').text = appDocData.getCurrentProject().unit()
145

    
146
        for equipment in appDocData.equipments:
147
            equipmentNode = Element('EQUIPMENT')
148
            equipmentNode.append(equipment.toXml())
149
            xml.append(equipmentNode)
150

    
151
        sortedList = sorted(appDocData.lineNos, key=lambda param: param.text())
152
        for lineno in sortedList:
153
            xml.append(lineno.toXml())
154

    
155
        for text in appDocData.texts:
156
            xml.append(text.toXml())
157
    except Exception as ex:
158
        from App import App
159
        from AppDocData import MessageType
160

    
161
        message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
162
                                                       sys.exc_info()[-1].tb_lineno)
163
        print(message)
164
        App.mainWnd().addMessage.emit(MessageType.Error, message)
165
    return xml
166

    
167

    
168
'''
169
    @history    2018.04.30  Jeongwoo    noteTextInfoList None Check
170
                2018.05.25  Jeongwoo    Remove parameter 'imgLineList' and Check if variable is None or not
171
'''
172

    
173

    
174
def generateXml(pidName, pidWidth, pidHeight, searchedSymbolList, textInfoList, noteTextInfoList):
175
    xml = Element(ROOT_NODE_NAME)  # Root Node
176
    SubElement(xml, ROOT_DWGNAME_NODE_NAME).text = pidName
177
    SubElement(xml, ROOT_SIZE_NODE_NAME).text = str(pidWidth) + "," + str(pidHeight)
178
    try:
179
        if searchedSymbolList is not None:
180
            symbolListNode = Element(SYMBOL_LIST_NODE_NAME)  # Symbol List Node
181
            sortedList = sorted(searchedSymbolList, key=lambda sym: sym.getName())
182
            for symbol in sortedList:
183
                node = getSymbolInfoNode(symbol)
184
                symbolListNode.append(node)
185

    
186
            xml.append(symbolListNode)
187

    
188
        if textInfoList is not None:
189
            textInfoListNode = Element(TEXT_INFO_LIST_NODE_NAME)  # Text Info List Node
190
            for textInfo in textInfoList:
191
                node = getTextInfoNode(textInfo)
192
                textInfoListNode.append(node)
193

    
194
            xml.append(textInfoListNode)
195

    
196
        noteTextInfoListNode = Element(NOTE_TEXT_INFO_LIST_NOTE_NAME)
197
        if noteTextInfoList is not None:
198
            for noteTextInfo in noteTextInfoList:
199
                node = getNoteTextInfoNode(noteTextInfo)
200
                noteTextInfoListNode.append(node)
201

    
202
        xml.append(noteTextInfoListNode)
203
    except Exception as ex:
204
        from App import App
205
        from AppDocData import MessageType
206

    
207
        message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
208
                                                       sys.exc_info()[-1].tb_lineno)
209
        print(message)
210
        App.mainWnd().addMessage.emit(MessageType.Error, message)
211

    
212
    return xml
213

    
214

    
215
def getSymbolInfoNode(symbol):
216
    sName = symbol.getName()
217
    sSp = symbol.getSp()
218
    sAngle = symbol.getRotatedAngle()
219
    sType = symbol.getType()
220
    sText = symbol.getText()
221
    sOriginalPoint = symbol.getOriginalPoint()
222
    sConnectionPoint = symbol.getConnectionPoint()
223
    sWidth = symbol.getWidth()
224
    sHeight = symbol.getHeight()
225
    sBaseSymbol = symbol.getBaseSymbol()
226
    sAdditionalSymbol = symbol.getAdditionalSymbol()
227

    
228
    sCategoryNode = Element(SCATEGORY_NODE_NAME)
229

    
230
    sNameNode = Element(SNAME_NODE_NAME)
231
    sNameNode.text = sName
232

    
233
    sTypeNode = Element(STYPE_NOTE_NAME)
234
    sTypeNode.text = sType
235

    
236
    sOriginalPointNode = Element(SSUB_ORIGINAL_POINT)
237
    sOpX = sSp[0] + int(sOriginalPoint.split(',')[0])
238
    sOpY = sSp[1] + int(sOriginalPoint.split(',')[1])
239
    sOriginalPointNode.text = str(sOpX) + "," + str(sOpY)
240

    
241
    sConnectionPointNode = Element(SSUB_CONNECTION_POINT)
242
    convertedConnectionPoint = ""
243
    if sConnectionPoint:
244
        splitConnectionPoint = sConnectionPoint.split("/")
245
        for index in range(len(splitConnectionPoint)):
246
            if index != 0:
247
                convertedConnectionPoint = convertedConnectionPoint + "/"
248
            item = splitConnectionPoint[index]
249
            sCpX = sSp[0] + int(item.split(',')[0])
250
            sCpY = sSp[1] + int(item.split(',')[1])
251
            tempStr = str(sCpX) + "," + str(sCpY)
252
            convertedConnectionPoint = convertedConnectionPoint + tempStr
253
    sConnectionPointNode.text = convertedConnectionPoint
254

    
255
    sBaseSymbolNode = Element(SSUB_PARENT)
256
    sBaseSymbolNode.text = sBaseSymbol
257

    
258
    if sAdditionalSymbol is not None:
259
        sAdditionalSymbolNode = Element(SSUB_CHILD)
260
        sAdditionalSymbolNode.text = sAdditionalSymbol
261
        sCategoryNode.append(sAdditionalSymbolNode)
262

    
263
    sAngleNode = Element(SSUB_ANGLE)
264
    sAngleNode.text = str(round(math.radians(sAngle), 2))
265

    
266
    sTextNode = Element(SSUB_TEXT)
267
    sTextNode.text = sText
268

    
269
    sStartPointNode = Element(SSUB_START_POINT)
270
    sStartPointNode.text = str(sSp[0]) + "," + str(sSp[1])
271

    
272
    sSizeNode = Element(SSUB_SIZE)
273
    sSizeNode.text = str(sWidth) + "," + str(sHeight)
274

    
275
    sCategoryNode.append(sNameNode)
276
    sCategoryNode.append(sTypeNode)
277
    sCategoryNode.append(sOriginalPointNode)
278
    sCategoryNode.append(sConnectionPointNode)
279
    sCategoryNode.append(sBaseSymbolNode)
280
    sCategoryNode.append(sAngleNode)
281
    sCategoryNode.append(sTextNode)
282
    sCategoryNode.append(sStartPointNode)
283
    sCategoryNode.append(sSizeNode)
284

    
285
    return sCategoryNode
286

    
287

    
288
def getTextInfoNode(textInfo):
289
    text = textInfo.getText()
290
    x = textInfo.getX()
291
    y = textInfo.getY()
292
    w = textInfo.getW()
293
    h = textInfo.getH()
294
    angle = textInfo.getAngle()
295

    
296
    tInfoNode = Element(TEXT_INFO_NODE_NAME)
297

    
298
    textNode = Element(TTEXT_NODE_NAME)
299
    textNode.text = text
300

    
301
    xNode = Element(TTEXT_X_NODE_NAME)
302
    xNode.text = str(x)
303

    
304
    yNode = Element(TTEXT_Y_NODE_NAME)
305
    yNode.text = str(y)
306

    
307
    widthNode = Element(TTEXT_WIDTH_NODE_NAME)
308
    widthNode.text = str(w)
309

    
310
    heightNode = Element(TTEXT_HEIGHT_NODE_NAME)
311
    heightNode.text = str(h)
312

    
313
    angleNode = Element(TTEXT_ANGLE_NODE_NAME)
314
    angleNode.text = str(round(math.radians(angle), 2))
315

    
316
    tInfoNode.append(textNode)
317
    tInfoNode.append(xNode)
318
    tInfoNode.append(yNode)
319
    tInfoNode.append(widthNode)
320
    tInfoNode.append(heightNode)
321
    tInfoNode.append(angleNode)
322

    
323
    return tInfoNode
324

    
325

    
326
def getNoteTextInfoNode(noteTextInfo):
327
    text = noteTextInfo.getText()
328
    x = noteTextInfo.getX()
329
    y = noteTextInfo.getY()
330
    w = noteTextInfo.getW()
331
    h = noteTextInfo.getH()
332
    angle = noteTextInfo.getAngle()
333

    
334
    ntInfoNode = Element(NOTE_TEXT_INFO_NOTE_NAME)
335

    
336
    textNode = Element(TNOTE_TEXT_NODE_NAME)
337
    textNode.text = text
338

    
339
    xNode = Element(TNOTE_TEXT_X_NODE_NAME)
340
    xNode.text = str(x)
341

    
342
    yNode = Element(TNOTE_TEXT_Y_NODE_NAME)
343
    yNode.text = str(y)
344

    
345
    widthNode = Element(TNOTE_TEXT_WIDTH_NODE_NAME)
346
    widthNode.text = str(w)
347

    
348
    heightNode = Element(TNOTE_TEXT_HEIGHT_NODE_NAME)
349
    heightNode.text = str(h)
350

    
351
    angleNode = Element(TNOTE_TEXT_ANGLE_NODE_NAME)
352
    angleNode.text = str(round(math.radians(angle), 2))
353

    
354
    ntInfoNode.append(textNode)
355
    ntInfoNode.append(xNode)
356
    ntInfoNode.append(yNode)
357
    ntInfoNode.append(widthNode)
358
    ntInfoNode.append(heightNode)
359
    ntInfoNode.append(angleNode)
360

    
361
    return ntInfoNode
362

    
363

    
364
'''
365
    @brief      Append LineInfo Data
366
    @author     Jeongwoo
367
    @date       2018.05.28
368
'''
369

    
370

    
371
def appendLineInfo(xmlPath, lineInfo):
372
    tree = parse(xmlPath)
373
    root = tree.getroot()
374
    lineInfosNode = root.find(LINE_INFOS_NODE_NAME)
375
    if lineInfosNode is not None:
376
        lineInfosNode.clear()
377
    else:
378
        lineInfosNode = Element(LINE_INFOS_NODE_NAME)
379
        root.append(lineInfosNode)
380
    for line in lineInfo:
381
        lineInfoNode = Element(LLINE_INFO_NODE_NAME)
382
        # uuidNode = Element(LLINE_UUID)
383
        # uuidNode.text = line.uid
384
        startPointNode = Element(LLINE_START_POINT_NODE_NAME)
385
        startPointNode.text = str(line.start_point()[0]) + "," + str(line.start_point()[1])
386
        endPointNode = Element(LLINE_END_POINT_NODE_NAME)
387
        endPointNode.text = str(line.end_point()[0]) + "," + str(line.end_point()[1])
388
        # lineInfoNode.append(uuidNode)
389
        lineInfoNode.append(startPointNode)
390
        lineInfoNode.append(endPointNode)
391
        lineInfosNode.append(lineInfoNode)
392

    
393
    ElementTree(root).write(xmlPath)
394

    
395

    
396
'''
397
    @brief      Write xml data by scene
398
    @author     Jeongwoo
399
    @date       2018.05.30
400
    @history    2018.05.30  Jeongwoo    Create node by item object
401
                2018.06.12  Jeongwoo    Add if-statement for QEngineeringLineNoTextItem data node
402
                2018.06.14  Jeongwoo    Add if-statement for QEngineeringUnknownItem data node
403
                2018.11.26  euisung     remove scene dependency
404
'''
405

    
406

    
407
def writeXmlOnScene(path, pidWidth, pidHeight, items, tracer_line_nos):
408
    from EngineeringAbstractItem import QEngineeringAbstractItem
409
    from EngineeringNoteItem import QEngineeringNoteItem
410
    from EngineeringTextItem import QEngineeringTextItem
411
    from EngineeringLineItem import QEngineeringLineItem
412
    from EngineeringLineNoTextItem import QEngineeringLineNoTextItem
413
    from EngineeringUnknownItem import QEngineeringUnknownItem
414
    from QEngineeringTrimLineNoTextItem import QEngineeringTrimLineNoTextItem
415
    from QEngineeringSizeTextItem import QEngineeringSizeTextItem
416
    from QEngineeringTagNoTextItem import QEngineeringTagNoTextItem
417
    from EngineeringValveOperCodeTextItem import QEngineeringValveOperCodeTextItem
418
    from EngineeringReservedWordTextItem import QEngineeringReservedWordTextItem
419
    from SymbolSvgItem import SymbolSvgItem
420
    from EngineeringVendorItem import QEngineeringVendorItem
421
    from EngineeringErrorItem import QEngineeringErrorItem
422
    from GraphicsBoundingBoxItem import QGraphicsBoundingBoxItem
423
    from EngineeringGraphicsLineItem import QEngineeringGraphicsLineItem
424

    
425
    xml = Element(ROOT_NODE_NAME)  # Root Node
426
    SubElement(xml, ROOT_DWGNAME_NODE_NAME).text = os.path.splitext(os.path.basename(path))[0]
427
    SubElement(xml, ROOT_SIZE_NODE_NAME).text = str(pidWidth) + "," + str(pidHeight)
428
    symbolListNode = Element(SYMBOL_LIST_NODE_NAME)  # Symbol List Node
429
    textInfoListNode = Element(TEXT_INFO_LIST_NODE_NAME)  # Text Info List Node
430
    noteTextInfoListNode = Element(NOTE_TEXT_INFO_LIST_NOTE_NAME)
431
    lineListNode = Element(LINE_INFOS_NODE_NAME)
432
    lineNoListNode = Element(LINE_NOS_NODE_NAME)
433
    unknownListNode = Element(UNKNOWNS_NODE_NAME)
434
    vendorListNode = Element(VENDOR_NODE_NAME)
435

    
436
    node_dictionary = {SymbolSvgItem: symbolListNode, QEngineeringTextItem: textInfoListNode,
437
                       QEngineeringNoteItem: noteTextInfoListNode,
438
                       QEngineeringLineItem: lineListNode, QEngineeringGraphicsLineItem: lineListNode,
439
                       QEngineeringLineNoTextItem: lineNoListNode,
440
                       QEngineeringUnknownItem: unknownListNode,
441
                       QEngineeringSizeTextItem: textInfoListNode, QEngineeringValveOperCodeTextItem: textInfoListNode,
442
                       QEngineeringTagNoTextItem: textInfoListNode,
443
                       QEngineeringReservedWordTextItem: textInfoListNode, QEngineeringVendorItem: vendorListNode}
444

    
445
    # trim line 추가
446
    trimLineNoListNode = Element(TRIM_LINE_NOS_NODE_NAME)
447

    
448
    try:
449
        resultDic = {}
450

    
451
        for item in items:
452
            key = str(type(item))
453
            if not key in resultDic:
454
                resultDic[key] = [0, []]
455

    
456
            node = None
457
            try:
458
                if issubclass(type(item), QEngineeringAbstractItem) and type(item) is not QGraphicsBoundingBoxItem and \
459
                        type(item) is not QEngineeringErrorItem:
460
                    node = item.toXml()
461
                else:
462
                    continue
463
            except Exception as ex:
464
                from App import App
465
                from AppDocData import MessageType
466

    
467
                message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
468
                                                               sys.exc_info()[-1].tb_lineno)
469
                App.mainWnd().addMessage.emit(MessageType.Error, message)
470
            finally:
471
                pass
472

    
473
            if node:
474
                resultDic[key][0] += 1
475
                _type = type(item)
476
                if issubclass(type(item), SymbolSvgItem): _type = SymbolSvgItem
477
                if _type in node_dictionary: node_dictionary[_type].append(node)
478
            else:
479
                resultDic[key][1].append(str(item.uid))
480

    
481
        for line in tracer_line_nos:
482
            if type(line) is QEngineeringTrimLineNoTextItem:
483
                trimNode = line.toXml()
484
                if trimNode:
485
                    resultDic[str(type(item))][0] += 1
486
                    trimLineNoListNode.append(trimNode)
487
                else:
488
                    resultDic[str(type(item))][1].append(str(line.uid))
489

    
490
        xml.append(symbolListNode)
491
        xml.append(textInfoListNode)
492
        xml.append(noteTextInfoListNode)
493
        xml.append(lineListNode)
494
        xml.append(lineNoListNode)
495
        xml.append(unknownListNode)
496
        xml.append(trimLineNoListNode)
497
        xml.append(vendorListNode)
498
        ElementTree(xml).write(path)
499
    except Exception as ex:
500
        from App import App
501
        from AppDocData import MessageType
502

    
503
        message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
504
                                                       sys.exc_info()[-1].tb_lineno)
505
        App.mainWnd().addMessage.emit(MessageType.Error, message)
506

    
507
    return resultDic
508

    
509

    
510
def indent(elem, level=0):
511
    i = "\n" + level * "  "
512
    if len(elem):
513
        if not elem.text or not elem.text.strip():
514
            elem.text = i + "  "
515
        if not elem.tail or not elem.tail.strip():
516
            elem.tail = i
517
        for elem in elem:
518
            indent(elem, level + 1)
519
        if not elem.tail or not elem.tail.strip():
520
            elem.tail = i
521
    else:
522
        if level and (not elem.tail or not elem.tail.strip()):
523
            elem.tail = i
524

    
525
    return elem
클립보드 이미지 추가 (최대 크기: 500 MB)