[GRASS-SVN] r58144 - grass/trunk/gui/wxpython/gmodeler

svn_grass at osgeo.org svn_grass at osgeo.org
Sun Nov 3 11:16:24 PST 2013


Author: martinl
Date: 2013-11-03 11:16:23 -0800 (Sun, 03 Nov 2013)
New Revision: 58144

Modified:
   grass/trunk/gui/wxpython/gmodeler/dialogs.py
   grass/trunk/gui/wxpython/gmodeler/frame.py
   grass/trunk/gui/wxpython/gmodeler/model.py
Log:
wxGUI/modeler: implement reordering items (work in progress)

Modified: grass/trunk/gui/wxpython/gmodeler/dialogs.py
===================================================================
--- grass/trunk/gui/wxpython/gmodeler/dialogs.py	2013-11-03 01:07:59 UTC (rev 58143)
+++ grass/trunk/gui/wxpython/gmodeler/dialogs.py	2013-11-03 19:16:23 UTC (rev 58144)
@@ -409,7 +409,7 @@
         
         self.itemList = ItemCheckListCtrl(parent = self.panel,
                                           window = self,
-                                          columns = [_("ID"), _("Name"),
+                                          columns = [_("Name"),
                                                      _("Command")],
                                           shape = shape)
         self.itemList.Populate(self.parent.GetModel().GetItems())
@@ -511,7 +511,7 @@
                                         label=" %s " % _("List of items in 'else' block"))
         self.itemListElse = ItemCheckListCtrl(parent = self.panel,
                                               window = self,
-                                              columns = [_("ID"), _("Name"),
+                                              columns = [_("Name"),
                                                          _("Command")],
                                               shape = shape)
         self.itemListElse.SetName('ElseBlockList')
@@ -580,7 +580,7 @@
 
 class ModelListCtrl(wx.ListCtrl,
                     listmix.ListCtrlAutoWidthMixin,
-                    listmix.TextEditMixin,
+#                    listmix.TextEditMixin,
                     listmix.ColumnSorterMixin):
     def __init__(self, parent, columns, id = wx.ID_ANY,
                  style = wx.LC_REPORT | wx.BORDER_NONE |
@@ -597,7 +597,7 @@
         
         wx.ListCtrl.__init__(self, parent, id = id, style = style, **kwargs)
         listmix.ListCtrlAutoWidthMixin.__init__(self)
-        listmix.TextEditMixin.__init__(self)
+#        listmix.TextEditMixin.__init__(self)
         listmix.ColumnSorterMixin.__init__(self, 4)
         
         i = 0
@@ -787,16 +787,15 @@
             shapeItems = list()
         
         i = 0
-        if len(self.columns) == 3: # ItemCheckList
+        if len(self.columns) == 2: # ItemCheckList
             checked = list()
         for action in data:
             if isinstance(action, ModelData) or \
                     action == self.shape:
                 continue
             
-            if len(self.columns) == 3:
-                self.itemDataMap[i] = [str(action.GetId()),
-                                       action.GetName(),
+            if len(self.columns) == 2:
+                self.itemDataMap[i] = [action.GetName(),
                                        action.GetLog()]
                 aId = action.GetBlockId()
                 if action.GetId() in shapeItems:
@@ -807,8 +806,7 @@
                 bId = action.GetBlockId()
                 if not bId:
                     bId = ''
-                self.itemDataMap[i] = [str(action.GetId()),
-                                       action.GetName(),
+                self.itemDataMap[i] = [action.GetName(),
                                        ','.join(map(str, bId)),
                                        action.GetLog()]
             
@@ -817,23 +815,21 @@
         self.itemCount = len(self.itemDataMap.keys())
         self.DeleteAllItems()
         i = 0
-        if len(self.columns) == 3:
-            for aid, name, desc in self.itemDataMap.itervalues():
-                index = self.InsertStringItem(sys.maxint, aid)
-                self.SetStringItem(index, 0, aid)
-                self.SetStringItem(index, 1, name)
-                self.SetStringItem(index, 2, desc)
+        if len(self.columns) == 2:
+            for name, desc in self.itemDataMap.itervalues():
+                index = self.InsertStringItem(sys.maxint, str(i))
+                self.SetStringItem(index, 0, name)
+                self.SetStringItem(index, 1, desc)
                 self.SetItemData(index, i)
                 if checked[i]:
                     self.CheckItem(index, True)
                 i += 1
         else:
-            for aid, name, inloop, desc in self.itemDataMap.itervalues():
-                index = self.InsertStringItem(sys.maxint, aid)
-                self.SetStringItem(index, 0, aid)
-                self.SetStringItem(index, 1, name)
-                self.SetStringItem(index, 2, inloop)
-                self.SetStringItem(index, 3, desc)
+            for name, inloop, desc in self.itemDataMap.itervalues():
+                index = self.InsertStringItem(sys.maxint, str(i))
+                self.SetStringItem(index, 0, name)
+                self.SetStringItem(index, 1, inloop)
+                self.SetStringItem(index, 2, desc)
                 self.SetItemData(index, i)
                 i += 1
                 
@@ -847,14 +843,12 @@
             self.DeleteItem(item)
             del self.itemDataMap[item]
             
-            aId = self.GetItem(item, 0).GetText()
-            action = model.GetItem(int(aId))
+            action = model.GetItem(item+1) # action indeces starts at 1
             if not action:
                 item = self.GetFirstSelected()
                 continue
             
-            model.RemoveItem(action)
-            canvas.GetDiagram().RemoveShape(action)
+            canvas.RemoveShapes([action])
             self.frame.ModelChanged()
             
             item = self.GetFirstSelected()
@@ -863,22 +857,6 @@
         
         event.Skip()
     
-    def OnRemoveAll(self, event):
-        """!Remove all variable(s) from the model"""
-        deleteDialog = wx.MessageBox(parent=self,
-                                     message=_("Selected data records (%d) will permanently deleted "
-                                               "from table. Do you want to delete them?") % \
-                                         (len(self.listOfSQLStatements)),
-                                     caption=_("Delete records"),
-                                     style=wx.YES_NO | wx.CENTRE)
-        if deleteDialog != wx.YES:
-            return False
-        
-        self.DeleteAllItems()
-        self.itemDataMap = dict()
-
-        self.parent.UpdateModelVariables()
-
     def OnEndEdit(self, event):
         """!Finish editing of item"""
         itemIndex = event.GetIndex()
@@ -886,62 +864,69 @@
         
         self.itemDataMap[itemIndex][columnIndex] = event.GetText()
         
-        aId = int(self.GetItem(itemIndex, 0).GetText())
-        action = self.frame.GetModel().GetItem(aId)
+        action = self.frame.GetModel().GetItem(itemIndex)
         if not action:
             event.Veto()
-        if columnIndex == 0:
-            action.SetId(int(event.GetText()))
         
         self.frame.ModelChanged()
 
     def OnReload(self, event = None):
         """!Reload list of actions"""
-        self.Populate(self.frame.GetModel().GetItems())
+        self.Populate(self.frame.GetModel().GetItems(objType=ModelAction))
 
     def OnRightUp(self, event):
         """!Mouse right button up"""
         if self.disablePopup:
             return
         
-        if not hasattr(self, "popupID1"):
-            self.popupID1 = wx.NewId()
-            self.popupID2 = wx.NewId()
-            self.popupID3 = wx.NewId()
-            self.popupID4 = wx.NewId()
-            self.Bind(wx.EVT_MENU, self.OnRemove,    id = self.popupID1)
-            self.Bind(wx.EVT_MENU, self.OnRemoveAll, id = self.popupID2)
-            self.Bind(wx.EVT_MENU, self.OnReload,    id = self.popupID3)
-            self.Bind(wx.EVT_MENU, self.OnNormalize, id = self.popupID4)
+        if not hasattr(self, "popupId"):
+            self.popupID = dict()
+            self.popupID['remove'] = wx.NewId()
+            self.popupID['reload'] = wx.NewId()
+            self.Bind(wx.EVT_MENU, self.OnRemove,    id = self.popupID['remove'])
+            self.Bind(wx.EVT_MENU, self.OnReload,    id = self.popupID['reload'])
 
         # generate popup-menu
         menu = wx.Menu()
-        menu.Append(self.popupID1, _("Delete selected"))
-        menu.Append(self.popupID2, _("Delete all"))
+        menu.Append(self.popupID['remove'], _("Delete selected"))
         if self.GetFirstSelected() == -1:
-            menu.Enable(self.popupID1, False)
-            menu.Enable(self.popupID2, False)
-        
+            menu.Enable(self.popupID['remove'], False)
         menu.AppendSeparator()
-        menu.Append(self.popupID4, _("Normalize"))
-        menu.Append(self.popupID3, _("Reload"))
+        menu.Append(self.popupID['reload'], _("Reload"))
         
         self.PopupMenu(menu)
         menu.Destroy()
     
-    def OnNormalize(self, event):
-        """!Update id of actions"""
-        model = self.frame.GetModel()
+    def MoveItems(self, items, up):
+        """!Move items in the list
+
+        @param items list of items to move
+        @param up True to move up otherwise down
+        """
+        if len(items) < 1:
+            return
         
-        aId = 1
-        for item in model.GetItems():
-            item.SetId(aId)
-            aId += 1
+        if items[0] == 0 and up:
+            del items[0]
+        if len(items) < 1:
+            return
         
-        self.OnReload(None)
-        self.frame.GetCanvas().Refresh()
-        self.frame.ModelChanged()
+        if items[-1] == len(self.itemDataMap.keys())-1 and not up:
+            del items[-1]
+        if len(items) < 1:
+            return
 
+        model = self.frame.GetModel()        
+        modelActions = model.GetItems(objType=ModelAction)
+        idxList = dict()
+        for i in items:
+            idxList[model.GetItemIndex(modelActions[i])] =  model.GetItemIndex(modelActions[i-1])
+        
+        # reorganize model items
+        model.ReorderItems(idxList)
+        model.Normalize()
+        self.Populate(model.GetItems(objType=ModelAction))
+        
 class ItemCheckListCtrl(ItemListCtrl, listmix.CheckListCtrlMixin):
     def __init__(self, parent, shape, columns, window = None, **kwargs):
         self.parent = parent
@@ -949,7 +934,7 @@
         
         ItemListCtrl.__init__(self, parent, columns, disablePopup = True, **kwargs)
         listmix.CheckListCtrlMixin.__init__(self)
-        self.SetColumnWidth(0, 50)
+        self.SetColumnWidth(0, 100)
         
         self.shape  = shape
         
@@ -969,12 +954,12 @@
         """!Get list of selected actions"""
         ids = { 'checked'   : list(),
                 'unchecked' : list() }
+        # action ids start at 1
         for i in range(self.GetItemCount()):
-            iId = int(self.GetItem(i, 0).GetText())
             if self.IsChecked(i):
-                ids['checked'].append(iId)
+                ids['checked'].append(i+1)
             else:
-                ids['unchecked'].append(iId)
+                ids['unchecked'].append(i+1)
             
         return ids
 

Modified: grass/trunk/gui/wxpython/gmodeler/frame.py
===================================================================
--- grass/trunk/gui/wxpython/gmodeler/frame.py	2013-11-03 01:07:59 UTC (rev 58143)
+++ grass/trunk/gui/wxpython/gmodeler/frame.py	2013-11-03 19:16:23 UTC (rev 58144)
@@ -907,7 +907,7 @@
     def DefineLoop(self, loop):
         """!Define loop with given list of items"""
         parent = loop
-        items = loop.GetItems()
+        items = loop.GetItems(self.GetModel().GetItems())
         if not items:
             return
         
@@ -928,7 +928,7 @@
             parent = item
         
         # close loop
-        item = loop.GetItems()[-1]
+        item = items[-1]
         rel = ModelRelation(parent = self, fromShape = item, toShape = loop)
         loop.AddRelation(rel)
         self.AddLine(rel)
@@ -1138,14 +1138,16 @@
             dlg.CentreOnParent()
             if dlg.ShowModal() == wx.ID_OK:
                 shape.SetText(dlg.GetCondition())
+                model = self.frame.GetModel()
+                modelActions = model.GetItems(objType=ModelAction)
                 ids = dlg.GetItems()
                 for b in ids.keys():
                     alist = list()
-                    for aId in ids[b]['unchecked']:
-                        action = self.frame.GetModel().GetItem(aId)
+                    for idx in ids[b]['unchecked']:
+                        action = modelActions[idx]
                         action.UnSetBlock(shape)
-                    for aId in ids[b]['checked']:
-                        action = self.frame.GetModel().GetItem(aId)
+                    for idx in ids[b]['checked']:
+                        action = modelActions[idx]
                         action.SetBlock(shape)
                         if action:
                             alist.append(action)
@@ -1464,9 +1466,15 @@
                                     label=" %s " % _("List of items - right-click to delete"))
         
         self.list = ItemListCtrl(parent = self,
-                                 columns = [_("ID"), _("Name"), _("In block"),
+                                 columns = [_("Name"), _("In block"),
                                             _("Command / Condition")])
         
+        self.btnMoveUp = wx.Button(parent=self, id=wx.ID_UP)
+        self.btnMoveDown = wx.Button(parent=self, id=wx.ID_DOWN)
+        
+        self.btnMoveUp.Bind(wx.EVT_BUTTON, self.OnMoveItemsUp)
+        self.btnMoveDown.Bind(wx.EVT_BUTTON, self.OnMoveItemsDown)
+        
         self._layout()
 
     def _layout(self):
@@ -1475,10 +1483,17 @@
         listSizer.Add(item = self.list, proportion = 1,
                       flag = wx.EXPAND)
         
-        mainSizer = wx.BoxSizer(wx.VERTICAL)
+        manageSizer = wx.BoxSizer(wx.VERTICAL)
+        manageSizer.Add(item=self.btnMoveUp, border = 5, flag = wx.ALL)
+        manageSizer.Add(item=self.btnMoveDown, border = 5,
+                        flag = wx.LEFT | wx.RIGHT)
+        
+        mainSizer = wx.BoxSizer(wx.HORIZONTAL)
         mainSizer.Add(item = listSizer, proportion = 1,
-                      flag = wx.EXPAND | wx.ALL | wx.ALIGN_CENTER, border = 5)
-        
+                      flag = wx.EXPAND | wx.ALL | wx.ALIGN_CENTER, border = 3)
+        mainSizer.Add(item = manageSizer, proportion = 0,
+                      flag = wx.EXPAND | wx.ALL | wx.ALIGN_CENTER, border = 3)
+
         self.SetSizer(mainSizer)
         mainSizer.Fit(self)
         
@@ -1486,6 +1501,40 @@
         """!Reload list of variables"""
         self.list.OnReload(None)
 
+    def _getSelectedItems(self):
+        """!Get list of selected items, indeces start at 0"""
+        items = []
+        current = -1
+        while True:
+            next = self.list.GetNextSelected(current)
+            if next == -1:
+                break
+            items.append(next)
+            current = next
+        
+        if not items:
+            GMessage(_("No items to selected."), parent = self)
+            
+        return items
+    
+    def OnMoveItemsUp(self, event):
+        """!Item moved up, update action ids"""
+        items = self._getSelectedItems()
+        if not items:
+            return
+        self.list.MoveItems(items, up = True)
+        self.parent.GetCanvas().Refresh()
+        self.parent.ModelChanged()
+
+    def OnMoveItemsDown(self, event):
+        """!Item moved up, update action ids"""
+        items = self._getSelectedItems()
+        if not items:
+            return
+        self.list.MoveItems(items, up = False)
+        self.parent.GetCanvas().Refresh()
+        self.parent.ModelChanged()
+    
 class PythonPanel(wx.Panel):
     def __init__(self, parent, id = wx.ID_ANY,
                  **kwargs):

Modified: grass/trunk/gui/wxpython/gmodeler/model.py
===================================================================
--- grass/trunk/gui/wxpython/gmodeler/model.py	2013-11-03 01:07:59 UTC (rev 58143)
+++ grass/trunk/gui/wxpython/gmodeler/model.py	2013-11-03 19:16:23 UTC (rev 58144)
@@ -53,7 +53,7 @@
 class Model(object):
     """!Class representing the model"""
     def __init__(self, canvas = None):
-        self.items      = list() # list of actions/loops/...
+        self.items   = list() # list of ordered items (action/loop/condition)
         
         # model properties
         self.properties = { 'name'        : _("model"),
@@ -68,7 +68,7 @@
     def GetCanvas(self):
         """!Get canvas or None"""
         return self.canvas
-    
+
     def GetItems(self, objType = None):
         """!Get list of model items
 
@@ -83,8 +83,8 @@
                 result.append(item)
         
         return result
-
-    def GetItem(self, aId):
+    
+    def GetItem(self, aId, objType=None):
         """!Get item of given id
 
         @param aId item id
@@ -92,13 +92,17 @@
         @return Model* instance
         @return None if no item found
         """
-        ilist = self.GetItems()
+        ilist = self.GetItems(objType)
         for item in ilist:
             if item.GetId() == aId:
                 return item
-        
+
         return None
 
+    def GetItemIndex(self, item):
+        """!Return list index of given item"""
+        return self.items.index(item)
+    
     def GetNumItems(self, actionOnly = False):
         """!Get number of items"""
         if actionOnly:
@@ -106,6 +110,17 @@
         
         return len(self.GetItems())
 
+    def ReorderItems(self, idxList):
+        for oldIdx, newIdx in idxList.iteritems():
+            item = self.items.pop(oldIdx)
+            self.items.insert(newIdx, item)
+
+    def Normalize(self):
+        iId = 1
+        for item in self.items:
+            item.SetLabel(iId)
+            iId += 1
+        
     def GetNextId(self):
         """!Get next id (data ignored)
 
@@ -138,7 +153,7 @@
     def Reset(self):
         """!Reset model"""
         self.items = list()
-        
+
     def RemoveItem(self, item):
         """!Remove item from model
         
@@ -147,8 +162,7 @@
         relList = list()
         upList = list()
         
-        if not isinstance(item, ModelData):
-            self.items.remove(item)
+        self.items.remove(item)
         
         if isinstance(item, ModelAction):
             for rel in item.GetRelations():
@@ -323,15 +337,10 @@
 
         # define loops & if/else items
         for loop in gxmXml.loops:
-            alist = list()
-            for aId in loop['items']:
-                action = self.GetItem(aId)
-                alist.append(action)
-            
-            loopItem = self.GetItem(loop['id'])
-            loopItem.SetItems(alist)
-            
-            for action in loopItem.GetItems():
+            loopItem = self.GetItem(loop['id'], objType=ModelLoop)
+            loopItem.SetItems(loop['items'])
+            for idx in loop['items']:
+                action = self.GetItem(idx, objType=ModelAction)
                 action.SetBlock(loopItem)
         
         for condition in gxmXml.conditions:
@@ -348,19 +357,17 @@
                 for action in items[b]:
                     action.SetBlock(conditionItem)
         
-    def AddItem(self, newItem):
+    def AddItem(self, newItem, pos = -1):
         """!Add item to the list"""
-        iId = newItem.GetId()
-        
-        i  = 0
+        if pos != -1:
+            self.items.insert(pos, newItem)
+        else:
+            self.items.append(newItem)
+        i = 1
         for item in self.items:
-            if item.GetId() > iId:
-                self.items.insert(i, newItem)
-                return
+            item.SetLabel(i)
             i += 1
         
-        self.items.append(newItem)
-        
     def IsValid(self):
         """Return True if model is valid"""
         if self.Validate():
@@ -621,9 +628,8 @@
                 params['variables']['params'].append(varDict)
                                 
                 for var in vlist:
-                    for action in item.GetItems():
-                        if not isinstance(action, ModelAction) or \
-                                not action.IsEnabled():
+                    for action in item.GetItems(self.GetItems()):
+                        if not action.IsEnabled():
                             continue
                         
                         varDict['value'] = var
@@ -767,7 +773,7 @@
 
 class ModelObject(object):
     def __init__(self, id = -1):
-        self.id   = id
+        self.id   = id     # internal id, should be not changed
         self.rels = list() # list of ModelRelations
         
         self.isEnabled = True
@@ -779,7 +785,11 @@
     def GetId(self):
         """!Get id"""
         return self.id
-    
+
+    def SetId(self, id):
+        """!Set id"""
+        self.id = id
+
     def AddRelation(self, rel):
         """!Record new relation
         """
@@ -925,15 +935,13 @@
         pen.SetWidth(width)
         self.SetPen(pen)
 
-    def SetId(self, id):
-        """!Set id"""
-        self.id = id
+    def SetLabel(self, idx=-1):
         cmd = self.task.get_cmd(ignoreErrors = True)
+        self.ClearText()
         if cmd and len(cmd) > 0:
-            self.ClearText()
-            self.AddText('(%d) %s' % (self.id, cmd[0]))
+            self.AddText('(%d) %s' % (idx, cmd[0]))
         else:
-            self.AddText('(%d) <<%s>>' % (self.id, _("unknown")))
+            self.AddText('(%d) <<%s>>' % (idx, _("unknown")))
         
     def SetProperties(self, params, propwin):
         """!Record properties dialog"""
@@ -1335,15 +1343,20 @@
         ModelObject.__init__(self, id)
         self.parent  = parent
         self.text    = text
-        self.items   = items  # list of items in the loop
+        self.itemIds = list() # unordered
         
     def GetText(self):
         """!Get loop text"""
         return self.text
 
-    def GetItems(self):
-        """!Get items (id)"""
-        return self.items
+    def GetItems(self, items):
+        """!Get sorted items by id"""
+        result = list()
+        for item in items:
+            if item.GetId() in self.itemIds:
+                result.append(item)
+        
+        return result
 
     def SetId(self, id):
         """!Set loop id"""
@@ -1371,9 +1384,10 @@
         self.rels = list()
    
 class ModelLoop(ModelItem, ogl.RectangleShape):
-    def __init__(self, parent, x, y, id = -1, width = None, height = None, text = '', items = []):
+    def __init__(self, parent, x, y, id=-1, idx=-1, width = None, height = None, text = '', items = []):
         """!Defines a loop"""
         ModelItem.__init__(self, parent, x, y, id, width, height, text, items)
+        self.cond = text
         
         if not width:
             width = UserSettings.Get(group='modeler', key='loop', subkey=('size', 'width'))
@@ -1388,10 +1402,6 @@
             self.SetY(y)
             self.SetPen(wx.BLACK_PEN)
             self.SetCornerRadius(100)
-            if text:
-                self.AddText('(' + str(self.id) + ') ' + text)
-            else:
-                self.AddText('(' + str(self.id) + ')')
         
         self._setBrush()
         
@@ -1407,6 +1417,13 @@
         wxColor = wx.Colour(color[0], color[1], color[2])
         self.SetBrush(wx.Brush(wxColor))
 
+    def SetLabel(self, idx=-1):
+        self.ClearText()
+        if self.cond:
+            self.AddText('(%d) %s' % (idx, self.cond))
+        else:
+            self.AddText('(%d)' % (idx))
+                         
     def Enable(self, enabled = True):
         """!Enable/disable action"""
         for item in self.items:
@@ -1425,7 +1442,7 @@
     
     def SetItems(self, items):
         """!Set items (id)"""
-        self.items = items
+        self.itemIds = items
 
     def OnDraw(self, dc):
         """!Draw loop in canvas"""



More information about the grass-commit mailing list