1 /* |
|
2 * Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies). |
|
3 * All rights reserved. |
|
4 * This component and the accompanying materials are made available |
|
5 * under the terms of "Eclipse Public License v1.0"" |
|
6 * which accompanies this distribution, and is available |
|
7 * at the URL "http://www.eclipse.org/legal/epl-v10.html". |
|
8 * |
|
9 * Initial Contributors: |
|
10 * Nokia Corporation - initial contribution. |
|
11 * |
|
12 * Contributors: |
|
13 * |
|
14 * Description: |
|
15 * |
|
16 */ |
|
17 |
|
18 #include "btcpuisearchview.h" |
|
19 #include "btuiviewutil.h" |
|
20 #include <QtGui/QGraphicsLinearLayout> |
|
21 #include <HbInstance> |
|
22 #include <HbDocumentLoader> |
|
23 #include <HbDataForm> |
|
24 #include <HbPushButton> |
|
25 #include <HbLabel> |
|
26 #include <HbListView> |
|
27 #include <HbMenu> |
|
28 #include <HbSelectionDialog> |
|
29 #include <HbGroupBox> |
|
30 #include <QString> |
|
31 #include <QStringList> |
|
32 #include <QDebug> |
|
33 #include <bluetoothuitrace.h> |
|
34 #include "btcpuimainview.h" |
|
35 #include "btdelegatefactory.h" |
|
36 #include "btabstractdelegate.h" |
|
37 #include "btcpuisearchlistviewitem.h" |
|
38 #include "btuidevtypemap.h" |
|
39 |
|
40 |
|
41 // docml to load |
|
42 const char* BTUI_SEARCHVIEW_DOCML = ":/docml/bt-search-view.docml"; |
|
43 |
|
44 BtCpUiSearchView::BtCpUiSearchView( |
|
45 BtSettingModel &settingModel, |
|
46 BtDeviceModel &deviceModel, |
|
47 QGraphicsItem *parent) : |
|
48 BtCpUiBaseView(settingModel,deviceModel, parent), mAbstractDelegate(0), mBtuiModelSortFilter(0) |
|
49 { |
|
50 bool ret(false); |
|
51 |
|
52 mQuery = 0; |
|
53 mLoader = 0; |
|
54 mSoftKeyBackAction = 0; |
|
55 |
|
56 mMainView = (BtCpUiMainView *) parent; |
|
57 mMainWindow = hbInstance->allMainWindows().first(); |
|
58 |
|
59 mSoftKeyBackAction = new HbAction(Hb::BackNaviAction, this); |
|
60 BTUI_ASSERT_X(mSoftKeyBackAction, "BtCpUiSearchView::BtCpUiSearchView", "can't create back action"); |
|
61 |
|
62 // Create view for the application. |
|
63 // Set the name for the view. The name should be same as the view's |
|
64 // name in docml. |
|
65 setObjectName("bt_search_view"); |
|
66 |
|
67 mLoader = new HbDocumentLoader(); |
|
68 BTUI_ASSERT_X( mLoader != 0, "BtCpUiSearchView::BtCpUiSearchView", "can't create mLoader" ); |
|
69 // Pass the view to documentloader. Document loader uses this view |
|
70 // when docml is parsed, instead of creating new view. |
|
71 QObjectList objectList; |
|
72 objectList.append(this); |
|
73 mLoader->setObjectTree(objectList); |
|
74 |
|
75 // read view info from docml file |
|
76 bool ok = false; |
|
77 mLoader->load( BTUI_SEARCHVIEW_DOCML, &ok ); |
|
78 // Exit if the file format is invalid |
|
79 BTUI_ASSERT_X( ok, "bt-search-view", "Invalid docml file" ); |
|
80 |
|
81 // Set title for the control panel |
|
82 // ToDo: check if deprecated API |
|
83 setTitle("Control Panel"); |
|
84 |
|
85 // assign automatically created widgets to local variables |
|
86 |
|
87 mDeviceIcon=0; |
|
88 // can't use qobject_cast since HbIcon is not derived from QObject! |
|
89 mDeviceIcon = qobject_cast<HbLabel *>( mLoader->findWidget( "icon" ) ); |
|
90 BTUI_ASSERT_X( mDeviceIcon != 0, "BtCpUiSearchView::BtCpUiSearchView", "Device Icon not found" ); |
|
91 |
|
92 mDataForm=0; |
|
93 mDataForm = qobject_cast<HbDataForm *>( mLoader->findWidget( "dataForm" ) ); |
|
94 BTUI_ASSERT_X( mDataForm != 0, "BtCpUiSearchView::BtCpUiSearchView", "dataForm not found" ); |
|
95 mDataForm->setHeading(hbTrId("txt_bt_subhead_bluetooth_found_devices")); |
|
96 |
|
97 mLabelSearching=0; |
|
98 mLabelSearching = qobject_cast<HbLabel *>( mLoader->findWidget( "label_searching" ) ); |
|
99 BTUI_ASSERT_X( mLabelSearching != 0, "BtCpUiSearchView::BtCpUiSearchView", "Searching not found" ); |
|
100 mLabelSearching->setPlainText(hbTrId("txt_bt_subhead_searching")); |
|
101 |
|
102 mDeviceList=0; |
|
103 mDeviceList = qobject_cast<HbListView *>( mLoader->findWidget( "deviceList" ) ); |
|
104 BTUI_ASSERT_X( mDeviceList != 0, "BtCpUiSearchView::BtCpUiSearchView", "Device List not found" ); |
|
105 |
|
106 |
|
107 mDeviceList->setSelectionMode( HbAbstractItemView::SingleSelection ); |
|
108 |
|
109 // read landscape orientation section from docml file if needed |
|
110 mOrientation = mMainWindow->orientation(); |
|
111 |
|
112 if (mOrientation == Qt::Horizontal) { |
|
113 mLoader->load(BTUI_SEARCHVIEW_DOCML, "landscape_ui", &ok); |
|
114 BTUI_ASSERT_X( ok, "BtCpUiSearchView::BtCpUiSearchView", "Invalid docml file: landscape section problem" ); |
|
115 } else { |
|
116 mLoader->load(BTUI_SEARCHVIEW_DOCML, "portrait_ui", &ok); |
|
117 BTUI_ASSERT_X( ok, "BtCpUiSearchView::BtCpUiSearchView", "Invalid docml file: portrait section problem" ); |
|
118 } |
|
119 |
|
120 // listen for orientation changes |
|
121 ret = connect(mMainWindow, SIGNAL(orientationChanged(Qt::Orientation)), |
|
122 this, SLOT(changeOrientation(Qt::Orientation))); |
|
123 BTUI_ASSERT_X( ret, "BtCpUiSearchView::BtCpUiSearchView()", "connect orientationChanged() failed"); |
|
124 |
|
125 // load tool bar actions |
|
126 mViewBy = static_cast<HbAction*>( mLoader->findObject( "viewByAction" ) ); |
|
127 BTUI_ASSERT_X( mViewBy, "BtCpUiSearchView::BtCpUiSearchView", "view by action missing" ); |
|
128 ret = connect(mViewBy, SIGNAL(triggered()), this, SLOT(viewByDeviceTypeDialog())); |
|
129 BTUI_ASSERT_X( ret, "BtCpUiSearchView::BtCpUiSearchView", "viewByAction can't connect" ); |
|
130 |
|
131 mStop = static_cast<HbAction*>( mLoader->findObject( "stopAction" ) ); |
|
132 BTUI_ASSERT_X( mStop, "BtCpUiSearchView::BtCpUiSearchView", "stopAction missing" ); |
|
133 ret = connect(mStop, SIGNAL(triggered()), this, SLOT(stopSearching())); |
|
134 BTUI_ASSERT_X( ret, "BtCpUiSearchView::BtCpUiSearchView", "stopAction can't connect" ); |
|
135 mStop->setEnabled(true); |
|
136 |
|
137 mRetry = static_cast<HbAction*>( mLoader->findObject( "retryAction" ) ); |
|
138 BTUI_ASSERT_X( mRetry, "BtCpUiSearchView::BtCpUiSearchView", "retryAction missing" ); |
|
139 ret = connect(mRetry, SIGNAL(triggered()), this, SLOT(retrySearch())); |
|
140 BTUI_ASSERT_X( ret, "BtCpUiSearchView::BtCpUiSearchView", "retryAction can't connect" ); |
|
141 // Disable for initial search |
|
142 mRetry->setEnabled(false); |
|
143 |
|
144 // load menu |
|
145 HbMenu *optionsMenu = qobject_cast<HbMenu *>(mLoader->findWidget("viewMenu")); |
|
146 BTUI_ASSERT_X( optionsMenu != 0, "BtCpUiSearchView::BtCpUiSearchView", "Options menu not found" ); |
|
147 this->setMenu(optionsMenu); |
|
148 |
|
149 ret = connect(mDeviceList, SIGNAL(activated(QModelIndex)), this, SLOT(deviceSelected(QModelIndex))); |
|
150 BTUI_ASSERT_X( ret, "BtCpUiSearchView::BtCpUiSearchView", "deviceSelected can't connect" ); |
|
151 |
|
152 // initialize device type list for "view by" option |
|
153 // Note: this list needs to be in the same order as enum devTypeSelectionList |
|
154 mDevTypeList << hbTrId("txt_bt_list_audio_devices") |
|
155 << hbTrId("txt_bt_list_computers") |
|
156 << hbTrId("txt_bt_list_input_devices") |
|
157 << hbTrId("txt_bt_list_phones") |
|
158 << hbTrId("txt_bt_list_other_devices"); |
|
159 |
|
160 // initialize sort model & create |
|
161 // inquiry delegate |
|
162 // Sort is set to dynamic sort filter = true in the class, will sort automatically |
|
163 mBtuiModelSortFilter = new BtuiModelSortFilter(this); |
|
164 mBtuiModelSortFilter->setSourceModel(mDeviceModel); |
|
165 mBtuiModelSortFilter->addDeviceMajorFilter( |
|
166 BtuiDevProperty::InRange, BtuiModelSortFilter::AtLeastMatch); |
|
167 mDeviceList->setModel(mBtuiModelSortFilter); |
|
168 // add sort order to show devices in the order they are found |
|
169 mBtuiModelSortFilter->setSortRole(BtDeviceModel::SeqNumRole); |
|
170 // Sort according to the first column (and the only column) in the listview - sorted according SeqNumRole |
|
171 mBtuiModelSortFilter->sort(0, Qt::AscendingOrder); |
|
172 |
|
173 BtCpUiSearchListViewItem *prototype = new BtCpUiSearchListViewItem(mDeviceList); |
|
174 prototype->setModelSortFilter(mBtuiModelSortFilter); |
|
175 mDeviceList->setItemPrototype(prototype); |
|
176 |
|
177 // Create the inquiry delegate. |
|
178 mAbstractDelegate = BtDelegateFactory::newDelegate(BtDelegate::Inquiry, mSettingModel, mDeviceModel ); |
|
179 |
|
180 |
|
181 } |
|
182 |
|
183 BtCpUiSearchView::~BtCpUiSearchView() |
|
184 { |
|
185 delete mLoader; // Also deletes all widgets that it constructed. |
|
186 |
|
187 setNavigationAction(0); |
|
188 disconnect( mSoftKeyBackAction ); |
|
189 delete mSoftKeyBackAction; |
|
190 |
|
191 if(mAbstractDelegate) { |
|
192 disconnect(mAbstractDelegate); |
|
193 delete mAbstractDelegate; |
|
194 } |
|
195 if(mBtuiModelSortFilter) { |
|
196 delete mBtuiModelSortFilter; |
|
197 } |
|
198 if ( mQuery ) { |
|
199 delete mQuery; |
|
200 } |
|
201 } |
|
202 |
|
203 void BtCpUiSearchView::changeOrientation( Qt::Orientation orientation ) |
|
204 { |
|
205 // ToDo: this does not handle redrawing list view items differently for portrait/landscape |
|
206 bool ok = false; |
|
207 mOrientation = orientation; |
|
208 |
|
209 if( orientation == Qt::Vertical ) { |
|
210 // load "portrait" section |
|
211 mLoader->load( BTUI_SEARCHVIEW_DOCML, "portrait_ui", &ok ); |
|
212 BTUI_ASSERT_X( ok, "BtCpUiSearchView::changeOrientation", "Invalid docml file: portrait section problem" ); |
|
213 } else { |
|
214 // load "landscape" section |
|
215 mLoader->load( BTUI_SEARCHVIEW_DOCML, "landscape_ui", &ok ); |
|
216 BTUI_ASSERT_X( ok, "BtCpUiSearchView::changeOrientation", "Invalid docml file: landscape section problem" ); |
|
217 } |
|
218 } |
|
219 |
|
220 |
|
221 void BtCpUiSearchView::viewByDeviceTypeDialog() |
|
222 { |
|
223 if ( !mQuery ) { |
|
224 mQuery = new HbSelectionDialog; |
|
225 mQuery->setStringItems(mDevTypeList, 0); |
|
226 mQuery->setSelectionMode(HbAbstractItemView::MultiSelection); |
|
227 |
|
228 QList<QVariant> current; |
|
229 current.append(QVariant(0)); |
|
230 mQuery->setSelectedItems(current); |
|
231 |
|
232 // Set the heading for the dialog. |
|
233 HbLabel *headingLabel = new HbLabel(hbTrId("txt_bt_title_show"), mQuery); |
|
234 mQuery->setHeadingWidget(headingLabel); |
|
235 } |
|
236 mQuery->open(this,SLOT(viewByDialogClosed(HbAction*))); |
|
237 } |
|
238 /*! |
|
239 Callback for HbSelectionDialog closing |
|
240 |
|
241 */ |
|
242 void BtCpUiSearchView::viewByDialogClosed(HbAction* action) |
|
243 { |
|
244 disconnect( mQuery ); // remove slot |
|
245 if (action == mQuery->actions().first()) { // user pressed "Ok" |
|
246 // Get selected items. |
|
247 QList<QVariant> selections; |
|
248 selections = mQuery->selectedItems(); |
|
249 |
|
250 int devTypesWanted = 0; |
|
251 |
|
252 for (int i=0; i < selections.count(); i++) { |
|
253 switch (selections.at(i).toInt()) { |
|
254 case BtUiDevAudioDevice: |
|
255 devTypesWanted |= BtuiDevProperty::AVDev; |
|
256 break; |
|
257 case BtUiDevComputer: |
|
258 devTypesWanted |= BtuiDevProperty::Computer; |
|
259 break; |
|
260 case BtUiDevInputDevice: |
|
261 devTypesWanted |= BtuiDevProperty::Peripheral; |
|
262 break; |
|
263 case BtUiDevPhone: |
|
264 devTypesWanted |= BtuiDevProperty::Phone; |
|
265 break; |
|
266 case BtUiDevOtherDevice: |
|
267 devTypesWanted |= (BtuiDevProperty::LANAccessDev | |
|
268 BtuiDevProperty::Toy | |
|
269 BtuiDevProperty::WearableDev | |
|
270 BtuiDevProperty::ImagingDev | |
|
271 BtuiDevProperty::HealthDev | |
|
272 BtuiDevProperty::UncategorizedDev); |
|
273 break; |
|
274 default: |
|
275 // should never get here |
|
276 BTUI_ASSERT_X(false, "BtCpUiSearchView::viewByDialogClosed()", |
|
277 "wrong device type in viewBy dialog!"); |
|
278 } |
|
279 } |
|
280 if (devTypesWanted) { |
|
281 mBtuiModelSortFilter->clearDeviceMajorFilters(); |
|
282 mBtuiModelSortFilter->addDeviceMajorFilter(BtuiDevProperty::InRange, |
|
283 BtuiModelSortFilter::AtLeastMatch); // device must be in range |
|
284 mBtuiModelSortFilter->addDeviceMajorFilter(devTypesWanted, |
|
285 BtuiModelSortFilter::RoughMatch); // device can be any one of selected ones |
|
286 } |
|
287 } |
|
288 } |
|
289 |
|
290 void BtCpUiSearchView::stopSearching() |
|
291 { |
|
292 // Stop searching |
|
293 |
|
294 // Stop search delegate |
|
295 mAbstractDelegate->cancel(); |
|
296 // reset view |
|
297 deviceSearchCompleted(KErrNone); |
|
298 } |
|
299 |
|
300 void BtCpUiSearchView::startSearchDelegate () |
|
301 { |
|
302 bool ret = false; |
|
303 |
|
304 // Connect to the signal from the BtDelegateInquiry for completion of the search request |
|
305 ret = connect(mAbstractDelegate, SIGNAL(commandCompleted(int)), this, SLOT(searchDelegateCompleted(int))); |
|
306 BTUI_ASSERT_X( ret, "BtCpUiSearchView::BtCpUiSearchView", "searchDelegateCompleted can't connect" ); |
|
307 |
|
308 // Connect to the signal from the BtuiModel when the search has been completed. |
|
309 ret = connect(mDeviceModel, SIGNAL(deviceSearchCompleted(int)), this, SLOT(deviceSearchCompleted(int))); |
|
310 BTUI_ASSERT_X( ret, "BtCpUiSearchView::BtCpUiSearchView", "deviceSearchCompleted can't connect" ); |
|
311 |
|
312 mAbstractDelegate->exec(QVariant()); |
|
313 } |
|
314 |
|
315 void BtCpUiSearchView::retrySearch() |
|
316 { |
|
317 // Retry search |
|
318 |
|
319 // Change label and buttons to reflect status |
|
320 mLabelSearching->setPlainText(hbTrId("txt_bt_subhead_searching")); |
|
321 mRetry->setEnabled(false); |
|
322 mStop->setEnabled(true); |
|
323 |
|
324 // Make use of the delegate and start the search. |
|
325 startSearchDelegate (); |
|
326 } |
|
327 |
|
328 void BtCpUiSearchView::setSoftkeyBack() |
|
329 { |
|
330 if (navigationAction() != mSoftKeyBackAction) { |
|
331 setNavigationAction(mSoftKeyBackAction); |
|
332 connect( mSoftKeyBackAction, SIGNAL(triggered()), this, SLOT(switchToPreviousView()) ); |
|
333 } |
|
334 } |
|
335 |
|
336 void BtCpUiSearchView::switchToPreviousView() |
|
337 { |
|
338 BTUI_ASSERT_X(mMainView, "BtCpUiSearchView::switchToPreviousView", "invalid mMainView"); |
|
339 mMainView->switchToPreviousView(); |
|
340 } |
|
341 |
|
342 void BtCpUiSearchView::activateView( const QVariant& value, bool fromBackButton ) |
|
343 { |
|
344 Q_UNUSED(value); |
|
345 |
|
346 // ToDo: consider whether orientation should be updated here rather than when orientation really changes; |
|
347 // advantage: if orientation changes temporarily in another view, but returns to previous setting before |
|
348 // search is reactived, there is no processing overhead |
|
349 |
|
350 setSoftkeyBack(); |
|
351 |
|
352 if ( !fromBackButton ) { |
|
353 // Sets the label and toolbar buttons |
|
354 retrySearch(); |
|
355 } |
|
356 } |
|
357 |
|
358 void BtCpUiSearchView::deactivateView() |
|
359 { |
|
360 mAbstractDelegate->cancel(); // Stop searching when leaving view |
|
361 deviceSearchCompleted(KErrNone); // reset view |
|
362 } |
|
363 |
|
364 void BtCpUiSearchView::searchDelegateCompleted(int error) |
|
365 { |
|
366 Q_UNUSED(error); |
|
367 |
|
368 } |
|
369 |
|
370 void BtCpUiSearchView::deviceSearchCompleted(int error) |
|
371 { |
|
372 //TODO - handle error. |
|
373 Q_UNUSED(error); |
|
374 |
|
375 mLabelSearching->setPlainText(hbTrId("txt_bt_subhead_search_done")); |
|
376 mRetry->setEnabled(true); |
|
377 mStop->setEnabled(false); |
|
378 |
|
379 // disconnect signals |
|
380 disconnect(mAbstractDelegate); |
|
381 disconnect(mDeviceModel); |
|
382 } |
|
383 |
|
384 void BtCpUiSearchView::deviceSelected(const QModelIndex& modelIndex) |
|
385 { |
|
386 QModelIndex index = mBtuiModelSortFilter->mapToSource(modelIndex); |
|
387 static_cast<BtCpUiMainView*>(mMainView)->goToDeviceView(index); |
|
388 } |
|