Skip to content

Commit a9bc2f7

Browse files
committed
add missing functionality to remote widget in manager
1 parent 20230bc commit a9bc2f7

File tree

5 files changed

+265
-14
lines changed

5 files changed

+265
-14
lines changed

core/remote.py

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
from pyqtgraph.Qt import QtCore
2323
from urllib.parse import urlparse
2424
from rpyc.utils.server import ThreadedServer
25+
from .util.models import DictTableModel, ListTableModel
2526
import rpyc
2627
import socket
2728

@@ -38,8 +39,10 @@ def __init__(self, threadManager, logger):
3839
self.tm = threadManager
3940
self.logger = logger
4041
#self.logger.logMsg('Nameserver is: {0}'.format(self.nameserver._pyroUri), msgType='status')
41-
self.remoteModules = list()
42-
self.sharedModules = dict()
42+
self.remoteModules = ListTableModel()
43+
self.remoteModules.headers[0] = 'Remote Modules'
44+
self.sharedModules = DictTableModel()
45+
self.sharedModules.headers[0] = 'Shared Modules'
4346

4447
def makeRemoteService(self):
4548
""" 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):
6871
6972
@return object: reference to the module
7073
"""
71-
if name in self.modules:
72-
return self.modules[name]
74+
if name in self.modules.storage:
75+
return self.modules.storage[name]
7376
else:
77+
self.logMsg('Client requested a module that is not shared.', msgType='error')
7478
return None
7579

7680
return RemoteModuleService
@@ -106,19 +110,19 @@ def shareModule(self, name, obj):
106110
@param str name: unique name that is used to access the module
107111
@param object obj: a reference to the module
108112
"""
109-
if name in self.sharedModules:
113+
if name in self.sharedModules.storage:
110114
self.logger.logMsg('Module {0} already shared.'.format(name), msgType='warning')
111-
self.sharedModules[name] = obj
115+
self.sharedModules.add(name, obj)
112116
self.logger.logMsg('Shared module {0}.'.format(name), msgType='status')
113117

114118
def unshareModule(self, name):
115119
""" Remove a module from the shared module list.
116120
117121
@param str name: unique name of the module that should not be accessible any more
118122
"""
119-
if name in self.sharedModules:
123+
if name in self.sharedModules.storage:
120124
self.logger.logMsg('Module {0} was not shared.'.format(name), msgType='error')
121-
self.sharedModules.popKey(name, None)
125+
self.sharedModules.pop(name)
122126

123127
def getRemoteModuleUrl(self, url):
124128
""" Get a remote module via its URL.

core/util/models.py

Lines changed: 225 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,225 @@
1+
# -*- coding: utf-8 -*-
2+
"""
3+
This file contains Qt models for Python data structures.
4+
5+
QuDi is free software: you can redistribute it and/or modify
6+
it under the terms of the GNU General Public License as published by
7+
the Free Software Foundation, either version 3 of the License, or
8+
(at your option) any later version.
9+
10+
QuDi is distributed in the hope that it will be useful,
11+
but WITHOUT ANY WARRANTY; without even the implied warranty of
12+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13+
GNU General Public License for more details.
14+
15+
You should have received a copy of the GNU General Public License
16+
along with QuDi. If not, see <http://www.gnu.org/licenses/>.
17+
18+
Copyright (C) 2015 Jan M. Binder [email protected]
19+
"""
20+
21+
from pyqtgraph.Qt import QtCore
22+
from collections import OrderedDict
23+
from .mutex import Mutex
24+
25+
class DictTableModel(QtCore.QAbstractTableModel):
26+
27+
def __init__(self):
28+
super().__init__()
29+
self.lock = Mutex()
30+
self.headers = ['Name']
31+
self.storage = OrderedDict()
32+
33+
def getKeyByNumber(self, n):
34+
i = 0
35+
length = len(self.storage)
36+
if n < 0 or n >= length:
37+
raise IndexError
38+
it = iter(self.storage)
39+
key = next(it)
40+
while(i<n):
41+
key = next(it)
42+
i += 1
43+
return key
44+
45+
def getNumberByKey(self, key):
46+
i = 0
47+
it = iter(self.storage)
48+
newkey = next(it)
49+
while(key != newkey):
50+
newkey = next(it)
51+
i += 1
52+
return i
53+
54+
def rowCount(self, parent = QtCore.QModelIndex()):
55+
""" Gives the number of stored items.
56+
57+
@return int: number of items
58+
"""
59+
return len(self.storage)
60+
61+
def columnCount(self, parent = QtCore.QModelIndex()):
62+
""" Gives the number of data fields.
63+
64+
@return int: number of data fields
65+
"""
66+
return len(self.headers)
67+
68+
def flags(self, index):
69+
""" Determines what can be done with entry cells in the table view.
70+
71+
@param QModelIndex index: cell fo which the flags are requested
72+
73+
@return Qt.ItemFlags: actins allowed fotr this cell
74+
"""
75+
return QtCore.Qt.ItemIsEnabled | QtCore.Qt.ItemIsSelectable
76+
77+
def data(self, index, role):
78+
""" Get data from model for a given cell. Data can have a role that affects display.
79+
80+
@param QModelIndex index: cell for which data is requested
81+
@param ItemDataRole role: role for which data is requested
82+
83+
@return QVariant: data for given cell and role
84+
"""
85+
if not index.isValid():
86+
return None
87+
elif role == QtCore.Qt.DisplayRole:
88+
key = self.getKeyByNumber(index.row())
89+
if index.column() == 0:
90+
return key
91+
elif index.column() == 1:
92+
return self.storage[key]
93+
else:
94+
return None
95+
else:
96+
return None
97+
98+
def headerData(self, section, orientation, role = QtCore.Qt.DisplayRole):
99+
""" Data for the table view headers.
100+
101+
@param int section: number of the column to get header data for
102+
@param Qt.Orientation: orientation of header (horizontal or vertical)
103+
@param ItemDataRole: role for which to get data
104+
105+
@return QVariant: header data for given column and role
106+
"""
107+
if section < 0 and section > len(self.headers):
108+
return None
109+
elif role != QtCore.Qt.DisplayRole:
110+
return None
111+
elif orientation != QtCore.Qt.Horizontal:
112+
return None
113+
else:
114+
return self.header[section]
115+
116+
def add(self, key, data):
117+
with self.lock:
118+
if key in self.storage:
119+
return None
120+
row = len(self.storage)
121+
self.beginInsertRows(QtCore.QModelIndex(), row, row)
122+
self.storage[key] = data
123+
self.endInsertRows()
124+
125+
def pop(self, key):
126+
with self.lock:
127+
if key in self.storage:
128+
row = self.getNumberByKey(key)
129+
self.beginRemoveRows(QtCore.QModelIndex(), row, row)
130+
ret = self.storage.pop(key)
131+
self.endRemoveRows()
132+
return ret
133+
134+
135+
class ListTableModel(QtCore.QAbstractTableModel):
136+
137+
def __init__(self):
138+
super().__init__()
139+
self.lock = Mutex()
140+
self.headers = ['Name']
141+
self.storage = list()
142+
143+
def rowCount(self, parent = QtCore.QModelIndex()):
144+
""" Gives the number of stored items.
145+
146+
@return int: number of items
147+
"""
148+
return len(self.storage)
149+
150+
def columnCount(self, parent = QtCore.QModelIndex()):
151+
""" Gives the number of data fields.
152+
153+
@return int: number of data fields
154+
"""
155+
return len(self.headers)
156+
157+
def flags(self, index):
158+
""" Determines what can be done with entry cells in the table view.
159+
160+
@param QModelIndex index: cell fo which the flags are requested
161+
162+
@return Qt.ItemFlags: actins allowed fotr this cell
163+
"""
164+
return QtCore.Qt.ItemIsEnabled | QtCore.Qt.ItemIsSelectable
165+
166+
def data(self, index, role):
167+
""" Get data from model for a given cell. Data can have a role that affects display.
168+
169+
@param QModelIndex index: cell for which data is requested
170+
@param ItemDataRole role: role for which data is requested
171+
172+
@return QVariant: data for given cell and role
173+
"""
174+
if not index.isValid():
175+
return None
176+
elif role == QtCore.Qt.DisplayRole:
177+
if index.column() == 0:
178+
return self.storage[index.row()]
179+
#elif index.column() == 1:
180+
# return item[1].thread
181+
else:
182+
return None
183+
else:
184+
return None
185+
186+
def headerData(self, section, orientation, role = QtCore.Qt.DisplayRole):
187+
""" Data for the table view headers.
188+
189+
@param int section: number of the column to get header data for
190+
@param Qt.Orientation: orientation of header (horizontal or vertical)
191+
@param ItemDataRole: role for which to get data
192+
193+
@return QVariant: header data for given column and role
194+
"""
195+
if section < 0 and section > len(self.headers):
196+
return None
197+
elif role != QtCore.Qt.DisplayRole:
198+
return None
199+
elif orientation != QtCore.Qt.Horizontal:
200+
return None
201+
else:
202+
return self.header[section]
203+
204+
def insert(self, n, data):
205+
with self.lock:
206+
if n >= 0 and n <= len(self.storage):
207+
self.beginInsertRows(QtCore.QModelIndex(), n, n)
208+
self.storage.insert(n, data)
209+
self.endInsertRows()
210+
211+
def append(self, data):
212+
with self.lock:
213+
n = len(self.storage)
214+
self.beginInsertRows(QtCore.QModelIndex(), n, n)
215+
self.storage.append(data)
216+
self.endInsertRows()
217+
218+
def pop(self, n):
219+
with self.lock:
220+
if n >= 0 and n < len(self.storage):
221+
self.beginRemoveRows(QtCore.QModelIndex(), n, n)
222+
ret = self.storage.pop(n)
223+
self.endRemoveRows()
224+
return ret
225+

gui/manager/managergui.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,8 @@ def activation(self, e=None):
111111
# remote widget
112112
self._mw.remoteWidget.hostLabel.setText('URL:')
113113
self._mw.remoteWidget.portLabel.setText('rpyc://{0}:{1}/'.format(self._manager.rm.hostname, self._manager.rm.server.port))
114+
self._mw.remoteWidget.remoteModuleListView.setModel(self._manager.rm.remoteModules)
115+
self._mw.remoteWidget.sharedModuleListView.setModel(self._manager.rm.sharedModules)
114116

115117
self._mw.config_display_dockWidget.hide()
116118
self._mw.remoteDockWidget.hide()

gui/manager/ui_logwidget.ui

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,8 +65,11 @@
6565
<property name="textElideMode">
6666
<enum>Qt::ElideNone</enum>
6767
</property>
68+
<property name="verticalScrollMode">
69+
<enum>QAbstractItemView::ScrollPerPixel</enum>
70+
</property>
6871
<property name="horizontalScrollMode">
69-
<enum>QAbstractItemView::ScrollPerItem</enum>
72+
<enum>QAbstractItemView::ScrollPerPixel</enum>
7073
</property>
7174
<property name="gridStyle">
7275
<enum>Qt::NoPen</enum>

gui/manager/ui_remotewidget.ui

Lines changed: 22 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
<rect>
77
<x>0</x>
88
<y>0</y>
9-
<width>400</width>
9+
<width>356</width>
1010
<height>300</height>
1111
</rect>
1212
</property>
@@ -21,16 +21,33 @@
2121
</property>
2222
</widget>
2323
</item>
24-
<item row="0" column="1">
24+
<item row="1" column="0" colspan="2">
25+
<widget class="QListView" name="sharedModuleListView">
26+
<property name="alternatingRowColors">
27+
<bool>true</bool>
28+
</property>
29+
<property name="uniformItemSizes">
30+
<bool>true</bool>
31+
</property>
32+
</widget>
33+
</item>
34+
<item row="1" column="2">
35+
<widget class="QListView" name="remoteModuleListView">
36+
<property name="alternatingRowColors">
37+
<bool>true</bool>
38+
</property>
39+
<property name="uniformItemSizes">
40+
<bool>true</bool>
41+
</property>
42+
</widget>
43+
</item>
44+
<item row="0" column="2">
2545
<widget class="QLabel" name="portLabel">
2646
<property name="text">
2747
<string>port</string>
2848
</property>
2949
</widget>
3050
</item>
31-
<item row="1" column="0" colspan="2">
32-
<widget class="QListView" name="listView"/>
33-
</item>
3451
</layout>
3552
</widget>
3653
<resources/>

0 commit comments

Comments
 (0)