|
1 /**************************************************************************** |
|
2 ** |
|
3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). |
|
4 ** All rights reserved. |
|
5 ** Contact: Nokia Corporation (qt-info@nokia.com) |
|
6 ** |
|
7 ** This file is part of the Qt Mobility Components. |
|
8 ** |
|
9 ** $QT_BEGIN_LICENSE:BSD$ |
|
10 ** You may use this file under the terms of the BSD license as follows: |
|
11 ** |
|
12 ** "Redistribution and use in source and binary forms, with or without |
|
13 ** modification, are permitted provided that the following conditions are |
|
14 ** met: |
|
15 ** * Redistributions of source code must retain the above copyright |
|
16 ** notice, this list of conditions and the following disclaimer. |
|
17 ** * Redistributions in binary form must reproduce the above copyright |
|
18 ** notice, this list of conditions and the following disclaimer in |
|
19 ** the documentation and/or other materials provided with the |
|
20 ** distribution. |
|
21 ** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor |
|
22 ** the names of its contributors may be used to endorse or promote |
|
23 ** products derived from this software without specific prior written |
|
24 ** permission. |
|
25 ** |
|
26 ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
|
27 ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
|
28 ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
|
29 ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
|
30 ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
|
31 ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
|
32 ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
|
33 ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
|
34 ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
|
35 ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
|
36 ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." |
|
37 ** $QT_END_LICENSE$ |
|
38 ** |
|
39 ****************************************************************************/ |
|
40 |
|
41 #include "contactlistpage.h" |
|
42 #ifdef BUILD_VERSIT |
|
43 #include "qversitreader.h" |
|
44 #include "qversitcontactimporter.h" |
|
45 #include "qversitwriter.h" |
|
46 #include "qversitcontactexporter.h" |
|
47 #endif |
|
48 |
|
49 #include <QtGui> |
|
50 |
|
51 ContactListPage::ContactListPage(QMainWindow *mainWindow, QWidget *parent) |
|
52 : QWidget(parent), m_mainWindow(mainWindow) |
|
53 { |
|
54 m_manager = 0; |
|
55 m_currentFilter = QContactFilter(); |
|
56 |
|
57 m_backendsCombo = new QComboBox(this); |
|
58 QStringList availableManagers = QContactManager::availableManagers(); |
|
59 availableManagers.removeAll("invalid"); |
|
60 foreach(QString managerName, availableManagers) { |
|
61 |
|
62 QMap<QString, QString> params; |
|
63 QString managerUri = QContactManager::buildUri(managerName, params); |
|
64 |
|
65 // Add some parameters to SIM backend so that we can use |
|
66 // all the stores. |
|
67 if (managerName == "symbiansim") { |
|
68 availableManagers.removeAll("symbiansim"); |
|
69 |
|
70 availableManagers.append("symbiansim:adn"); |
|
71 params.insert("store", "ADN"); |
|
72 managerUri = QContactManager::buildUri(managerName, params); |
|
73 m_availableManagers.insert(availableManagers.last(), managerUri); |
|
74 |
|
75 availableManagers.append("symbiansim:fdn"); |
|
76 params.clear(); |
|
77 params.insert("store", "FDN"); |
|
78 managerUri = QContactManager::buildUri(managerName, params); |
|
79 m_availableManagers.insert(availableManagers.last(), managerUri); |
|
80 |
|
81 availableManagers.append("symbiansim:sdn"); |
|
82 params.clear(); |
|
83 params.insert("store", "SDN"); |
|
84 managerUri = QContactManager::buildUri(managerName, params); |
|
85 m_availableManagers.insert(availableManagers.last(), managerUri); |
|
86 } |
|
87 else { |
|
88 m_availableManagers.insert(managerName, managerUri); |
|
89 } |
|
90 } |
|
91 m_backendsCombo->addItems(availableManagers); |
|
92 connect(m_backendsCombo, SIGNAL(currentIndexChanged(QString)), this, SLOT(backendSelected())); |
|
93 m_filterActiveLabel = new QLabel(tr("Filter active")); |
|
94 m_filterActiveLabel->setSizePolicy(QSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed)); |
|
95 |
|
96 QVBoxLayout *bookLayout = new QVBoxLayout; |
|
97 QFormLayout *backendLayout = new QFormLayout; |
|
98 backendLayout->addRow(tr("Store:"), m_backendsCombo); |
|
99 backendLayout->addRow(m_filterActiveLabel); |
|
100 bookLayout->addLayout(backendLayout); |
|
101 |
|
102 m_contactsList = new QListWidget(this); |
|
103 bookLayout->addWidget(m_contactsList); |
|
104 |
|
105 // Action buttons at the bottom |
|
106 QHBoxLayout *btnLayout1 = new QHBoxLayout; |
|
107 |
|
108 QPushButton* addBtn = new QPushButton(tr("&Add"), this); |
|
109 connect(addBtn, SIGNAL(clicked()), this, SLOT(addClicked())); |
|
110 btnLayout1->addWidget(addBtn); |
|
111 |
|
112 QPushButton* editBtn = new QPushButton(tr("&Edit"), this); |
|
113 connect(editBtn, SIGNAL(clicked()), this, SLOT(editClicked())); |
|
114 btnLayout1->addWidget(editBtn); |
|
115 |
|
116 QPushButton* deleteBtn = new QPushButton(tr("&Delete"), this); |
|
117 connect(deleteBtn, SIGNAL(clicked()), this, SLOT(deleteClicked())); |
|
118 btnLayout1->addWidget(deleteBtn); |
|
119 |
|
120 bookLayout->addLayout(btnLayout1); |
|
121 |
|
122 setLayout(bookLayout); |
|
123 |
|
124 // Add items to the menu |
|
125 if (m_mainWindow) { |
|
126 #if defined(Q_OS_SYMBIAN) || defined(Q_WS_MAEMO_5) || defined(Q_OS_WINCE) |
|
127 // These platforms need their menu items added directly to the menu bar. |
|
128 QMenuBar *optionsMenu = m_mainWindow->menuBar(); |
|
129 #else |
|
130 QMenu *optionsMenu = new QMenu(tr("&Contacts"), this); |
|
131 m_mainWindow->menuBar()->addMenu(optionsMenu); |
|
132 #endif |
|
133 QAction* filterAction = new QAction(tr("Apply &Filter..."), this); |
|
134 connect(filterAction, SIGNAL(triggered()), this, SLOT(filterClicked())); |
|
135 optionsMenu->addAction(filterAction); |
|
136 QAction* clearFilterAction = new QAction(tr("&Clear Filter"), this); |
|
137 connect(clearFilterAction, SIGNAL(triggered()), this, SIGNAL(clearFilter())); |
|
138 optionsMenu->addAction(clearFilterAction); |
|
139 optionsMenu->addSeparator(); |
|
140 |
|
141 #ifdef BUILD_VERSIT |
|
142 QAction* importAction = new QAction(tr("&Import contacts..."), this); |
|
143 connect(importAction, SIGNAL(triggered()), this, SLOT(importClicked())); |
|
144 optionsMenu->addAction(importAction); |
|
145 QAction* exportAction = new QAction(tr("Ex&port contacts..."), this); |
|
146 connect(exportAction, SIGNAL(triggered()), this, SLOT(exportClicked())); |
|
147 optionsMenu->addAction(exportAction); |
|
148 optionsMenu->addSeparator(); |
|
149 #endif |
|
150 #if !(defined(Q_WS_MAEMO_5) || defined(Q_WS_MAEMO_6)) |
|
151 // Maemo applications don't have an Exit button in the menu. |
|
152 QAction* exitAction = new QAction(tr("E&xit"), this); |
|
153 connect(exitAction, SIGNAL(triggered()), qApp, SLOT(quit())); |
|
154 optionsMenu->addAction(exitAction); |
|
155 #endif |
|
156 } |
|
157 |
|
158 // force update to backend. |
|
159 QTimer::singleShot(0, this, SLOT(backendSelected())); |
|
160 } |
|
161 |
|
162 ContactListPage::~ContactListPage() |
|
163 { |
|
164 QList<QContactManager*> initialisedManagers = m_initialisedManagers.values(); |
|
165 while (!initialisedManagers.isEmpty()) { |
|
166 QContactManager *deleteMe = initialisedManagers.takeFirst(); |
|
167 delete deleteMe; |
|
168 } |
|
169 } |
|
170 |
|
171 void ContactListPage::backendSelected() |
|
172 { |
|
173 QString managerUri = m_availableManagers.value(m_backendsCombo->currentText()); |
|
174 |
|
175 // first, check to see if they reselected the same backend. |
|
176 if (m_manager && m_manager->managerUri() == managerUri) |
|
177 return; |
|
178 |
|
179 // the change is real. update. |
|
180 if (m_initialisedManagers.contains(managerUri)) { |
|
181 m_manager = m_initialisedManagers.value(managerUri); |
|
182 } else { |
|
183 m_manager = QContactManager::fromUri(managerUri); |
|
184 if (m_manager->error()) { |
|
185 QMessageBox::information(this, tr("Failed!"), QString("Failed to open store!\n(error code %1)").arg(m_manager->error())); |
|
186 delete m_manager; |
|
187 m_manager = 0; |
|
188 return; |
|
189 } |
|
190 m_initialisedManagers.insert(managerUri, m_manager); |
|
191 } |
|
192 |
|
193 // signal that the manager has changed. |
|
194 emit managerChanged(m_manager); |
|
195 |
|
196 // and... rebuild the list. |
|
197 rebuildList(m_currentFilter); |
|
198 } |
|
199 |
|
200 void ContactListPage::rebuildList(const QContactFilter& filter) |
|
201 { |
|
202 m_currentFilter = QContactManagerEngine::canonicalizedFilter(filter); |
|
203 |
|
204 m_filterActiveLabel->setVisible(m_currentFilter != QContactFilter()); |
|
205 |
|
206 m_contactsList->clear(); |
|
207 m_idToListIndex.clear(); |
|
208 m_contacts = m_manager->contacts(m_currentFilter); |
|
209 foreach (QContact contact, m_contacts) { |
|
210 QListWidgetItem *currItem = new QListWidgetItem; |
|
211 currItem->setData(Qt::DisplayRole, contact.displayLabel()); |
|
212 currItem->setData(Qt::UserRole, contact.localId()); // also store the id of the contact. |
|
213 m_idToListIndex.insert(contact.localId(), m_contactsList->count()); |
|
214 m_contactsList->addItem(currItem); |
|
215 } |
|
216 } |
|
217 |
|
218 void ContactListPage::addClicked() |
|
219 { |
|
220 if (m_manager) |
|
221 emit showEditorPage(QContactLocalId(0)); |
|
222 } |
|
223 |
|
224 void ContactListPage::editClicked() |
|
225 { |
|
226 if (m_contactsList->currentItem()) |
|
227 emit showEditorPage(QContactLocalId(m_contactsList->currentItem()->data(Qt::UserRole).toUInt())); |
|
228 // else, nothing selected; ignore. |
|
229 } |
|
230 |
|
231 void ContactListPage::filterClicked() |
|
232 { |
|
233 if (m_manager) |
|
234 emit showFilterPage(m_currentFilter); |
|
235 } |
|
236 |
|
237 void ContactListPage::deleteClicked() |
|
238 { |
|
239 if (!m_manager) { |
|
240 qWarning() << "No manager selected; cannot delete."; |
|
241 return; |
|
242 } |
|
243 |
|
244 if (!m_contactsList->currentItem()) { |
|
245 qWarning() << "Nothing to delete."; |
|
246 return; |
|
247 } |
|
248 |
|
249 QContactLocalId contactId = QContactLocalId(m_contactsList->currentItem()->data(Qt::UserRole).toUInt()); |
|
250 bool success = m_manager->removeContact(contactId); |
|
251 if (success) { |
|
252 delete m_contactsList->takeItem(m_contactsList->currentRow()); |
|
253 } |
|
254 else |
|
255 QMessageBox::information(this, "Failed!", "Failed to delete contact!"); |
|
256 } |
|
257 |
|
258 void ContactListPage::importClicked() |
|
259 { |
|
260 #ifdef BUILD_VERSIT |
|
261 if (!m_manager) { |
|
262 qWarning() << "No manager selected; cannot import"; |
|
263 return; |
|
264 } |
|
265 QString fileName = QFileDialog::getOpenFileName(this, |
|
266 tr("Select vCard file"), ".", tr("vCard files (*.vcf)")); |
|
267 QFile file(fileName); |
|
268 file.open(QIODevice::ReadOnly); |
|
269 if (file.isReadable()) { |
|
270 QVersitReader reader; |
|
271 reader.setDevice(&file); |
|
272 if (reader.startReading() && reader.waitForFinished()) { |
|
273 QVersitContactImporter importer; |
|
274 if (importer.importDocuments(reader.results())) { |
|
275 QList<QContact> contacts = importer.contacts(); |
|
276 QMap<int, QContactManager::Error> errorMap; |
|
277 QList<QContact>::iterator it = contacts.begin(); |
|
278 while (it != contacts.end()) { |
|
279 *it = m_manager->compatibleContact(*it); |
|
280 it++; |
|
281 } |
|
282 m_manager->saveContacts(&contacts, &errorMap); |
|
283 rebuildList(m_currentFilter); |
|
284 } |
|
285 } |
|
286 } |
|
287 #endif |
|
288 } |
|
289 |
|
290 void ContactListPage::exportClicked() |
|
291 { |
|
292 #ifdef BUILD_VERSIT |
|
293 if (!m_manager) { |
|
294 qWarning() << "No manager selected; cannot export"; |
|
295 return; |
|
296 } |
|
297 QString fileName = QFileDialog::getSaveFileName(this, tr("Save vCard"), |
|
298 "./contacts.vcf", |
|
299 tr("vCards (*.vcf)")); |
|
300 QFile file(fileName); |
|
301 file.open(QIODevice::WriteOnly); |
|
302 if (file.isWritable()) { |
|
303 QVersitContactExporter exporter; |
|
304 if(exporter.exportContacts(m_contacts, QVersitDocument::VCard30Type)) { |
|
305 QList<QVersitDocument> documents = exporter.documents(); |
|
306 QVersitWriter writer; |
|
307 writer.setDevice(&file); |
|
308 writer.startWriting(documents); |
|
309 writer.waitForFinished(); |
|
310 } |
|
311 } |
|
312 #endif |
|
313 } |