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
- -
-
-