browsercore/appfw/Api/Views/ImageView.cpp
branchGCC_SURGE
changeset 8 2e16851ffecd
parent 2 bf4420e9fa4d
parent 6 1c3b8676e58c
equal deleted inserted replaced
2:bf4420e9fa4d 8:2e16851ffecd
     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