Completed
Push — master ( ac0a27...6f0f8d )
by Jan
04:44
created

ConfigMainWindow.setConfigEditor()   A

Complexity

Conditions 2

Size

Total Lines 12

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
dl 0
loc 12
rs 9.4285
c 0
b 0
f 0
1
# -*- coding: utf-8 -*-
2
"""
3
Qudi is free software: you can redistribute it and/or modify
4
it under the terms of the GNU General Public License as published by
5
the Free Software Foundation, either version 3 of the License, or
6
(at your option) any later version.
7
8
Qudi is distributed in the hope that it will be useful,
9
but WITHOUT ANY WARRANTY; without even the implied warranty of
10
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11
GNU General Public License for more details.
12
13
You should have received a copy of the GNU General Public License
14
along with Qudi. If not, see <http://www.gnu.org/licenses/>.
15
16
Copyright (c) the Qudi Developers. See the COPYRIGHT.txt file at the
17
top-level directory of this distribution and at <https://github.com/Ulm-IQO/qudi/>
18
"""
19
if __package__ is None:
20
    import __init__
0 ignored issues
show
Unused Code introduced by
The import __init__ seems to be unused.
Loading history...
21
    __package__ = 'config_gui'
0 ignored issues
show
Bug Best Practice introduced by
This seems to re-define the built-in __package__.

It is generally discouraged to redefine built-ins as this makes code very hard to read.

Loading history...
22
else:
23
    import __init__
24
25
from qtpy import QtCore, QtGui, QtWidgets, uic
0 ignored issues
show
Unused Code introduced by
Unused QtGui imported from qtpy
Loading history...
26
27
from pyflowgraph.graph_view import GraphView
0 ignored issues
show
Unused Code introduced by
Unused GraphView imported from pyflowgraph.graph_view
Loading history...
28
from pyflowgraph.graph_view_widget import GraphViewWidget
0 ignored issues
show
Unused Code introduced by
Unused GraphViewWidget imported from pyflowgraph.graph_view_widget
Loading history...
29
from pyflowgraph.node import Node
30
from pyflowgraph.port import InputPort, OutputPort, IOPort
0 ignored issues
show
Unused Code introduced by
Unused IOPort imported from pyflowgraph.port
Loading history...
31
32
import sys
33
import os
34
35
sys.path.append(os.getcwd())
36
from gui.colordefs import QudiPalettePale as palette
0 ignored issues
show
Bug introduced by
The name colordefs does not seem to exist in module gui.
Loading history...
37
import core.config
0 ignored issues
show
Bug introduced by
The name config does not seem to exist in module core.
Loading history...
38
from menu import ModMenu
39
from port import QudiPortType
40
from config_model import ModuleConfigModel
41
from collections import OrderedDict
42
43
import listmods
44
import logging
45
import argparse
46
47
class ModNode:
48
49
    def __init__(self, module, node):
50
        self.module = module
51
        self.node = node
52
        self.cfgmodel = ModuleConfigModel(module)
53
54
class ConfigMainWindow(QtWidgets.QMainWindow):
55
    """ This class represents the Manager Window.
56
    """
57
    def __init__(self, loadfile=None):
58
        """ Create the Manager Window.
59
        """
60
        # Get the path to the *.ui file
61
        this_dir = os.path.dirname(__file__)
62
        ui_file = os.path.join(this_dir, 'ui_config_window.ui')
63
        self.log = logging.getLogger(__name__)
64
65
        # Load it
66
        super().__init__()
67
        uic.loadUi(ui_file, self)
68
69
        self.modnodes = dict()
70
        self.globalsection = OrderedDict()
71
        self.currentFile = ''
72
73
        # palette
74
        self.colors = {
75
            'hardware': palette.c2,
76
            'logic': palette.c1,
77
            'gui': palette.c4,
78
            '': palette.c3
79
        }
80
81
        # init
82
        self.setupUi()
83
        self.show()
0 ignored issues
show
Bug introduced by
The Instance of ConfigMainWindow does not seem to have a member named show.

This check looks for calls to members that are non-existent. These calls will fail.

The member could have been renamed or removed.

Loading history...
84
85
        if loadfile is not None:
86
            self.loadConfigFile(loadfile)
87
88
    def setupUi(self):
89 View Code Duplication
        self.actionNew_configuration.triggered.connect(self.newConfigFile)
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
Bug introduced by
The Instance of ConfigMainWindow does not seem to have a member named actionNew_configuration.

This check looks for calls to members that are non-existent. These calls will fail.

The member could have been renamed or removed.

Loading history...
90
        self.actionSave_configuration.triggered.connect(self.saveConfigFile)
0 ignored issues
show
Bug introduced by
The Instance of ConfigMainWindow does not seem to have a member named actionSave_configuration.

This check looks for calls to members that are non-existent. These calls will fail.

The member could have been renamed or removed.

Loading history...
91
        self.actionSave_configuration_as.triggered.connect(self.saveConfigFileAs)
0 ignored issues
show
Bug introduced by
The Instance of ConfigMainWindow does not seem to have a member named actionSave_configuration_as.

This check looks for calls to members that are non-existent. These calls will fail.

The member could have been renamed or removed.

Loading history...
92
        self.actionOpen_configuration.triggered.connect(self.openConfigFile)
0 ignored issues
show
Bug introduced by
The Instance of ConfigMainWindow does not seem to have a member named actionOpen_configuration.

This check looks for calls to members that are non-existent. These calls will fail.

The member could have been renamed or removed.

Loading history...
93
        self.actionDelete_selected_nodes.triggered.connect(self.graphView.deleteSelectedNodes)
0 ignored issues
show
Bug introduced by
The Instance of ConfigMainWindow does not seem to have a member named actionDelete_selected_nodes.

This check looks for calls to members that are non-existent. These calls will fail.

The member could have been renamed or removed.

Loading history...
Bug introduced by
The Instance of ConfigMainWindow does not seem to have a member named graphView.

This check looks for calls to members that are non-existent. These calls will fail.

The member could have been renamed or removed.

Loading history...
94
        self.actionFrame_selected_nodes.triggered.connect(self.graphView.frameSelectedNodes)
0 ignored issues
show
Bug introduced by
The Instance of ConfigMainWindow does not seem to have a member named actionFrame_selected_nodes.

This check looks for calls to members that are non-existent. These calls will fail.

The member could have been renamed or removed.

Loading history...
Bug introduced by
The Instance of ConfigMainWindow does not seem to have a member named graphView.

This check looks for calls to members that are non-existent. These calls will fail.

The member could have been renamed or removed.

Loading history...
95
        self.actionFrame_all_nodes.triggered.connect(self.graphView.frameAllNodes)
0 ignored issues
show
Bug introduced by
The Instance of ConfigMainWindow does not seem to have a member named actionFrame_all_nodes.

This check looks for calls to members that are non-existent. These calls will fail.

The member could have been renamed or removed.

Loading history...
Bug introduced by
The Instance of ConfigMainWindow does not seem to have a member named graphView.

This check looks for calls to members that are non-existent. These calls will fail.

The member could have been renamed or removed.

Loading history...
96
97
        # add module menu
98
        self.findModules()
99
        self.mmroot = ModMenu(self.m)
100
        for mod in self.mmroot.modules:
101
            mod.sigAddModule.connect(self.addModule)
102
        self.actionAdd_Module.setMenu(self.mmroot)
0 ignored issues
show
Bug introduced by
The Instance of ConfigMainWindow does not seem to have a member named actionAdd_Module.

This check looks for calls to members that are non-existent. These calls will fail.

The member could have been renamed or removed.

Loading history...
103
104
        # node change signals
105
        self.graphView.nodeAdded.connect(self.nodeAdded)
0 ignored issues
show
Bug introduced by
The Instance of ConfigMainWindow does not seem to have a member named graphView.

This check looks for calls to members that are non-existent. These calls will fail.

The member could have been renamed or removed.

Loading history...
106
        self.graphView.nodeRemoved.connect(self.nodeRemoved)
0 ignored issues
show
Bug introduced by
The Instance of ConfigMainWindow does not seem to have a member named graphView.

This check looks for calls to members that are non-existent. These calls will fail.

The member could have been renamed or removed.

Loading history...
107
        self.graphView.nodeNameChanged.connect(self.nodeNameChanged)
0 ignored issues
show
Bug introduced by
The Instance of ConfigMainWindow does not seem to have a member named graphView.

This check looks for calls to members that are non-existent. These calls will fail.

The member could have been renamed or removed.

Loading history...
108
        self.graphView.selectionChanged.connect(self.selectedNodesChanged)
0 ignored issues
show
Bug introduced by
The Instance of ConfigMainWindow does not seem to have a member named graphView.

This check looks for calls to members that are non-existent. These calls will fail.

The member could have been renamed or removed.

Loading history...
109
110
    def findModules(self):
111
        modules = listmods.find_pyfiles(os.getcwd())
0 ignored issues
show
Bug introduced by
The Module listmods does not seem to have a member named find_pyfiles.

This check looks for calls to members that are non-existent. These calls will fail.

The member could have been renamed or removed.

Loading history...
112
        m, i_s, ie, oe = listmods.check_qudi_modules(modules)
0 ignored issues
show
Bug introduced by
The Module listmods does not seem to have a member named check_qudi_modules.

This check looks for calls to members that are non-existent. These calls will fail.

The member could have been renamed or removed.

Loading history...
Unused Code introduced by
The variable i_s seems to be unused.
Loading history...
113
        self.m = m
114
115
        if len(oe) > 0 or len(ie) > 0:
116
            print('\n==========  ERRORS:  ===========', file=sys.stderr)
117
            for e in oe:
118
                print(e[0], file=sys.stderr)
119
                print(e[1], file=sys.stderr)
120
121
            for e in ie:
122
                print(e[0], file=sys.stderr)
123
                print(e[1], file=sys.stderr)
124
       #  print(self.m)
125
126
    def addModule(self, module, name=None, pos=(0,0)):
127
        """ Add a module to the GraphView
128
        """
129
130
        # sort out the module name
131
        if name is None:
132
            name = 'new_module'
133
        n = 1
134
        if self.graphView.hasNode(name):
0 ignored issues
show
Bug introduced by
The Instance of ConfigMainWindow does not seem to have a member named graphView.

This check looks for calls to members that are non-existent. These calls will fail.

The member could have been renamed or removed.

Loading history...
135
            while self.graphView.hasNode('{}{}'.format(name, n)):
0 ignored issues
show
Bug introduced by
The Instance of ConfigMainWindow does not seem to have a member named graphView.

This check looks for calls to members that are non-existent. These calls will fail.

The member could have been renamed or removed.

Loading history...
136
                n += 1
137
            name = '{}{}'.format(name, n)
138
139
        # chart view
140
        g = self.graphView
0 ignored issues
show
Bug introduced by
The Instance of ConfigMainWindow does not seem to have a member named graphView.

This check looks for calls to members that are non-existent. These calls will fail.

The member could have been renamed or removed.

Loading history...
141
142
        # new node in chart
143
        node = Node(g, name)
144
145
        # coloring
146
        node.setColor(self.colors[module.base])
147
148
        # check where the module belongs and what it can connect to
149
        for cname, conn in module.connections.items():
0 ignored issues
show
Unused Code introduced by
The variable cname seems to be unused.
Loading history...
150
            port_type = QudiPortType('in', module.base, [conn.interface])
151
            node.addPort(InputPort(node, g, conn.name, palette.c3, port_type))
152
153
        if module.base != 'gui':
154
            port_type = QudiPortType('out', module.base, module.interfaces)
155
            node.addPort(OutputPort(node, g, 'out', palette.c3, port_type))
156
157
        # set position in view
158
        node.setGraphPos(QtCore.QPointF(pos[0], pos[1]))
159
160
        # save the module instance and node relatonship
161
        self.modnodes[name] = ModNode(module, node)
162
        # add node to view
163
        g.addNode(node)
164
165
    def openConfigFile(self):
166
        defaultconfigpath = ''
167
        filename = QtWidgets.QFileDialog.getOpenFileName(
168
            self,
169
            'Load Configration',
170
            defaultconfigpath ,
171
            'Configuration files (*.cfg)')[0]
172
        if len(filename) > 0:
173
            print('Open:', filename)
174
            self.loadConfigFile(filename)
175
176
    def loadConfigFile(self, filename):
177
        config = core.config.load(filename)
0 ignored issues
show
Bug introduced by
The Module core does not seem to have a member named config.

This check looks for calls to members that are non-existent. These calls will fail.

The member could have been renamed or removed.

Loading history...
178
        self.configToNodes(config)
179
        self.currentFile = filename
180
        self.graphView.frameAllNodes()
0 ignored issues
show
Bug introduced by
The Instance of ConfigMainWindow does not seem to have a member named graphView.

This check looks for calls to members that are non-existent. These calls will fail.

The member could have been renamed or removed.

Loading history...
181
182
    def newConfigFile(self):
183
        self.graphView.reset()
0 ignored issues
show
Bug introduced by
The Instance of ConfigMainWindow does not seem to have a member named graphView.

This check looks for calls to members that are non-existent. These calls will fail.

The member could have been renamed or removed.

Loading history...
184
        self.configFileName = 'New configuration'
185
        self.updateWindowTitle(self.configFileName, extra='*')
186
187
    def saveConfigFile(self):
188
        if os.path.isfile(self.currentFile):
189
            config = self.nodesToConfig()
190
            core.config.save(self.currentFile, config)
0 ignored issues
show
Bug introduced by
The Module core does not seem to have a member named config.

This check looks for calls to members that are non-existent. These calls will fail.

The member could have been renamed or removed.

Loading history...
191
        else:
192
             self.saveConfigFileAs()
193
194
    def saveConfigFileAs(self):
195
        defaultconfigpath = os.path.dirname(self.currentFile)
196
        filename = QtWidgets.QFileDialog.getSaveFileName(
197
            self,
198
            'Save Configration As',
199
            defaultconfigpath ,
200
            'Configuration files (*.cfg)')[0]
201
        if len(filename) > 0:
202
            print('Save:', filename)
203
            config = self.nodesToConfig()
204
            core.config.save(filename, config)
0 ignored issues
show
Bug introduced by
The Module core does not seem to have a member named config.

This check looks for calls to members that are non-existent. These calls will fail.

The member could have been renamed or removed.

Loading history...
205
            self.currentFile = filename
206
207
    def updateWindowTitle(self, filename, extra=''):
208
        self.setWindowTitle('{}{} - Qudi configuration editor'.format(filename, extra))
0 ignored issues
show
Bug introduced by
The Instance of ConfigMainWindow does not seem to have a member named setWindowTitle.

This check looks for calls to members that are non-existent. These calls will fail.

The member could have been renamed or removed.

Loading history...
209
210
    def configToNodes(self, config):
211
        self.addNodes(config)
212
        self.connectNodes(config)
213
214
    def addNodes(self, config):
215
        pos = [0, 0]
216
        for base, conf_modules in config.items():
217
            if base not in ['hardware', 'logic', 'gui']:
218
                continue
219
            for mod_conf_name, mod_conf_values in conf_modules.items():
220
                mc = 'module.Class'
221
                #print(base, mod_conf_name, mod_conf_values)
222
                if mc in mod_conf_values and self.mmroot.hasModule(base + '.' + mod_conf_values[mc]):
223
                    mod = self.mmroot.getModule(base + '.' + mod_conf_values[mc])
224
                    self.addModule(mod, mod_conf_name, pos)
225
                pos[1] += 100
226
            pos[0] += 600
227
            pos[1] = 0
228
229
    def connectNodes(self, config):
230
        for base, conf_modules in config.items():
231
            if base not in ['hardware', 'logic', 'gui']:
232
                continue
233
            for conf_mod_name, conf_mod_values in conf_modules.items():
234
                if 'connect' in conf_mod_values:
235
                    dst_mod_name = conf_mod_name
236
                    for conn_in, conn_out in conf_mod_values['connect'].items():
237
                        src_mod_name = conn_out
238
                        if conf_mod_name not in self.modnodes:
239
                            self.log.error(
240
                                'Target module {} not present while connecting {} to {}'
241
                                ''.format(dst_mod_name, conn_in, src_mod_name))
242
                            continue
243
                        conn_names_dst = [c.name for cn, c in self.modnodes[dst_mod_name].module.connections.items()]
244
                        if conn_in not in conn_names_dst:
245
                            self.log.error(
246
                                'Target connector {} not present while connecting {} to {}.{}'
247
                                ''.format(conn_in, src_mod_name, dst_mod_name, conn_in))
248
                            continue
249
                        if src_mod_name not in self.modnodes:
250
                            self.log.error(
251
                                'Source module {} not present while connecting it to {}.{}'
252
                                ''.format(src_mod_name, dst_mod_name, conn_in))
253
                            continue
254
255
                        try:
256
                            self.graphView.connectPorts(
0 ignored issues
show
Bug introduced by
The Instance of ConfigMainWindow does not seem to have a member named graphView.

This check looks for calls to members that are non-existent. These calls will fail.

The member could have been renamed or removed.

Loading history...
257
                                self.modnodes[src_mod_name].node,
258
                                'out',
259
                                self.modnodes[dst_mod_name].node,
260
                                conn_in)
261
                        except:
262
                            self.log.exception(
263
                                'pyflowgraph failed while connecting {} to {}.{}'
264
                                ''.format(src_mod_name, dst_mod_name, conn_in))
265
266
        self.globalsection = config['global']
267
268
    def nodesToConfig(self):
269
        """ Convert nodes into OrderedDict for saving.
270
        """
271
        config = OrderedDict()
272
        config['global'] = OrderedDict()
273
        config['hardware'] = OrderedDict()
274
        config['logic'] = OrderedDict()
275
        config['gui'] = OrderedDict()
276
277
        for key, value in self.globalsection.items():
278
            config['global'][key] = value
279
280
        for mod_name, mod in self.modnodes.items():
281
            entry = OrderedDict()
282
            path = mod.module.path.split('.')
283
284
            if len(path) > 1 and path[0] in ('hardware', 'logic', 'gui'):
285
                config[path[0]][mod_name] = entry
286
                entry['module.Class'] = '.'.join(path[1:])
287
288
                portin = (mod.node.getPort(x[0]) for x in mod.module.conn)
289
                conndict = OrderedDict()
290
                for port in portin:
291
                    conns = port.inCircle().getConnections()
292
                    if len(conns) == 1:
293
                        c = tuple(conns)[0]
294
                        src = c.getSrcPort()
295
                        node = src.getNode()
296
                        conndict[port.getName()] = '{}.{}'.format(node.getName(), src.getName())
297
                if len(conndict) > 0:
298
                    entry['connect'] = conndict
299
                # FIXME: rest of the configuration
300
            print(entry)
301
        return config
302
303
    def nodeAdded(self, node):
304
        pass
305
306
    def nodeRemoved(self, node):
307
        pass
308
309
    def nodeNameChanged(self, oldName, newName):
310
        if oldName == newName:
311
            return
312
313
        modnode = self.modnodes.pop(oldName)
314
        if newName in self.modnodes:
315
            newName = newName + '2'
316
        self.modnodes[newName] = modnode
317
318
    @QtCore.Slot(list, list)
319
    def selectedNodesChanged(self, oldSelection, newSelection):
0 ignored issues
show
Unused Code introduced by
The argument oldSelection seems to be unused.
Loading history...
320
        if len(newSelection) > 0:
321
            self.setConfigEditor(newSelection[0])
322
323
    def setConfigEditor(self, node):
324
            name = node.getName()
325
            modnode = self.modnodes[name]
326
            try:
327
                self.nameLineEdit.textEdited.disconnect()
0 ignored issues
show
Bug introduced by
The Instance of ConfigMainWindow does not seem to have a member named nameLineEdit.

This check looks for calls to members that are non-existent. These calls will fail.

The member could have been renamed or removed.

Loading history...
328
            except:
329
                pass
0 ignored issues
show
Unused Code introduced by
This except handler seems to be unused and could be removed.

Except handlers which only contain pass and do not have an else clause can usually simply be removed:

try:
    raises_exception()
except:  # Could be removed
    pass
Loading history...
330
            self.nameLineEdit.setText(name)
0 ignored issues
show
Bug introduced by
The Instance of ConfigMainWindow does not seem to have a member named nameLineEdit.

This check looks for calls to members that are non-existent. These calls will fail.

The member could have been renamed or removed.

Loading history...
331
            self.nameLineEdit.textEdited.connect(modnode.node.setName)
0 ignored issues
show
Bug introduced by
The Instance of ConfigMainWindow does not seem to have a member named nameLineEdit.

This check looks for calls to members that are non-existent. These calls will fail.

The member could have been renamed or removed.

Loading history...
332
            self.mcLabel.setText(modnode.module.path)
0 ignored issues
show
Bug introduced by
The Instance of ConfigMainWindow does not seem to have a member named mcLabel.

This check looks for calls to members that are non-existent. These calls will fail.

The member could have been renamed or removed.

Loading history...
333
            self.tableView.setModel(modnode.cfgmodel)
0 ignored issues
show
Bug introduced by
The Instance of ConfigMainWindow does not seem to have a member named tableView.

This check looks for calls to members that are non-existent. These calls will fail.

The member could have been renamed or removed.

Loading history...
334
            self.tableView.resizeColumnsToContents()
0 ignored issues
show
Bug introduced by
The Instance of ConfigMainWindow does not seem to have a member named tableView.

This check looks for calls to members that are non-existent. These calls will fail.

The member could have been renamed or removed.

Loading history...
335
336
337
if __name__ == "__main__":
338
    parser = argparse.ArgumentParser(prog='config_gui')
339
    parser.add_argument('-c', '--config', default=None, help='configuration file')
340
    args = parser.parse_args()
341
342
    app = QtWidgets.QApplication(sys.argv)
343
    mw = ConfigMainWindow(loadfile=args.config)
344
    app.exec_()
345
346