Adding support for DB access from unit tests
[ipypbx] / src / ipypbx / controllers.py
index 61fc6f9..316e329 100644 (file)
@@ -122,13 +122,30 @@ class BaseController(QtCore.QObject):
 
         # Select first row in the view list.
         self.view_display.toFirst()
-        
-        # Register signals for this controller.
-        for data in self.getSignalsData():
+
+        # Signals for this controller.
+        signal_data = (
+            (getattr(self.views, self.basename + 'Add'), 'clicked()',
+             self.add),
+            (self.model, 'primeInsert(int,QSqlRecord&)', self.objectAdded),
+            (self.view_list.selectionModel(),
+             'currentRowChanged(QModelIndex,QModelIndex)',
+             self.view_display, 'setCurrentModelIndex(QModelIndex)'),
+            (self.parent().controllers.get('connection', self
+                                           ).view_list.selectionModel(),
+             'currentRowChanged(QModelIndex,QModelIndex)',
+             self.connectionChange),            
+            (getattr(self.views, self.basename + 'Save'), 'clicked()',
+             self.save))
+
+        # Connect all signals.
+        for data in signal_data:
             if len(data) == 3:
+                # Connect to python function.
                 sender, signal, receiver = data
                 QtCore.QObject.connect(sender, QtCore.SIGNAL(signal), receiver)
             elif len(data) == 4:
+                # Connect to Qt slot.
                 sender, signal, receiver, slot = data
                 QtCore.QObject.connect(
                     sender, QtCore.SIGNAL(signal), receiver, QtCore.SLOT(slot))
@@ -153,20 +170,6 @@ class BaseController(QtCore.QObject):
             field for field in self.fields
             if not field in self.view_display_fields_hidden]        
 
-    def getSignalsData(self):
-        """
-        Default signals built from controller's base name.
-        """
-        # Default signals handle row selection, Add and Save buttons.
-        return [
-            (getattr(self.views, self.basename + 'Add'), 'clicked()', self.add),
-            (self.view_list.selectionModel(),
-             'currentRowChanged(QModelIndex,QModelIndex)',
-             self.view_display, 'setCurrentModelIndex(QModelIndex)'),
-            (getattr(self.views, self.basename + 'Save'), 'clicked()',
-             self.save),
-            ]
-
     def add(self):
         """
         Add new object.
@@ -182,11 +185,19 @@ class BaseController(QtCore.QObject):
         # Focust to the first displayed field.
         self.getFieldWidget(self.getDisplayFields()[0]).setFocus()
 
+    def connectionChange(self, index, row):
+        """
+        Overload to handle connection change.
+        """
+        return NotImplemented
+
     def save(self):
         """
         Save to database.
         """
+        index = self.view_list.currentIndex()
         self.view_display.submit()
+        self.view_list.setCurrentIndex(index)
         self.getFieldWidget('Add').setEnabled(True)
 
 
@@ -206,51 +217,61 @@ class ConnectionController(BaseController):
 
     def __init__(self, parent=None, views=None):
         super(ConnectionController, self).__init__(parent, views)
-        
-        self.last_row = -1
 
         for row in range(self.model.rowCount()):
-            # Get local IP address and port from the table.
-            local_ip_address = self.model.record(row).value(
-                'local_ip_address').toString()
-            local_port, _ok = self.model.record(row).value('local_port').toInt()
-            if not _ok:
-                local_port = None
-
-            server = http.FreeswitchConfigServer()
-            server.setSocket(local_ip_address, local_port)
+            # Get local IP address and port from the table for each row.
+            server = http.FreeswitchConfigServer(self.parent(), )
+            server.setSocketData(*self.getSocketData(row))
             server.startServer()
             self.servers.append(server)
+
+    def getSocketData(self, row):
+        """
+        Return socket data for given row number.
+        """
+        record = self.model.record(row)
+        
+        # Local IP address.
+        local_ip_address = record.value('local_ip_address').toString()
+
+        # Local port.
+        local_port, _ok = record.value('local_port').toInt()
+        if not _ok:
+            local_port = None
+
+        # Connection ID.
+        connection_id, _ok = record.value('id').toInt()
+        if not _ok:
+            connection_id = None
+        
+        return local_ip_address, local_port, connection_id
     
-    def connectionEdit(self, index):
+    def connectionChange(self, index):
         """
         Restart config server on connection change if necessary.
-        """        
+        """
         current_row = index.row()
         if current_row != -1:
-            self.last_row = current_row
             # Select the new row.
             connection_id, _ok = index.model().data(
-                index.sibling(index.row(), 0)).toInt()
-            #self.connection_id = connection_id
-            #if not self.model.rowCount():
-            #    self.add()
-        
+                index.sibling(current_row, 0)).toInt()
 
-    def connectionAdd(self):
+            # Apply new socket location.
+            self.servers[current_row].setSocketData(
+                *self.getSocketData(current_row))
+        
+    def objectAdded(self, row, record):
         """
         New connection added.
         """
-        num_rows = self.model.rowCount()
+        self.addServer(*self.getSocketData(row))
         
-        
-    def addServer(self, host, port):
+    def addServer(self, host=None, port=None, connection_id=None):
         """
         Add a new config server.
         """
-
-        server = http.FreeswitchConfigServer(self)
-        server.setSocket(host, port)
+        server = http.FreeswitchConfigServer(self.model)
+        server.setSocketData(host, port, connection_id)
         server.startServer()
         self.servers.append(server)
 
@@ -259,22 +280,6 @@ class ConnectionChangeListenerController(BaseController):
     """
     Mixin class for reacting on connection change.
     """
-    def getSignalsData(self):
-        """
-        Listen to connection change signal.
-        """
-        # Find connection controller in controller registry.
-        connection_controller = self.parent().controllers['connection']
-        
-        signals = [
-            (self.model, 'primeInsert(int,QSqlRecord&)', self.setConnectionId),
-            (connection_controller.view_list.selectionModel(),
-             'currentRowChanged(QModelIndex,QModelIndex)',
-             self.connectionChange)]
-        signals.extend(super(
-            ConnectionChangeListenerController, self).getSignalsData())
-        return signals
-        
     def connectionChange(self, index):
         """
         Connection change handler.
@@ -282,18 +287,28 @@ class ConnectionChangeListenerController(BaseController):
         Filters table by a new connection ID and stores last connection ID
         locally.
         """
-        if index.row() != -1:
+        index_row = index.row()
+        if index_row != -1:
+            # Get connection_id field value.
             connection_id, _ok = index.model().data(
                 index.sibling(index.row(), 0)).toInt()
             self.connection_id = connection_id
-            self.model.setFilter(
-                'ipypbxweb_%s.connection_id = %i' %
-                (self.basename, connection_id))
+
+            # Filter is customizable in order to allow ugly hacks :-)
+            self.model.setFilter(self.getFilter(connection_id))
+
+            # Select first row.
             self.view_list.selectRow(0)
+
+            # Create a new object if none exist.
             if not self.model.rowCount():
                 self.add()
 
-    def setConnectionId(self, row, record):
+    def getFilter(self, connection_id):
+        return 'ipypbxweb_%s.connection_id = %i' % (
+            self.basename, connection_id)        
+
+    def objectAdded(self, row, record):
         """
         Set connection_id from currently selected connection.
         """
@@ -346,6 +361,7 @@ class GatewayController(ConnectionChangeListenerController):
         QtCore.QT_TRANSLATE_NOOP('MainWindow', 'Password'),
         QtCore.QT_TRANSLATE_NOOP('MainWindow', 'Realm'),
         QtCore.QT_TRANSLATE_NOOP('MainWindow', 'From Domain'),
+        QtCore.QT_TRANSLATE_NOOP('MainWindow', 'Extension'),
         QtCore.QT_TRANSLATE_NOOP('MainWindow', 'Expire In Seconds'),
         QtCore.QT_TRANSLATE_NOOP('MainWindow', 'Retry In Seconds'),
         QtCore.QT_TRANSLATE_NOOP('MainWindow', 'Caller ID In From Field'),
@@ -383,7 +399,20 @@ class ExtensionController(ConnectionChangeListenerController):
         QtCore.QT_TRANSLATE_NOOP('MainWindow', 'Authenticate Calls'),
         QtCore.QT_TRANSLATE_NOOP('MainWindow', 'Is Active'))
     view_list_fields = 'Destination Match',
+    view_display_fields_hidden = 'ID', 'Connection ID', 'Endpoint ID'
     relations = (
         ('domain_id', 'Domain ID', 'domain', 'host_name'),
-        ('endpoint_id', 'Endpoint ID', 'endpoint', 'user_id'))
+#        ('endpoint_id', 'Endpoint ID', 'endpoint', 'user_id'),
+        )
+        
+    def objectAdded(self, row, record):
+        record.setValue(
+            'xml_dialplan', '<action application="echo" data=""/>')
+        super(ExtensionController, self).objectAdded(row, record)
         
+    def getFilter(self, connection_id):
+        # Workaround for Qt bug:
+        # http://bugreports.qt.nokia.com/browse/QTBUG-8217 . Apparently they
+        # don't hurry to fix it.
+        return '1 = 1) or (ipypbxweb_%s.connection_id = %i' % (
+            self.basename, connection_id)