From a9bc2f77926b8fc46873c7e945527fdf7c4c221d Mon Sep 17 00:00:00 2001 From: Jan Binder Date: Fri, 31 Jul 2015 11:56:28 +0000 Subject: [PATCH] add missing functionality to remote widget in manager --- core/remote.py | 20 +-- core/util/models.py | 225 +++++++++++++++++++++++++++++++++ gui/manager/managergui.py | 2 + gui/manager/ui_logwidget.ui | 5 +- gui/manager/ui_remotewidget.ui | 27 +++- 5 files changed, 265 insertions(+), 14 deletions(-) create mode 100644 core/util/models.py diff --git a/core/remote.py b/core/remote.py index 7f95c4607f..91881e2a29 100644 --- a/core/remote.py +++ b/core/remote.py @@ -22,6 +22,7 @@ from pyqtgraph.Qt import QtCore from urllib.parse import urlparse from rpyc.utils.server import ThreadedServer +from .util.models import DictTableModel, ListTableModel import rpyc import socket @@ -38,8 +39,10 @@ def __init__(self, threadManager, logger): self.tm = threadManager self.logger = logger #self.logger.logMsg('Nameserver is: {0}'.format(self.nameserver._pyroUri), msgType='status') - self.remoteModules = list() - self.sharedModules = dict() + self.remoteModules = ListTableModel() + self.remoteModules.headers[0] = 'Remote Modules' + self.sharedModules = DictTableModel() + self.sharedModules.headers[0] = 'Shared Modules' def makeRemoteService(self): """ A function that returns a class containing a module list hat can be manipulated from the host. @@ -68,9 +71,10 @@ def exposed_getModule(self, name): @return object: reference to the module """ - if name in self.modules: - return self.modules[name] + if name in self.modules.storage: + return self.modules.storage[name] else: + self.logMsg('Client requested a module that is not shared.', msgType='error') return None return RemoteModuleService @@ -106,9 +110,9 @@ def shareModule(self, name, obj): @param str name: unique name that is used to access the module @param object obj: a reference to the module """ - if name in self.sharedModules: + if name in self.sharedModules.storage: self.logger.logMsg('Module {0} already shared.'.format(name), msgType='warning') - self.sharedModules[name] = obj + self.sharedModules.add(name, obj) self.logger.logMsg('Shared module {0}.'.format(name), msgType='status') def unshareModule(self, name): @@ -116,9 +120,9 @@ def unshareModule(self, name): @param str name: unique name of the module that should not be accessible any more """ - if name in self.sharedModules: + if name in self.sharedModules.storage: self.logger.logMsg('Module {0} was not shared.'.format(name), msgType='error') - self.sharedModules.popKey(name, None) + self.sharedModules.pop(name) def getRemoteModuleUrl(self, url): """ Get a remote module via its URL. diff --git a/core/util/models.py b/core/util/models.py new file mode 100644 index 0000000000..ae4c04b894 --- /dev/null +++ b/core/util/models.py @@ -0,0 +1,225 @@ +# -*- coding: utf-8 -*- +""" +This file contains Qt models for Python data structures. + +QuDi is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +QuDi is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with QuDi. If not, see . + +Copyright (C) 2015 Jan M. Binder jan.binder@uni-ulm.de +""" + +from pyqtgraph.Qt import QtCore +from collections import OrderedDict +from .mutex import Mutex + +class DictTableModel(QtCore.QAbstractTableModel): + + def __init__(self): + super().__init__() + self.lock = Mutex() + self.headers = ['Name'] + self.storage = OrderedDict() + + def getKeyByNumber(self, n): + i = 0 + length = len(self.storage) + if n < 0 or n >= length: + raise IndexError + it = iter(self.storage) + key = next(it) + while(i len(self.headers): + return None + elif role != QtCore.Qt.DisplayRole: + return None + elif orientation != QtCore.Qt.Horizontal: + return None + else: + return self.header[section] + + def add(self, key, data): + with self.lock: + if key in self.storage: + return None + row = len(self.storage) + self.beginInsertRows(QtCore.QModelIndex(), row, row) + self.storage[key] = data + self.endInsertRows() + + def pop(self, key): + with self.lock: + if key in self.storage: + row = self.getNumberByKey(key) + self.beginRemoveRows(QtCore.QModelIndex(), row, row) + ret = self.storage.pop(key) + self.endRemoveRows() + return ret + + +class ListTableModel(QtCore.QAbstractTableModel): + + def __init__(self): + super().__init__() + self.lock = Mutex() + self.headers = ['Name'] + self.storage = list() + + def rowCount(self, parent = QtCore.QModelIndex()): + """ Gives the number of stored items. + + @return int: number of items + """ + return len(self.storage) + + def columnCount(self, parent = QtCore.QModelIndex()): + """ Gives the number of data fields. + + @return int: number of data fields + """ + return len(self.headers) + + def flags(self, index): + """ Determines what can be done with entry cells in the table view. + + @param QModelIndex index: cell fo which the flags are requested + + @return Qt.ItemFlags: actins allowed fotr this cell + """ + return QtCore.Qt.ItemIsEnabled | QtCore.Qt.ItemIsSelectable + + def data(self, index, role): + """ Get data from model for a given cell. Data can have a role that affects display. + + @param QModelIndex index: cell for which data is requested + @param ItemDataRole role: role for which data is requested + + @return QVariant: data for given cell and role + """ + if not index.isValid(): + return None + elif role == QtCore.Qt.DisplayRole: + if index.column() == 0: + return self.storage[index.row()] + #elif index.column() == 1: + # return item[1].thread + else: + return None + else: + return None + + def headerData(self, section, orientation, role = QtCore.Qt.DisplayRole): + """ Data for the table view headers. + + @param int section: number of the column to get header data for + @param Qt.Orientation: orientation of header (horizontal or vertical) + @param ItemDataRole: role for which to get data + + @return QVariant: header data for given column and role + """ + if section < 0 and section > len(self.headers): + return None + elif role != QtCore.Qt.DisplayRole: + return None + elif orientation != QtCore.Qt.Horizontal: + return None + else: + return self.header[section] + + def insert(self, n, data): + with self.lock: + if n >= 0 and n <= len(self.storage): + self.beginInsertRows(QtCore.QModelIndex(), n, n) + self.storage.insert(n, data) + self.endInsertRows() + + def append(self, data): + with self.lock: + n = len(self.storage) + self.beginInsertRows(QtCore.QModelIndex(), n, n) + self.storage.append(data) + self.endInsertRows() + + def pop(self, n): + with self.lock: + if n >= 0 and n < len(self.storage): + self.beginRemoveRows(QtCore.QModelIndex(), n, n) + ret = self.storage.pop(n) + self.endRemoveRows() + return ret + diff --git a/gui/manager/managergui.py b/gui/manager/managergui.py index 42e927754d..19f5038b40 100644 --- a/gui/manager/managergui.py +++ b/gui/manager/managergui.py @@ -111,6 +111,8 @@ def activation(self, e=None): # remote widget self._mw.remoteWidget.hostLabel.setText('URL:') self._mw.remoteWidget.portLabel.setText('rpyc://{0}:{1}/'.format(self._manager.rm.hostname, self._manager.rm.server.port)) + self._mw.remoteWidget.remoteModuleListView.setModel(self._manager.rm.remoteModules) + self._mw.remoteWidget.sharedModuleListView.setModel(self._manager.rm.sharedModules) self._mw.config_display_dockWidget.hide() self._mw.remoteDockWidget.hide() diff --git a/gui/manager/ui_logwidget.ui b/gui/manager/ui_logwidget.ui index 279be9ee71..b1335b4f4b 100644 --- a/gui/manager/ui_logwidget.ui +++ b/gui/manager/ui_logwidget.ui @@ -65,8 +65,11 @@ Qt::ElideNone + + QAbstractItemView::ScrollPerPixel + - QAbstractItemView::ScrollPerItem + QAbstractItemView::ScrollPerPixel Qt::NoPen diff --git a/gui/manager/ui_remotewidget.ui b/gui/manager/ui_remotewidget.ui index ef7ad70728..6894dd469c 100644 --- a/gui/manager/ui_remotewidget.ui +++ b/gui/manager/ui_remotewidget.ui @@ -6,7 +6,7 @@ 0 0 - 400 + 356 300 @@ -21,16 +21,33 @@ - + + + + true + + + true + + + + + + + true + + + true + + + + port - - -