1 # Copyright (c) Stas Shtin, 2010
3 # This file is part of IPyPBX.
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.
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.
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/>.
18 from PyQt4 import QtCore, QtGui, QtSql
21 class BaseController(QtCore.QObject):
23 Base class for other controllers.
25 Doesn't do anything useful on its own.
27 # TODO: possibly use a separate class for options and a meta-class.
30 view_display_fields = ()
31 view_display_fields_hidden = 'ID', 'Connection ID'
32 is_bound_to_connection = True
34 def __init__(self, model=None, view_list=None, view_display=None, parent=None, views=None):
35 super(BaseController, self).__init__(parent=parent)
40 classname = self.__class__.__name__
42 classname[:-10] if classname.endswith('Controller')
44 self.basename = self.basename[0].lower() + self.basename[1:]
46 # Are we given an existing model?
49 # Otherwise initialize a new model.
51 self.model = QtSql.QSqlTableModel(parent)
52 self.model.setTable('ipypbxweb_%s' % self.basename.lower())
53 self.model.setEditStrategy(self.model.OnRowChange)
55 # Create model header from fields list.
56 for i, field in enumerate(self.fields):
57 self.model.setHeaderData(
58 i, QtCore.Qt.Horizontal,
59 QtCore.QVariant(QtGui.QApplication.translate(
60 "MainWindow", field, None,
61 QtGui.QApplication.UnicodeUTF8)))
66 # Are we given an existing view list?
68 self.view_list = view_list
69 # Otherwise get view list from the parent.
71 self.view_list = getattr(views, self.basename + 'ViewList')
72 self.view_list.setModel(self.model)
74 # Hide fields not meant for display.
75 for i, field in enumerate(self.fields):
76 if field not in self.view_list_fields:
77 self.view_list.hideColumn(i)
79 # Stretch headers to fill all available width.
80 self.view_list.setSelectionMode(QtGui.QTableView.SingleSelection)
81 self.view_list.setSelectionBehavior(QtGui.QTableView.SelectRows)
82 self.view_list.resizeColumnsToContents()
83 self.view_list.resizeRowsToContents()
84 self.view_list.horizontalHeader().setStretchLastSection(True)
87 self.view_list.selectRow(0)
89 # Are we given an existing view display?
91 self.view_display = view_display
92 # Otherwise get view display from the parent.
94 self.view_display = QtGui.QDataWidgetMapper(parent)
95 self.view_display.setModel(self.model)
97 display_fields = self.getDisplayFields()
99 for i, field in enumerate(self.fields):
100 if field in display_fields:
101 field_widget = self.getFieldWidget(field)
102 self.view_display.addMapping(field_widget, i)
104 # Select first row in the view list.
105 self.view_display.toFirst()
107 # Register signals for this controller.
108 for data in self.getSignalsData():
110 sender, signal, receiver = data
111 QtCore.QObject.connect(sender, QtCore.SIGNAL(signal), receiver)
113 sender, signal, receiver, slot = data
114 QtCore.QObject.connect(
115 sender, QtCore.SIGNAL(signal), receiver, QtCore.SLOT(slot))
117 def getFieldWidget(self, field):
119 Return widget for given field name.
123 self.basename + ''.join(word.capitalize()
124 for word in field.split(' ')))
126 def getDisplayFields(self):
128 Return list of display fields.
130 If view_display_fields is not send, display all fields except
131 the first one that is usually the ID.
134 field for field in self.fields
135 if not field in self.view_display_fields_hidden]
137 def getSignalsData(self):
139 Default signals built from controller's base name.
141 # Default signals handle row selection, Add and Save buttons.
143 (getattr(self.views, self.basename + 'Add'), 'clicked()', self.add),
144 (self.view_list.selectionModel(),
145 'currentRowChanged(QModelIndex,QModelIndex)',
146 self.view_display, 'setCurrentModelIndex(QModelIndex)'),
147 (getattr(self.views, self.basename + 'Save'), 'clicked()',
154 # Add a new row to list view.
155 num_rows = self.model.rowCount()
156 self.model.insertRows(num_rows, 1)
157 self.view_list.selectRow(num_rows)
159 # Disable adding more than one row.
160 self.getFieldWidget('Add').setEnabled(False)
162 # Focust to the first displayed field.
163 self.getFieldWidget(self.getDisplayFields()[0]).setFocus()
165 # TODO: set default values?
171 self.view_display.submit()
172 self.getFieldWidget('Add').setEnabled(True)
175 class ConnectionController(BaseController):
177 Connections controller.
180 QtCore.QT_TRANSLATE_NOOP('MainWindow', 'ID'),
181 QtCore.QT_TRANSLATE_NOOP('MainWindow', 'Name'),
182 QtCore.QT_TRANSLATE_NOOP('MainWindow', 'Local IP Address'),
183 QtCore.QT_TRANSLATE_NOOP('MainWindow', 'Local Port'),
184 QtCore.QT_TRANSLATE_NOOP('MainWindow', 'Freeswitch IP Address'),
185 QtCore.QT_TRANSLATE_NOOP('MainWindow', 'Freeswitch Port'))
186 view_list_fields = 'Name', 'Freeswitch IP Address', 'Freeswitch Port'
189 class ConnectionChangeListenerController(BaseController):
191 Mixin class for reacting on connection change.
193 def getSignalsData(self):
195 Listen to connection change signal.
197 connection_controller = self.parent().controllers[0]
200 (connection_controller.view_list.selectionModel(),
201 'currentRowChanged(QModelIndex,QModelIndex)',
202 self.connectionChange),
203 (self.model, 'primeInsert(int,QSqlRecord&)',
204 self.setConnectionId)]
205 signals.extend(super(
206 ConnectionChangeListenerController, self).getSignalsData())
209 def connectionChange(self, index):
211 Connection change handler.
213 Filters table by a new connection ID and stores last connection ID
216 if index.row() != -1:
217 connection_id, ok = index.model().data(
218 index.sibling(index.row(), 0)).toInt()
219 self.connection_id = connection_id
220 self.model.setFilter('connection_id = %i' % connection_id)
222 def setConnectionId(self, row, record):
223 record.setValue('connection_id', self.connection_id)
226 class SipProfileController(ConnectionChangeListenerController):
228 SIP Profile controller.
231 QtCore.QT_TRANSLATE_NOOP('MainWindow', 'ID'),
232 QtCore.QT_TRANSLATE_NOOP('MainWindow', 'Connection ID'),
233 QtCore.QT_TRANSLATE_NOOP('MainWindow', 'Name'),
234 QtCore.QT_TRANSLATE_NOOP('MainWindow', 'External RTP IP'),
235 QtCore.QT_TRANSLATE_NOOP('MainWindow', 'External SIP IP'),
236 QtCore.QT_TRANSLATE_NOOP('MainWindow', 'RTP IP'),
237 QtCore.QT_TRANSLATE_NOOP('MainWindow', 'SIP IP'),
238 QtCore.QT_TRANSLATE_NOOP('MainWindow', 'SIP Port'),
239 QtCore.QT_TRANSLATE_NOOP('MainWindow', 'Accept Blind Registration'),
240 QtCore.QT_TRANSLATE_NOOP('MainWindow', 'Authenticate Calls'),
241 QtCore.QT_TRANSLATE_NOOP('MainWindow', 'Is Active'))
242 view_list_fields = 'Name', 'SIP IP', 'SIP Port'
245 class DomainController(ConnectionChangeListenerController):
250 QtCore.QT_TRANSLATE_NOOP('MainWindow', 'ID'),
251 QtCore.QT_TRANSLATE_NOOP('MainWindow', 'Connection ID'),
252 QtCore.QT_TRANSLATE_NOOP('MainWindow', 'SIP Profile ID'),
253 QtCore.QT_TRANSLATE_NOOP('MainWindow', 'Host Name'),
254 QtCore.QT_TRANSLATE_NOOP('MainWindow', 'Is Active'))
255 view_list_fields = 'SIP Profile', 'Host Name'
258 class GatewayController(ConnectionChangeListenerController):
263 QtCore.QT_TRANSLATE_NOOP('MainWindow', 'ID'),
264 QtCore.QT_TRANSLATE_NOOP('MainWindow', 'Connection ID'),
265 QtCore.QT_TRANSLATE_NOOP('MainWindow', 'SIP Profile ID'),
266 QtCore.QT_TRANSLATE_NOOP('MainWindow', 'Name'),
267 QtCore.QT_TRANSLATE_NOOP('MainWindow', 'Username'),
268 QtCore.QT_TRANSLATE_NOOP('MainWindow', 'Password'),
269 QtCore.QT_TRANSLATE_NOOP('MainWindow', 'Realm'),
270 QtCore.QT_TRANSLATE_NOOP('MainWindow', 'From Domain'),
271 QtCore.QT_TRANSLATE_NOOP('MainWindow', 'Expire In Seconds'),
272 QtCore.QT_TRANSLATE_NOOP('MainWindow', 'Retry In Seconds'),
273 QtCore.QT_TRANSLATE_NOOP('MainWindow', 'Caller ID In From Field'),
274 QtCore.QT_TRANSLATE_NOOP('MainWindow', 'Is Active'))
275 view_list_fields = 'SIP Profile ID', 'Name'
278 class EndpointController(ConnectionChangeListenerController):
283 QtCore.QT_TRANSLATE_NOOP('MainWindow', 'ID'),
284 QtCore.QT_TRANSLATE_NOOP('MainWindow', 'Connection ID'),
285 QtCore.QT_TRANSLATE_NOOP('MainWindow', 'User ID'),
286 QtCore.QT_TRANSLATE_NOOP('MainWindow', 'Password'),
287 QtCore.QT_TRANSLATE_NOOP('MainWindow', 'Domain ID'),
288 QtCore.QT_TRANSLATE_NOOP('MainWindow', 'Is Active'))
289 view_list_fields = 'User ID', 'Domain ID'
292 class ExtensionController(ConnectionChangeListenerController):
294 Extension controller.
297 QtCore.QT_TRANSLATE_NOOP('MainWindow', 'ID'),
298 QtCore.QT_TRANSLATE_NOOP('MainWindow', 'Connection ID'),
299 QtCore.QT_TRANSLATE_NOOP('MainWindow', 'Destination Match'),
300 QtCore.QT_TRANSLATE_NOOP('MainWindow', 'XML Dialplan'),
301 QtCore.QT_TRANSLATE_NOOP('MainWindow', 'Domain ID'),
302 QtCore.QT_TRANSLATE_NOOP('MainWindow', 'Endpoint ID'),
303 QtCore.QT_TRANSLATE_NOOP('MainWindow', 'Authenticate Calls'),
304 QtCore.QT_TRANSLATE_NOOP('MainWindow', 'Is Active'))
305 view_list_fields = 'Destination Match',