1 /* |
|
2 * Copyright (c) 2009 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 |
|
19 #include <QStack> |
|
20 #include <qpainter.h> |
|
21 #include "WrtPageManager.h" |
|
22 #include "FlowInterface.h" |
|
23 #include "ImageView_p.h" |
|
24 #include "ImageView.h" |
|
25 |
|
26 #include "qwebhistory.h" |
|
27 #include "qwebframe.h" |
|
28 #include "qwebelement.h" |
|
29 #include "wrtbrowsercontainer.h" |
|
30 #include "webpagedata.h" |
|
31 |
|
32 #include <QDebug> |
|
33 |
|
34 |
|
35 #define NO_IMAGE -1 |
|
36 #define IMAGE_ALT "alt" |
|
37 #define IMAGE_SOURCE "src" |
|
38 |
|
39 namespace WRT { |
|
40 |
|
41 ImageViewPrivate::ImageViewPrivate(WrtPageManager * mgr, QWidget* parent) : |
|
42 m_flowInterface(0), |
|
43 m_widgetParent(parent), |
|
44 m_graphicsWidgetParent(0), |
|
45 m_pageManager(mgr), |
|
46 m_imageIndex(0), |
|
47 m_activePage(0), |
|
48 m_isActive(false) |
|
49 { |
|
50 Q_ASSERT(m_pageManager); |
|
51 init(); |
|
52 } |
|
53 |
|
54 ImageViewPrivate::ImageViewPrivate(WrtPageManager * mgr, QGraphicsWidget* parent) : |
|
55 m_flowInterface(0), |
|
56 m_widgetParent(0), |
|
57 m_graphicsWidgetParent(parent), |
|
58 m_pageManager(mgr), |
|
59 m_imageIndex(0), |
|
60 m_activePage(0), |
|
61 m_isActive(false) |
|
62 { |
|
63 Q_ASSERT(m_pageManager); |
|
64 init(); |
|
65 } |
|
66 |
|
67 ImageViewPrivate::~ImageViewPrivate() |
|
68 { |
|
69 } |
|
70 |
|
71 void ImageViewPrivate::init() |
|
72 { |
|
73 // create the view's actions |
|
74 m_actionForward = new QAction("Forward",m_widgetParent); |
|
75 m_actionForward->setObjectName("Forward"); |
|
76 m_actionBack = new QAction("Back",m_widgetParent); |
|
77 m_actionBack->setObjectName("Back"); |
|
78 m_actionOK = new QAction("OK",m_widgetParent); |
|
79 m_actionOK->setObjectName("OK"); |
|
80 m_actionCancel = new QAction("Cancel",m_widgetParent); |
|
81 m_actionCancel->setObjectName("OK"); |
|
82 } |
|
83 |
|
84 /*! |
|
85 * \class ImageView |
|
86 * |
|
87 * \brief The base class for the ImageViews |
|
88 * |
|
89 * This class is responsible for.... |
|
90 */ |
|
91 |
|
92 /*! |
|
93 Basic ImageView constructor requires a PageManager to manage the pages |
|
94 and a parent QWidget |
|
95 */ |
|
96 ImageView::ImageView(WrtPageManager * pageMgr, QWidget* parent) : |
|
97 d(new ImageViewPrivate(pageMgr, parent)) |
|
98 { |
|
99 // always trigger an update to track the images regardless of whether active or not |
|
100 connect(d->m_pageManager, SIGNAL(loadFinished(bool)), this, SLOT(updateImageList(bool))); |
|
101 } |
|
102 |
|
103 /*! |
|
104 Basic ImageView constructor requires a PageManager to manage the pages |
|
105 and a parent QGraphicsWidget |
|
106 */ |
|
107 ImageView::ImageView(WrtPageManager * pageMgr, QGraphicsWidget* parent) : |
|
108 d(new ImageViewPrivate(pageMgr, parent)) |
|
109 { |
|
110 // always trigger an update to track the images regardless of whether active or not |
|
111 connect(d->m_pageManager, SIGNAL(loadFinished(bool)), this, SLOT(updateImageList(bool))); |
|
112 } |
|
113 |
|
114 |
|
115 ImageView::~ImageView() |
|
116 { |
|
117 delete d; |
|
118 } |
|
119 |
|
120 /*! |
|
121 Retrieve the WrtPageManager assigned to this view |
|
122 */ |
|
123 WrtPageManager* ImageView::wrtPageManager() |
|
124 { |
|
125 return d->m_pageManager; |
|
126 } |
|
127 |
|
128 /*! |
|
129 Update image list. This is automatically called when a page loads |
|
130 regardless of if the view is active or not. |
|
131 */ |
|
132 void ImageView::updateImageList(bool ok) |
|
133 { |
|
134 d->m_activePage = d->m_pageManager->currentPage(); |
|
135 |
|
136 if(!d->m_activePage) |
|
137 return; |
|
138 |
|
139 // reset image list |
|
140 d->m_imageList.clear(); |
|
141 |
|
142 // walk the tree of images to fetch all available images on a page. |
|
143 QStack<QWebFrame*> stackOfFrames; |
|
144 stackOfFrames.push(d->m_activePage->mainFrame()); |
|
145 while( !stackOfFrames.isEmpty()) |
|
146 { |
|
147 QWebFrame* f = stackOfFrames.pop(); |
|
148 |
|
149 foreach( QWebElement element, |
|
150 f->findAllElements( "img" )) |
|
151 { |
|
152 bool found = false; |
|
153 QRect r = element.geometry(); |
|
154 if( r.size().isEmpty()) |
|
155 { |
|
156 continue; |
|
157 } |
|
158 |
|
159 QString imgsrc = element.attribute( IMAGE_SOURCE ); |
|
160 |
|
161 if( imgsrc.isEmpty()) |
|
162 found = true; // do not add empty image in any case |
|
163 else |
|
164 { |
|
165 foreach( QImage c_img,d->m_imageList ) |
|
166 { |
|
167 if( imgsrc == c_img.text( IMAGE_SOURCE )) |
|
168 { |
|
169 found = true; |
|
170 break; |
|
171 } |
|
172 } |
|
173 |
|
174 } |
|
175 |
|
176 if( !found ) |
|
177 { |
|
178 QImage img( element.geometry().size(),QImage::Format_RGB32 ); |
|
179 QPainter p( static_cast<QPaintDevice *>(&img) ); |
|
180 #if defined CWRTINTERNALWEBKIT |
|
181 f->renderElement( &p,element,QPoint( 0,0 )); |
|
182 // fixme. implementation is in QtWebKit ToT, not yet in QtWebKit 4.6 beta |
|
183 // #elif QT_VERSION >= 0x040600 |
|
184 // element.render(&p); |
|
185 #endif |
|
186 img.setText( IMAGE_SOURCE,imgsrc ); |
|
187 img.setText( IMAGE_ALT,element.attribute( IMAGE_ALT )); |
|
188 d->m_imageList.append( img ); |
|
189 } |
|
190 } |
|
191 |
|
192 foreach (QWebFrame *child, f->childFrames()) |
|
193 stackOfFrames.push(child); |
|
194 } |
|
195 |
|
196 // IF we're active, update the visible image list |
|
197 if(d->m_flowInterface && d->m_isActive) |
|
198 refreshFlowInterface(); |
|
199 } |
|
200 |
|
201 |
|
202 /*! |
|
203 Return the widget handle of this view |
|
204 */ |
|
205 QWidget* ImageView::qWidget() const |
|
206 { |
|
207 return d->m_flowInterface; |
|
208 } |
|
209 |
|
210 /*! |
|
211 Return the title of this view for display |
|
212 */ |
|
213 QString ImageView::title() |
|
214 { |
|
215 return QString("ImageView"); |
|
216 } |
|
217 |
|
218 /*! |
|
219 Return whether this view is active or not |
|
220 */ |
|
221 bool ImageView::isActive() |
|
222 { |
|
223 return d->m_isActive; |
|
224 } |
|
225 |
|
226 |
|
227 /*! |
|
228 Return the list of public QActions most relevant to the view's current context |
|
229 (most approptiate for contextual menus, etc. |
|
230 */ |
|
231 QList<QAction*> ImageView::getContext() |
|
232 { |
|
233 // for now, all actions valid at all times |
|
234 // but there may be some logic here to determine context |
|
235 QList<QAction*> contextList; |
|
236 contextList << |
|
237 d->m_actionForward << |
|
238 d->m_actionBack << |
|
239 d->m_actionOK << |
|
240 d->m_actionCancel; |
|
241 return contextList; |
|
242 } |
|
243 |
|
244 /*! |
|
245 Get the current image from the flow interface |
|
246 */ |
|
247 QImage ImageView::getCurrent() const |
|
248 { |
|
249 int index = d->m_flowInterface->centerIndex(); |
|
250 QImage img(d->m_flowInterface->slide(index)); |
|
251 if(!img.isNull()) |
|
252 return img; |
|
253 return QImage(); |
|
254 } |
|
255 |
|
256 /*! |
|
257 Get the current image count (valid even if view is not active) |
|
258 */ |
|
259 int ImageView::getCurrentImageCount() |
|
260 { |
|
261 return d->m_imageList.count(); |
|
262 } |
|
263 |
|
264 /*! |
|
265 Return the view's Forward QAction |
|
266 For scrolling the history view forwards |
|
267 */ |
|
268 QAction * ImageView::getActionForward() |
|
269 { |
|
270 return d->m_actionForward; |
|
271 } |
|
272 |
|
273 /*! |
|
274 Return the view's Back QAction |
|
275 For scrolling the history view backwards |
|
276 */ |
|
277 QAction * ImageView::getActionBack() |
|
278 { |
|
279 return d->m_actionBack; |
|
280 } |
|
281 |
|
282 /*! |
|
283 Return the view's OK QAction |
|
284 For invoking the view's OK |
|
285 */ |
|
286 QAction * ImageView::getActionOK() |
|
287 { |
|
288 return d->m_actionOK; |
|
289 } |
|
290 |
|
291 /*! |
|
292 Return the view's Cancel QAction |
|
293 For invoking the view's Cancel |
|
294 */ |
|
295 QAction * ImageView::getActionCancel() |
|
296 { |
|
297 return d->m_actionCancel; |
|
298 } |
|
299 |
|
300 void ImageView::refreshFlowInterface() |
|
301 { |
|
302 if(!d->m_flowInterface) |
|
303 return; |
|
304 |
|
305 // clear |
|
306 d->m_flowInterface->clear(); |
|
307 if (d->m_imageList.count() > 0) { |
|
308 for (int i=0; i < d->m_imageList.count(); i++) |
|
309 d->m_flowInterface->addSlide(d->m_imageList.at(i)); |
|
310 |
|
311 d->m_flowInterface->setCenterIndex(0); |
|
312 centerIndexChanged(0); |
|
313 } |
|
314 updateActions(0); |
|
315 } |
|
316 |
|
317 /*! |
|
318 activate the view's resources. Could be connected by client to view visibility |
|
319 */ |
|
320 void ImageView::activate() |
|
321 { |
|
322 Q_ASSERT(!d->m_isActive); |
|
323 |
|
324 if(!d->m_flowInterface) |
|
325 return; |
|
326 |
|
327 d->m_flowInterface->init(); |
|
328 |
|
329 // now forward visual flow lite's signals |
|
330 connect(d->m_flowInterface, SIGNAL(centerIndexChanged(int)), SIGNAL(centerIndexChanged(int))); |
|
331 connect(d->m_flowInterface, SIGNAL(ok(int)), this, SLOT(chooseImage(int))); |
|
332 connect(d->m_flowInterface, SIGNAL(cancel()), this, SIGNAL(cancel())); |
|
333 |
|
334 // internally process the index change signal as well |
|
335 connect(d->m_flowInterface, SIGNAL(centerIndexChanged(int)), this, SLOT(updateActions(int))); |
|
336 |
|
337 // auto-link relevant actions to slots |
|
338 connect(d->m_actionForward, SIGNAL(triggered()), this, SLOT(forward())); |
|
339 connect(d->m_actionBack, SIGNAL(triggered()), this, SLOT(back())); |
|
340 |
|
341 // show and set index |
|
342 d->m_imageIndex = 0; |
|
343 d->m_isActive = true; |
|
344 |
|
345 // finally update the images at the end (will also update the interface) just before showing |
|
346 updateImageList(true); |
|
347 d->m_flowInterface->show(); |
|
348 } |
|
349 |
|
350 /*! |
|
351 deactivate the view's resources. Could be connected by client to view visibility |
|
352 */ |
|
353 void ImageView::deactivate() |
|
354 { |
|
355 Q_ASSERT(d->m_isActive); |
|
356 |
|
357 if(!d->m_flowInterface) |
|
358 return; |
|
359 |
|
360 // disconnect signals |
|
361 disconnect(d->m_flowInterface, SIGNAL(centerIndexChanged(int)), this, SIGNAL(centerIndexChanged(int))); |
|
362 disconnect(d->m_flowInterface, SIGNAL(ok(int)), this, SLOT(chooseImage(int))); |
|
363 disconnect(d->m_flowInterface, SIGNAL(cancel()), this, SIGNAL(cancel())); |
|
364 |
|
365 // internally process the index change signal as well |
|
366 disconnect(d->m_flowInterface, SIGNAL(centerIndexChanged(int)), this, SLOT(updateActions(int))); |
|
367 |
|
368 // auto-link relevant actions to slots |
|
369 disconnect(d->m_actionForward, SIGNAL(triggered()), this, SLOT(forward())); |
|
370 disconnect(d->m_actionBack, SIGNAL(triggered()), this, SLOT(back())); |
|
371 |
|
372 // cleanup |
|
373 d->m_flowInterface->deleteLater(); |
|
374 d->m_flowInterface = NULL; |
|
375 d->m_isActive = false; |
|
376 } |
|
377 |
|
378 /*! |
|
379 set the history view's center index |
|
380 */ |
|
381 void ImageView::setCenterIndex(int index) |
|
382 { |
|
383 // first emit center index change |
|
384 //emit centerIndexChanged(index); |
|
385 |
|
386 d->m_imageIndex = index - d->m_activePage->history()->currentItemIndex(); |
|
387 QWebHistoryItem item = d->m_activePage->history()->itemAt(d->m_imageIndex); |
|
388 QString title; |
|
389 if (item.isValid()) { |
|
390 title = item.title(); |
|
391 if (title.isNull() || title.isEmpty()) { |
|
392 title = item.url().toString(); |
|
393 } |
|
394 } |
|
395 emit titleChanged(title); |
|
396 emit centerIndexChanged(index); |
|
397 } |
|
398 |
|
399 /*! |
|
400 scroll forward in the view |
|
401 */ |
|
402 void ImageView::forward() |
|
403 { |
|
404 if(!d->m_flowInterface) |
|
405 return; |
|
406 |
|
407 d->m_flowInterface->showNext(); |
|
408 } |
|
409 |
|
410 /*! |
|
411 scroll back in the view |
|
412 */ |
|
413 void ImageView::back() |
|
414 { |
|
415 if(!d->m_flowInterface) |
|
416 return; |
|
417 |
|
418 d->m_flowInterface->showPrevious(); |
|
419 } |
|
420 |
|
421 void ImageView::updateActions(int centerIndex) |
|
422 { |
|
423 d->m_actionBack->setEnabled(centerIndex != 0); |
|
424 d->m_actionForward->setEnabled(centerIndex < (d->m_activePage->history()->count() - 1)); |
|
425 } |
|
426 |
|
427 |
|
428 |
|
429 void ImageView::chooseImage(int index) |
|
430 { |
|
431 QImage img(d->m_flowInterface->slide(index)); |
|
432 if(!img.isNull()) |
|
433 emit ok(img); |
|
434 } |
|
435 |
|
436 /*! |
|
437 \fn void ImageView::centerIndexChanged(int index); |
|
438 emitted when the center index changed |
|
439 */ |
|
440 |
|
441 /*! |
|
442 \fn void ImageView::ok(QImage img); |
|
443 emitted when the ok action has occured, contains history index at the time of close |
|
444 */ |
|
445 |
|
446 /*! |
|
447 \fn void ImageView::cancel(); |
|
448 emitted when the cancel action has occured |
|
449 */ |
|
450 |
|
451 } // namespace WRT |
|