Пример #1
0
    def closeEvent(self, event):
        if self.confirmexit and QMessageBox.question(
                self, 'Quit', 'Do you really want to quit?',
                QMessageBox.Yes | QMessageBox.No) == QMessageBox.No:
            event.ignore()
            return

        for panel in self.panels:
            if not panel.requestClose():
                event.ignore()
                return

        if self.autosavelayout:
            self.saveWindowLayout()
        with self.sgroup as settings:
            self.saveSettings(settings)
        for panel in self.panels:
            with panel.sgroup as settings:
                panel.saveSettings(settings)

        for window in list(self.windows.values()):
            if not window.close():
                event.ignore()
                return

        if self.helpWindow:
            self.helpWindow.close()

        if self.client.isconnected:
            self.on_actionConnect_triggered(False)

        event.accept()
        QApplication.instance().quit()
Пример #2
0
    def _handle_table_paste(self):
        indices = []
        for index in self.tableView.selectedIndexes():
            indices.append((index.row(), index.column()))

        if not indices:
            return
        top_left = indices[0]

        data_type = QApplication.instance().clipboard().mimeData()

        if not data_type.hasText():
            # Don't paste images etc.
            return

        clipboard_text = QApplication.instance().clipboard().text()
        copied_table = extract_table_from_clipboard_text(clipboard_text)

        if len(copied_table) == 1 and len(copied_table[0]) == 1:
            # Only one value, so put it in all selected cells
            self._do_bulk_update(copied_table[0][0])
            return

        self.model.update_data_from_clipboard(
            copied_table, top_left, self._get_hidden_column_indices())
Пример #3
0
 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())
Пример #4
0
 def doInit(self, mode):
     self._qtapp = QApplication(sys.argv)
     self._qtapp.setOrganizationName('nicos')
     self._qtapp.setApplicationName('history')
     self._window = StandaloneHistoryWindow(self)
     # if no cache was given on the command line...
     if not self._config['cache']:
         dlg = SettingsDialog(self._window)
         dlg.exec_()
         self._setROParam('cache', dlg.cacheBox.currentText())
         self._setROParam('prefix', dlg.prefixEdit.text())
     CacheClient.doInit(self, mode)
Пример #5
0
def waitCursor():
    """Context manager creating an hour glass style cursor for longer-running
    blocking tasks inside GUI code.  Example::

        with waitCursor():
            # process takes some time
            pass
    """
    try:
        QApplication.setOverrideCursor(Qt.WaitCursor)
        yield
    finally:
        QApplication.restoreOverrideCursor()
Пример #6
0
 def on_client_connected(self):
     # retrieve datasets and put them into the scans window
     pd = QProgressDialog(labelText='Transferring datasets, please wait...')
     pd.setRange(0, 1)
     pd.setCancelButton(None)
     pd.show()
     QApplication.processEvents()
     datasets = self.client.ask('getdataset', '*', default=[])
     self.bulk_adding = True
     for dataset in (datasets or []):
         try:
             self.on_client_dataset(dataset)
         except Exception:
             from nicos.clients.gui.main import log
             log.error('Error adding dataset', exc=1)
     self.bulk_adding = False
     pd.setValue(1)
     pd.close()
Пример #7
0
 def event(self, event):
     if self._reconfiguring and event.type() == 76:  # LayoutRequest
         self._reconfiguring = False
         # always resize first; works around layout bugs where the full
         # screen window is actually made larger than the full screen
         self.resize(self.sizeHint())
         if self._wantFullScreen:
             self.setGeometry(QApplication.screens()[0].geometry())
     return QMainWindow.event(self, event)
Пример #8
0
 def on_roiItemClicked(self, event):
     if event.getButtons() & MouseEvent.RIGHT_BUTTON:
         if isinstance(event.roi.reference, FitResult):
             menu = QMenu(self)
             actionClipboard = QAction("Copy fit values to clipboard", menu)
             menu.addAction(actionClipboard)
             p0dc = event.getDC()
             selectedItem = menu.exec_(
                 self.mapToGlobal(QPoint(p0dc.x, p0dc.y)))
             if selectedItem == actionClipboard:
                 res = event.roi.reference
                 text = '\n'.join(
                     (n + '\t' if n else '\t') +
                     (v + '\t' if isinstance(v, string_types) else '%g\t' %
                      v) +
                     (dv if isinstance(dv, string_types) else '%g' % dv)
                     for (n, v, dv) in res.label_contents)
                 QApplication.clipboard().setText(text)
Пример #9
0
class StandaloneHistoryApp(CacheClient):

    parameters = {
        'views':
        Param('Strings specifying views (from command line)',
              type=listof(str)),
    }

    def doInit(self, mode):
        self._qtapp = QApplication(sys.argv)
        self._qtapp.setOrganizationName('nicos')
        self._qtapp.setApplicationName('history')
        self._window = StandaloneHistoryWindow(self)
        # if no cache was given on the command line...
        if not self._config['cache']:
            dlg = SettingsDialog(self._window)
            dlg.exec_()
            self._setROParam('cache', dlg.cacheBox.currentText())
            self._setROParam('prefix', dlg.prefixEdit.text())
        CacheClient.doInit(self, mode)

    def getDeviceList(self, only_explicit=True, special_clause=None):
        devlist = [
            key[:-6] for (key, _) in self.query_db('')
            if key.endswith('/value')
        ]
        if special_clause:
            devlist = [
                dn for dn in devlist if eval(special_clause, {'dn': dn})
            ]
        return sorted(devlist)

    def getDeviceParam(self, devname, parname):
        return self.get(devname, parname)

    def getDeviceParams(self, devname):
        ldevname = devname.lower()
        index = len(ldevname) + 1
        return {
            key[index:]: value
            for (key, value) in self.query_db('')
            if key.startswith(ldevname + '/')
        }

    def getDeviceParamInfo(self, _):
        return {}  # we can't deliver this info from the cache alone

    def start(self):
        self._startup_done.wait(2)
        self._window.openViews(self.views)
        self._window.show()
        try:
            self._qtapp.exec_()
        except KeyboardInterrupt:
            pass
        self._stoprequest = True

    def _propagate(self, data):
        self._window.newValue.emit(data)
Пример #10
0
    def mouseMoveEvent(self, event):
        if not (event.buttons() & Qt.LeftButton):
            return
        if not self._dragStartPos.isNull() and \
           self.tabAt(self._dragStartPos) != -1 and \
           (event.pos() - self._dragStartPos).manhattanLength() \
           < QApplication.startDragDistance():
            self._dragInitiated = True
        if (event.buttons() == Qt.LeftButton) and self._dragInitiated and \
           not self.geometry().contains(event.pos()):
            finishMoveEvent = QMouseEvent(QEvent.MouseMove, event.pos(),
                                          Qt.NoButton, Qt.NoButton,
                                          Qt.NoModifier)
            QTabBar.mouseMoveEvent(self, finishMoveEvent)

            drag = QDrag(self)
            mimedata = QMimeData()
            mimedata.setData('action', b'application/tab-detach')
            drag.setMimeData(mimedata)

            if QT_VER == 4:
                pixmap = QPixmap.grabWidget(self.parentWidget().currentWidget())
            else:
                pixmap = self.parentWidget().currentWidget().grab()
            pixmap = pixmap.scaled(640, 480, Qt.KeepAspectRatio)
            drag.setPixmap(pixmap)
            drag.setDragCursor(QPixmap(), Qt.LinkAction)

            dragged = drag.exec_(Qt.MoveAction)
            if dragged == Qt.IgnoreAction:
                # moved outside of tab widget
                event.accept()
                self.tabDetached.emit(self.tabAt(self._dragStartPos),
                                      QCursor.pos())
            elif dragged == Qt.MoveAction:
                # moved inside of tab widget
                if not self._dragDroppedPos.isNull():
                    event.accept()
                    self.tabMoved.emit(self.tabAt(self._dragStartPos),
                                       self.tabAt(self._dragDroppedPos))
                    self._dragDroppedPos = QPoint()
        else:
            QTabBar.mouseMoveEvent(self, event)
Пример #11
0
class CacheInspector(CICacheClient):
    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 start(self):
        self._window.show()
        if self.cache:
            self.connect(self.cache)
        try:
            self._qtapp.exec_()
        except KeyboardInterrupt:
            pass
        self._stoprequest = True
Пример #12
0
 def copy():
     QApplication.clipboard().setText(tb+'\n', QClipboard.Selection)
     QApplication.clipboard().setText(tb+'\n', QClipboard.Clipboard)
Пример #13
0
 def setQSS(style_file):
     with open(style_file, 'r', encoding='utf-8') as fd:
         try:
             QApplication.instance().setStyleSheet(fd.read())
         except Exception as e:
             print(e)
Пример #14
0
def main(argv):
    global log  # pylint: disable=global-statement

    userpath = path.join(path.expanduser('~'), '.config', 'nicos')

    # Set up logging for the GUI instance.
    initLoggers()
    log = NicosLogger('gui')
    log.parent = None
    log.setLevel(logging.INFO)
    log.addHandler(ColoredConsoleHandler())
    log.addHandler(
        NicosLogfileHandler(path.join(userpath, 'log'),
                            'gui',
                            use_subdir=False))

    # set up logging for unhandled exceptions in Qt callbacks
    def log_unhandled(*exc_info):
        traceback.print_exception(*exc_info)
        log.exception('unhandled exception in QT callback', exc_info=exc_info)

    sys.excepthook = log_unhandled

    app = QApplication(argv, organizationName='nicos', applicationName='gui')

    opts = parseargs()

    if opts.configfile is None:
        try:
            config.apply()
        except RuntimeError:
            pass
        # If "demo" is detected automatically, let the user choose their
        # instrument configuration.
        need_dialog = config.instrument is None or \
                      (config.setup_package == 'nicos_demo' and
                       config.instrument == 'demo' and
                       'INSTRUMENT' not in os.environ)
        if need_dialog:
            opts.configfile = InstrSelectDialog.select(
                'Your instrument could not be automatically detected.')
            if opts.configfile is None:
                return
        else:
            opts.configfile = path.join(config.setup_package_path,
                                        config.instrument, 'guiconfig.py')

    with open(opts.configfile, 'rb') as fp:
        configcode = fp.read()
    gui_conf = processGuiConfig(configcode)
    gui_conf.stylefile = ''

    if gui_conf.options.get('facility') in ['ess', 'sinq']:
        gui_conf.stylefile = f"{config.nicos_root}" \
                             f"/nicos/clients/flowui/guiconfig.qss"

    stylefiles = [
        path.join(userpath, 'style-%s.qss' % sys.platform),
        path.join(userpath, 'style.qss'),
        path.splitext(opts.configfile)[0] + '-%s.qss' % sys.platform,
        path.splitext(opts.configfile)[0] + '.qss',
    ]

    for stylefile in [gui_conf.stylefile] or stylefiles:
        if path.isfile(stylefile):
            try:
                with open(stylefile, 'r', encoding='utf-8') as fd:
                    app.setStyleSheet(fd.read())
                gui_conf.stylefile = stylefile
                break
            except Exception:
                log.warning('Error setting user style sheet from %s',
                            stylefile,
                            exc=1)

    mainwindow_cls = _mainwindow_cls.get(
        gui_conf.options.get('facility', 'default'))
    mainwindow = mainwindow_cls(log, gui_conf, opts.viewonly, opts.tunnel)
    log.addHandler(DebugHandler(mainwindow))

    if opts.connect:
        parsed = parseConnectionString(opts.connect, DEFAULT_PORT)
        if parsed:
            cdata = ConnectionData(**parsed)
            cdata.viewonly = opts.viewonly
            mainwindow.setConnData(cdata)
            if cdata.password is not None:
                # we have a password, connect right away
                mainwindow.client.connect(mainwindow.conndata)
            else:
                # we need to ask for password, override last preset (uses given
                # connection data) and force showing connect window
                mainwindow.lastpreset = ''
                mainwindow.autoconnect = True
    mainwindow.startup()

    return app.exec_()
Пример #15
0
    def initGui(self):
        def log_unhandled(*exc_info):
            traceback.print_exception(*exc_info)
            self.log.exception('unhandled exception in QT callback',
                               exc_info=exc_info)
        sys.excepthook = log_unhandled

        self._qtapp = QApplication(['qtapp'], organizationName='nicos',
                                   applicationName='gui')
        self._master = master = MonitorWindow()

        if self._geometry == 'fullscreen':
            master.showFullScreen()
            master._wantFullScreen = True
            # In some Qt5 versions, showFullScreen is buggy and doesn't
            # actually resize the window (but hides decoration etc).
            # So, explicitly set the geometry of the first screen.
            master.setGeometry(QApplication.screens()[0].geometry())
            QCursor.setPos(master.geometry().bottomRight())
        elif isinstance(self._geometry, tuple):
            w, h, x, y = self._geometry
            master.setGeometry(x, y, w, h)

        # colors used for the display of watchdog warnings, not for the
        # individual value displays
        self._bgcolor = QColor('gray')
        self._black = QColor('black')
        self._red = QColor('red')
        self._gray = QColor('gray')

        master.setWindowTitle(self.title)
        self._bgcolor = master.palette().color(QPalette.Window)

        timefont  = QFont(self.font, self._timefontsize)
        blockfont = QFont(self.font, self._fontsizebig)
        warnfont  = QFont(self.font, self._fontsizebig)
        warnfont.setBold(True)
        labelfont = QFont(self.font, self._fontsize)
        stbarfont = QFont(self.font, int(self._fontsize * 0.8))
        valuefont = QFont(self.valuefont or self.font, self._fontsize)

        blheight = QFontMetrics(blockfont).height()
        tiheight = QFontMetrics(timefont).height()

        # split window into to panels/frames below each other:
        # one displays time, the other is divided further to display blocks.
        # first the timeframe:
        masterframe = QFrame(master)
        masterlayout = QVBoxLayout()
        if self.title:
            self._titlelabel = QLabel(
                '', master, font=timefont, autoFillBackground=True,
                alignment=Qt.AlignHCenter)
            pal = self._titlelabel.palette()
            pal.setColor(QPalette.WindowText, self._gray)
            self._titlelabel.setPalette(pal)
            self._titlelabel.setSizePolicy(QSizePolicy.Preferred,
                                           QSizePolicy.Fixed)
            self._master.updateTitle.connect(self._titlelabel.setText)
            masterlayout.addWidget(self._titlelabel)
            masterlayout.addSpacing(0.2 * tiheight)
        else:
            self._titlelabel = None

        self._warnpanel = QFrame(master)
        self._warnpanel.setVisible(False)

        warningslayout = QVBoxLayout()
        lbl = QLabel('Warnings', self._warnpanel, font=warnfont)
        lbl.setSizePolicy(QSizePolicy.Preferred, QSizePolicy.Fixed)
        warningslayout.addWidget(lbl)
        self._warnlabel = SqueezedLabel('', self._warnpanel, font=blockfont)
        warningslayout.addWidget(self._warnlabel)
        self._warnpanel.setLayout(warningslayout)
        masterlayout.addWidget(self._warnpanel)
        master.switchWarnPanel.connect(self._switch_warnpanel)

        displayframe = QFrame(master)
        self._plots = {}

        colorScheme = lightColorScheme if self.colors == 'light' else None
        fontCache = {1.0: valuefont}

        def _create_field(groupframe, field):

            def _setup(widget):
                fontscale = field.get('fontscale', 1.0)
                if fontscale not in fontCache:
                    fontCache[fontscale] = scaledFont(valuefont, fontscale)
                widget.valueFont = fontCache[fontscale]
                widget.setFont(labelfont)
                for key in field:
                    if key in widget.properties:
                        setattr(widget, key, field[key])
                widget.setSource(self)
                if hasattr(widget, 'widgetInfo'):
                    widget.widgetInfo.connect(self.newWidgetInfo)
                return widget

            if isinstance(field, str):
                field = {'dev': field}
            if 'min' in field:
                field['min'] = repr(field['min'])
            if 'max' in field:
                field['max'] = repr(field['max'])
            setups = field.get('setups', None)

            if 'gui' in field:
                resource = findResource(field.pop('gui'))
                try:
                    instance = uic.loadUi(resource)
                except Exception as err:
                    self.log.exception('could not load .ui file %r, ignoring',
                                       resource)
                    instance = QLabel('%r could not be loaded:\n%s' %
                                      (resource, err))
                else:
                    for child in instance.findChildren(NicosWidget):
                        _setup(child)
                instance.setups = setups
                return instance
            elif 'widget' in field:
                widget_class = self._class_import(field.pop('widget'))
                widget = widget_class(groupframe)
                if isinstance(widget, NicosWidget):
                    _setup(widget)
                for child in widget.findChildren(NicosWidget):
                    _setup(child)
                widget.setups = setups
                return widget
            elif 'plot' in field and plot_available:
                # XXX make this more standard
                plotwidget = self._plots.get(field['plot'])
                if plotwidget:
                    plotwidget.devices += [field.get('dev', field.get('key', ''))]
                    plotwidget.names += [field.get('name', field.get('dev', field.get('key', '')))]
                    return None
                plotwidget = TrendPlot(groupframe)
                _setup(plotwidget)
                plotwidget.legend = field.get('legend', True)
                plotwidget.plotwindow = field.get('plotwindow', 3600)
                plotwidget.plotinterval = field.get('plotinterval', 2)
                self._plots[field['plot']] = plotwidget
                plotwidget.devices = [field.get('dev', field.get('key', ''))]
                plotwidget.names = [field.get('name', field.get('dev', field.get('key', '')))]
                plotwidget.setups = setups
                return plotwidget
            elif 'picture' in field:
                picwidget = PictureDisplay(groupframe)
                picwidget.filepath = field['picture']
                picwidget.setups = setups
                return _setup(picwidget)
            else:
                display = ValueDisplay(groupframe, colorScheme=colorScheme,
                                       showExpiration=self.noexpired)
                display.setups = setups
                return _setup(display)

        # now iterate through the layout and create the widgets to display it
        displaylayout = QVBoxLayout(spacing=20)
        for superrow in self.layout:
            boxlayout = QHBoxLayout(spacing=20)
            boxlayout.setContentsMargins(10, 10, 10, 10)
            for column in superrow:
                columnlayout = QVBoxLayout(spacing=0.8*blheight)
                for block in column:
                    block = self._resolve_block(block)
                    blocklayout_outer = QHBoxLayout()
                    blocklayout_outer.addStretch()
                    blocklayout = QVBoxLayout()
                    blocklayout.addSpacing(0.5 * blheight)
                    blockbox = BlockBox(displayframe, block._title, blockfont,
                                        block._options)
                    for row in block:
                        if row in (None, '---'):
                            blocklayout.addSpacing(12)
                        else:
                            rowlayout = QHBoxLayout()
                            rowlayout.addStretch()
                            rowlayout.addSpacing(self._padding)
                            for field in row:
                                fieldwidget = _create_field(blockbox, field)
                                if fieldwidget:
                                    rowlayout.addWidget(fieldwidget)
                                    rowlayout.addSpacing(self._padding)
                                    if fieldwidget.setups:
                                        if blockbox.setups:
                                            blockbox._onlyfields.append(fieldwidget)
                                        else:
                                            self._onlyfields.append(fieldwidget)
                                            # start hidden
                                            fieldwidget.setHidden(True)
                            rowlayout.addStretch()
                            blocklayout.addLayout(rowlayout)
                    if blockbox.setups:
                        self._onlyblocks.append((blocklayout_outer, blockbox))
                        blockbox.setHidden(True)  # start hidden
                    blocklayout.addSpacing(0.3 * blheight)
                    blockbox.setLayout(blocklayout)
                    blocklayout_outer.addWidget(blockbox)
                    blocklayout_outer.addStretch()
                    columnlayout.addLayout(blocklayout_outer)
                columnlayout.addStretch()
                boxlayout.addLayout(columnlayout)
            displaylayout.addLayout(boxlayout)
        displayframe.setLayout(displaylayout)

        for plot in self._plots.values():
            plot.setSource(self)

        masterlayout.addWidget(displayframe)

        masterframe.setLayout(masterlayout)
        master.setCentralWidget(masterframe)

        # initialize status bar
        self._statuslabel = QLabel(font=stbarfont)
        master.statusBar().addWidget(self._statuslabel)
        self._statustimer = None
        master.show()
Пример #16
0
def wait_cursor():
    try:
        QApplication.setOverrideCursor(QCursor(Qt.WaitCursor))
        yield
    finally:
        QApplication.restoreOverrideCursor()
Пример #17
0
 def setQSS(self, stylefile):
     with open(stylefile, 'r') as fd:
         try:
             QApplication.instance().setStyleSheet(fd.read())
         except Exception as e:
             print(e)
Пример #18
0
                return
            self._setStart(v)

        elif index == self._SPLIT_END:
            _lockWidth(self._head)
            if v <= self.start():
                return
            self._setEnd(v)

        _unlockWidth(self._tail)
        _unlockWidth(self._head)
        _unlockWidth(self._handle)


#-------------------------------------------------------------------------------
# MAIN
#-------------------------------------------------------------------------------

if __name__ == '__main__':
    app = QApplication(sys.argv)
    rs = QRangeSlider()
    rs.show()
    rs.setRange(15, 35)
    rs.setBackgroundStyle(
        'background: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 #222, stop:1 #333);'
    )
    rs.handle.setStyleSheet(
        'background: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 #282, stop:1 #393);'
    )
    app.exec_()
Пример #19
0
    def keyPressEvent(self, kev):
        key_code = kev.key()

        # if it's a shifted scroll key...
        if kev.modifiers() & Qt.ShiftModifier and \
                self.scrollWidget and \
                key_code in self.scrollingKeys:
            # create a new, unshifted key event and send it to the
            # scrolling widget
            nev = QKeyEvent(kev.type(), kev.key(), Qt.NoModifier)
            QApplication.sendEvent(self.scrollWidget, nev)
            return

        if key_code == Qt.Key_Escape:
            # abort history search
            self.setText(self._start_text)
            self._current = -1
            self.escapePressed.emit()
            QLineEdit.keyPressEvent(self, kev)

        elif key_code == Qt.Key_Up:
            # go earlier
            if self._current == -1:
                self._start_text = self.text()
                self._current = len(self.history)
            self.stepHistory(-1)
        elif key_code == Qt.Key_Down:
            # go later
            if self._current == -1:
                return
            self.stepHistory(1)

        elif key_code == Qt.Key_PageUp:
            # go earlier with prefix
            if self._current == -1:
                self._current = len(self.history)
                self._start_text = self.text()
            prefix = self.text()[:self.cursorPosition()]
            self.stepHistoryUntil(prefix, 'up')

        elif key_code == Qt.Key_PageDown:
            # go later with prefix
            if self._current == -1:
                return
            prefix = self.text()[:self.cursorPosition()]
            self.stepHistoryUntil(prefix, 'down')

        elif key_code == Qt.Key_Return or key_code == Qt.Key_Enter:
            # accept - add to history and do normal processing
            self._current = -1
            text = self.text()
            if text and (not self.history or self.history[-1] != text):
                # append to history, but only if it isn't equal to the last
                self.history.append(text)
            self._completer.setCompletionPrefix('')
            self._completer.setModel(QStringListModel([], self))
            QLineEdit.keyPressEvent(self, kev)

        else:
            # process normally
            QLineEdit.keyPressEvent(self, kev)
Пример #20
0
 def _handle_copy_cells(self):
     selected_data = self._extract_selected_data()
     clipboard_text = convert_table_to_clipboard_text(selected_data)
     QApplication.instance().clipboard().setText(clipboard_text)
Пример #21
0
 def on_runBtn_clicked(self):
     # Make sure we add the command to the history.
     event = QKeyEvent(QKeyEvent.KeyPress, Qt.Key_Enter, Qt.NoModifier)
     QApplication.postEvent(self.commandInput, event)
Пример #22
0
def main():
    app = QApplication(sys.argv)
    myWindow = MainWindow()
    myWindow.resize(800, 600)
    myWindow.show()
    sys.exit(app.exec_())