View list row selection works
[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.setColumnHidden(i, True)
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             #connect(ui.bookTable->selectionModel(), SIGNAL(currentRowChanged(QModelIndex,QModelIndex)),
136             # mapper, SLOT(setCurrentModelIndex(QModelIndex)));
137             
138             (self.view_list.selectionModel(), 'currentRowChanged(QModelIndex,QModelIndex)',
139              self.view_display, 'setCurrentModelIndex(QModelIndex)'),
140             (getattr(self.views, self.basename + 'Save'), 'clicked()',
141              self.save),
142             )
143
144     def add(self):
145         """
146         Add new object.
147         """
148         # Add a new row to list view.
149         num_rows = self.model.rowCount()
150         self.model.insertRows(num_rows, 1)
151         self.view_list.selectRow(num_rows)
152
153         # Disable adding more than one row.
154         getattr(self.views, self.basename + 'Add').setEnabled(False)
155
156         # Focust to the first displayed field.
157         self.getFieldWidget(self.getDisplayFields()[0]).setFocus()
158
159         # Clear all displayed fields.
160         for field in self.getDisplayFields():
161             self.getFieldWidget(field).clear()
162         
163     def select(self, row):
164         """
165         Select an object from the list.
166         """
167         # Fill in form based on selection.
168         
169         
170         #self.parent.ui.connectionName.setText(self.currentConnection.name)
171         #self.parent.ui.connectionLocalIpAddress.setText(
172         #    self.currentConnection.local_ip_address)
173         #self.parent.ui.connectionLocalPort.setText(
174         #    unicode(self.currentConnection.local_port))
175         #self.parent.ui.connectionFreeswitchIpAddress.setText(
176         #    self.currentConnection.freeswitch_ip_address)
177         #self.parent.ui.connectionFreeswitchPort.setText(
178         #    unicode(self.currentConnection.freeswitch_port))
179
180     def save(self):
181         """
182         TODO: Default implementation.
183         """
184         return NotImplemented
185
186
187 class ConnectionController(BaseController):
188     """
189     Connections handler.
190     """
191     fields = (
192         'ID', 'Name', 'Local IP Address', 'Local Port',
193         'Freeswitch IP Address', 'Freeswitch Port')
194     view_list_fields = ('Name', 'Freeswitch IP Address', 'Freeswitch Port')
195     
196     def clone(self):
197         """
198         TODO: Clone an existing connection.
199
200         This creates a new connection with bound data copied from another one.
201         """
202
203     def save(self):
204         """
205         Save new or existing connection.
206         """
207         name = unicode(self.parent.ui.connectionName.text())
208
209         # Add to connection list if we've created it.
210         if self.currentConnection is None:            
211             #self.currentConnection = models.Connection(store=state.store)            
212             self.connections.append(self.currentConnection)
213             self.parent.ui.connectionList.addItem(name)
214
215         self.currentConnection.name = name
216         self.currentConnection.local_ip_address = unicode(
217             self.parent.ui.connectionLocalIpAddress.text())
218         self.currentConnection.local_port = int(
219             self.parent.ui.connectionLocalPort.text())
220         self.currentConnection.freeswitch_ip_address = unicode(
221             self.parent.ui.connectionFreeswitchIpAddress.text())
222         self.currentConnection.freeswitch_port = int(
223             self.parent.ui.connectionFreeswitchPort.text())
224
225         self.currentConnection.checkpoint()