Added base controller class and implementation for connections tab
[ipypbx] / src / ipypbx / controllers.py
1 # Copyright (c) Stas Shtin, 2010
2
3 # This file is part of IPyPBX.
4
5 # IPyPBX 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 # IPyPBX 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 IPyPBX.  If not, see <http://www.gnu.org/licenses/>.
17
18 #from ipypbx import models
19 from PyQt4 import QtCore, QtGui, QtSql
20
21
22 class BaseController(QtCore.QObject):
23     """
24     Base class for other controllers.
25
26     Doesn't do anything useful on its own.
27     """
28     fields = ()
29     hidden_fields = ()
30     visible_fields = ()
31     
32     def __init__(self, model=None, view_list=None, view_display=None, parent=None):
33         super(BaseController, self).__init__(parent)
34         
35         # Find out base name.
36         classname = self.__class__.__name__
37         self.base_name = (
38             classname[:-10] if classname.endswith('Controller')
39             else classname)
40         self.base_name = self.base_name[0].lower() + self.base_name[1:]
41
42         if model:
43             # We're given an existing model.
44             self.model = model
45         else:
46             # Initialize a new model.
47             self.model = QtSql.QSqlTableModel(parent)
48             self.model.setTable(self.base_name + 's')
49
50             # Create model header from fields list.
51             for i, field in enumerate(self.fields):
52                 self.model.setHeaderData(
53                     i, QtCore.Qt.Horizontal, QtCore.QVariant(field))
54
55             # Fetch model data.
56             self.model.select()
57
58         if view_list:
59             # We're given an existing view list.
60             self.view_list = view_list
61         else:
62             # Get view list from the parent.
63             self.view_list = getattr(parent, self.base_name + 'ViewList')
64             self.view_list.setModel(self.model)
65
66             # Hide fields not meant for display.
67             for i, field in enumerate(self.fields):
68                 if (field in self.hidden_fields or
69                     field not in self.visible_fields):
70                     self.view_list.setColumnHidden(i, True)
71
72             # Stretch headers to fill all available width.
73             self.view_list.setSelectionMode(QtGui.QTableView.SingleSelection)
74             self.view_list.setSelectionBehavior(QtGui.QTableView.SelectRows)
75             self.view_list.resizeColumnsToContents()
76             self.view_list.resizeRowsToContents()
77             self.view_list.horizontalHeader().setStretchLastSection(True)
78
79         if view_display:
80             # We're given an existing view display.
81             self.view_display = view_display
82         else:
83             # Get view display from the parent.
84             self.view_display = getattr(parent, self.base_name + 'ViewDisplay')
85             self.view_display.setModel(self.model)
86
87         # Register signals for this controller.
88         for sender, signal, receiver in self.getSignalsData():
89             QtCore.QObject.connect(sender, QtCore.SIGNAL(signal), receiver)        
90
91     def getSignalsData(self):
92         """
93         Default signals built from controller's base name.
94         """
95         parent = self.parent()
96         
97         return (
98             (getattr(parent, self.base_name + 'Add'), 'clicked()', self.add),
99             (getattr(parent, self.base_name + 'ViewList'),
100              'currentRowChanged(int)', self.select),
101             (getattr(parent, self.base_name + 'Save'), 'clicked()',
102              self.save),
103             )
104
105     def add(self):
106         """
107         TODO: Default implementation.
108         """
109         return NotImplemented
110     
111     def save(self):
112         """
113         TODO: Default implementation.
114         """
115         return NotImplemented
116
117     def add(self):
118         """
119         TODO: Default implementation.
120         """
121         return NotImplemented
122
123
124 class ConnectionController(BaseController):
125     """
126     Connections handler.
127     """
128     fields = (
129         'ID', 'Name', 'Local IP Address', 'Local Port',
130         'Freeswitch IP Address', 'Freeswitch Port')
131     visible_fields = ('Name', 'Freeswitch IP Address', 'Freeswitch Port')
132     
133     def select(self, row):
134         """
135         Select another connection as current.
136         """
137         self.currentConnection = self.connections[row]
138
139         # Fill in form based on selection.
140         self.parent.ui.connectionName.setText(self.currentConnection.name)
141         self.parent.ui.connectionLocalIpAddress.setText(
142             self.currentConnection.local_ip_address)
143         self.parent.ui.connectionLocalPort.setText(
144             unicode(self.currentConnection.local_port))
145         self.parent.ui.connectionFreeswitchIpAddress.setText(
146             self.currentConnection.freeswitch_ip_address)
147         self.parent.ui.connectionFreeswitchPort.setText(
148             unicode(self.currentConnection.freeswitch_port))
149
150     def clone(self):
151         """
152         TODO: Clone an existing connection.
153
154         This creates a new connection with bound data copied from another one.
155         """
156
157     def add(self):
158         """
159         Add new connection.
160         """
161         self.currentConnection = None
162
163         name_template = 'New connection [{0:02}]'
164         for i in xrange(1, 100):
165             name = name_template.format(i)
166             connection_exists = False
167             for connection in self.connections:
168                 if connection.name == name:
169                     connection_exists = True
170                     break
171
172             if not connection_exists:
173                 break
174             
175         self.parent.ui.connectionName.setText('New connection')
176         self.parent.ui.connectionName.setFocus()
177         self.parent.ui.connectionName.selectAll()
178         self.parent.ui.connectionLocalIpAddress.clear()
179         self.parent.ui.connectionLocalPort.clear()
180         self.parent.ui.connectionFreeswitchIpAddress.clear()
181         self.parent.ui.connectionFreeswitchPort.clear()
182
183     def save(self):
184         """
185         Save new or existing connection.
186         """
187         name = unicode(self.parent.ui.connectionName.text())
188
189         # Add to connection list if we've created it.
190         if self.currentConnection is None:            
191             #self.currentConnection = models.Connection(store=state.store)            
192             self.connections.append(self.currentConnection)
193             self.parent.ui.connectionList.addItem(name)
194
195         self.currentConnection.name = name
196         self.currentConnection.local_ip_address = unicode(
197             self.parent.ui.connectionLocalIpAddress.text())
198         self.currentConnection.local_port = int(
199             self.parent.ui.connectionLocalPort.text())
200         self.currentConnection.freeswitch_ip_address = unicode(
201             self.parent.ui.connectionFreeswitchIpAddress.text())
202         self.currentConnection.freeswitch_port = int(
203             self.parent.ui.connectionFreeswitchPort.text())
204
205         self.currentConnection.checkpoint()