3263273296fc7a50aabd4ea1ceb92fe449cae839
[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     view_list_fields = ()
30     view_display_fields = ()
31     
32     def __init__(self, model=None, view_list=None, view_display=None, parent=None, views=None):
33         super(BaseController, self).__init__(parent=parent)
34
35         self.views = views
36         
37         # Find out base name.
38         classname = self.__class__.__name__
39         self.basename = (
40             classname[:-10] if classname.endswith('Controller')
41             else classname)
42         self.basename = self.basename[0].lower() + self.basename[1:]
43
44         # Are we given an existing model?
45         if model:
46             self.model = model
47         # Otherwise initialize a new model.
48         else:
49             self.model = QtSql.QSqlTableModel(parent)
50             self.model.setTable(self.basename + 's')
51
52             # Create model header from fields list.
53             for i, field in enumerate(self.fields):
54                 self.model.setHeaderData(
55                     i, QtCore.Qt.Horizontal, QtCore.QVariant(field))
56
57             # Fetch model data.
58             self.model.select()
59
60         # Are we given an existing view list?
61         if view_list:
62             self.view_list = view_list
63         # Otherwise get view list from the parent.            
64         else:
65             self.view_list = getattr(views, self.basename + 'ViewList')
66             self.view_list.setModel(self.model)
67
68             # Hide fields not meant for display.
69             for i, field in enumerate(self.fields):
70                 if field not in self.view_list_fields:
71                     self.view_list.hideColumn(i)
72
73             # Stretch headers to fill all available width.
74             self.view_list.setSelectionMode(QtGui.QTableView.SingleSelection)
75             self.view_list.setSelectionBehavior(QtGui.QTableView.SelectRows)
76             self.view_list.resizeColumnsToContents()
77             self.view_list.resizeRowsToContents()
78             self.view_list.horizontalHeader().setStretchLastSection(True)
79         self.view_list.selectRow(0)
80
81         # Are we given an existing view display?
82         if view_display:
83             self.view_display = view_display
84         # Otherwise get view display from the parent.
85         else:
86             self.view_display = QtGui.QDataWidgetMapper(parent)
87             self.view_display.setModel(self.model)
88
89             # If view_display_fields is not send, display all fields except
90             # the first one that is usually the ID.
91             display_fields = self.getDisplayFields()
92             for i, field in enumerate(self.fields):
93                 if field in display_fields:
94                     field_widget = self.getFieldWidget(field)
95                     self.view_display.addMapping(field_widget, i)
96
97         # Select first row in the view list.
98         self.view_display.toFirst()
99         
100         # Register signals for this controller.
101         for data in self.getSignalsData():
102             if len(data) == 3:
103                 sender, signal, receiver = data
104                 QtCore.QObject.connect(sender, QtCore.SIGNAL(signal), receiver)
105             elif len(data) == 4:
106                 sender, signal, receiver, slot = data
107                 QtCore.QObject.connect(
108                     sender, QtCore.SIGNAL(signal), receiver, QtCore.SLOT(slot))
109                                        
110
111     def getDisplayFields(self):
112         """
113         Return the list of fields to display.
114
115         If it's not set explicitly, use all defined fields except the first
116         which usually is the primary key.
117         """
118         return self.view_display_fields or self.fields[1:]
119
120     def getFieldWidget(self, field):
121         """
122         Return widget for given field name.
123         """
124         return getattr(
125             self.views,
126             self.basename + ''.join(word.capitalize()
127                                     for word in field.split(' ')))
128
129     def getSignalsData(self):
130         """
131         Default signals built from controller's base name.
132         """
133         return (
134             (getattr(self.views, self.basename + 'Add'), 'clicked()', self.add),
135             (self.view_list.selectionModel(),
136              'currentRowChanged(QModelIndex,QModelIndex)',
137              self.view_display, 'setCurrentModelIndex(QModelIndex)'),
138             (getattr(self.views, self.basename + 'Save'), 'clicked()',
139              self.save),
140             )
141
142     def add(self):
143         """
144         Add new object.
145         """
146         # Add a new row to list view.
147         num_rows = self.model.rowCount()
148         self.model.insertRows(num_rows, 1)
149         self.view_list.selectRow(num_rows)
150
151         # Disable adding more than one row.
152         self.getFieldWidget('Add').setEnabled(False)
153
154         # Focust to the first displayed field.
155         self.getFieldWidget(self.getDisplayFields()[0]).setFocus()
156
157         # Clear all displayed fields.
158         for field in self.getDisplayFields():
159             self.getFieldWidget(field).clear()
160         
161     def save(self):
162         """
163         Save currently selected object.
164         """
165         #print self.model.isDirty(self.view_list.currentRow())
166         #print self.view_list.selectedIndexes()[0].row()
167
168         #if self.model.isDirty(self.view_display.currentIndex()), self.model.rowCount()
169         self.view_display.submit()
170         self.getFieldWidget('Add').setEnabled(True)
171         
172
173
174 class ConnectionController(BaseController):
175     """
176     Connections handler.
177     """
178     fields = (
179         'ID', 'Name', 'Local IP Address', 'Local Port',
180         'Freeswitch IP Address', 'Freeswitch Port')
181     view_list_fields = ('Name', 'Freeswitch IP Address', 'Freeswitch Port')
182     
183     def clone(self):
184         """
185         TODO: Clone an existing connection.
186
187         This creates a new connection with bound data copied from another one.
188         """
189
190     def _save(self):
191         """
192         Save new or existing connection.
193         """
194         name = unicode(self.parent.ui.connectionName.text())
195
196         # Add to connection list if we've created it.
197         if self.currentConnection is None:            
198             #self.currentConnection = models.Connection(store=state.store)            
199             self.connections.append(self.currentConnection)
200             self.parent.ui.connectionList.addItem(name)
201
202         self.currentConnection.name = name
203         self.currentConnection.local_ip_address = unicode(
204             self.parent.ui.connectionLocalIpAddress.text())
205         self.currentConnection.local_port = int(
206             self.parent.ui.connectionLocalPort.text())
207         self.currentConnection.freeswitch_ip_address = unicode(
208             self.parent.ui.connectionFreeswitchIpAddress.text())
209         self.currentConnection.freeswitch_port = int(
210             self.parent.ui.connectionFreeswitchPort.text())
211
212         self.currentConnection.checkpoint()