프로젝트

일반

사용자정보

개정판 54eedb38

ID54eedb3843de2864843545f36dfffe7b9cc27e18
상위 7c2ecafc
하위 8bd101dc, 8516a808

백흠경이(가) 약 5년 전에 추가함

issue #622: 사용자가 도면을 닫을때 도면의 데이타가 변경되었을 경우 저장 여부를 확인하는 창을 띄운다

Change-Id: I9225fde70ec295babd31d6c7b9e2fd76808660bb

차이점 보기:

DTI_PID/DTI_PID/App.py
18 18

  
19 19
class App(QApplication):
20 20
    """ This is App class inherits from QApplication """
21

  
22
    NAME = 'Digital P&ID'
23

  
21 24
    def __init__(self, args):
22 25
        import locale
23 26

  
DTI_PID/DTI_PID/Commands/SaveWorkCommand.py
7 7
from PyQt5.QtGui import *
8 8
from PyQt5.QtWidgets import *
9 9

  
10

  
10 11
class SaveWorkCommand(QThread):
11 12
    display_message = pyqtSignal(Enum, str)
12 13
    show_progress = pyqtSignal(int)
......
42 43
                        if item.area == titleBlockProp[0]:
43 44
                            titleBlockItems.append(item)
44 45

  
45
            db_items = [item for item in items if issubclass(type(item), QEngineeringAbstractItem) and type(item) is not QGraphicsBoundingBoxItem and type(item) is not QEngineeringErrorItem and type(item) is not QEngineeringLineNoTextItem]
46
            db_items = [item for item in items if issubclass(type(item), QEngineeringAbstractItem) and type(
47
                item) is not QGraphicsBoundingBoxItem and type(item) is not QEngineeringErrorItem and type(
48
                item) is not QEngineeringLineNoTextItem]
46 49
            db_items.extend([item for item in items if type(item) is QEngineeringLineNoTextItem])
47 50
            db_items.extend([line for line in appDocData.tracerLineNos if type(line) is QEngineeringTrimLineNoTextItem])
48 51
            db_items.extend(titleBlockItems)
......
59 62
        except Exception as ex:
60 63
            from AppDocData import MessageType
61 64

  
62
            message = 'error occurred({}) in {}:{}'.format(repr(ex), sys.exc_info()[-1].tb_frame.f_code.co_filename, sys.exc_info()[-1].tb_lineno)
65
            message = 'error occurred({}) in {}:{}'.format(repr(ex), sys.exc_info()[-1].tb_frame.f_code.co_filename,
66
                                                           sys.exc_info()[-1].tb_lineno)
63 67
            self.display_message.emit(MessageType.Error, message)
64 68

  
65 69
    @staticmethod
......
70 74

  
71 75
        app_doc_data = AppDocData.instance()
72 76
        path = os.path.join(app_doc_data.getCurrentProject().getTempPath(), app_doc_data.imgName + '.xml')
73
        result = xg.writeXmlOnScene(path, app_doc_data.activeDrawing.width, app_doc_data.activeDrawing.height, app_doc_data.allItems, app_doc_data.tracerLineNos)
74
        
77
        result = xg.writeXmlOnScene(path, app_doc_data.activeDrawing.width, app_doc_data.activeDrawing.height,
78
                                    app_doc_data.allItems, app_doc_data.tracerLineNos)
79

  
75 80
        resultStr = '[저장 결과]'
76 81

  
77 82
        for item in result.items():
DTI_PID/DTI_PID/Drawing.py
20 20
from EngineeringUnknownItem import QEngineeringUnknownItem
21 21
from QEngineeringTrimLineNoTextItem import QEngineeringTrimLineNoTextItem
22 22

  
23

  
23 24
class Source:
24 25
    """ This is Source class """
26

  
25 27
    def __init__(self, source):
26 28
        if type(source) is np.ndarray:
27 29
            self.source = Image.fromarray(source)
......
31 33
            self.source = Image.fromqimage(source)
32 34
        elif type(source) is QPixmap:
33 35
            self.source = Image.fromqpixmap(source)
34
        
36

  
35 37
    '''
36 38
        @history    2018.05.18  Jeongwoo    When Parameter [rect] is None, return whole image
37 39
    '''
38
    def getPyImageOnRect(self, rect = None):
40

  
41
    def getPyImageOnRect(self, rect=None):
39 42
        if rect is not None:
40 43
            return self.source.copy().crop((rect.left(), rect.top(), rect.right(), rect.bottom()))
41 44
        else:
42 45
            return self.source.copy()
43 46

  
44
    def getQImageOnRect(self, rect = None):
47
    def getQImageOnRect(self, rect=None):
45 48
        image = ImageQt(self.getPyImageOnRect(rect))
46 49
        return image.convertToFormat(QImage.Format_RGBA8888)
47 50

  
51

  
48 52
class Drawing:
49 53
    '''
50 54
        @brief  construction
51 55
        @author humkyung
52 56
        @date   2018.07.07
53 57
    '''
58

  
54 59
    def __init__(self, uid, name, datetime):
55 60
        import uuid
56 61
        app_doc_data = AppDocData.instance()
......
68 73

  
69 74
        self.width = 0
70 75
        self.height = 0
71
        self._attrs = [['Drawing No', ''], ['Rev No', ''], ['Unit', '']] # attributes
76
        self._attrs = [['Drawing No', ''], ['Rev No', ''], ['Unit', '']]  # attributes
77
        self._modified = False
72 78

  
73 79
    def __del__(self):
74 80
        """ destructor """
......
89 95
        @author humkyung
90 96
        @date   2018.07.07
91 97
    '''
98

  
92 99
    @property
93 100
    def attrs(self):
94 101
        return self._attrs
......
98 105
        @author humkyung
99 106
        @date   2018.07.07
100 107
    '''
108

  
101 109
    @attrs.setter
102 110
    def attrs(self, value):
103 111
        self._attrs = value
......
107 115
        self.width, self.height = image.size
108 116
        self.currentPidSource = Source(image)
109 117

  
118
    @property
119
    def modified(self):
120
        """getter of modified"""
121
        return self._modified
122

  
123
    @modified.setter
124
    def modified(self, value):
125
        """setter of modified"""
126
        self._modified = value
127

  
110 128
    '''
111 129
        @brief  set attribute
112 130
        @author humkyung
113 131
        @date   2018.07.07
114 132
    '''
133

  
115 134
    def setAttr(self, name, value):
116 135
        attrs = [attr for attr in self._attrs if attr[0] == name]
117 136
        if attrs:
......
123 142

  
124 143
    def from_database(self):
125 144
        """ load all components of drawing """
126
        
145

  
127 146
        items = []
128 147
        tracer_line_nos = []
129 148
        app_doc_data = AppDocData.instance()
......
136 155
                if item: items.append(item)
137 156

  
138 157
            # parse texts
139
            for text in [component for component in components if component['Name'] == 'Text' and component['SymbolType_UID'] == -1]:
158
            for text in [component for component in components if
159
                         component['Name'] == 'Text' and component['SymbolType_UID'] == -1]:
140 160
                item = QEngineeringTextItem.from_database(text)
141 161
                if item:
142 162
                    item.uid = text['UID']
......
144 164
                    items.append(item)
145 165

  
146 166
            # note
147
            for note in [component for component in components if component['Name'] == 'Note' and component['SymbolType_UID'] == -1]:
167
            for note in [component for component in components if
168
                         component['Name'] == 'Note' and component['SymbolType_UID'] == -1]:
148 169
                item = QEngineeringTextItem.from_database(note)
149 170
                if item is not None:
150 171
                    item.uid = note['UID']
151 172
                    items.append(item)
152 173

  
153
            for line in [component for component in components if component['Name'] == 'Line' and component['SymbolType_UID'] == -1]:
174
            for line in [component for component in components if
175
                         component['Name'] == 'Line' and component['SymbolType_UID'] == -1]:
154 176
                item = QEngineeringLineItem.from_database(line)
155 177
                if item: items.append(item)
156 178

  
157
            for unknown in [component for component in components if component['Name'] == 'Unknown' and component['SymbolType_UID'] == -1]:
179
            for unknown in [component for component in components if
180
                            component['Name'] == 'Unknown' and component['SymbolType_UID'] == -1]:
158 181
                item = QEngineeringUnknownItem.from_database(unknown)
159 182
                if item: items.append(item)
160 183

  
161
            for component in [component for component in components if component['Name'] == 'Line NO' and component['SymbolType_UID'] == -1]:
184
            for component in [component for component in components if
185
                              component['Name'] == 'Line NO' and component['SymbolType_UID'] == -1]:
162 186
                line_no = QEngineeringLineNoTextItem.from_database(component)
163 187
                if type(line_no) is QEngineeringLineNoTextItem:
164 188
                    runs = app_doc_data.get_pipe_runs(str(line_no.uid))
......
175 199
                        line_run.owner = line_no
176 200
                        line_no.runs.append(line_run)
177 201

  
178
            for component in [component for component in components if component['Name'] == 'Trim Line NO' and component['SymbolType_UID'] == -1]:
202
            for component in [component for component in components if
203
                              component['Name'] == 'Trim Line NO' and component['SymbolType_UID'] == -1]:
179 204
                tracer_line_no = QEngineeringTrimLineNoTextItem()
180 205
                tracer_line_no.uid = uuid.UUID(component['UID'])
181 206

  
......
191 216
                            matches[0].owner = tracer_line_no
192 217
                            line_run.items.append(matches[0])
193 218
                tracer_line_no.runs.append(line_run)
194
                
219

  
195 220
                tracer_line_nos.append(tracer_line_no)
196 221

  
197
            for component in [component for component in components if component['Name'] == 'VendorPackage' and component['SymbolType_UID'] == -1]:
222
            for component in [component for component in components if
223
                              component['Name'] == 'VendorPackage' and component['SymbolType_UID'] == -1]:
198 224
                item = QEngineeringVendorItem.from_database(component)
199 225
                if item: items.append(item)
200 226
        except Exception as ex:
201 227
            from App import App
202 228
            from AppDocData import MessageType
203 229

  
204
            message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename, sys.exc_info()[-1].tb_lineno)
230
            message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
231
                                                           sys.exc_info()[-1].tb_lineno)
205 232
            App.mainWnd().addMessage.emit(MessageType.Error, message)
206 233
        finally:
207
            return items,tracer_line_nos
234
            return items, tracer_line_nos
208 235

  
209 236
    def export(self, path):
210 237
        """ save items of drawing to given xml file """
211 238
        import XmlGenerator as xg
212 239

  
213
        items,tracer_line_nos = self.from_database()
240
        items, tracer_line_nos = self.from_database()
214 241
        xg.writeXmlOnScene(path, self.width, self.height, items, tracer_line_nos)
215 242

  
216 243
    def transfer(self, database):
......
226 253
                cursor.execute(sql, (self.name,))
227 254
                sql = database.to_sql('delete from INSTRUMENT_DATA_LIST where PNID_NO=?')
228 255
                cursor.execute(sql, (self.name,))
229
                sql = database.to_sql('delete from TitleBlockValues where Drawings_UID=(select UID from Drawings where [Name]=?)')
256
                sql = database.to_sql(
257
                    'delete from TitleBlockValues where Drawings_UID=(select UID from Drawings where [Name]=?)')
230 258
                cursor.execute(sql, (self.name,))
231
                sql = database.to_sql('delete from LineNoAttributes where Components_UID in (select UID from Components where Drawings_UID=(select UID from Drawings where Name=?))')
259
                sql = database.to_sql(
260
                    'delete from LineNoAttributes where Components_UID in (select UID from Components where Drawings_UID=(select UID from Drawings where Name=?))')
232 261
                cursor.execute(sql, (self.name,))
233
                sql = database.to_sql('delete from Attributes where Components_UID in (select UID from Components where Drawings_UID=(select UID from Drawings where Name=?))')
262
                sql = database.to_sql(
263
                    'delete from Attributes where Components_UID in (select UID from Components where Drawings_UID=(select UID from Drawings where Name=?))')
234 264
                cursor.execute(sql, (self.name,))
235
                sql = database.to_sql('delete from Associations where Components_UID in (select UID from Components where Drawings_UID=(select UID from Drawings where Name=?))')
265
                sql = database.to_sql(
266
                    'delete from Associations where Components_UID in (select UID from Components where Drawings_UID=(select UID from Drawings where Name=?))')
236 267
                cursor.execute(sql, (self.name,))
237
                sql = database.to_sql('delete from Points where Components_UID in (select UID from Components where Drawings_UID=(select UID from Drawings where Name=?))')
268
                sql = database.to_sql(
269
                    'delete from Points where Components_UID in (select UID from Components where Drawings_UID=(select UID from Drawings where Name=?))')
238 270
                cursor.execute(sql, (self.name,))
239
                sql = database.to_sql('delete from PipeRunItems where PipeRuns_UID in (select UID from PipeRuns where Drawings_UID=(select UID from Drawings where Name=?))')
271
                sql = database.to_sql(
272
                    'delete from PipeRunItems where PipeRuns_UID in (select UID from PipeRuns where Drawings_UID=(select UID from Drawings where Name=?))')
240 273
                cursor.execute(sql, (self.name,))
241 274
                sql = database.to_sql('delete from PipeRuns where Drawings_UID=(select UID from Drawings where Name=?)')
242 275
                cursor.execute(sql, (self.name,))
243
                sql = database.to_sql('delete from Components where Drawings_UID=(select UID from Drawings where Name=?)')
276
                sql = database.to_sql(
277
                    'delete from Components where Drawings_UID=(select UID from Drawings where Name=?)')
244 278
                cursor.execute(sql, (self.name,))
245 279
                sql = database.to_sql('delete from Drawings where Name=?')
246 280
                cursor.execute(sql, (self.name,))
......
252 286
                for component in components:
253 287
                    sql = database.to_sql('insert into Components(UID,Drawings_UID,Symbol_UID,X,Y,Width,Height,Rotation,Area,Value,Owner,[From],[To],Connected,[Supplied By],SpecialItemTypes_UID, OriginIndex) \
254 288
                        values(?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)')
255
                    cursor.execute(sql, (component['UID'], component['Drawings_UID'], component['Symbol_UID'], 
256
                        component['X'], component['Y'], component['Width'], component['Height'], component['Rotation'], component['Area'],
257
                        component['Value'], component['Owner'], component['From'], component['To'], component['Connected'], 
258
                        component['Supplied By'], component['SpecialItemTypes_UID'], component['OriginIndex']))
289
                    cursor.execute(sql, (component['UID'], component['Drawings_UID'], component['Symbol_UID'],
290
                                         component['X'], component['Y'], component['Width'], component['Height'],
291
                                         component['Rotation'], component['Area'],
292
                                         component['Value'], component['Owner'], component['From'], component['To'],
293
                                         component['Connected'],
294
                                         component['Supplied By'], component['SpecialItemTypes_UID'],
295
                                         component['OriginIndex']))
259 296

  
260 297
                for component in components:
261 298
                    pipe_runs = app_doc_data.get_pipe_runs(component['UID'])
262 299
                    for pipe_run in pipe_runs:
263
                        sql = database.to_sql('insert into PipeRuns(UID,Drawings_UID,Type,Owner,[Index]) values(?,?,?,?,?)')
300
                        sql = database.to_sql(
301
                            'insert into PipeRuns(UID,Drawings_UID,Type,Owner,[Index]) values(?,?,?,?,?)')
264 302
                        cursor.execute(sql, (pipe_run[0], pipe_run[1], pipe_run[2], pipe_run[3], pipe_run[4]))
265 303
                        pipe_run_items = app_doc_data.get_pipe_run_items(pipe_run[0])
266 304
                        for pipe_run_item in pipe_run_items:
267
                            sql = database.to_sql('insert into PipeRunItems(UID,PipeRuns_UID,[Index],Components_UID) values(?,?,?,?)')
268
                            cursor.execute(sql, (pipe_run_item[0], pipe_run_item[1], pipe_run_item[2], pipe_run_item[3]))
305
                            sql = database.to_sql(
306
                                'insert into PipeRunItems(UID,PipeRuns_UID,[Index],Components_UID) values(?,?,?,?)')
307
                            cursor.execute(sql,
308
                                           (pipe_run_item[0], pipe_run_item[1], pipe_run_item[2], pipe_run_item[3]))
269 309

  
270 310
                    connectors = app_doc_data.get_component_connectors(component['UID'])
271 311
                    for connector in connectors:
272
                        sql = database.to_sql('insert into Points(Components_UID,[Index],X,Y,Connected,Connected_At) values(?,?,?,?,?,?)')
273
                        cursor.execute(sql, (connector['Components_UID'], connector['Index'], connector['X'], connector['Y'], connector['Connected'], connector['Connected_At']))
312
                        sql = database.to_sql(
313
                            'insert into Points(Components_UID,[Index],X,Y,Connected,Connected_At) values(?,?,?,?,?,?)')
314
                        cursor.execute(sql, (
315
                        connector['Components_UID'], connector['Index'], connector['X'], connector['Y'],
316
                        connector['Connected'], connector['Connected_At']))
274 317

  
275 318
                    associations = app_doc_data.get_component_associations(component['UID'])
276 319
                    for assoc in associations:
277
                        sql = database.to_sql('insert into Associations(UID,[Type],Components_UID,Association) values(?,?,?,?)')
278
                        cursor.execute(sql, (assoc['UID'], assoc['Type'], assoc['Components_UID'], assoc['Association']))
320
                        sql = database.to_sql(
321
                            'insert into Associations(UID,[Type],Components_UID,Association) values(?,?,?,?)')
322
                        cursor.execute(sql,
323
                                       (assoc['UID'], assoc['Type'], assoc['Components_UID'], assoc['Association']))
279 324

  
280 325
                    attributes = app_doc_data.get_component_attributes(component['UID'])
281 326
                    for attr in attributes:
282
                        sql = database.to_sql('insert into Attributes(UID,Components_UID,SymbolAttribute_UID,Value) values(?,?,?,?)')
283
                        cursor.execute(sql, (attr['UID'], attr['Components_UID'], attr['SymbolAttribute_UID'], attr['Value']))
327
                        sql = database.to_sql(
328
                            'insert into Attributes(UID,Components_UID,SymbolAttribute_UID,Value) values(?,?,?,?)')
329
                        cursor.execute(sql, (
330
                        attr['UID'], attr['Components_UID'], attr['SymbolAttribute_UID'], attr['Value']))
284 331

  
285 332
                    conn.commit()
286 333
                # Catch the exception
......
290 337

  
291 338
                print(sql)
292 339
                from App import App
293
                message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename, sys.exc_info()[-1].tb_lineno)
294
                App.mainWnd().addMessage.emit(MessageType.Error, message)
340
                message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
341
                                                               sys.exc_info()[-1].tb_lineno)
342
                App.mainWnd().addMessage.emit(MessageType.Error, message)
DTI_PID/DTI_PID/MainWindow.py
91 91
    '''
92 92

  
93 93
    def __init__(self):
94
        from App import App
94 95
        from LineTypeConditions import LineTypeConditions
95 96

  
96 97
        super(self.__class__, self).__init__()
......
120 121
        _translate = QCoreApplication.translate
121 122
        version = QCoreApplication.applicationVersion()
122 123
        # set title
123
        self.setWindowTitle(_translate("Digital P&ID({}) - {}".format(version, project.name),
124
                                       "Digital P&ID({}) - {}".format(version, project.name)))
124
        self.setWindowTitle(_translate(f"{App.NAME}({version}) - {project.name}",
125
                                       f"{App.NAME}({version}) - {project.name}"))
125 126

  
126 127
        self.lineComboBox = QComboBox(self.toolBar)
127 128
        for condition in LineTypeConditions.items():
......
318 319
        self.tableWidgetInconsistency.setSortingEnabled(True)
319 320

  
320 321
    def eventFilter(self, source, event):
321
        """
322
        display mouse position of graphics view
323
        """
322
        """display mouse position of graphics view"""
324 323
        if (event.type() == QEvent.MouseMove):
325 324
            pos = self.graphicsView.mapToScene(event.pos())
326 325
            self._label_mouse.setText('mouse pos : ({},{})'.format(round(pos.x()), round(pos.y())))
......
328 327
        return QWidget.eventFilter(self, source, event)
329 328

  
330 329
    def closeEvent(self, event):
331
        """ close main window """
330
        """ask user to save drawing which is modified"""
331

  
332
        self.save_drawing_if_necessary()
332 333
        AppDocData.instance().clear()
334
        event.accept()
333 335

  
334 336
    def inconsistencyTableKeyPressEvent(self, event):
335 337
        try:
......
654 656
                                                          sys.exc_info()[-1].tb_lineno)
655 657
            self.addMessage.emit(MessageType.Error, message)
656 658

  
659
    def save_drawing_if_necessary(self):
660
        """ask to user to save drawing or not when drawing is modified"""
661

  
662
        app_doc_data = AppDocData.instance()
663
        if app_doc_data.activeDrawing and app_doc_data.activeDrawing.modified:
664
            if QMessageBox.Yes == QMessageBox.question(self, self.tr("Question"),
665
                                                       self.tr("Do you want to save drawing?"),
666
                                                       QMessageBox.Yes | QMessageBox.No):
667
                self.actionSaveCliked()
668

  
657 669
    '''
658 670
        @brief      action save click event
659 671
        @author     kyouho
......
666 678
    '''
667 679

  
668 680
    def actionSaveCliked(self):
669
        from datetime import datetime
670 681
        from EngineeringAbstractItem import QEngineeringAbstractItem
671 682
        from SaveWorkCommand import SaveWorkCommand
672 683

  
673 684
        try:
674
            appDocData = AppDocData.instance()
675
            if appDocData.imgName is None:
685
            app_doc_data = AppDocData.instance()
686
            if app_doc_data.imgName is None:
676 687
                self.showImageSelectionMessageBox()
677 688
                return
678 689

  
679
            appDocData.clearItemList(False)
690
            app_doc_data.clearItemList(False)
680 691

  
681 692
            items = self.graphicsView.scene.items()
682 693
            for item in items:
683 694
                if issubclass(type(item), QEngineeringAbstractItem):
684
                    appDocData.allItems.append(item)
695
                    app_doc_data.allItems.append(item)
685 696
                    if issubclass(type(item), QEngineeringTextItem):
686
                        appDocData.texts.append(item)
697
                        app_doc_data.texts.append(item)
687 698

  
688 699
            itemTypes = []
689 700
            for item in items:
......
701 712
            self._save_work_cmd.finished.connect(self.save_finished)
702 713

  
703 714
            self._save_work_cmd.start()
704

  
705 715
        except Exception as ex:
706
            message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
716
            message = 'error occurred({}) in {}:{}'.format(repr(ex), sys.exc_info()[-1].tb_frame.f_code.co_filename,
707 717
                                                          sys.exc_info()[-1].tb_lineno)
708 718
            self.addMessage.emit(MessageType.Error, message)
709 719

  
710 720
    def save_finished(self):
711 721
        """reload drawing list"""
722

  
712 723
        self._save_work_cmd.show_progress.emit(100)
713 724
        QMessageBox.about(self.graphicsView, self.tr('Information'), self._save_work_cmd.resultStr)
714 725
        self.load_drawing_list()
715 726

  
727
        app_doc_data = AppDocData.instance()
728
        app_doc_data.activeDrawing.modified = False
729
        title = self.windowTitle()
730
        self.setWindowTitle(title[:-1] if title[-1] == '*' else title)
731

  
716 732
    '''
717 733
        @brief      refresh resultPropertyTableWidget
718 734
        @author     kyouho
......
832 848
        self.graphicsView.useDefaultCommand()
833 849
        self.graphicsView.zoomImageInit()
834 850

  
851
    def scene_changed(self):
852
        """update modified flag"""
853

  
854
        app_doc_data = AppDocData.instance()
855
        app_doc_data.activeDrawing.modified = True
856
        title = self.windowTitle()
857
        self.setWindowTitle(title if title[-1] == '*' else title + '*')
858

  
835 859
    def onConvertPDFToImage(self):
836 860
        """
837 861
        @brief      convert to selected pdf to image
......
1251 1275

  
1252 1276
    def onOpenImageDrawing(self, path=None):
1253 1277
        from Drawing import Drawing
1254
        from xml.etree.ElementTree import Element, SubElement, dump, ElementTree, parse
1255 1278

  
1256 1279
        try:
1280
            self.save_drawing_if_necessary()
1281
            if hasattr(self, '_save_work_cmd'):
1282
                self._save_work_cmd.wait()
1283

  
1257 1284
            app_doc_data = AppDocData.instance()
1285

  
1258 1286
            project = app_doc_data.getCurrentProject()
1259 1287

  
1260 1288
            self.path = self.graphicsView.loadImageFromFile(project.getDrawingFilePath(),
......
1283 1311

  
1284 1312
                try:
1285 1313
                    self.show_Progress_bar()
1314

  
1315
                    # disconnect scene changed if signal is connected
1316
                    if self.graphicsView.scene.receivers(self.graphicsView.scene.contents_changed) > 0:
1317
                        self.graphicsView.scene.contents_changed.disconnect()
1318

  
1286 1319
                    # Load data
1287 1320
                    path = os.path.join(app_doc_data.getCurrentProject().getTempPath(), app_doc_data.imgName + '.xml')
1288 1321
                    configs = app_doc_data.getConfigs('Data Load', 'Xml First')
......
1290 1323
                        self.loadRecognitionResultFromXml(path)
1291 1324
                    else:
1292 1325
                        self.load_drawing(app_doc_data.activeDrawing)
1326

  
1327
                    # connect scene changed signal
1328
                    self.graphicsView.scene.contents_changed.connect(self.scene_changed)
1293 1329
                finally:
1294 1330
                    if hasattr(self, 'progress'):
1295 1331
                        self.progress.setValue(self.progress.maximum())
DTI_PID/DTI_PID/Shapes/EngineeringLineItem.py
11 11
except ImportError:
12 12
    try:
13 13
        from PyQt4.QtCore import Qt, QRectF, pyqtSignal, QT_VERSION_STR, QRect
14
        from PyQt4.QtGui import QGraphicsView, QGraphicsScene, QImage, QPixmap, QPainterPath, QFileDialog, QGraphicsLineItem
14
        from PyQt4.QtGui import QGraphicsView, QGraphicsScene, QImage, QPixmap, QPainterPath, QFileDialog, \
15
            QGraphicsLineItem
15 16
    except ImportError:
16 17
        raise ImportError("ImageViewerQt: Requires PyQt5 or PyQt4.")
17 18

  
......
19 20
import shapely
20 21
from LineTypeConditions import LineTypeConditions
21 22

  
23

  
22 24
class QEngineeringLineItem(QGraphicsLineItem, QEngineeringAbstractItem):
23 25
    """ This is engineering line item """
24 26

  
......
32 34
                    2018.05.15  Jeongwoo    Change method to call parent's __init__
33 35
                    humkyung 2018.06.21 add vertices to parameter
34 36
    '''
37

  
35 38
    def __init__(self, vertices=[], thickness=None, parent=None, uid=None):
36 39
        import uuid
37 40
        from EngineeringConnectorItem import QEngineeringConnectorItem
......
45 48
            self.uid = uuid.uuid4() if uid is None else uuid.UUID(uid)
46 49
            self.thickness = thickness
47 50

  
48
            self.setPen(QPen(Qt.blue, 4, Qt.SolidLine)) # set default pen
49
            self.isCreated = True 
51
            self.setPen(QPen(Qt.blue, 4, Qt.SolidLine))  # set default pen
52
            self.isCreated = True
50 53

  
51 54
            self._owner = None
52 55
            self._flowMark = None
53 56
            configs = AppDocData.instance().getConfigs('Line', 'Default Type')
54 57
            self._lineType = None
55
            self.lineType = configs[0].value if 1 == len(configs) else 'Secondary' # defulat line type is 'Secondary'
58
            self.lineType = configs[0].value if 1 == len(configs) else 'Secondary'  # defulat line type is 'Secondary'
56 59

  
57 60
            self._properties = \
58
                {\
59
                    SymbolProp(None, 'Size', 'Size Text Item', Expression='self.EvaluatedSize'):None,\
60
                    SymbolProp(None, 'Flow Mark', 'Size Text Item', Expression='self.EvaluatedSize'):None
61
                { \
62
                    SymbolProp(None, 'Size', 'Size Text Item', Expression='self.EvaluatedSize'): None, \
63
                    SymbolProp(None, 'Flow Mark', 'Size Text Item', Expression='self.EvaluatedSize'): None
61 64
                }
62 65

  
63
            self.setFlags(QGraphicsItem.ItemIsSelectable|QGraphicsItem.ItemIsFocusable)
66
            self.setFlags(QGraphicsItem.ItemIsSelectable | QGraphicsItem.ItemIsFocusable)
64 67

  
65 68
            self.setAcceptHoverEvents(True)
66 69
            self.setAcceptTouchEvents(True)
......
70 73

  
71 74
            if vertices:
72 75
                self.setLine(vertices[0][0], vertices[0][1], vertices[1][0], vertices[1][1])
73
                
76

  
74 77
                index = 0
75 78
                for vertex in vertices:
76
                    connector = QEngineeringConnectorItem(parent=self, index=index+1)
79
                    connector = QEngineeringConnectorItem(parent=self, index=index + 1)
77 80
                    connector.setPos(vertex)
78 81
                    connector.setParentItem(self)
79 82
                    # connector의 connectPoint, sceneConnectPoint를 vertex로 함 추후 좀 알아봐서 수정 필요
......
81 84
                    connector.sceneConnectPoint = vertex
82 85

  
83 86
                    # add connector move able
84
                    connector.setFlags(QGraphicsItem.ItemIsSelectable|QGraphicsItem.ItemIsFocusable)
87
                    connector.setFlags(QGraphicsItem.ItemIsSelectable | QGraphicsItem.ItemIsFocusable)
85 88
                    connector.setAcceptTouchEvents(True)
86 89
                    connector.transfer.onPosChanged.connect(self.onConnectorPosChaned)
87 90

  
......
90 93
                    index = index + 1
91 94

  
92 95
                self.update_arrow()
93
                
94
                tooltip = '<b>{}</b><br>({},{})-({},{})'.format(str(self.uid), vertices[0][0], vertices[0][1], vertices[1][0], vertices[1][1])
96

  
97
                tooltip = '<b>{}</b><br>({},{})-({},{})'.format(str(self.uid), vertices[0][0], vertices[0][1],
98
                                                                vertices[1][0], vertices[1][1])
95 99
                self.setToolTip(tooltip)
96 100
        except Exception as ex:
97 101
            from App import App
98 102
            from AppDocData import MessageType
99 103

  
100
            message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename, sys.exc_info()[-1].tb_lineno)
104
            message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
105
                                                           sys.exc_info()[-1].tb_lineno)
101 106
            App.mainWnd().addMessage.emit(MessageType.Error, message)
102 107

  
103 108
    def __str__(self):
......
109 114
        """ getter of flow mark """
110 115
        import uuid
111 116

  
112
        for prop,value in self._properties.items():
117
        for prop, value in self._properties.items():
113 118
            if prop.is_selectable and type(value) is uuid.UUID and self.scene():
114 119
                matches = [x for x in self.scene().items() if hasattr(x, 'uid') and str(x.uid) == str(value)]
115 120
                if matches: self._properties[prop] = matches[0]
116
            
121

  
117 122
            if prop.Expression: self._properties[prop] = eval(prop.Expression)
118
            
123

  
119 124
        return self._properties
120 125

  
121 126
    def set_property(self, property, value):
122 127
        """ set property with given value """
123 128
        if issubclass(type(value), QEngineeringAbstractItem): self.add_assoc_item(value, 0)
124
        matches = [prop for prop,_ in self._properties.items() if prop.Attribute == property]
129
        matches = [prop for prop, _ in self._properties.items() if prop.Attribute == property]
125 130
        if matches: self._properties[matches[0]] = value
126 131

  
127 132
    def prop(self, name):
128 133
        """ return the value of given property with name """
129
        matches = [(prop,value) for prop,value in self.properties.items() if prop.Attribute == name]
134
        matches = [(prop, value) for prop, value in self.properties.items() if prop.Attribute == name]
130 135
        if matches: return matches[0][1]
131 136

  
132 137
        return None
......
135 140
    def Size(self):
136 141
        """ always return None """
137 142
        return None
138
    
143

  
139 144
    @property
140 145
    def EvaluatedSize(self):
141 146
        from EngineeringReducerItem import QEngineeringReducerItem
......
147 152
                at = matches[0].items.index(self)
148 153
                upstream = matches[0].items[:at]
149 154
                upstream.reverse()
150
                prev = self 
155
                prev = self
151 156
                for item in upstream:
152 157
                    if type(item) is QEngineeringReducerItem:
153
                        if item.connectors[0].connectedItem is prev:    ### Main Size
158
                        if item.connectors[0].connectedItem is prev:  ### Main Size
154 159
                            if item.MainSubSize: return item.MainSubSize[0]
155 160
                        elif item.connectors[1].connectedItem is prev:  ### Sub Size
156 161
                            if item.MainSubSize: return item.MainSubSize[1]
......
162 167
                prev = self
163 168
                for item in downstream:
164 169
                    if type(item) is QEngineeringReducerItem:
165
                        if item.connectors[0].connectedItem is prev:    ### Main Size
170
                        if item.connectors[0].connectedItem is prev:  ### Main Size
166 171
                            if item.MainSubSize: return item.MainSubSize[0]
167 172
                        elif item.connectors[1].connectedItem is prev:  ### Sub Size
168 173
                            if item.MainSubSize: return item.MainSubSize[1]
......
173 178
                if 'Drain' == matches[0].Type:
174 179
                    from AppDocData import AppDocData
175 180
                    return AppDocData.instance().drain_size
176
                    
181

  
177 182
            return self.owner.Size
178 183

  
179 184
        return None
......
183 188
        @author humkyung
184 189
        @date   2018.05.10
185 190
    '''
191

  
186 192
    @property
187 193
    def owner(self):
188 194
        import uuid
......
190 196
        if self._owner and type(self._owner) is uuid.UUID:
191 197
            matches = [x for x in self.scene().items() if hasattr(x, 'uid') and str(x.uid) == str(self._owner)]
192 198
            if matches: self._owner = matches[0]
193
        
199

  
194 200
        if type(self._owner) is not uuid.UUID and type(self._owner) is not str:
195 201
            return self._owner
196 202
        else:
......
203 209
        @date   2018.05.10
204 210
        @history    2018.05.17  Jeongwoo    Add Calling setColor
205 211
    '''
212

  
206 213
    @owner.setter
207 214
    def owner(self, value):
208 215
        self._owner = value
......
216 223
        @author humkyung
217 224
        @date   2018.06.21
218 225
    '''
226

  
219 227
    @property
220 228
    def flowMark(self):
221 229
        return self._flowMark
......
225 233
        @author humkyung
226 234
        @date   2018.06.21
227 235
    '''
236

  
228 237
    @flowMark.setter
229 238
    def flowMark(self, value):
230 239
        self._flowMark = value
......
234 243
        @author humkyung
235 244
        @date   2018.06.27
236 245
    '''
246

  
237 247
    @property
238 248
    def lineType(self):
239 249
        return self._lineType
240
    
250

  
241 251
    '''
242 252
        @brief  setter of lineType
243 253
        @author humkyung
244 254
        @date   2018.06.27
245 255
    '''
256

  
246 257
    @lineType.setter
247 258
    def lineType(self, value):
248 259
        from AppDocData import AppDocData
......
252 263
        docData = AppDocData.instance()
253 264
        configs = docData.getLineTypeConfig(self._lineType)
254 265
        if configs:
255
            _pen = self.pen() 
266
            _pen = self.pen()
256 267
            _pen.setWidth(configs[2])
257 268
            _pen.setStyle(configs[3])
258 269
            self.setPen(_pen)
......
265 276
    '''
266 277
        @brief  clone an object
267 278
    '''
279

  
268 280
    def clone(self):
269 281
        clone = QEngineeringLineItem()
270
        #clone._vertices = copy.deepcopy(self._vertices)
271
        #for vertex in clone._vertices:
282
        # clone._vertices = copy.deepcopy(self._vertices)
283
        # for vertex in clone._vertices:
272 284
        #    clone._pol.append(QPointF(vertex[0], vertex[1]))
273 285
        clone.buildItem()
274 286
        clone.isCreated = self.isCreated
......
287 299
        @author humkyung
288 300
        @date   2018.04.16
289 301
    '''
302

  
290 303
    def startPoint(self):
291 304
        at = self.line().p1()
292 305
        return (at.x(), at.y())
......
296 309
        @author humkyung
297 310
        @date   2018.04.16
298 311
    '''
312

  
299 313
    def endPoint(self):
300 314
        at = self.line().p2()
301 315
        return (at.x(), at.y())
......
305 319
        @author humkyung
306 320
        @date   2018.04.14
307 321
    '''
322

  
308 323
    def dotProduct(self, lhs, rhs):
309
        return sum([lhs[i]*rhs[i] for i in range(len(lhs))])
324
        return sum([lhs[i] * rhs[i] for i in range(len(lhs))])
310 325

  
311 326
    '''
312 327
        @brief  distance between line and point
313 328
        @author humkyung
314 329
        @date   2018.04.16
315 330
    '''
331

  
316 332
    def distanceTo(self, pt):
317 333
        from shapely.geometry import Point, LineString
318 334

  
......
328 344
        @author humkyung
329 345
        @date   2018.04.21
330 346
    '''
347

  
331 348
    def perpendicular(self):
332 349
        import math
333 350

  
334 351
        dx = self.endPoint()[0] - self.startPoint()[0]
335 352
        dy = self.endPoint()[1] - self.startPoint()[1]
336
        dx,dy = -dy,dx
337
        length = math.sqrt(dx*dx + dy*dy)
353
        dx, dy = -dy, dx
354
        length = math.sqrt(dx * dx + dy * dy)
338 355
        dx /= length
339 356
        dy /= length
340 357

  
341
        return (dx,dy)
358
        return (dx, dy)
342 359

  
343 360
    '''
344 361
        @brief  return angle of line in radian
345 362
        @author humkyung
346 363
        @date   2018.04.22
347 364
    '''
365

  
348 366
    def angle(self):
349 367
        import math
350 368

  
......
352 370
        endPt = self.endPoint()
353 371
        dx = endPt[0] - startPt[0]
354 372
        dy = endPt[1] - startPt[1]
355
        dot = self.dotProduct((1,0), (dx, dy))
356
        length = math.sqrt(dx*dx + dy*dy)
357
        return math.acos(dot/length)
373
        dot = self.dotProduct((1, 0), (dx, dy))
374
        length = math.sqrt(dx * dx + dy * dy)
375
        return math.acos(dot / length)
358 376

  
359 377
    '''
360 378
        @brief  return length of line
361 379
        @author humkyung
362 380
        @date   2018.05.08
363 381
    '''
382

  
364 383
    def length(self):
365 384
        import math
366 385

  
......
368 387
        endPt = self.endPoint()
369 388
        dx = endPt[0] - startPt[0]
370 389
        dy = endPt[1] - startPt[1]
371
        return math.sqrt(dx*dx + dy*dy)
390
        return math.sqrt(dx * dx + dy * dy)
372 391

  
373 392
    '''
374 393
        @brief  check if line is horizontal
375 394
        @author humkyung
376 395
        @date   2018.04.27
377 396
    '''
397

  
378 398
    def isHorizontal(self):
379 399
        import math
380 400

  
......
390 410
        @author humkyung
391 411
        @date   2018.04.27
392 412
    '''
413

  
393 414
    def isVertical(self):
394 415
        import math
395 416

  
......
407 428
        @history    Jeongwoo 2018.05.15 Add normalize
408 429
                    Jeongwoo 2018.05.16 Add length == 0 check
409 430
    '''
431

  
410 432
    def intersection(self, line):
411 433
        import math
412 434
        from shapely.geometry import Point, LineString
......
415 437
        endPt = self.endPoint()
416 438
        dx = endPt[0] - startPt[0]
417 439
        dy = endPt[1] - startPt[1]
418
        length = math.sqrt(dx*dx + dy*dy)
440
        length = math.sqrt(dx * dx + dy * dy)
419 441
        if length == 0:
420 442
            return None
421 443
        dx /= length
422 444
        dy /= length
423
        lhs = LineString([(startPt[0] - dx*20, startPt[1] - dy*20), (endPt[0] + dx*20, endPt[1] + dy*20)])
445
        lhs = LineString([(startPt[0] - dx * 20, startPt[1] - dy * 20), (endPt[0] + dx * 20, endPt[1] + dy * 20)])
424 446
        rhs = LineString(line)
425 447
        return lhs.intersection(rhs)
426 448

  
......
438 460
        import math
439 461

  
440 462
        try:
441
            vectors = [(self.endPoint()[0]-self.startPoint()[0], self.endPoint()[1]-self.startPoint()[1]), (rhs.endPoint()[0]-rhs.startPoint()[0], rhs.endPoint()[1]-rhs.startPoint()[1])]
463
            vectors = [(self.endPoint()[0] - self.startPoint()[0], self.endPoint()[1] - self.startPoint()[1]),
464
                       (rhs.endPoint()[0] - rhs.startPoint()[0], rhs.endPoint()[1] - rhs.startPoint()[1])]
442 465
            angle = self.getAngle(rhs)
443 466
            if (angle == 0) or (angle == math.pi): return True
444 467
        except ZeroDivisionError:
......
453 476
        @history    Jeongwoo 18.05.15 Add check pt's type
454 477
                    Jeongwoo 18.05.16 Add length == 0 check
455 478
    '''
479

  
456 480
    def is_connectable(self, line, toler=20):
457 481
        import math
458 482

  
......
461 485

  
462 486
        dx = endPt[0] - startPt[0]
463 487
        dy = endPt[1] - startPt[1]
464
        length = math.sqrt(dx*dx + dy*dy)
488
        length = math.sqrt(dx * dx + dy * dy)
465 489
        if length == 0:
466 490
            return False
467 491
        dx /= length
468 492
        dy /= length
469
        extendedLine = [(startPt[0] - dx*toler, startPt[1] - dy*toler), (endPt[0] + dx*toler, endPt[1] + dy*toler)]
493
        extendedLine = [(startPt[0] - dx * toler, startPt[1] - dy * toler),
494
                        (endPt[0] + dx * toler, endPt[1] + dy * toler)]
470 495
        pt = self.intersection(extendedLine)
471 496

  
472 497
        return (pt is not None) and (type(pt) == shapely.geometry.point.Point)
......
476 501
        @date       2018.06.26
477 502
        @history    humkyung 2018.07.03 allow item to be line or symbol
478 503
    '''
504

  
479 505
    def is_connected(self, item, at=QEngineeringAbstractItem.CONNECTED_AT_PT):
480 506
        """ check if given item is connected to self """
481 507

  
482
        _connectors = [connector for connector in self.connectors if (connector.connectedItem == item and connector._connected_at == at)]
508
        _connectors = [connector for connector in self.connectors if
509
                       (connector.connectedItem == item and connector._connected_at == at)]
483 510
        return len(_connectors) > 0
484 511

  
485 512
    '''
......
487 514
        @author     kyouho
488 515
        @date       2018.07.25
489 516
    '''
490
    def joinTo(self, item = None):
517

  
518
    def joinTo(self, item=None):
491 519
        import math
492 520
        from SymbolSvgItem import SymbolSvgItem
493 521

  
......
503 531
                for i in range(len(pts)):
504 532
                    dx = pts[i][0] - selected[0]
505 533
                    dy = pts[i][1] - selected[1]
506
                    if math.sqrt(dx*dx + dy*dy) < 10:
507
                        line = QLineF(QPointF(pts[i][0], pts[i][1]), QPointF(endPoint[0], endPoint[1])) if self._selectedIndex == 0 else QLineF(QPointF(startPoint[0], startPoint[1]), QPointF(pts[i][0], pts[i][1]))
534
                    if math.sqrt(dx * dx + dy * dy) < 10:
535
                        line = QLineF(QPointF(pts[i][0], pts[i][1]),
536
                                      QPointF(endPoint[0], endPoint[1])) if self._selectedIndex == 0 else QLineF(
537
                            QPointF(startPoint[0], startPoint[1]), QPointF(pts[i][0], pts[i][1]))
508 538
                        self.setLine(line)
509 539
                        self.update()
510 540
                        break
......
525 555
                elif endPoint[0] == connector2Point[0] and endPoint[1] == connector2Point[1]:
526 556
                    self.connectors[1].connectedItem = item
527 557

  
528

  
529 558
    '''
530 559
        @brief      arrange vertex order
531 560
        @author     humkyung
532 561
        @date       2018.07.04
533 562
    '''
563

  
534 564
    def arrangeVertexOrder(self, arranged):
535 565
        import math
536 566

  
......
545 575
                index += 1
546 576
                dx = _pt[0] - pt[0]
547 577
                dy = _pt[1] - pt[1]
548
                dist = math.sqrt(dx*dx + dy*dy)
578
                dist = math.sqrt(dx * dx + dy * dy)
549 579
                if minDist is None or dist < minDist:
550 580
                    minDist = dist
551 581
                    indexed = index
552
                    
582

  
553 583
        if indexed == 1 or indexed == 4:
554 584
            self.reverse()
555 585

  
......
559 589
        @date       2018.06.25
560 590
        @history    humkyung 2018.06.27 check line type
561 591
    '''
592

  
562 593
    def isExtendable(self, line, toler=5):
563 594
        import math
564 595
        from SymbolSvgItem import SymbolSvgItem
565 596

  
566 597
        if self.lineType == line.lineType:
567 598
            if self.isHorizontal() and line.isHorizontal():
568
                flag = (line.connectors[0].connectedItem is not None and issubclass(type(line.connectors[0].connectedItem), SymbolSvgItem)) or (line.connectors[1].connectedItem is not None and issubclass(type(line.connectors[1].connectedItem), SymbolSvgItem))
599
                flag = (line.connectors[0].connectedItem is not None and issubclass(
600
                    type(line.connectors[0].connectedItem), SymbolSvgItem)) or (
601
                                   line.connectors[1].connectedItem is not None and issubclass(
602
                               type(line.connectors[1].connectedItem), SymbolSvgItem))
569 603
                return (flag and (math.fabs(self.startPoint()[1] - line.startPoint()[1]) < toler))
570 604
            elif self.isVertical() and line.isVertical():
571
                flag = (line.connectors[0].connectedItem is not None and issubclass(type(line.connectors[0].connectedItem), SymbolSvgItem)) or (line.connectors[1].connectedItem is not None and issubclass(type(line.connectors[1].connectedItem), SymbolSvgItem))
605
                flag = (line.connectors[0].connectedItem is not None and issubclass(
606
                    type(line.connectors[0].connectedItem), SymbolSvgItem)) or (
607
                                   line.connectors[1].connectedItem is not None and issubclass(
608
                               type(line.connectors[1].connectedItem), SymbolSvgItem))
572 609
                return (flag and (math.fabs(self.startPoint()[0] - line.startPoint()[0]) < toler))
573
            
610

  
574 611
        return False
575
        
612

  
576 613
    def is_external_point(self, pt):
577 614
        """ check given pt is located outside of line """
578 615
        import math
......
581 618
            dx = self.endPoint()[0] - self.startPoint()[0]
582 619
            dy = self.endPoint()[1] - self.startPoint()[1]
583 620
            lineLength = math.sqrt(dx * dx + dy * dy)
584
            
621

  
585 622
            dx = pt.x - self.startPoint()[0]
586 623
            dy = pt.y - self.startPoint()[1]
587 624
            length = math.sqrt(dx * dx + dy * dy)
......
596 633

  
597 634
            return False
598 635
        except Exception as ex:
599
            from App import App 
636
            from App import App
600 637
            from AppDocData import MessageType
601 638

  
602
            message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename, sys.exc_info()[-1].tb_lineno)
639
            message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
640
                                                           sys.exc_info()[-1].tb_lineno)
603 641
            App.mainWnd().addMessage.emit(MessageType.Error, message)
604 642

  
605 643
    '''
......
608 646
        @history    humkyung 2018.05.08 check if line is possible to be connected
609 647
                    Jeongwoo 2018.05.15 Split if-statement and Connect each symbol and line
610 648
    '''
649

  
611 650
    def connect_if_possible(self, obj, toler=20):
612 651
        """ connect line or symbol is able to be connected and return symbol or line connected to connectors """
613 652
        """ this method not update item's position """
......
618 657

  
619 658
        res = []
620 659

  
621
        startPt = self.startPoint() 
660
        startPt = self.startPoint()
622 661
        endPt = self.endPoint()
623 662

  
624 663
        try:
......
627 666
                    pt = obj.connectors[i].sceneConnectPoint
628 667
                    if (Point(startPt[0], startPt[1]).distance(Point(pt[0], pt[1])) < toler):
629 668
                        if self.connectors[0].connectedItem is None and obj.connectors[i].connectedItem is None:
630
                            self.connectors[0].connect(obj) 
669
                            self.connectors[0].connect(obj)
631 670
                            obj.connectors[i].connect(self)
632 671
                            res.append(obj)
633 672
                            res.append(obj.connectors[i].sceneConnectPoint)
......
641 680
                _startPt = obj.startPoint()
642 681
                _endPt = obj.endPoint()
643 682
                if self.distanceTo(_startPt) < toler:
644
                    if((Point(startPt[0], startPt[1]).distance(Point(_startPt[0], _startPt[1])) < toler)):
683
                    if ((Point(startPt[0], startPt[1]).distance(Point(_startPt[0], _startPt[1])) < toler)):
645 684
                        self.connectors[0].connect(obj)
646 685
                        obj.connectors[0].connect(self)
647 686
                        res.append(obj)
648
                    elif((Point(endPt[0], endPt[1]).distance(Point(_startPt[0], _startPt[1])) < toler)):
687
                    elif ((Point(endPt[0], endPt[1]).distance(Point(_startPt[0], _startPt[1])) < toler)):
649 688
                        self.connectors[1].connect(obj)
650 689
                        obj.connectors[0].connect(self)
651 690
                        res.append(obj)
......
664 703
                    else:
665 704
                        obj.connectors[1].connect(self, at=QEngineeringAbstractItem.CONNECTED_AT_BODY)
666 705
        except Exception as ex:
667
            from App import App 
706
            from App import App
668 707
            from AppDocData import MessageType
669 708

  
670
            message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename, sys.exc_info()[-1].tb_lineno)
709
            message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
710
                                                           sys.exc_info()[-1].tb_lineno)
671 711
            App.mainWnd().addMessage.emit(MessageType.Error, message)
672 712

  
673 713
        return res
......
677 717
        @author     kyouho
678 718
        @date       2018.08.30
679 719
    '''
720

  
680 721
    def disconnectedItemAtConnector(self, connector):
681 722
        for conn in self.connectors:
682 723
            if conn.isOverlapConnector(connector):
......
686 727
        """ reverse if from is connected to second connector """
687 728
        if not _from: raise ValueError
688 729

  
689
        if self.connectors[1].connectedItem == _from: self.reverse() 
730
        if self.connectors[1].connectedItem == _from: self.reverse()
690 731

  
691 732
    '''
692 733
        @brief      reverse line
693 734
        @author     humkyung
694 735
        @date       2018.07.03
695 736
    '''
737

  
696 738
    def reverse(self):
697 739
        line = self.line()
698 740
        self.setLine(QLineF(line.p2(), line.p1()))
......
706 748
        @date       2018.05.08
707 749
        @history    2018.05.24  Jeongwoo    Modifying Draw Flow Arrow
708 750
    '''
751

  
709 752
    def addFlowArrow(self):
710 753
        import numpy as np
711 754
        import cv2
......
715 758
        from shapely.geometry import Point
716 759
        from QEngineeringFlowArrowItem import QEngineeringFlowArrowItem
717 760
        from AppDocData import AppDocData
718
        
761

  
719 762
        try:
720 763
            docData = AppDocData.instance()
721 764
            area = docData.getArea('Drawing')
......
739 782
            docData = AppDocData.instance()
740 783
            area = docData.getArea('Drawing')
741 784
            img = np.array(AppDocData.instance().getCurrentPidSource().getPyImageOnRect(rect))
742
            
785

  
743 786
            imgLine = cv2.threshold(cv2.cvtColor(img, cv2.COLOR_BGR2GRAY), 127, 255, cv2.THRESH_BINARY)[1]
744 787
            # remove noise
745 788
            imgLine = cv2.bitwise_not(imgLine)
......
749 792
            if contours:
750 793
                contours = sorted(contours, key=cv2.contourArea, reverse=True)
751 794
                [x, y, w, h] = cv2.boundingRect(contours[0])
752
                if w > 10 and w < 100 and h > 10 and h < 100:   # check arrow mark size
753
                    imgArrowMark = imgLine[y:y+h, x:x+w]
795
                if w > 10 and w < 100 and h > 10 and h < 100:  # check arrow mark size
796
                    imgArrowMark = imgLine[y:y + h, x:x + w]
754 797

  
755 798
                    # DEBUG - display flow arrow area
756 799
                    '''
......
764 807
                    # up to here
765 808

  
766 809
                    edges = cv2.Canny(imgArrowMark, 50, 150, apertureSize=3)
767
                    lines = cv2.HoughLinesP(edges, 1, np.pi/180, 10, minLineLength=10, maxLineGap=5)
810
                    lines = cv2.HoughLinesP(edges, 1, np.pi / 180, 10, minLineLength=10, maxLineGap=5)
768 811

  
769 812
                    ####### HoughLinesP
770 813
                    if lines is not None:
......
775 818
                                dx = x2 - x1
776 819
                                dy = y2 - y1
777 820
                                selected = line
778
                                length = math.sqrt(dx*dx + dy*dy)
821
                                length = math.sqrt(dx * dx + dy * dy)
779 822
                                if maxLength is None or length > maxLength:
780 823
                                    maxLength = length
781 824
                                    selected = line
......
783 826
                        for x1, y1, x2, y2 in selected:
784 827
                            dx = math.fabs(x2 - x1)
785 828
                            dy = math.fabs(y2 - y1)
786
                            length = math.sqrt(dx*dx + dy*dy)
829
                            length = math.sqrt(dx * dx + dy * dy)
787 830
                            dx /= length
788 831
                            dy /= length
789
                            if (self.isVertical() and (dx < 0.001 or math.fabs(dx - 1) < 0.001)) or (self.isHorizontal() and (dx < 0.001 or math.fabs(dx - 1) < 0.001)): continue 
832
                            if (self.isVertical() and (dx < 0.001 or math.fabs(dx - 1) < 0.001)) or (
833
                                    self.isHorizontal() and (dx < 0.001 or math.fabs(dx - 1) < 0.001)): continue
790 834
                            dist1 = self.distanceTo((rect.left() + x + x1, rect.top() + y + y1))
791 835
                            dist2 = self.distanceTo((rect.left() + x + x2, rect.top() + y + y2))
792
                            if dist1 > dist2:   # point which's distance is longer would be start point
836
                            if dist1 > dist2:  # point which's distance is longer would be start point
793 837
                                _start = (rect.left() + x + x1, rect.top() + y + y1)
794 838
                                _end = (rect.left() + x + x2, rect.top() + y + y2)
795 839
                            else:
796 840
                                _start = (rect.left() + x + x2, rect.top() + y + y2)
797 841
                                _end = (rect.left() + x + x1, rect.top() + y + y1)
798
                            
842

  
799 843
                            # DEBUG display detected line
800 844
                            '''
801 845
                            poly = QEngineeringPolylineItem()
......
810 854
                            dist1 = Point(startPt[0], startPt[1]).distance(Point(_start[0], _start[1]))
811 855
                            dist2 = Point(startPt[0], startPt[1]).distance(Point(_end[0], _end[1]))
812 856
                            if dist1 > dist2:
813
                                startPt,endPt = endPt,startPt
814
                                direction[0],direction[1] = -direction[0],-direction[1]
857
                                startPt, endPt = endPt, startPt
858
                                direction[0], direction[1] = -direction[0], -direction[1]
815 859
                                self.reverse()
816
                                    
860

  
817 861
                        '''
818 862
                        center = [(startPt[0]+endPt[0])*0.5, (startPt[1]+endPt[1])*0.5]
819 863
                        arrow = QEngineeringFlowArrowItem(center, direction)
......
827 871
                else:
828 872
                    pass
829 873
        except Exception as ex:
830
            from App import App 
874
            from App import App
831 875
            from AppDocData import MessageType
832 876

  
833
            message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename, sys.exc_info()[-1].tb_lineno)
877
            message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
878
                                                           sys.exc_info()[-1].tb_lineno)
834 879
            App.mainWnd().addMessage.emit(MessageType.Error, message)
835 880

  
836 881
    '''
......
839 884
        @date   2018.04.22
840 885
        @history    kyouho  2018.07.24  add symbol angle, transform rotateRadians(-angle -> angle)
841 886
    '''
887

  
842 888
    def insertSymbol(self, symbol, pos):
843 889
        import math
844 890
        from shapely.geometry import Point
845 891
        from shapely import affinity
846 892

  
847 893
        vec = self.perpendicular()
848
        line = [(pos.x() - vec[0]*20, pos.y() - vec[1]*20),(pos.x() + vec[0]*20, pos.y() + vec[1]*20)]
894
        line = [(pos.x() - vec[0] * 20, pos.y() - vec[1] * 20), (pos.x() + vec[0] * 20, pos.y() + vec[1] * 20)]
849 895
        origin = self.intersection(line)
850 896
        transform = QTransform()
851 897
        transform.translate(origin.x, origin.y)
......
853 899
        transform.rotateRadians(-angle)
854 900
        transform.translate(-symbol.symbolOrigin[0], -symbol.symbolOrigin[1])
855 901
        symbol.setTransform(transform)
856
        #save angle
902
        # save angle
857 903
        symbol.angle = round(angle, 2)
858
        if 2 == len(symbol.connectors):    # 2 way component
904
        if 2 == len(symbol.connectors):  # 2 way component
859 905
            for i in range(len(symbol.connectors)):
860
                rotatedPt = affinity.rotate(Point(symbol.connectors[i].connectPoint[0] - symbol.symbolOrigin[0], symbol.connectors[i].connectPoint[1] - symbol.symbolOrigin[1]), -angle, Point(0, 0), use_radians=True)
861
                symbol.connectors[i].sceneConnectPoint = (origin.x+rotatedPt.x, origin.y+rotatedPt.y)
906
                rotatedPt = affinity.rotate(Point(symbol.connectors[i].connectPoint[0] - symbol.symbolOrigin[0],
907
                                                  symbol.connectors[i].connectPoint[1] - symbol.symbolOrigin[1]),
908
                                            -angle, Point(0, 0), use_radians=True)
909
                symbol.connectors[i].sceneConnectPoint = (origin.x + rotatedPt.x, origin.y + rotatedPt.y)
862 910

  
863 911
            dx1 = symbol.connectors[0].sceneConnectPoint[0] - self.startPoint()[0]
864 912
            dy1 = symbol.connectors[0].sceneConnectPoint[1] - self.startPoint()[1]
865
            length1 = math.sqrt(dx1*dx1 + dy1*dy1)
913
            length1 = math.sqrt(dx1 * dx1 + dy1 * dy1)
866 914
            dx2 = symbol.connectors[1].sceneConnectPoint[0] - self.startPoint()[0]
867 915
            dy2 = symbol.connectors[1].sceneConnectPoint[1] - self.startPoint()[1]
868
            length2 = math.sqrt(dx2*dx2 + dy2*dy2)
916
            length2 = math.sqrt(dx2 * dx2 + dy2 * dy2)
869 917

  
870 918
            if length1 < length2:
871 919
                processLine = QEngineeringLineItem([symbol.connectors[1].sceneConnectPoint, self.endPoint()])
......
873 921
                processLine.connectors[1].connectedItem = self.connectors[1].connectedItem
874 922
                self.scene().addItem(processLine)
875 923

  
876
                line = QLineF(self.line().p1(), QPointF(symbol.connectors[0].sceneConnectPoint[0], symbol.connectors[0].sceneConnectPoint[1]))
924
                line = QLineF(self.line().p1(), QPointF(symbol.connectors[0].sceneConnectPoint[0],
925
                                                        symbol.connectors[0].sceneConnectPoint[1]))
877 926
                self.setLine(line)
878 927
                self.connectors[1].connectedItem = symbol
879 928

  
......
885 934
                processLine.connectors[1].connectedItem = self.connectors[1].connectedItem
886 935
                self.scene().addItem(processLine)
887 936

  
888
                line = QLineF(self.line().p1(), QPointF(symbol.connectors[1].sceneConnectPoint[0], symbol.connectors[1].sceneConnectPoint[1]))
937
                line = QLineF(self.line().p1(), QPointF(symbol.connectors[1].sceneConnectPoint[0],
938
                                                        symbol.connectors[1].sceneConnectPoint[1]))
889 939
                self.setLine(line)
890 940
                self.connectors[1].connectedItem = symbol
891 941

  
892 942
                symbol.connectors[0].connectedItem = processLine
893 943
                symbol.connectors[1].connectedItem = self
894
                
895 944

  
896 945
            self.joinTo(symbol)
897 946
            processLine.joinTo(symbol)
898 947
            self.update()
899
            
948

  
900 949
        symbol.loc = [origin.x - symbol.symbolOrigin[0], origin.y - symbol.symbolOrigin[1]]
901 950
        symbol.size = [symbol.boundingRect().width(), symbol.boundingRect().height()]
902 951
        self.scene().addItem(symbol)
903
    
952

  
904 953
    '''
905 954
        @brief  redraw symbol
906 955
        @author kyouho
907 956
        @date   2018.07.25
908 957
    '''
958

  
909 959
    def reDrawLine(self, symbol, point):
910 960
        for index in range(len(self.connectors)):
911 961
            if self.connectors[index].connectedItem == symbol:
912
                #startPoint
962
                # startPoint
913 963
                if index == 0:
914 964
                    line = QLineF(QPointF(point[0], point[1]), self.line().p2())
915 965
                    self.setLine(line)
916 966
                    self.connectors[0].setPos([point[0], point[1]])
917
                #endpoint
967
                # endpoint
918 968
                else:
919 969
                    line = QLineF(self.line().p1(), QPointF(point[0], point[1]))
920 970
                    self.setLine(line)
921 971
                    self.connectors[1].setPos([point[0], point[1]])
922
        
923 972

  
924
        
925 973
        ## startPoint에 symbol
926
        #if self.connectors[0].connectedItem == symbol:
974
        # if self.connectors[0].connectedItem == symbol:
927 975
        #    if self.startPoint()[0] == symbol.connectors[0].sceneConnectPoint[0] and self.startPoint()[1] == symbol.connectors[0].sceneConnectPoint[1]:
928 976
        #        line = QLineF(QPointF(changedConnPoint1[0], changedConnPoint1[1]), self.line().p2())
929 977
        #        self.setLine(line)
......
931 979
        #        line = QLineF(QPointF(changedConnPoint2[0], changedConnPoint2[1]), self.line().p2())
932 980
        #        self.setLine(line)
933 981
        ## endPoint에 symbol
934
        #elif self.connectors[1].connectedItem == symbol:
982
        # elif self.connectors[1].connectedItem == symbol:
935 983
        #    if self.endPoint()[0] == symbol.connectors[0].sceneConnectPoint[0] and self.endPoint()[1] == symbol.connectors[0].sceneConnectPoint[1]:
936 984
        #        line = QLineF(self.line().p1(), QPointF(changedConnPoint1[0], changedConnPoint1[1]))
937 985
        #        self.setLine(line)
......
946 994
        @author humkyung
947 995
        @date   2018.04.23
948 996
    '''
997

  
949 998
    def removeSymbol(self, symbol):
950 999
        import math
951 1000

  
952 1001
        if 2 == len(symbol.connectors):  # 2-way component
953
            connected = symbol.connectors[0].connectedItem if symbol.connectors[0].connectedItem is not self else symbol.connectors[1].connectedItem
954
            
1002
            connected = symbol.connectors[0].connectedItem if symbol.connectors[0].connectedItem is not self else \
1003
            symbol.connectors[1].connectedItem
1004

  
955 1005
            pts = []
956 1006
            pts.append(self.startPoint())
957 1007
            pts.append(self.endPoint())
......
964 1014
            end = None
965 1015
            maxDist = None
966 1016
            for i in range(len(pts)):
967
                for j in range(i+1,len(pts)):
1017
                for j in range(i + 1, len(pts)):
968 1018
                    dx = pts[i][0] - pts[j][0]
969 1019
                    dy = pts[i][1] - pts[j][1]
970
                    dist = math.sqrt(dx*dx + dy*dy)
1020
                    dist = math.sqrt(dx * dx + dy * dy)
971 1021
                    if maxDist is None:
972 1022
                        maxDist = dist
973 1023
                        start = pts[i]
......
977 1027
                        start = pts[i]
978 1028
                        end = pts[j]
979 1029

  
980
            if (pts[0] == end) or (pts[1] == start): start,end = end,start
1030
            if (pts[0] == end) or (pts[1] == start): start, end = end, start
981 1031

  
982 1032
            line = QLineF(QPointF(start[0], start[1]), QPointF(end[0], end[1]))
983 1033
            self.setLine(line)
984
            #self.buildItem()
1034
            # self.buildItem()
985 1035
            self.update()
986 1036

  
987 1037
    def validate(self):
......
1021 1071
                    errors.append(error)
1022 1072

  
1023 1073
                # check line to symbol
1024
                elif issubclass(type(connector.connectedItem), SymbolSvgItem) and type(connector.connectedItem) is not QEngineeringEquipmentItem:
1074
                elif issubclass(type(connector.connectedItem), SymbolSvgItem) and type(
1075
                        connector.connectedItem) is not QEngineeringEquipmentItem:
1025 1076
                    matches = [conn for conn in connector.connectedItem.connectors if conn.connectedItem is self]
1026 1077
                    # check if two items are connected each other
1027 1078
                    if not matches:
......
1051 1102

  
1052 1103
                        indices = [0, 0]
1053 1104
                        indices[0] = 1 if QPointF(center[0], center[1]) == self.line().p1() else 2
1054
                        matches = [conn for conn in connector.connectedItem.connectors if conn.connectedItem == self and conn._connected_at == QEngineeringAbstractItem.CONNECTED_AT_PT]
1105
                        matches = [conn for conn in connector.connectedItem.connectors if
1106
                                   conn.connectedItem == self and conn._connected_at == QEngineeringAbstractItem.CONNECTED_AT_PT]
1055 1107
                        if matches:
1056
                            indices[1] = 1 if QPointF(matches[0].center()[0], matches[0].center()[1]) == connector.connectedItem.line().p1() else 2
1108
                            indices[1] = 1 if QPointF(matches[0].center()[0], matches[0].center()[
1109
                                1]) == connector.connectedItem.line().p1() else 2
1057 1110

  
1058
                        if indices[0] == indices[1]: 
1111
                        if indices[0] == indices[1]:
1059 1112
                            error = SymbolSvgItem.createItem('Error', dataPath)
1060 1113
                            error.setPosition(connector.center())
1061 1114
                            error.parent = self
......
1089 1142
                errors.append(error)
1090 1143

  
1091 1144
        except Exception as ex:
1092
            from App import App 
1145
            from App import App
1093 1146
            from AppDocData import MessageType
1094 1147

  
1095
            message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename, sys.exc_info()[-1].tb_lineno)
1148
            message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
1149
                                                           sys.exc_info()[-1].tb_lineno)
1096 1150
            App.mainWnd().addMessage.emit(MessageType.Error, message)
1097
        
1151

  
1098 1152
        return errors
1099 1153

  
1100 1154
    '''
......
1102 1156
        @author humkyung
1103 1157
        @date   2018.07.05
1104 1158
    '''
1159

  
1105 1160
    def update_line_type(self):
1106 1161
        import uuid
1107 1162
        from LineTypeConditions import LineTypeConditions
1108 1163

  
1109 1164
        try:
1110
            pool,visited,items = [self],[],[]
1165
            pool, visited, items = [self], [], []
1111 1166
            while pool:
1112 1167
                obj = pool.pop()
1113 1168
                visited.append(obj)
1114 1169

  
1115 1170
                """ connected items """
1116
                connected = [connector.connectedItem for connector in obj.connectors if connector.connectedItem and not type(connector.connectedItem) is uuid.UUID]
1171
                connected = [connector.connectedItem for connector in obj.connectors if
1172
                             connector.connectedItem and not type(connector.connectedItem) is uuid.UUID]
1117 1173
                """ connected lines at point """
1118
                lines = [connector.connectedItem for connector in obj.connectors if connector.connectedItem and type(connector.connectedItem) is QEngineeringLineItem and connector._connected_at == QEngineeringAbstractItem.CONNECTED_AT_PT]
1174
                lines = [connector.connectedItem for connector in obj.connectors if connector.connectedItem and type(
1175
                    connector.connectedItem) is QEngineeringLineItem and connector._connected_at == QEngineeringAbstractItem.CONNECTED_AT_PT]
1119 1176
                """ add items not in 'connected' to items list """
1120 1177
                items.extend([item for item in connected if item not in lines])
1121 1178
                """ add items not visited to pool """
......
1126 1183
                    self.lineType = condition.name
1127 1184
                    break
1128 1185
        except Exception as ex:
1129
            from App import App 
1186
            from App import App
... 이 차이점은 표시할 수 있는 최대 줄수를 초과해서 이 차이점은 잘렸습니다.

내보내기 Unified diff

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