Fix widgets selection order
[ipypbx] / src / ipypbx / controllers.py
index 2bb3169..1277d3a 100644 (file)
 # along with IPyPBX.  If not, see <http://www.gnu.org/licenses/>.
 
 #from ipypbx import models
-from PyQt4 import QtCore
+from PyQt4 import QtCore, QtGui, QtSql
 
 
-class BaseHandler(object):
+class BaseController(QtCore.QObject):
     """
-    Base class for various entity handlers.
+    Base class for other controllers.
 
     Doesn't do anything useful on its own.
     """
-    items = None
-    current_items = None
-
-    def __init__(self, parent):
-        self.parent = parent
-        self.initState()
+    fields = ()
+    view_list_fields = ()
+    view_display_fields = ()
+    
+    def __init__(self, model=None, view_list=None, view_display=None, parent=None, views=None):
+        super(BaseController, self).__init__(parent=parent)
+
+        self.views = views
+        
+        # Find out base name.
+        classname = self.__class__.__name__
+        self.basename = (
+            classname[:-10] if classname.endswith('Controller')
+            else classname)
+        self.basename = self.basename[0].lower() + self.basename[1:]
+
+        if model:
+            # We're given an existing model.
+            self.model = model
+        else:
+            # Initialize a new model.
+            self.model = QtSql.QSqlTableModel(parent)
+            self.model.setTable(self.basename + 's')
+
+            # Create model header from fields list.
+            for i, field in enumerate(self.fields):
+                self.model.setHeaderData(
+                    i, QtCore.Qt.Horizontal, QtCore.QVariant(field))
+
+            # Fetch model data.
+            self.model.select()
+
+        if view_list:
+            # We're given an existing view list.
+            self.view_list = view_list
+        else:
+            # Get view list from the parent.
+            self.view_list = getattr(views, self.basename + 'ViewList')
+            self.view_list.setModel(self.model)
+
+            # Hide fields not meant for display.
+            for i, field in enumerate(self.fields):
+                if field not in self.view_list_fields:
+                    self.view_list.setColumnHidden(i, True)
+
+            # Stretch headers to fill all available width.
+            self.view_list.setSelectionMode(QtGui.QTableView.SingleSelection)
+            self.view_list.setSelectionBehavior(QtGui.QTableView.SelectRows)
+            self.view_list.resizeColumnsToContents()
+            self.view_list.resizeRowsToContents()
+            self.view_list.horizontalHeader().setStretchLastSection(True)
+
+        if view_display:
+            # We're given an existing view display.
+            self.view_display = view_display
+        else:
+            # Get view display from the parent.
+            self.view_display = QtGui.QDataWidgetMapper(parent)
+            #getattr(parent, self.basename + 'ViewDisplay')
+            self.view_display.setModel(self.model)
+
+            # If view_display_fields is not send, display all fields except
+            # the first one that is usually the ID.
+            display_fields = self.view_display_fields or self.fields[1:]
+            for i, field in enumerate(self.fields):
+                if field in display_fields:
+                    field_name = self.basename + ''.join(
+                        word.capitalize() for word in field.split(' '))
+                    self.view_display.addMapping(
+                        getattr(views, field_name), i)
+
+        # Register signals for this controller.
+        for sender, signal, receiver in self.getSignalsData():
+            QtCore.QObject.connect(sender, QtCore.SIGNAL(signal), receiver)        
+
+    def getSignalsData(self):
+        """
+        Default signals built from controller's base name.
+        """
+        return (
+            (getattr(self.views, self.basename + 'Add'), 'clicked()', self.add),
+            (getattr(self.views, self.basename + 'ViewList'),
+             'currentRowChanged(int)', self.select),
+            (getattr(self.views, self.basename + 'Save'), 'clicked()',
+             self.save),
+            )
 
-    def initState(self):
+    def add(self):
+        """
+        Add new connection.
+        """
+        num_rows = self.model.rowCount()
+        self.model.insertRows(num_rows, 1)
+        self.view_list.selectRow(num_rows)
+        getattr(self.views, self.basename + 'Add').setEnabled(False)
+            
+        #self.parent.ui.connectionName.setText('New connection')
+        #self.parent.ui.connectionName.setFocus()
+        #self.parent.ui.connectionName.selectAll()
+        #self.parent.ui.connectionLocalIpAddress.clear()
+        #self.parent.ui.connectionLocalPort.clear()
+        #self.parent.ui.connectionFreeswitchIpAddress.clear()
+        #self.parent.ui.connectionFreeswitchPort.clear()
+    
+    def save(self):
+        """
+        TODO: Default implementation.
+        """
         return NotImplemented
 
 
-class ConnectionController(QtCore.QObject):
+class ConnectionController(BaseController):
     """
     Connections handler.
     """
-#    def initState(self):
-#        self.connections = []
-#        #self.connections = list(state.store.query(models.Connection))
-#        self.currentConnection = None
-
-#        for connection in self.connections:
-#            self.parent.ui.connectionList.addItem(connection.name)
-
-#        if self.connections:
-#            print self.parent.ui.connectionList.currentRow()
-#            self.parent.ui.connectionList.setCurrentRow(0)
-#            QtCore.QObject.emit(
-#                self.parent.ui.connectionList, QtCore.SIGNAL('currentRowChanged(int)'), 0)
-        
+    fields = (
+        'ID', 'Name', 'Local IP Address', 'Local Port',
+        'Freeswitch IP Address', 'Freeswitch Port')
+    view_list_fields = ('Name', 'Freeswitch IP Address', 'Freeswitch Port')
+    
     def select(self, row):
         """
         Select another connection as current.
@@ -78,34 +169,6 @@ class ConnectionController(QtCore.QObject):
         This creates a new connection with bound data copied from another one.
         """
 
-    def add(self):
-        """
-        Add new connection.
-        """
-        print '!'
-        print self.parent
-        self.currentConnection = None
-
-        name_template = 'New connection [{0:02}]'
-        for i in xrange(1, 100):
-            name = name_template.format(i)
-            connection_exists = False
-            for connection in self.connections:
-                if connection.name == name:
-                    connection_exists = True
-                    break
-
-            if not connection_exists:
-                break
-            
-        self.parent.ui.connectionName.setText('New connection')
-        self.parent.ui.connectionName.setFocus()
-        self.parent.ui.connectionName.selectAll()
-        self.parent.ui.connectionLocalIpAddress.clear()
-        self.parent.ui.connectionLocalPort.clear()
-        self.parent.ui.connectionFreeswitchIpAddress.clear()
-        self.parent.ui.connectionFreeswitchPort.clear()
-
     def save(self):
         """
         Save new or existing connection.