프로젝트

일반

사용자정보

통계
| 개정판:

hytos / DTI_PID / DTI_PID / XmlGenerator.py @ 03d1b1d2

이력 | 보기 | 이력해설 | 다운로드 (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
def appendLineInfo(xmlPath, lineInfo):
370
    tree = parse(xmlPath)
371
    root = tree.getroot()
372
    lineInfosNode = root.find(LINE_INFOS_NODE_NAME)
373
    if lineInfosNode is not None:
374
        lineInfosNode.clear()
375
    else:
376
        lineInfosNode = Element(LINE_INFOS_NODE_NAME)
377
        root.append(lineInfosNode)
378
    for line in lineInfo:
379
        lineInfoNode = Element(LLINE_INFO_NODE_NAME)
380
        # uuidNode = Element(LLINE_UUID)
381
        # uuidNode.text = line.uid
382
        startPointNode = Element(LLINE_START_POINT_NODE_NAME)
383
        startPointNode.text = str(line.start_point()[0]) + "," + str(line.start_point()[1])
384
        endPointNode = Element(LLINE_END_POINT_NODE_NAME)
385
        endPointNode.text = str(line.end_point()[0]) + "," + str(line.end_point()[1])
386
        # lineInfoNode.append(uuidNode)
387
        lineInfoNode.append(startPointNode)
388
        lineInfoNode.append(endPointNode)
389
        lineInfosNode.append(lineInfoNode)
390

    
391
    ElementTree(root).write(xmlPath)
392

    
393
def write_to_xml(path, pidWidth, pidHeight, items, tracer_line_nos):
394
    """write xml data"""
395
    from EngineeringAbstractItem import QEngineeringAbstractItem
396
    from EngineeringNoteItem import QEngineeringNoteItem
397
    from EngineeringTextItem import QEngineeringTextItem
398
    from EngineeringLineItem import QEngineeringLineItem
399
    from EngineeringLineNoTextItem import QEngineeringLineNoTextItem
400
    from EngineeringUnknownItem import QEngineeringUnknownItem
401
    from QEngineeringTrimLineNoTextItem import QEngineeringTrimLineNoTextItem
402
    from QEngineeringSizeTextItem import QEngineeringSizeTextItem
403
    from QEngineeringTagNoTextItem import QEngineeringTagNoTextItem
404
    from EngineeringValveOperCodeTextItem import QEngineeringValveOperCodeTextItem
405
    from EngineeringReservedWordTextItem import QEngineeringReservedWordTextItem
406
    from SymbolSvgItem import SymbolSvgItem
407
    from EngineeringVendorItem import QEngineeringVendorItem
408
    from EngineeringErrorItem import QEngineeringErrorItem
409
    from GraphicsBoundingBoxItem import QGraphicsBoundingBoxItem
410
    from EngineeringGraphicsLineItem import QEngineeringGraphicsLineItem
411

    
412
    xml = Element(ROOT_NODE_NAME)  # Root Node
413
    """write boundingbox"""
414
    app_doc_data = AppDocData.instance()
415
    areas = app_doc_data.getAreaList()
416
    matches = [x for x in areas if x.name == 'Size']
417
    if matches:
418
        xml.attrib['BoundingBox'] = f"{matches[0].x},{matches[0].y},{matches[0].width},{matches[0].height}"
419
    """up to here"""
420

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

    
431
    node_dictionary = {SymbolSvgItem: symbolListNode, QEngineeringTextItem: textInfoListNode,
432
                       QEngineeringNoteItem: noteTextInfoListNode,
433
                       QEngineeringLineItem: lineListNode, QEngineeringGraphicsLineItem: lineListNode,
434
                       QEngineeringLineNoTextItem: lineNoListNode,
435
                       QEngineeringUnknownItem: unknownListNode,
436
                       QEngineeringSizeTextItem: textInfoListNode, QEngineeringValveOperCodeTextItem: textInfoListNode,
437
                       QEngineeringTagNoTextItem: textInfoListNode,
438
                       QEngineeringReservedWordTextItem: textInfoListNode, QEngineeringVendorItem: vendorListNode}
439

    
440
    # trim line 추가
441
    trimLineNoListNode = Element(TRIM_LINE_NOS_NODE_NAME)
442

    
443
    try:
444
        resultDic = {}
445

    
446
        for item in items:
447
            key = str(type(item))
448
            if not key in resultDic:
449
                resultDic[key] = [0, []]
450

    
451
            node = None
452
            try:
453
                if issubclass(type(item), QEngineeringAbstractItem) and type(item) is not QGraphicsBoundingBoxItem and \
454
                        type(item) is not QEngineeringErrorItem:
455
                    node = item.toXml()
456
                else:
457
                    continue
458
            except Exception as ex:
459
                from App import App
460
                from AppDocData import MessageType
461

    
462
                message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
463
                                                               sys.exc_info()[-1].tb_lineno)
464
                App.mainWnd().addMessage.emit(MessageType.Error, message)
465
            finally:
466
                pass
467

    
468
            if node:
469
                resultDic[key][0] += 1
470
                _type = type(item)
471
                if issubclass(type(item), SymbolSvgItem): _type = SymbolSvgItem
472
                if _type in node_dictionary: node_dictionary[_type].append(node)
473
            else:
474
                resultDic[key][1].append(str(item.uid))
475

    
476
        for line in tracer_line_nos:
477
            key = str(type(line))
478
            if not key in resultDic:
479
                resultDic[key] = [0, []]
480
            if issubclass(type(line), QEngineeringTrimLineNoTextItem):
481
                trimNode = line.toXml()
482
                if trimNode:
483
                    resultDic[key][0] += 1
484
                    trimLineNoListNode.append(trimNode)
485
                else:
486
                    resultDic[key][1].append(str(line.uid))
487

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

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

    
505
    return xml, resultDic
506

    
507

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

    
523
    return elem