def __init__(self, parent, client, **settings): QMainWindow.__init__(self, parent) self.client = client self.setWindowTitle(' ') # window title is unnecessary flags = self.windowFlags() flags |= Qt.WindowStaysOnTopHint flags ^= Qt.WindowMinimizeButtonHint self.setWindowFlags(flags) self.sgroup = SettingGroup('EstopTool') with self.sgroup as settings: self.restoreGeometry(settings.value('geometry', '', QByteArray)) icon = QIcon(':/estop') icon.addFile(':/estopdown', mode=QIcon.Active) self.btn = PicButton(icon, self) widget = QWidget(self) layout = QHBoxLayout() layout.addWidget(self.btn) layout.setContentsMargins(3, 3, 3, 3) widget.setLayout(layout) self.setCentralWidget(widget) self.btn.clicked.connect(self.dostop) self.setFixedSize(self.minimumSize()) self.show()
def loadNicosData(self): while self.topLevelItemCount() > 0: self.takeTopLevelItem(0) # list of topLevelItems representing the directories in # nicos_*: for example instruments, ... self.topLevelItems = [] for directory in setupcontroller.setup_directories: self.topLevelItems.append( QTreeWidgetItem([directory], ItemTypes.Directory)) self.addTopLevelItems(self.topLevelItems) # ask the controller to return the setups for current directory # add the setups as childitems for setup_directory in self.topLevelItems: # directories can neither be dragged nor have something dropped on setup_directory.setFlags(setup_directory.flags() & ~Qt.ItemIsDragEnabled & ~Qt.ItemIsDropEnabled) setup_directory.setIcon( 0, QIcon(path.join(getResDir(), 'folder.png'))) for setup in setupcontroller.setup_directories[ setup_directory.text(0)]: treeWidgetItem = QTreeWidgetItem([setup.name], ItemTypes.Setup) # scripts cannot be dragged, but they can have # something dropped on them (a device). treeWidgetItem.setFlags(treeWidgetItem.flags() & ~Qt.ItemIsDragEnabled) treeWidgetItem.setIcon( 0, QIcon(path.join(getResDir(), 'setup.png'))) treeWidgetItem.setup = setup setup_directory.addChild(treeWidgetItem) # setup for this directory has been loaded, add the devices. currentIndex = 0 while currentIndex < setup_directory.childCount(): currentItem = setup_directory.child(currentIndex) setup = currentItem.setup devices = setup.devices.keys() for device in devices: # read setup and add all the devices as child tree items deviceItem = QTreeWidgetItem([device], ItemTypes.Device) # devices can be dragged, but they can't have something # dropped on them. deviceItem.setFlags(deviceItem.flags() & ~Qt.ItemIsDropEnabled) deviceItem.device = setup.devices[device] currentItem.addChild(deviceItem) # icons for all devices deviceIndex = 0 while deviceIndex < currentItem.childCount(): currentItem.child(deviceIndex).setIcon( 0, QIcon(path.join(getResDir(), 'device.png'))) deviceIndex += 1 currentIndex += 1 self.setSortingEnabled(True) self.sortByColumn(0, Qt.AscendingOrder)
def __init__(self, parent, client, **configs): QDialog.__init__(self, parent) DlgUtils.__init__(self, self.toolName) loadUi(self, 'tools/downtime.ui') self.sendBtn = self.buttonBox.addButton('&Send', QDialogButtonBox.AcceptRole) self.sendBtn.setIcon(QIcon(':/mail')) self.sendBtn.setDisabled(True) self.parentwindow = parent self.client = client if hasattr(parent, 'mainwindow'): self.mainwindow = parent.mainwindow self.log = NicosLogger(self.toolName) self.log.parent = self.mainwindow.log else: self.log = configs.get('log', None) self.sgroup = SettingGroup(self.toolName) self._sender = configs.get('sender', '*****@*****.**') self._receiver = configs.get('receiver', '*****@*****.**') self._mailserver = configs.get('mailserver', '') or \ self._getDeviceComponent('experiment', 'mailserver', 'smtp.frm2.tum.de') self._instrument = configs.get('instrument', '') or \ self._getDeviceComponent('instrument', 'instrument', 'DEMO') t = self.mailheaderText.text().replace('{{instrument}}', self._instrument) self.mailheaderText.setText(t) self.startDown.setDateTime(QDateTime.currentDateTime().addSecs(-3600)) self.endDown.setDateTime(QDateTime.currentDateTime()) self.errorText.setVisible(False) with self.sgroup as settings: self.loadSettings(settings) self.reasons.clearEditText()
def createWindow(self, wtype): # for the history_wintype or editor_wintype if wtype == -1: return self try: wconfig = self.gui_conf.windows[wtype] except IndexError: # config outdated, window type doesn't exist return if wtype in self.windows: window = self.windows[wtype] window.activateWindow() return window window = AuxiliaryWindow(self, wtype, wconfig) if window.centralLayout.count(): window.setWindowIcon(QIcon(':/' + wconfig.icon)) self.windows[wtype] = window window.closed.connect(self.on_auxWindow_closed) for panel in window.panels: panel.updateStatus(self.current_status) window.show() return window else: del window return None
def newDeviceAddedSlot(self, deviceName, _classString): setupItem = self.getCurrentSetupItem() if setupItem.setup.abspath not in self.setupWidgets.keys(): self.loadSetup(setupItem.setup, setupItem.parent().text(0)) uncombinedModule = _classString.split('.') classname = uncombinedModule.pop() module = '.'.join(uncombinedModule) classes = inspect.getmembers(classparser.modules[module], predicate=inspect.isclass) _class = [_class[1] for _class in classes if _class[0] == classname][0] parameters = { key: '' for key in _class.parameters.keys() if _class.parameters[key].mandatory is True } device = setupcontroller.Device(deviceName, _classString, parameters=parameters) setupItem.setup.devices[deviceName] = device deviceWidget = DeviceWidget(self.setupWidgets[setupItem.setup.abspath]) deviceWidget.editedDevice.connect(self.editedSetupSlot) deviceWidget.loadDevice(device) self.workarea.addWidget(deviceWidget) self.deviceWidgets[setupItem.setup.abspath][deviceName] = deviceWidget deviceItem = QTreeWidgetItem([deviceName], ItemTypes.Device) deviceItem.setFlags(deviceItem.flags() & ~Qt.ItemIsDropEnabled) deviceItem.device = setupItem.setup.devices[deviceName] deviceItem.setIcon(0, QIcon(path.join(getResDir(), 'device.png'))) setupItem.insertChild(0, deviceItem) self.treeWidget.itemActivated.emit(deviceItem, 0) if not setupItem.setup.edited: setupItem.setText(0, '*' + setupItem.text(0)) setupItem.setup.edited = True
def doInit(self, mode): CICacheClient.doInit(self, self._mode) self._qtapp = QApplication(sys.argv) self._qtapp.setOrganizationName('nicos') self._qtapp.setApplicationName('cacheinspector') self._window = MainWindow(self) self._window.setWindowIcon(QIcon(':/inspector')) session._qthandler.setStatusbar(self._window.statusBar())
def _create_device_item(self, devname, add_cat=False): ldevname = devname.lower() # get all cache keys pertaining to the device params = self.client.getDeviceParams(devname) if not params: return lowlevel_device = params.get('lowlevel') or False if lowlevel_device and not self._show_lowlevel: return if 'nicos.core.data.sink.DataSink' in params.get('classes', []) and \ not self._show_lowlevel: return # remove still-existing previous item for the same device name if ldevname in self._devitems: self.on_client_device(('destroy', [devname])) cat = self._dev2setup.get(devname) if cat is None: # device is not in any setup? reread setup info self._read_setup_info() cat = self._dev2setup.get(devname) if cat is None: # still not there -> give up return if cat not in self._catitems: display_order = self._setupinfo[cat].get('display_order', 50) representative = self._setupinfo[cat].get('extended', {}).get( 'representative', '').lower() catitem = SetupTreeWidgetItem(cat, display_order, representative) catitem.setToolTip(0, self._setupinfo[cat].get('description', '')) f = catitem.font(0) f.setBold(True) catitem.setFont(0, f) catitem.setIcon(0, QIcon(':/setup')) self._catitems[cat] = catitem if add_cat: self.tree.addTopLevelItem(catitem) catitem.setExpanded(True) else: catitem = self._catitems[cat] # create a tree node for the device devitem = QTreeWidgetItem(catitem, [devname, '', ''], DEVICE_TYPE) devitem.setForeground(0, lowlevelBrush[lowlevel_device]) devitem.setFont(0, lowlevelFont[lowlevel_device]) if self.useicons: devitem.setIcon(0, self.statusIcon[OK]) devitem.setToolTip(0, params.get('description', '')) self._devitems[ldevname] = devitem # fill the device info with dummy values, will be populated below self._devinfo[ldevname] = DevInfo(devname) # let the cache handler process all properties for key, value in iteritems(params): self.on_client_cache( (0, ldevname + '/' + key, OP_TELL, cache_dump(value)))
def __init__(self, parent, connpresets, lastpreset, lastdata, tunnel=''): QDialog.__init__(self, parent) loadUi(self, 'dialogs/auth.ui') self.connpresets = connpresets if isinstance(lastpreset, QPyNullVariant): lastpreset = None pal = self.quickList.palette() pal.setColor(QPalette.Window, pal.color(QPalette.Base)) self.quickList.setPalette(pal) if len(connpresets) < 3: self.quickList.hide() else: self.quickList.setStyleSheet('padding: 10px 5px;') self.quickList.clear() maxw = 64 icon = QIcon(':/appicon') metric = QFontMetrics(self.quickList.font()) for preset in sorted(connpresets): item = QListWidgetItem(preset, self.quickList) item.setIcon(icon) maxw = max(maxw, metric.width(preset)) self.quickList.setGridSize(QSize(maxw + 8, 72)) # the automatic sizing still leads to a vertical scrollbar hint = self.quickList.sizeHint() hint.setHeight(hint.height() + 50) hint.setWidth(max(4.7 * maxw, 330)) self.quickList.setMinimumSize(hint) self.resize(self.sizeHint()) self.presetOrAddr.addItems(sorted(connpresets)) self.presetOrAddr.setEditText(lastpreset) if not lastpreset and lastdata: # if we have no stored last preset connection, put in the raw data self.presetOrAddr.setEditText('%s:%s' % (lastdata.host, lastdata.port)) self.viewonly.setChecked(lastdata.viewonly) self.userName.setText(lastdata.user) self.password.setFocus() self.viaFrame.setHidden(not tunnel) if tunnel: host, username, password = splitTunnelString(tunnel) self.remotePassword.setText(password) if not password: self.remotePassword.setFocus() self.remoteUserName.setText(username) if not username: self.remoteUserName.setFocus() self.remoteHost.setText(host) if not host: self.remoteHost.setFocus() self.presetFrame.hide() self.resize(QSize(self.width(), self.minimumSize().height()))
def setStatus(self, status, exception=False): if status == self.current_status: return if self.client.last_action_at and \ self.current_status == 'running' and \ status in ('idle', 'paused') and \ current_time() - self.client.last_action_at > 20: # show a visual indication of what happened if status == 'paused': msg = 'Script is now paused.' elif exception: msg = 'Script has exited with an error.' else: msg = 'Script has finished.' self.trayIcon.showMessage(self.instrument, msg) self.client.last_action_at = 0 self.current_status = status is_connected = status != 'disconnected' if is_connected: self.actionConnect.setText('Disconnect') self.statusLabel.setText('\u2713 Connected') self.update_instrument_text() self.update_experiment_text() else: self.actionConnect.setText('Connect to server...') self.statusLabel.setText('Disconnected') self.setTitlebar(False) # new status icon pixmap = QPixmap(':/' + status + ('exc' if exception else '')) new_icon = QIcon() new_icon.addPixmap(pixmap, QIcon.Disabled) self.trayIcon.setIcon(new_icon) self.trayIcon.setToolTip('%s status: %s' % (self.instrument, status)) if self.showtrayicon: self.trayIcon.show() if self.promptWindow and status != 'paused': self.promptWindow.close() # propagate to panels for panel in self.panels: panel.updateStatus(status, exception) for window in self.windows.values(): for panel in window.panels: panel.updateStatus(status, exception)
def _createIcons(cls): # hack to make non-Qt usage as in checksetups work if not hasattr(cls, 'statusIcon'): cls.statusIcon = { OK: QIcon(':/leds/status_green'), WARN: QIcon(':/leds/status_warn'), BUSY: QIcon(':/leds/status_yellow'), NOTREACHED: QIcon(':/leds/status_red'), DISABLED: QIcon(':/leds/status_white'), ERROR: QIcon(':/leds/status_red'), UNKNOWN: QIcon(':/leds/status_unknown'), }
def insertItem(self, *widgets): item = QWidget(self.frame) item._widgets = widgets layout = QHBoxLayout() layout.setContentsMargins(0, 0, 0, 0) for widget in widgets: layout.addWidget(widget) if self.allow_reorder: btn = QPushButton(QIcon(':/up'), '', item) btn._item = item btn.clicked.connect(self.on_upBtn_clicked) layout.addWidget(btn) btn = QPushButton(QIcon(':/down'), '', item) btn._item = item btn.clicked.connect(self.on_downBtn_clicked) layout.addWidget(btn) btn = QPushButton(QIcon(':/remove'), '', item) btn._item = item btn.clicked.connect(self.on_removeBtn_clicked) layout.addWidget(btn) item.setLayout(layout) self.layout.insertWidget(self.layout.count() - 2, item) self.items.append(item)
def _newSetup(self, instrument=None): dlg = NewSetupDialog([ item.text(0) for item in self.topLevelItems if item.type() == ItemTypes.Directory ], instrument) if dlg.exec_(): fileName = dlg.getValue() if not fileName: QMessageBox.warning(self, 'Error', 'No setup name entered.') return None, None if not fileName.endswith('.py'): fileName += '.py' if dlg.isSpecialSetup(): abspath = path.join(getNicosDir(), 'nicos_mlz', dlg.currentInstrument(), 'setups', 'special', fileName) else: abspath = path.join(getNicosDir(), 'nicos_mlz', dlg.currentInstrument(), 'setups', fileName) if abspath in [ i.abspath for i in setupcontroller.setup_directories[ dlg.currentInstrument()] ]: QMessageBox.warning(self, 'Error', 'Setup already exists!') return None, None try: open(abspath, 'w', encoding='utf-8').close() except OSError: QMessageBox.warning(self, 'Error', 'Could not create new ' 'setup!') return None, None setupcontroller.addSetup(dlg.currentInstrument(), abspath) newSetup = None for setup in setupcontroller.setup_directories[ dlg.currentInstrument()]: if setup.abspath == abspath: newSetup = setup treeWidgetItem = QTreeWidgetItem(['*' + newSetup.name], ItemTypes.Setup) treeWidgetItem.setFlags(treeWidgetItem.flags() & ~Qt.ItemIsDragEnabled) treeWidgetItem.setIcon(0, QIcon(path.join(getResDir(), 'setup.png'))) treeWidgetItem.setup = newSetup treeWidgetItem.setup.edited = True return treeWidgetItem, dlg.currentInstrument() return None, None
def __init__(self, parent, client): uipath = findResource('nicos_ess/loki/gui/ui_files/table.ui') Cmdlet.__init__(self, parent, client, uipath) self.measdef = self.meas_def_class() self.updateTable() for loop in LOOPS: self.outerLoop.addItem(loop) self.outerLoop.setCurrentIndex(0) client.experiment.connect(self.on_client_experiment) self.expandBtn = QToolButton() self.expandBtn.setIcon(QIcon(':/down')) self.expandBtn.setAutoRaise(True) self.expandBtn.clicked.connect(self.on_expandBtn_clicked) self.table.setCornerWidget(self.expandBtn)
def createWindowContent(self): self.sgroup = SettingGroup('MainWindow') with self.sgroup as settings: loadUserStyle(self, settings) # load saved settings and stored layout for panel config self.loadSettings(settings) # create panels in the main window widget = createWindowItem(self.gui_conf.main_window, self, self, self, self.log) if widget: self.centralLayout.addWidget(widget) self.centralLayout.setContentsMargins(0, 0, 0, 0) # call postInit after creation of all panels for panel in self.panels: panel.postInit() with self.sgroup as settings: # geometry and window appearance loadBasicWindowSettings(self, settings) self.update() # load auxiliary windows state self.loadAuxWindows(settings) if len(self.splitstate) == len(self.splitters): for sp, st in zip(self.splitters, self.splitstate): sp.restoreState(st) if not self.gui_conf.windows: self.menuBar().removeAction(self.menuWindows.menuAction()) for i, wconfig in enumerate(self.gui_conf.windows): action = ToolAction(self.client, QIcon(':/' + wconfig.icon), wconfig.name, wconfig.options, self) self.toolBarWindows.addAction(action) self.menuWindows.addAction(action) def window_callback(on, i=i): self.createWindow(i) action.triggered[bool].connect(window_callback) if not self.gui_conf.windows: self.toolBarWindows.hide() else: self.toolBarWindows.show() createToolMenu(self, self.gui_conf.tools, self.menuTools) if isinstance(self.gui_conf.main_window, tabbed) and widget: widget.tabChangedTab(0)
def __init__(self, parent, client): uipath = findResource('nicos_mlz/kws1/gui/table.ui') Cmdlet.__init__(self, parent, client, uipath) self.measdef = self.meas_def_class(rtmode=False) self.rt_settings = RtConfigDialog.DEFAULT_SETTINGS.copy() self.rtConfBtn.setEnabled(False) self.updateTable() for loop in LOOPS: self.outerLoop.addItem(loop) self.outerLoop.setCurrentIndex(0) client.experiment.connect(self.on_client_experiment) self.expandBtn = QToolButton() self.expandBtn.setIcon(QIcon(':/down')) self.expandBtn.setAutoRaise(True) self.expandBtn.clicked.connect(self.on_expandBtn_clicked) self.table.setCornerWidget(self.expandBtn)
def dropEvent(self, event): """ To satisfy Qt, a call to TreeWidgetContextMenu.dropEvent is neccessary. Else, the animation would look really gross and suggest the object might actually not have been copied. But after the call, the newly appended child item seems to be completely useless: It carries neither data nor does it emit the treeWidget's itemActivated signal. This may be a bug or my inability to find what's wrong. Because of that, I need to construct my own item, find the old one and replace it with my new one. """ target = self.getSetupOfDropPos(event.pos()) if self.dragItem.device.name in target.setup.devices.keys(): QMessageBox.warning( self, 'Error', 'The target setup already ' 'contains a device with that name!') self.dragItem = None event.ignore() return count = 0 previousItems = [] while count < target.childCount(): previousItems.append(target.child(count)) count += 1 TreeWidgetContextMenu.dropEvent(self, event) count = 0 afterDropItems = [] while count < target.childCount(): afterDropItems.append(target.child(count)) count += 1 newItem = None for child in afterDropItems: if child not in previousItems: newItem = child index = target.indexOfChild(newItem) target.takeChild(index) deviceName = self.dragItem.device.name target.setup.devices[deviceName] = deepcopy(self.dragItem.device) deviceItem = QTreeWidgetItem([deviceName], ItemTypes.Device) deviceItem.setFlags(deviceItem.flags() & ~Qt.ItemIsDropEnabled) deviceItem.device = target.setup.devices[deviceName] deviceItem.setIcon(0, QIcon(path.join(getResDir(), 'device.png'))) target.insertChild(index, deviceItem) self.deviceAdded.emit(target, deviceName) self.itemActivated.emit(deviceItem, 0)
def __init__(self, parent, nmin, allow_enter=False): QScrollArea.__init__(self, parent) self.setWidgetResizable(True) self.frame = QFrame(self) self.layout = QVBoxLayout() self.layout.setContentsMargins(2, 2, 2, 2) self.addBtn = QPushButton(QIcon(':/add'), '', self.frame) self.addBtn.clicked.connect(self.on_addBtn_clicked) self.addBtn.setSizePolicy( QSizePolicy(QSizePolicy.Fixed, QSizePolicy.Preferred)) self.layout.addWidget(self.addBtn) self.layout.addStretch() self.frame.setLayout(self.layout) self.setWidget(self.frame) self.items = [] self.nmin = nmin self.allow_enter = allow_enter
def __init__(self, parent, client, options): Panel.__init__(self, parent, client, options) loadUi(self, findResource('nicos_demo/demo/gui/sanspanel.ui')) self.current_status = None self._idle = QColor('#99FF99') self._busy = QColor(Qt.yellow) self.statusBar = QStatusBar(self) policy = self.statusBar.sizePolicy() policy.setVerticalPolicy(QSizePolicy.Fixed) self.statusBar.setSizePolicy(policy) self.statusBar.setSizeGripEnabled(False) self.layout().addWidget(self.statusBar) client.cache.connect(self.on_client_cache) run = self.buttonBox.button(QDialogButtonBox.Yes) run.setText('Run') run.setIcon(QIcon(':/continue')) self.buttonBox.accepted.connect(self.on_start_clicked)
def __init__(self): self._reconfiguring = False QMainWindow.__init__(self) # set app icon in multiple sizes icon = QIcon() icon.addFile(':/appicon') icon.addFile(':/appicon-16') icon.addFile(':/appicon-48') self.setWindowIcon(icon) self.keyChange.connect(lambda obj, args: obj.on_keyChange(*args)) self.reconfigure.connect(self.do_reconfigure) self.sgroup = SettingGroup('Monitor') with self.sgroup as settings: # geometry and window appearance loadBasicWindowSettings(self, settings)
def __init__(self, reason, parent=None): QDialog.__init__(self, parent) loadUi(self, 'dialogs/instr_select.ui') icon = QIcon(':/appicon-16') if reason: self.reasonLbl.setText(reason) else: self.reasonLbl.hide() self.saveBox.hide() self.confTree.itemDoubleClicked.connect(self.handleDoubleClick) for entry in sorted(os.listdir(config.nicos_root)): full = path.join(config.nicos_root, entry) if not (entry.startswith('nicos_') and path.isdir(full)): continue pkgitem = QTreeWidgetItem(self.confTree, [entry]) pkgitem.setIcon(0, icon) for subentry in sorted(os.listdir(full)): configfile = path.join(full, subentry, 'guiconfig.py') if not path.isfile(configfile): continue item = QTreeWidgetItem(pkgitem, [subentry]) item.setData(0, QTreeWidgetItem.UserType, configfile)
def groupIcon(self): return QIcon(':/setup')
def get_icon(icon_name): return QIcon(path.join(icons_path, icon_name))
def __init__(self, log, gui_conf, viewonly=False, tunnel=''): QMainWindow.__init__(self) DlgUtils.__init__(self, 'NICOS') loadUi(self, self.ui) # set app icon in multiple sizes icon = QIcon() icon.addFile(':/appicon') icon.addFile(':/appicon-16') icon.addFile(':/appicon-48') self.setWindowIcon(icon) if tunnel and SSHTunnelForwarder is None: self.showError('You want to establish a connection to NICOS via ' "a SSH tunnel, but the 'sshtunnel' module is not " 'installed. The tunneling feature will disabled.') self.tunnel = tunnel if SSHTunnelForwarder is not None else '' self.tunnelServer = None # hide admin label until we are connected as admin self.adminLabel.hide() # our logger instance self.log = log # window for displaying errors self.errorWindow = None # window for "prompt" event confirmation self.promptWindow = None # debug console window, if opened self.debugConsole = None # log messages sent by the server self.messages = [] # are we in expert mode? (always false on startup) self.expertmode = False # no wrapping at startup self.allowoutputlinewrap = False # set-up the initial connection data self.conndata = ConnectionData(host='localhost', port=1301, user='******', password=None, viewonly=viewonly) # state members self.current_status = None # connect the client's events self.client = NicosGuiClient(self, self.log) self.client.error.connect(self.on_client_error) self.client.broken.connect(self.on_client_broken) self.client.failed.connect(self.on_client_failed) self.client.connected.connect(self.on_client_connected) self.client.disconnected.connect(self.on_client_disconnected) self.client.status.connect(self.on_client_status) self.client.showhelp.connect(self.on_client_showhelp) self.client.clientexec.connect(self.on_client_clientexec) self.client.plugplay.connect(self.on_client_plugplay) self.client.watchdog.connect(self.on_client_watchdog) self.client.prompt.connect(self.on_client_prompt) # data handling setup self.data = DataHandler(self.client) # panel configuration self.gui_conf = gui_conf self.initDataReaders() self.mainwindow = self # determine if there is an editor window type, because we would like to # have a way to open files from a console panel later self.editor_wintype = self.gui_conf.find_panel( ('editor.EditorPanel', 'nicos.clients.gui.panels.editor.EditorPanel')) self.history_wintype = self.gui_conf.find_panel( ('history.HistoryPanel', 'nicos.clients.gui.panels.history.HistoryPanel')) # additional panels self.panels = [] self.splitters = [] self.windowtypes = [] self.windows = {} # setting presets self.instrument = self.gui_conf.name self.createWindowContent() # timer for reconnecting self.reconnectTimer = QTimer(singleShot=True, timeout=self._reconnect) self._reconnect_count = 0 self._reconnect_time = 0 # timer for session keepalive, every 12 hours self.keepaliveTimer = QTimer(singleShot=False, timeout=self._keepalive) self.keepaliveTimer.start(self.keepaliveInterval) # setup tray icon self.trayIcon = QSystemTrayIcon(self) self.trayIcon.activated.connect(self.on_trayIcon_activated) self.trayMenu = QMenu(self) nameAction = self.trayMenu.addAction(self.instrument) nameAction.setEnabled(False) self.trayMenu.addSeparator() toggleAction = self.trayMenu.addAction('Hide main window') toggleAction.setCheckable(True) toggleAction.triggered[bool].connect( lambda hide: self.setVisible(not hide)) self.trayIcon.setContextMenu(self.trayMenu) # help window self.helpWindow = None # watchdog window self.watchdogWindow = None # plug-n-play notification windows self.pnpWindows = {} # create initial state self._init_toolbar()
def icon(self): if self.widget_class.designer_icon is None: return QIcon() return QIcon(self.widget_class.designer_icon)
def _reinit(self): classes = self.devinfo.classes if sip.isdeleted(self.devitem): # The item we're controlling has been removed from the list (e.g. # due to client reconnect), get it again. self.devitem = self.device_panel._devitems.get( self.devname.lower()) # No such device anymore... if self.devitem is None: self.close() return self.deviceName.setText('Device: %s' % self.devname) self.setWindowTitle('Control %s' % self.devname) self.settingsBtn = self.buttonBox.button( QDialogButtonBox.RestoreDefaults) self.settingsBtn.clicked.connect(self.on_settingsBtn_clicked) # trigger parameter poll self.client.eval('%s.pollParams()' % self.devname, None) # now get all cache keys pertaining to the device and set the # properties we want params = self.client.getDeviceParams(self.devname) self.paraminfo = self.client.getDeviceParamInfo(self.devname) self.paramvalues = dict(params) # put parameter values in the list widget self.paramItems.clear() self.paramList.clear() for key, value in sorted(iteritems(params)): if self.paraminfo.get(key): # normally, show only userparams, except in expert mode is_userparam = self.paraminfo[key]['userparam'] if is_userparam or self.device_panel._show_lowlevel: self.paramItems[key] = item = \ QTreeWidgetItem(self.paramList, [key, str(value)]) # display non-userparams in grey italics, like lowlevel # devices in the device list if not is_userparam: item.setFont(0, lowlevelFont[True]) item.setForeground(0, lowlevelBrush[True]) # set description label if params.get('description'): self.description.setText(params['description']) else: self.description.setVisible(False) # check how to refer to the device in commands: if it is lowlevel, # we need to use quotes self.devrepr = srepr(self.devname) if params.get('lowlevel', True) \ else self.devname # show "Set alias" group box if it is an alias device if 'alias' in params: if params['alias']: self.deviceName.setText(self.deviceName.text() + ' (alias for %s)' % params['alias']) alias_config = self.client.eval('session.alias_config', {}) self.aliasTarget = QComboBox(self) self.aliasTarget.setEditable(True) if self.devname in alias_config: items = [t[0] for t in alias_config[self.devname]] self.aliasTarget.addItems(items) if params['alias'] in items: self.aliasTarget.setCurrentIndex( items.index(params['alias'])) self.targetLayoutAlias.takeAt(1).widget().deleteLater() self.targetLayoutAlias.insertWidget(1, self.aliasTarget) if self.client.viewonly: self.setAliasBtn.setEnabled(False) else: self.aliasGroup.setVisible(False) historyBtn = self.buttonBox.button(QDialogButtonBox.Reset) # show current value/status if it is readable if 'nicos.core.device.Readable' not in classes: self.valueFrame.setVisible(False) self.buttonBox.removeButton(historyBtn) else: self.valuelabel.setText(self.devitem.text(1)) self.statuslabel.setText(self.devitem.text(2)) self.statusimage.setPixmap(self.devitem.icon(0).pixmap(16, 16)) setForegroundBrush(self.statuslabel, self.devitem.foreground(2)) setBackgroundBrush(self.statuslabel, self.devitem.background(2)) # modify history button: add icon and set text historyBtn.setIcon(QIcon(':/find')) historyBtn.setText('Plot history...') historyBtn.clicked.connect(self.on_historyBtn_clicked) if self.client.viewonly: self.limitFrame.setVisible(False) self.targetFrame.setVisible(False) return # add a menu for the "More" button self.moveBtns.clear() menu = QMenu(self) if 'nicos.core.mixins.HasLimits' in classes: menu.addAction(self.actionSetLimits) if 'nicos.core.mixins.HasOffset' in classes: menu.addAction(self.actionAdjustOffset) if 'nicos.devices.abstract.CanReference' in classes: menu.addAction(self.actionReference) if 'nicos.devices.abstract.Coder' in classes: menu.addAction(self.actionSetPosition) if 'nicos.core.device.Moveable' in classes: if not menu.isEmpty(): menu.addSeparator() menu.addAction(self.actionFix) menu.addAction(self.actionRelease) if 'nicos.core.mixins.CanDisable' in classes: if not menu.isEmpty(): menu.addSeparator() menu.addAction(self.actionEnable) menu.addAction(self.actionDisable) if not menu.isEmpty(): menuBtn = QPushButton('More', self) menuBtn.setMenu(menu) self.moveBtns.addButton(menuBtn, QDialogButtonBox.ResetRole) def reset(checked): self.device_panel.exec_command('reset(%s)' % self.devrepr) def stop(checked): self.device_panel.exec_command('stop(%s)' % self.devrepr, immediate=True) self.moveBtns.addButton('Reset', QDialogButtonBox.ResetRole)\ .clicked.connect(reset) if 'nicos.core.device.Moveable' in classes or \ 'nicos.core.device.Measurable' in classes: self.moveBtns.addButton('Stop', QDialogButtonBox.ResetRole)\ .clicked.connect(stop) # show target and limits if the device is Moveable if 'nicos.core.device.Moveable' not in classes: self.limitFrame.setVisible(False) self.targetFrame.setVisible(False) else: if 'nicos.core.mixins.HasLimits' not in classes: self.limitFrame.setVisible(False) else: self.limitMin.setText(str(params['userlimits'][0])) self.limitMax.setText(str(params['userlimits'][1])) # insert a widget to enter a new device value # allowEnter=False because we catch pressing Enter ourselves self.target = DeviceValueEdit(self, dev=self.devname, useButtons=True, allowEnter=False) self.target.setClient(self.client) def btn_callback(target): self.device_panel.exec_command('move(%s, %s)' % (self.devrepr, srepr(target))) self.target.valueChosen.connect(btn_callback) self.targetFrame.layout().takeAt(1).widget().deleteLater() self.targetFrame.layout().insertWidget(1, self.target) def move(checked): try: target = self.target.getValue() except ValueError: return self.device_panel.exec_command('move(%s, %s)' % (self.devrepr, srepr(target))) if self.target.getValue() is not Ellipsis: # (button widget) self.moveBtn = self.moveBtns.addButton( 'Move', QDialogButtonBox.AcceptRole) self.moveBtn.clicked.connect(move) else: self.moveBtn = None if params.get('fixed') and self.moveBtn: self.moveBtn.setEnabled(False) self.moveBtn.setText('(fixed)')
def __init__(self, parent, client, options): Panel.__init__(self, parent, client, options) loadUi(self, 'panels/status.ui') self.stopcounting = False self.menus = None self.bar = None self.queueFrame.hide() self.statusLabel.hide() self.pause_color = QColor('#ffdddd') self.idle_color = parent.user_color self.script_queue = ScriptQueue(self.queueFrame, self.queueView) self.current_line = -1 self.current_request = {} self.curlineicon = QIcon(':/currentline') self.errlineicon = QIcon(':/errorline') empty = QPixmap(16, 16) empty.fill(Qt.transparent) self.otherlineicon = QIcon(empty) self.traceView.setItemDelegate(LineDelegate(24, self.traceView)) self.stopcounting = bool(options.get('stopcounting', False)) if self.stopcounting: tooltip = 'Aborts the current executed script' self.actionStop.setToolTip(tooltip) self.actionStop.setText('Abort current script') self.actionStop2.setToolTip(tooltip) self.showETA = bool(options.get('eta', False)) self.etaWidget.hide() client.request.connect(self.on_client_request) client.processing.connect(self.on_client_processing) client.blocked.connect(self.on_client_blocked) client.status.connect(self.on_client_status) client.initstatus.connect(self.on_client_initstatus) client.disconnected.connect(self.on_client_disconnected) client.rearranged.connect(self.on_client_rearranged) client.updated.connect(self.on_client_updated) client.eta.connect(self.on_client_eta) bar = QToolBar('Script control') bar.setObjectName(bar.windowTitle()) # unfortunately it is not wise to put a menu in its own dropdown menu, # so we have to duplicate the actionBreak and actionStop... dropdown1 = QMenu('', self) dropdown1.addAction(self.actionBreak) dropdown1.addAction(self.actionBreakCount) dropdown1.addAction(self.actionFinishEarly) self.actionBreak2.setMenu(dropdown1) dropdown2 = QMenu('', self) dropdown2.addAction(self.actionStop) dropdown2.addAction(self.actionFinish) dropdown2.addAction(self.actionFinishEarlyAndStop) self.actionStop2.setMenu(dropdown2) bar.addAction(self.actionBreak2) bar.addAction(self.actionContinue) bar.addAction(self.actionStop2) bar.addAction(self.actionEmergencyStop) self.bar = bar # self.mainwindow.addToolBar(bar) menu = QMenu('&Script control', self) menu.addAction(self.actionBreak) menu.addAction(self.actionBreakCount) menu.addAction(self.actionContinue) menu.addAction(self.actionFinishEarly) menu.addSeparator() menu.addAction(self.actionStop) menu.addAction(self.actionFinish) menu.addAction(self.actionFinishEarlyAndStop) menu.addSeparator() menu.addAction(self.actionEmergencyStop) self.mainwindow.menuBar().insertMenu( self.mainwindow.menuWindows.menuAction(), menu) self.activeGroup = QActionGroup(self) self.activeGroup.addAction(self.actionBreak) self.activeGroup.addAction(self.actionBreak2) self.activeGroup.addAction(self.actionBreakCount) self.activeGroup.addAction(self.actionContinue) self.activeGroup.addAction(self.actionStop) self.activeGroup.addAction(self.actionStop2) self.activeGroup.addAction(self.actionFinish) self.activeGroup.addAction(self.actionFinishEarly) self.activeGroup.addAction(self.actionFinishEarlyAndStop) self._status = 'idle'
def on_client_disconnected(self): DefaultMainWindow.on_client_disconnected(self) self.actionConnect.setIcon( QIcon("resources/material/icons/power-24px.svg"))