프로젝트

일반

사용자정보

통계
| 개정판:

hytos / DTI_PID / DTI_PID / TextItemFactory.py @ 724bd358

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

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

    
4
from SingletonInstance import SingletonInstance
5
import re
6

    
7
try:
8
    from PyQt5.QtCore import *
9
    from PyQt5.QtGui import *
10
    from PyQt5.QtWidgets import *
11
except ImportError:
12
    try:
13
        from PyQt4.QtCore import *
14
        from PyQt4.QtGui import *
15
    except ImportError:
16
        raise ImportError("ImageViewerQt: Requires PyQt5 or PyQt4.")
17
from AppDocData import *
18
import sys, os
19

    
20
sys.path.insert(0, os.path.dirname(os.path.realpath(__file__)) + '\\Shapes')
21
from EngineeringTextItem import QEngineeringTextItem
22
from EngineeringLineNoTextItem import QEngineeringLineNoTextItem
23
from EngineeringNoteItem import QEngineeringNoteItem
24
from QEngineeringSizeTextItem import QEngineeringSizeTextItem
25
from QEngineeringTagNoTextItem import QEngineeringTagNoTextItem
26
from EngineeringValveOperCodeTextItem import QEngineeringValveOperCodeTextItem
27
from EngineeringReservedWordTextItem import QEngineeringReservedWordTextItem
28
from SpecialItemTypesDialog import SpecialItemTypes
29

    
30

    
31
class TextItemFactory(SingletonInstance):
32
    """ This is TextItemFactor class """
33

    
34
    def __init__(self):
35
        self.delimiter = '"'
36
        self.lineNoDelimiter = '!-!'
37

    
38
    '''
39
        @history    2018.04.27  Jeongwoo    Add condition on elif-statement (delimiter != '' and lineNoConfig != '')
40
                    humkyung 2018.05.02 create engineering size text item if condition matches
41
                    humkyung 2018.06.19 set line no's color
42
                    kyouho 2018.07.04 edit for isLineNo method (add parameter)
43
                    humkyung 2018.08.08 fill linePropertyData and tagSeqNoPattern if given data is None
44
                    euisung 2018.11.19  now textitemfactory set plain text in createTextItem() for allowables
45
    '''
46

    
47
    def createTextItem(self, textInfo, lineNoConfig=None):
48
        from Configs import LineNoConfig, TagNoConfig
49
        import csv
50

    
51
        item = None
52

    
53
        try:
54
            text = textInfo.getText()
55
            docData = AppDocData.instance()
56

    
57
            configs = docData.getConfigs('Size', 'Delimiter')
58
            sizeDelimiters = configs[0].value.upper().replace(' ', '').split(',') if 1 == len(configs) else None
59

    
60
            _no_config = None
61
            # check is line no
62
            line_no_configs = LineNoConfig.instance()
63
            if line_no_configs:
64
                if not lineNoConfig:
65
                    for line_no_config in line_no_configs:
66
                        result = line_no_config.parse(text)
67
                        if result[0]:
68
                            sizeUnit = line_no_config.unit
69
                            _no_config = line_no_config.value
70
                            break
71
                else:
72
                    matches = [line for line in line_no_configs if lineNoConfig in line.value]
73
                    if matches:
74
                        result = matches[0].parse(text)
75
                        if result[0]:
76
                            sizeUnit = matches[0].unit
77
                            _no_config = matches[0].value
78
                        else:
79
                            for line_no_config in line_no_configs:
80
                                result = line_no_config.parse(text)
81
                                if result[0]:
82
                                    sizeUnit = line_no_config.unit
83
                                    _no_config = line_no_config.value
84
                                    break
85
                    else:
86
                        for line_no_config in line_no_configs:
87
                            result = line_no_config.parse(text)
88
                            if result[0]:
89
                                sizeUnit = line_no_config.unit
90
                                _no_config = line_no_config.value
91
                                break
92
            else:
93
                result = (False,)
94

    
95
            # check is tag no
96
            tag_no_configs = TagNoConfig.instance(tag=True)
97
            if tag_no_configs:
98
                for tag_no_config in tag_no_configs:
99
                    tagResult = tag_no_config.parse(text)
100
                    if tagResult[0]:
101
                        sizeUnit = tag_no_config.unit
102
                        break
103
            else:
104
                tagResult = (False,)
105

    
106
            if result[0]:
107
                item = QEngineeringLineNoTextItem()
108
                item.set_property('Config', self.delimiter.join(list(csv.reader([_no_config], delimiter=self.delimiter, escapechar='^'))[0]))
109
                text = ''.join(result[1])
110
                for i in result[2]:
111
                    text = text[:i] + '\n' + text[i:]
112
                item.setPlainText(text)
113

    
114
                # get color option
115
                configs = docData.getConfigs('Line Color', 'Visible Option')
116
                if configs:
117
                    visibleOption = configs[0].value
118
                else:
119
                    visibleOption = 'Random'
120

    
121
                configs = docData.getConfigs('Color Property', 'State')
122
                if configs:
123
                    color_property = configs[0].value
124

    
125
                # set line no color
126
                if visibleOption == 'Random':
127
                    rgb = docData.colors
128
                    item.change_color(QColor(rgb.red, rgb.green, rgb.blue).name())
129
                else:
130
                    #configs = docData.getConfigs('Line No', 'Configuration')
131
                    configs = list(csv.reader([_no_config], delimiter=self.delimiter, escapechar='^'))[0]
132

    
133
                    values = result[1]
134
                    index = configs.index(color_property)
135
                    if index >= 0:
136
                        value = values[index]
137
                        line_properties = docData.getLinePropertiesByUID(color_property)
138
                        if line_properties[0].Attribute.replace(' ', '') == 'NominalDiameter':
139
                            if sizeUnit == "Inch":
140
                                value = docData.convertInchToMetric(value)
141

    
142
                        configs = docData.getConfigs(color_property, value)
143
                        if configs:
144
                            data = configs[0].value
145
                            rgb = data.split(',')
146
                            item.change_color(QColor(int(rgb[0]), int(rgb[1]), int(rgb[2])).name())
147
                    # up to here
148
                docData.tracerLineNos.append(item)
149
            elif tagResult[0]:
150
                item = QEngineeringTagNoTextItem()
151
                text = ''.join(tagResult[1])
152
                item.setToolTip('TAG NO = {}'.format(text))
153
                item.setPlainText(text)
154
            else:
155
                item = self.create_note_no_text(textInfo)
156
                for sizeDelimiter in sizeDelimiters:
157
                    sizeTextInfo = self.isSizeText(text, sizeDelimiter)
158
                    if sizeTextInfo:
159
                        break
160
                if item:
161
                    pass
162
                #elif self.is_reserved_word(text):
163
                #    item = QEngineeringReservedWordTextItem()
164
                #    item.setToolTip('Reserved Word = {}'.format(text))
165
                #    item.setPlainText(text)
166
                elif sizeTextInfo:
167
                    item = QEngineeringSizeTextItem(mainSubSize=sizeTextInfo[1], sizeDelimiter=sizeTextInfo[2])
168
                    item.setToolTip('SIZE = {}'.format(sizeTextInfo[0]))
169
                    item.setPlainText(sizeTextInfo[0])
170
                #elif self.isTagNoText(text):
171
                #    item = QEngineeringTagNoTextItem()
172
                #    item.setToolTip('TAG NO = {}'.format(text))
173
                #    item.setPlainText(text)
174
                #elif self.is_valve_operation_code(text):
175
                #    item = QEngineeringValveOperCodeTextItem()
176
                #    item.setToolTip('Valve Operation Code = {}'.format(text))
177
                #    item.setPlainText(text)
178
                else:
179
                    text = self.fix_dictionary_word(text)
180
                    item = QEngineeringTextItem()
181
                    item.setToolTip(text)
182
                    item.setPlainText(text)
183
                    item.special_item_type = SpecialItemTypes.instance().find_match_exactly(item)
184
                #docData.texts.append(item)
185
        except Exception as ex:
186
            from App import App
187
            from AppDocData import MessageType
188

    
189
            message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
190
                                                           sys.exc_info()[-1].tb_lineno)
191
            App.mainWnd().addMessage.emit(MessageType.Error, message)
192

    
193
        return item
194

    
195
    '''
196
        @brief      Check Text startwith word
197
        @author     kyouho
198
        @date       2018.07.04
199
    '''
200

    
201
    def isStartWithWord(self, text, word):
202
        sliceText = text[0:len(word[0])]
203
        if sliceText == word[0]:
204
            return (True, text[len(sliceText):len(text)], word[1])
205
        else:
206
            return (False,)
207

    
208
    '''
209
        @brief      Check Text startwith number
210
        @author     kyouho
211
        @date       2018.07.05
212
    '''
213

    
214
    def isStartWithNumber(self, text):
215
        sliceText = text[0:1]
216
        num = ''
217
        if self.isNumber(sliceText):
218
            text = text[1:len(text)]
219
            num += text
220
            while len(text) > 0:
221
                sliceText = text[0:1]
222

    
223
                if self.isNumber(sliceText):
224
                    text = text[1:len(text)]
225
                    num += text
226
                else:
227
                    break
228

    
229
            return (True, text, num)
230
        else:
231
            return (False,)
232

    
233
    '''
234
        @brief      Check Number
235
        @author     kyouho
236
        @date       2018.07.05
237
        @history    kyouho 2018.07.09   add Refular Expression
238
    '''
239

    
240
    def isNumber(self, num):
241
        p = re.compile('(^[0-9]+$)')
242
        result = p.match(num)
243

    
244
        if result:
245
            return True
246
        else:
247
            return False
248

    
249
    '''
250
        @brief      Check Number
251
        @author     kyouho
252
        @date       2018.07.05
253
    '''
254

    
255
    def isTagSeqNo(self, text, pattern):
256
        try:
257
            if pattern is not None:
258
                attr = text
259
                result = eval(pattern)
260
                if self.isNumber(result):
261
                    sliceText = text[0:len(result)]
262
                    return (True, text[len(sliceText):len(text)], sliceText)
263
                else:
264
                    return (False,)
265
            else:
266
                return (False,)
267
        except Exception as ex:
268
            print('error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
269
                                                       sys.exc_info()[-1].tb_lineno))
270

    
271
    '''
272
        @brief      Check Number
273
        @author     kyouho
274
        @date       2018.07.05
275
    '''
276

    
277
    def isLimitWord(self, text, pattern):
278
        try:
279
            if pattern is not None:
280
                attr = text
281
                length = pattern[0]
282
                isNumber = pattern[1]
283

    
284
                if length:  # Length가 있으면 Length만큼 문자열을 가져와 길이를 검사한다.
285
                    result = eval('attr[:' + str(length) + ']')
286
                    if int(length) != len(result):
287
                        return (False,)
288
                elif isNumber:
289
                    match = re.search(re.compile('^[0-9]+'), attr)
290
                    if match:
291
                        result = match.group(match.start())
292
                    else:
293
                        return (False,)
294
                else:
295
                    result = attr
296

    
297
                if isNumber:
298
                    if self.isNumber(result):
299
                        sliceText = text[0:len(result)]
300
                        return (True, text[len(sliceText):len(text)], sliceText)
301
                    else:
302
                        return (False,)
303
                else:
304
                    sliceText = text[0:len(result)]
305
                    return (True, text[len(sliceText):len(text)], sliceText)
306
            else:
307
                return (False,)
308
        except Exception as ex:
309
            print('error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
310
                                                       sys.exc_info()[-1].tb_lineno))
311

    
312
    '''
313
        @brief      Check if given text is Note No Text (ex : NOTE 1, NOTE 2, ...)
314
        @author     Jeongwoo
315
        @date       2018.04.26
316
        @history    2018.05.16  Jeongwoo    Modify Validator flag
317
    '''
318

    
319
    def create_note_no_text(self, textInfo):
320
        item = None
321

    
322
        appDocData = AppDocData.instance()
323
        configs = appDocData.getConfigs('Note No Tag Rule', 'Note No Expression')
324
        if 1 == len(configs) and configs[0].value:
325
            expression = configs[0].value
326
            match = re.search(re.compile(expression), textInfo.getText())
327

    
328
            if match:
329
                configs = appDocData.getConfigs('Note No Tag Rule', 'Note No Symbol Name')
330
                if 1 == len(configs) and configs[0].value:
331
                    symbol_names = configs[0].value.split(',')
332
                    for symbol in appDocData.symbols:
333
                        if symbol.name in symbol_names and symbol.includes(
334
                                textInfo.center) and '"' not in textInfo.getText():
335
                            item = QEngineeringNoteItem(symbol=symbol)
336
                            item.owner = symbol
337
                            symbol.add_assoc_item(item, 0)
338
                            break
339
                else:
340
                    item = QEngineeringNoteItem()
341

    
342
                if item:
343
                    item.setToolTip(textInfo.getText())
344
                    item.setPlainText(textInfo.getText())
345

    
346
        return item
347

    
348
    '''
349
        @brief  check if given text is size text
350
        @author humkyung
351
        @date   2018.05.02
352
    '''
353

    
354
    def isSizeText(self, text, delimiter='X'):
355
        from NominalPipeSize import NominalPipeSizeTable
356

    
357
        try:
358
            sizeUnit = None
359
            configs = AppDocData.instance().getConfigs('Project', 'Unit')
360
            sizeUnit = configs[0].value if 1 == len(configs) else 'Imperial'
361

    
362
            pipe_sizes = NominalPipeSizeTable.instance().pipe_sizes
363

    
364
            text = text.replace("'", '"').replace(' ', '').upper()
365

    
366
            if delimiter != '/' and delimiter in text:
367
                if len([_text for _text in text.split(delimiter.upper()) if len(_text) > 0]) < 2:
368
                    return False
369
                if text.count(delimiter) != 1:
370
                    return False
371

    
372
            first, second = None, None
373
            # for imperial
374
            if sizeUnit == 'Imperial' and text.find('"') is not -1 and delimiter == '/':
375
                first = text[:text.find('"') + 1]
376
                second = text[text.find('"') + 1:].replace(delimiter.upper(), '',
377
                                            1).strip() if delimiter is not None else text[text.find('"') + 1:].strip()
378
            elif sizeUnit == 'Imperial':
379
                first = text.split(delimiter.upper())[0]
380
                second = text.split(delimiter.upper())[1] if len(text.split(delimiter.upper())) == 2 else None
381
            # for metric
382
            else:
383
                split_text = text.strip().split(delimiter.upper())
384
                if len(split_text) > 2:
385
                    return False
386
                first = split_text[0]
387
                second = split_text[1] if len(split_text) is 2 else None
388

    
389
            tokens = [first, second] if second is not None and len(second) is not 0 else [first]
390
            index = 0
391
            for token in tokens:
392
                matches = [(sizeData.find(token, sizeUnit) if sizeUnit else sizeData.find(token)) for sizeData in pipe_sizes
393
                        if (sizeData.find(token, sizeUnit) if sizeUnit else sizeData.find(token))]
394
                if matches:
395
                    tokens[index] = matches[0]
396
                else:
397
                    return False
398
                index += 1
399

    
400
            if len(tokens) == 2:
401
                if self.inch_to_number(tokens[0]) < self.inch_to_number(tokens[1]):
402
                    tokens[0], tokens[1] = tokens[1], tokens[0]
403
            return [delimiter.join(tokens), tokens, delimiter]
404
        except Exception as ex:
405
            from App import App
406
            message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
407
                                                              sys.exc_info()[-1].tb_lineno)
408
            App.mainWnd().addMessage.emit(MessageType.Error, message)
409
            return False
410

    
411
    def inch_to_number(self, inch_str):
412
        try:
413
            app_doc_data = AppDocData.instance()
414
            configs = app_doc_data.getConfigs('Size', 'Symbol')
415
            size_symbols = configs[0].value.replace(' ', '').split(',') if 1 == len(configs) else ['"']
416

    
417
            inchs = str(inch_str)
418
            for symbol in size_symbols:
419
                inchs = inchs.replace(symbol, '')
420
            inchs = inchs.lstrip('0').replace(' ', '-').replace('"', '').split('-')
421

    
422
            number = 0
423
            for inch in inchs:
424
                if '/' not in inch:
425
                    number += float(inch)
426
                else:
427
                    fraction = inch.split('/')
428
                    number += float(fraction[0]) / float(fraction[1])
429
        except Exception as ex:
430
            from App import App
431
            from AppDocData import MessageType
432
            message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
433
                                                            sys.exc_info()[-1].tb_lineno)
434
            App.mainWnd().addMessage.emit(MessageType.Error, message)
435

    
436
            return 0
437

    
438
        return number
439

    
440
    '''
441
        @brief  check if given text is tag no
442
        @author humkyung
443
        @date   2018.05.03
444
    '''
445

    
446
    def isTagNoText(self, text):
447
        from CodeTables import CodeTable
448

    
449
        found = CodeTable.instance('EqpTagNames').find_match_exactly(text)
450

    
451
        return True if found else False
452

    
453
    def is_valve_operation_code(self, text):
454
        """
455
        check if given text is valve operation code
456
        """
457
        from CodeTables import CodeTable
458

    
459
        found = CodeTable.instance('ValveOperCodes').find_match_exactly(text)
460

    
461
        return True if found else False
462

    
463
    def fix_dictionary_word(self, text):
464
        """ fix if given text is in dictionary """
465
        from CodeTables import CodeTable
466

    
467
        found = CodeTable.instance('Dictionary').find_match_exactly(text)
468

    
469
        return found if found else text
470

    
471
    def is_reserved_word(self, text):
472
        """ check if given text is reserved words """
473
        from CodeTables import CodeTable
474

    
475
        found = CodeTable.instance('ReservedWords').find_match_exactly(text)
476

    
477
        return True if found else False
클립보드 이미지 추가 (최대 크기: 500 MB)