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 = ()
33 def __init__(self, model=None, view_list=None, view_display=None, parent=None, views=None):
34 super(BaseController, self).__init__(parent=parent)
39 classname = self.__class__.__name__
41 classname[:-10] if classname.endswith('Controller')
43 self.basename = self.basename[0].lower() + self.basename[1:]
45 # Are we given an existing model?
48 # Otherwise initialize a new model.
50 self.model = QtSql.QSqlTableModel(parent)
51 self.model.setTable('ipypbxweb_%s' % self.basename.lower())
53 # Create model header from fields list.
54 for i, field in enumerate(self.fields):
55 self.model.setHeaderData(
56 i, QtCore.Qt.Horizontal, QtCore.QVariant(field))
61 # Are we given an existing view list?
63 self.view_list = view_list
64 # Otherwise get view list from the parent.
66 self.view_list = getattr(views, self.basename + 'ViewList')
67 self.view_list.setModel(self.model)
69 # Hide fields not meant for display.
70 for i, field in enumerate(self.fields):
71 if field not in self.view_list_fields:
72 self.view_list.hideColumn(i)
74 # Stretch headers to fill all available width.
75 self.view_list.setSelectionMode(QtGui.QTableView.SingleSelection)
76 self.view_list.setSelectionBehavior(QtGui.QTableView.SelectRows)
77 self.view_list.resizeColumnsToContents()
78 self.view_list.resizeRowsToContents()
79 self.view_list.horizontalHeader().setStretchLastSection(True)
80 self.view_list.selectRow(0)
82 # Are we given an existing view display?
84 self.view_display = view_display
85 # Otherwise get view display from the parent.
87 self.view_display = QtGui.QDataWidgetMapper(parent)
88 self.view_display.setModel(self.model)
90 # If view_display_fields is not send, display all fields except
91 # the first one that is usually the ID.
92 display_fields = self.getDisplayFields()
93 for i, field in enumerate(self.fields):
94 if field in display_fields:
95 field_widget = self.getFieldWidget(field)
96 self.view_display.addMapping(field_widget, i)
98 # Select first row in the view list.
99 self.view_display.toFirst()
101 # Register signals for this controller.
102 for data in self.getSignalsData():
104 sender, signal, receiver = data
105 QtCore.QObject.connect(sender, QtCore.SIGNAL(signal), receiver)
107 sender, signal, receiver, slot = data
108 QtCore.QObject.connect(
109 sender, QtCore.SIGNAL(signal), receiver, QtCore.SLOT(slot))
112 def getDisplayFields(self):
114 Return the list of fields to display.
116 If it's not set explicitly, use all defined fields except the first
117 which usually is the primary key.
119 # Do we have the fields to display explicitly set?
120 if self.view_display_fields:
121 fields = self.view_display_fields
123 # Do we have hidden fields set?
124 if self.view_display_fields_hidden:
125 hidden = self.view_display_fields_hidden
126 # If not, hide the first one.
128 hidden = self.fields[0]
130 # Filter away all hidden fields.
131 fields = [field for field in self.fields if not field in hidden]
135 def getFieldWidget(self, field):
137 Return widget for given field name.
141 self.basename + ''.join(word.capitalize()
142 for word in field.split(' ')))
144 def getSignalsData(self):
146 Default signals built from controller's base name.
148 # Default signals handle row selection, Add and Save buttons.
150 (getattr(self.views, self.basename + 'Add'), 'clicked()', self.add),
151 (self.view_list.selectionModel(),
152 'currentRowChanged(QModelIndex,QModelIndex)',
153 self.view_display, 'setCurrentModelIndex(QModelIndex)'),
154 (getattr(self.views, self.basename + 'Save'), 'clicked()',
162 # Add a new row to list view.
163 num_rows = self.model.rowCount()
164 self.model.insertRows(num_rows, 1)
165 self.view_list.selectRow(num_rows)
167 # Disable adding more than one row.
168 self.getFieldWidget('Add').setEnabled(False)
170 # Focust to the first displayed field.
171 self.getFieldWidget(self.getDisplayFields()[0]).setFocus()
173 # Clear all displayed fields.
174 for field in self.getDisplayFields():
175 self.getFieldWidget(field).clear()
181 # For now we just submit everything - QT seems to be able to handle it
183 self.view_display.submit()
184 self.getFieldWidget('Add').setEnabled(True)
188 class ConnectionController(BaseController):
190 Connections controller.
193 'ID', 'Name', 'Local IP Address', 'Local Port',
194 'Freeswitch IP Address', 'Freeswitch Port')
195 view_list_fields = 'Name', 'Freeswitch IP Address', 'Freeswitch Port'
199 TODO: Clone an existing connection.
201 This creates a new connection with bound data copied from another one.
204 class SipProfileController(BaseController):
206 SIP Profile controller.
209 'ID', 'Connection ID', 'Name', 'External RTP IP', 'External SIP IP',
210 'RTP IP', 'SIP IP', 'SIP Port', 'Accept Blind Registration',
211 'Authenticate Calls', 'Is Active')
212 view_list_fields = 'Name', 'SIP IP', 'SIP Port'
213 view_display_fields_hidden = 'ID', 'Connection ID'
216 class DomainController(BaseController):
220 fields = 'ID', 'SIP Profile ID', 'Host Name', 'Is Active'
221 view_list_fields = 'SIP Profile ID', 'Host Name', 'Is Active'
224 class GatewayController(BaseController):
229 'ID', 'SIP Profile ID', 'Name', 'Username', 'Password', 'Realm',
230 'From Domain', 'Expire In Seconds', 'Retry In Seconds',
231 'Caller ID In From Field', 'Is Active')
232 view_list_fields = 'SIP Profile ID', 'Name'
235 class EndpointController(BaseController):
239 fields = 'ID', 'User ID', 'Password', 'Domain ID', 'Is Active'
242 class ExtensionController(BaseController):
244 Extension controller.
247 'ID', 'Destination Match', 'XML Dialplan', 'Domain ID', 'Endpoint ID',
248 'Authenticate Calls', 'Is Active')
249 view_list_fields = 'Destination Match', 'Domain ID', 'Endpoint ID'