--- a/ProjectController.py Fri Nov 09 13:26:06 2018 +0100
+++ b/ProjectController.py Wed Nov 14 11:32:08 2018 +0100
@@ -1768,7 +1768,7 @@
# Launch Service Discovery dialog
- dialog = UriEditor(self.AppFrame)
+ dialog = UriEditor(self.AppFrame, self) answer = dialog.ShowModal()
--- a/connectors/PYRO/__init__.py Fri Nov 09 13:26:06 2018 +0100
+++ b/connectors/PYRO/__init__.py Wed Nov 14 11:32:08 2018 +0100
@@ -126,7 +126,10 @@
if servicetype != "PYROS":
- secpath = os.path.join(str(confnodesroot.ProjectPath), 'psk', ID+'.secret')
+ secdir = os.path.join(str(confnodesroot.ProjectPath), 'psk') + if not os.path.exists(secdir): + secpath = os.path.join(secdir, ID+'.secret') with open(secpath, 'w') as f:
--- a/connectors/PYRO_dialog.py Fri Nov 09 13:26:06 2018 +0100
+++ b/connectors/PYRO_dialog.py Wed Nov 14 11:32:08 2018 +0100
@@ -14,17 +14,19 @@
model = [('host',_("Host:")),
-secure_model = model + [('ID',_("ID:"))]
-models = [("LOCAL", []), ("PYRO",model), ("PYROS",secure_model)]
+# (scheme, model, secure) +models = [("LOCAL", [], False), ("PYRO", model, False), ("PYROS", model, True)] Schemes = list(zip(*models)[0])
-ModelsDict = dict(models)
+_PerSchemeConf = {sch : (mod,sec) for sch,mod,sec in models} class PYRO_dialog(SchemeEditor):
def __init__(self, scheme, *args, **kwargs):
- self.model = ModelsDict[scheme]
+ # ID selector is enabled only on PYROS (secure) + self.model, self.EnableIDSelector = _PerSchemeConf[scheme] SchemeEditor.__init__(self, scheme, *args, **kwargs)
@@ -38,6 +40,8 @@
return template.format(**fields)
--- a/connectors/SchemeEditor.py Fri Nov 09 13:26:06 2018 +0100
+++ b/connectors/SchemeEditor.py Wed Nov 14 11:32:08 2018 +0100
@@ -6,14 +6,20 @@
from __future__ import absolute_import
from itertools import repeat, izip_longest
+from functools import partial +from controls.IDManager import IDManager class SchemeEditor(wx.Panel):
def __init__(self, scheme, parent, *args, **kwargs):
wx.Panel.__init__(self, parent, *args, **kwargs)
- self.mainSizer = wx.FlexGridSizer(cols=2, hgap=10, rows=5, vgap=10)
+ self.fieldsizer = wx.FlexGridSizer(cols=2, hgap=10, vgap=10) + if self.EnableIDSelector: + self.model = self.model + [("ID", _("ID:"))] for tag, label in self.model:
txtctrl = wx.TextCtrl(parent=self, size=wx.Size(200, -1))
@@ -21,11 +27,20 @@
(wx.StaticText(self, label=label), wx.ALIGN_CENTER_VERTICAL),
- self.mainSizer.AddWindow(win, flag=flag)
+ self.fieldsizer.AddWindow(win, flag=flag) + self.fieldsizer.AddSpacer(20) - self.mainSizer.AddSpacer(20)
- self.SetSizer(self.mainSizer)
+ if self.EnableIDSelector: + self.mainsizer = wx.FlexGridSizer(cols=2, hgap=10, vgap=10) + self.mainsizer.AddSizer(self.fieldsizer) + self.idselector = IDManager( + partial(wx.CallAfter, parent.SetURI)) + self.mainsizer.AddWindow(self.idselector) + self.SetSizer(self.mainsizer) + self.SetSizer(self.fieldsizer) def SetFields(self, fields):
for tag, label in self.model:
--- a/connectors/WAMP_dialog.py Fri Nov 09 13:26:06 2018 +0100
+++ b/connectors/WAMP_dialog.py Wed Nov 14 11:32:08 2018 +0100
@@ -14,12 +14,12 @@
model = [('host',_("Host:")),
class WAMP_dialog(SchemeEditor):
def __init__(self, *args, **kwargs):
+ self.EnableIDSelector = True SchemeEditor.__init__(self, *args, **kwargs)
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/controls/IDManager.py Wed Nov 14 11:32:08 2018 +0100
@@ -0,0 +1,210 @@
+# See COPYING file for copyrights details. +from __future__ import absolute_import +import wx.dataview as dv +def _GetInitialData(psk_path): + # [(ID, Desc, LastKnownURI, LastConnect) + data_path = os.path.join(psk_path, 'management.json') + if os.path.isdir(psk_path): + # load known keys metadata + # {ID:(Desc, LastKnownURI, LastConnect)} + recovered_data = json.loads(open(data_path).read()) \ + if os.path.exists(data_path) else {} + # go through all secret files available an build data + # out of data recoverd from json and list of secret. + # this implicitly filters IDs out of metadata who's + psk_files = os.listdir(psk_path) + for filename in psk_files: + if filename.endswith('.secret'): + ID = filename[:-7] # strip filename extension + meta = recovered_data.get(ID, + ['', # default description + None]) # last connection date +def _DeleteID(psk_path, ID): + secret_path = os.path.join(psk_path, ID+'.secret') +def _SaveData(psk_path, data): + if not os.path.isdir(psk_path): + data_path = os.path.join(psk_path, 'management.json') + to_store = {row[0]:row[1:] for row in data} + with open(data_path, 'w') as f: + f.write(json.dumps(to_store)) +class IDManagerModel(dv.PyDataViewIndexListModel): + def __init__(self, psk_path, columncount): + self.psk_path = psk_path + self.columncount = columncount + self.data = _GetInitialData(psk_path) + dv.PyDataViewIndexListModel.__init__(self, len(self.data)) + _SaveData(self.psk_path, self.data) + def GetColumnType(self, col): + def GetValueByRow(self, row, col): + return self.data[row][col] + def SetValueByRow(self, value, row, col): + self.data[row][col] = value + def GetColumnCount(self): + return len(self.data[0]) if self.data else self.columncount + def GetAttrByRow(self, row, col, attr): + def Compare(self, item1, item2, col, ascending): + if not ascending: # swap sort order? + item2, item1 = item1, item2 + row1 = self.GetRow(item1) + row2 = self.GetRow(item2) + return cmp(int(self.data[row1][col]), int(self.data[row2][col])) + return cmp(self.data[row1][col], self.data[row2][col]) + def DeleteRows(self, rows): + rows.sort(reverse=True) + _DeleteID(self.psk_path, ID) + def AddRow(self, value): + self.data.append(value) +colflags = dv.DATAVIEW_COL_RESIZABLE|dv.DATAVIEW_COL_SORTABLE +class IDManager(wx.Panel): + def __init__(self, parent, ctr, SelectURICallBack, *args, **kwargs): + wx.Panel.__init__(self, parent, -1, size=(400,200)) + self.isManager = SelectURICallBack is None + self.SelectURICallBack = SelectURICallBack + dvStyle = wx.BORDER_THEME | dv.DV_ROW_LINES + # no multiple selection in selector mode + dvStyle |= dv.DV_MULTIPLE + self.dvc = dv.DataViewCtrl(self, style = dvStyle) + args = lambda *a,**k:(a,k) + args(_("ID"), 0, width = 100), + args(_("Last URI"), 1, width = 80), + args(_("Description"), 2, width = 200, + mode = dv.DATAVIEW_CELL_EDITABLE + else dv.DATAVIEW_CELL_INERT), + args(_("Last connection"), 3, width = 100), + self.model = IDManagerModel( + os.path.join(str(ctr.ProjectPath), 'psk'), + self.dvc.AssociateModel(self.model) + for a,k in ColumnsDesc: + self.dvc.AppendTextColumn(*a,**dict(k, flags = colflags)) + # - update ID field of scheme editor + # - enable use URI button + self.Sizer = wx.BoxSizer(wx.VERTICAL) + self.Sizer.Add(self.dvc, 1, wx.EXPAND) + btnbox = wx.BoxSizer(wx.HORIZONTAL) + # deletion of secret and metadata + deleteButton = wx.Button(self, label=_("Delete ID")) + self.Bind(wx.EVT_BUTTON, self.OnDeleteButton, deleteButton) + btnbox.Add(deleteButton, 0, wx.LEFT|wx.RIGHT, 5) + exportButton = wx.Button(self, label=_("Export all")) + self.Bind(wx.EVT_BUTTON, self.OnExportButton, exportButton) + btnbox.Add(exportButton, 0, wx.LEFT|wx.RIGHT, 5) + # import with a merge -> duplicates are asked for + importButton = wx.Button(self, label=_("Import")) + self.Bind(wx.EVT_BUTTON, self.OnImportButton, importButton) + btnbox.Add(importButton, 0, wx.LEFT|wx.RIGHT, 5) + # use last known URI button + # TODO : disable use URI button until something selected + selectButton = wx.Button(self, label=_("Use last URI")) + self.Bind(wx.EVT_BUTTON, self.OnSelectButton, selectButton) + btnbox.Add(selectButton, 0, wx.LEFT|wx.RIGHT, 5) + self.Sizer.Add(btnbox, 0, wx.TOP|wx.BOTTOM, 5) + def OnDeleteButton(self, evt): + items = self.dvc.GetSelections() + rows = [self.model.GetRow(item) for item in items] + # Ask if user really wants to delete + if wx.MessageBox(_('Are you sure to delete selected IDs?'), + wx.YES_NO | wx.CENTRE | wx.NO_DEFAULT) != wx.YES: + self.model.DeleteRows(rows) + def OnSelectButton(self, evt): + # TODO : call SetURICallback with URI from curent selection. + wx.YES_NO | wx.CENTRE | wx.NO_DEFAULT) + def OnExportButton(self, evt): + wx.YES_NO | wx.CENTRE | wx.NO_DEFAULT) + def OnImportButton(self, evt): + wx.YES_NO | wx.CENTRE | wx.NO_DEFAULT) --- a/dialogs/UriEditor.py Fri Nov 09 13:26:06 2018 +0100
+++ b/dialogs/UriEditor.py Wed Nov 14 11:32:08 2018 +0100
@@ -27,7 +27,8 @@
- def __init__(self, parent, uri=''):
+ def __init__(self, parent, ctr, uri=''): name='UriEditor', parent=parent,
--- a/editors/ConfTreeNodeEditor.py Fri Nov 09 13:26:06 2018 +0100
+++ b/editors/ConfTreeNodeEditor.py Wed Nov 14 11:32:08 2018 +0100
@@ -345,7 +345,7 @@
uri = CTR_BeremizRoot.getURI_location().strip()
- dialog = UriEditor(CTR_AppFrame, uri)
+ dialog = UriEditor(CTR_AppFrame, CTR, uri) if dialog.ShowModal() == wx.ID_OK:
CTR_BeremizRoot.setURI_location(dialog.GetURI())