ginebra2/ChromeDOM.cpp
branchGCC_SURGE
changeset 8 2e16851ffecd
parent 6 1c3b8676e58c
child 15 73c48011b8c7
equal deleted inserted replaced
2:bf4420e9fa4d 8:2e16851ffecd
     1 /*
     1 /*
     2 * Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
     2 * Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3 * All rights reserved.
     3 * All rights reserved.
     4 * This component and the accompanying materials are made available
     4 *
     5 * under the terms of "Eclipse Public License v1.0"
     5 * This program is free software: you can redistribute it and/or modify
     6 * which accompanies this distribution, and is available
     6 * it under the terms of the GNU Lesser General Public License as published by
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
     7 * the Free Software Foundation, version 2.1 of the License.
     8 *
     8 *
     9 * Initial Contributors:
     9 * This program is distributed in the hope that it will be useful,
    10 * Nokia Corporation - initial contribution.
    10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
    11 *
    11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    12 * Contributors:
    12 * GNU Lesser General Public License for more details.
    13 *
    13 *
    14 * Description: 
    14 * You should have received a copy of the GNU Lesser General Public License
       
    15 * along with this program.  If not,
       
    16 * see "http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html/".
       
    17 *
       
    18 * Description:
       
    19 * 
    15 *
    20 *
    16 */
    21 */
    17 
       
    18 
    22 
    19 #include <QtGui>
    23 #include <QtGui>
    20 #include <QWebElement>
    24 #include <QWebElement>
    21 #include <QWebFrame>
    25 #include <QWebFrame>
    22 #include <QWebPage>
    26 #include <QWebPage>
    25 #include "ChromeRenderer.h"
    29 #include "ChromeRenderer.h"
    26 #include "ChromeSnippet.h"
    30 #include "ChromeSnippet.h"
    27 #include "ChromeWidget.h"
    31 #include "ChromeWidget.h"
    28 #include "WebChromeSnippet.h"
    32 #include "WebChromeSnippet.h"
    29 #include "WebChromeContainerSnippet.h"
    33 #include "WebChromeContainerSnippet.h"
    30 #include "GreenChromeSnippet.h"
    34 #include "PageSnippet.h"
    31 #include "BlueChromeSnippet.h"
    35 #include "PageItem.h"
    32 #include "ScrollZoomWidget.h"
    36 #include "ProgressBarItem.h"
    33 #include "ProgressSnippet.h"
    37 #include "ProgressBarSnippet.h"
    34 #include "TextEditItem.h"
       
    35 #include "ToolbarChromeItem.h"
    38 #include "ToolbarChromeItem.h"
    36 #include "ContentToolbarChromeItem.h"
    39 #include "ContentToolbarChromeItem.h"
    37 #include "iconsnippet.h"
    40 #include "ContentToolbarSnippet.h"
    38 #include "iconwidget.h"
    41 #include "WindowToolbarSnippet.h"
       
    42 #include "RecentUrlToolbarSnippet.h"
       
    43 #include "BookmarksToolbarSnippet.h"
       
    44 #include "SettingsToolbarSnippet.h"
    39 #include "ActionButton.h"
    45 #include "ActionButton.h"
    40 #include "UrlSearchSnippet.h"
       
    41 #include "ActionButtonSnippet.h"
    46 #include "ActionButtonSnippet.h"
    42 #include "mostvisitedpageview.h"
    47 #include "mostvisitedpageview.h"
    43 #include "mostvisitedsnippet.h"
    48 #include "mostvisitedsnippet.h"
       
    49 #include "UrlSearchSnippet.h"
       
    50 #include "EditorSnippet.h"
    44 
    51 
    45 #include <QDebug>
    52 #include <QDebug>
    46 
    53 
    47 //TODO: Replace JS strings with DOM api. Make stateful: i.e. get the doc element from the current page
    54 //TODO: Replace JS strings with DOM api. Make stateful: i.e. get the doc element from the current page
    48 
    55 
    55       m_bytes(0)
    62       m_bytes(0)
    56   {
    63   {
    57     m_renderer = m_chrome->renderer();
    64     m_renderer = m_chrome->renderer();
    58     m_renderer->clearRenderList();
    65     m_renderer->clearRenderList();
    59   }
    66   }
    60   
    67 
    61   ChromeDOM::~ChromeDOM()
    68   ChromeDOM::~ChromeDOM()
    62   {
    69   {
    63   }
    70   }
    64 
    71 
    65   QVariant ChromeDOM::evalInChromeContext(QString js){
    72   QVariant ChromeDOM::evalInChromeContext(QString js){
    66     return m_page->mainFrame()->evaluateJavaScript(js);
    73     return m_page->mainFrame()->evaluateJavaScript(js);
    67   }
    74   }
    68   
    75 
    69   QWebElement ChromeDOM::getElementById(const QString &id)
    76   QWebElement ChromeDOM::getElementById(const QString &id)
    70   {
    77   {
    71     return m_page->mainFrame()->documentElement().findFirst("#" + id);
    78     return m_page->mainFrame()->documentElement().findFirst("#" + id);
    72   }
    79   }
    73   
    80 
    74   QRect ChromeDOM::getElementRect(const QString &id)
    81   QRect ChromeDOM::getElementRect(const QString &id)
    75   {
    82   {
    76     return getElementById(id).geometry();
    83     return getElementById(id).geometry();
    77   }
    84   }
    78   
    85 
    79   QSize ChromeDOM::getElementSize(const QString &id)
    86   QSize ChromeDOM::getElementSize(const QString &id)
    80   {
    87   {
    81     QRect rect = getElementRect(id);
    88     QRect rect = getElementRect(id);
    82     return QSize(rect.width(), rect.height());
    89     return QSize(rect.width(), rect.height());
    83   }
    90   }
    84   
    91 
    85   QString ChromeDOM::getElementAttribute(const QString &id, const QString &attribute)
    92   QString ChromeDOM::getElementAttribute(const QString &id, const QString &attribute)
    86   {
    93   {
    87     return getElementById(id).attribute(attribute);
    94     return getElementById(id).attribute(attribute);
    88   }
    95   }
    89   
    96 
    90   //Get the cacheable script element. Only one is allowed so get the first one.
    97   //Get the cacheable script element. Only one is allowed so get the first one.
    91   /*QString ChromeDOM::getCacheableScript()
    98   /*QString ChromeDOM::getCacheableScript()
    92   {
    99   {
    93     QWebElement doc = m_page->mainFrame()->documentElement();
   100     QWebElement doc = m_page->mainFrame()->documentElement();
    94     return doc.findAll("script.GinebraCacheable").toList()[0].toPlainText();
   101     return doc.findAll("script.GinebraCacheable").toList()[0].toPlainText();
    95   }
   102   }
    96   */
   103   */
    97 
   104 
    98   //Get a list of cached handlers for a snippet
   105   //Get a list of cached handlers for a snippet
    99   
   106 
   100   QList<CachedHandler> ChromeDOM::getCachedHandlers(const QString &elementId, const QRectF & ownerArea)
   107   QList<CachedHandler> ChromeDOM::getCachedHandlers(const QString &elementId, const QRectF & ownerArea)
   101   {
   108   {
   102     QWebElement snippet = getElementById(elementId);
   109     QWebElement snippet = getElementById(elementId);
   103     QList <QWebElement> controls =  snippet.findAll(".GinebraCached").toList();
   110     QList <QWebElement> controls =  snippet.findAll(".GinebraCached").toList();
   104     QList <CachedHandler> handlers;
   111     QList <CachedHandler> handlers;
   105     for(int i = 0; i < controls.size(); i++){
   112     for (int i = 0; i < controls.size(); i++){
   106       QWebElement elem = controls.at(i);
   113       QWebElement elem = controls.at(i);
   107       //Element rectangle relative to snippet, so we can handle mouse events relative to snippet
   114       //Element rectangle relative to snippet, so we can handle mouse events relative to snippet
   108       //qDebug() << "====> Owner X: " << ownerArea.x() << " Owner Width: " << ownerArea.width() << " Elem X: " << elem.geometry().x() << " Elem Width: " << elem.geometry().width();
   115       //qDebug() << "====> Owner X: " << ownerArea.x() << " Owner Width: " << ownerArea.width() << " Elem X: " << elem.geometry().x() << " Elem Width: " << elem.geometry().width();
   109       QRectF elemRect(elem.geometry().x() - ownerArea.x(), elem.geometry().y() - ownerArea.y(), elem.geometry().width(), elem.geometry().height()); 
   116       QRectF elemRect(elem.geometry().x() - ownerArea.x(), elem.geometry().y() - ownerArea.y(), elem.geometry().width(), elem.geometry().height());
   110       //NB: For now we handle only onclick from cache. Should add at least long-press too.
   117       //NB: For now we handle only onclick from cache. Should add at least long-press too.
   111       CachedHandler handler(elem.attribute("id"), elem.attribute("data-GinebraOnClick"), elemRect, m_chrome, elem.attribute("data-GinebraTargetView"));
   118       CachedHandler handler(elem.attribute("id"), elem.attribute("data-GinebraOnClick"), elemRect, m_chrome, elem.attribute("data-GinebraTargetView"));
   112       //qDebug() << "Cached handler" << handler.elementId() << ": "  << handler.script() << ": "  << handler.rect();
   119       //qDebug() << "Cached handler" << handler.elementId() << ": "  << handler.script() << ": "  << handler.rect();
   113       handlers.append(handler);
   120       handlers.append(handler);
   114     }
   121     }
   115     return handlers;  
   122     return handlers;
       
   123   }
       
   124   
       
   125 
       
   126 //TODO: Get rid of rectangle argument to snippets. This is redundant with the element argument!!
       
   127 //TODO: Rewrite using function table
       
   128   
       
   129   ChromeSnippet * ChromeDOM::nativeSnippetForClassName(const QString & className, const QString elementId,  QWebElement element)
       
   130   {
       
   131       QRectF rect = element.geometry();
       
   132       
       
   133       if (className == "ContentToolbar") {
       
   134           return ContentToolbarSnippet::instance(elementId, m_chrome, element);
       
   135       }
       
   136       else if (className == "WindowToolbar") {
       
   137           return WindowToolbarSnippet::instance(elementId, m_chrome, element);
       
   138       }
       
   139       else if (className == "RecentUrlToolbar") {
       
   140           return RecentUrlToolbarSnippet::instance(elementId, m_chrome, element);
       
   141       }
       
   142       else if (className == "BookmarksToolbar") {
       
   143           return BookmarksToolbarSnippet::instance(elementId, m_chrome, element);
       
   144       }
       
   145       else if (className == "SettingsToolbar") {
       
   146           return SettingsToolbarSnippet::instance(elementId, m_chrome, element);
       
   147       }
       
   148       else if (className == "MostVisitedPagesWidget") {
       
   149           return MostVisitedSnippet::instance(elementId, m_chrome, element);
       
   150       }
       
   151       else if (className == "ActionButton") {
       
   152           return ActionButtonSnippet::instance(elementId, m_chrome, element);
       
   153       }
       
   154       else if (className == "PageSnippet") {
       
   155           return PageSnippet::instance(elementId, m_chrome, element);
       
   156       }
       
   157       else if (className == "UrlSearchSnippet") {
       
   158           return GUrlSearchSnippet::instance(elementId, m_chrome, element);
       
   159       }
       
   160       else if (className == "TextEditSnippet") {
       
   161           return EditorSnippet::instance(elementId, m_chrome, element);
       
   162       }
       
   163       else {
       
   164           ChromeSnippet* result = new ChromeSnippet(elementId, m_chrome, 0, element);
       
   165           result->setChromeWidget(new QGraphicsWidget());
       
   166           return result;
       
   167       }
   116   }
   168   }
   117   
   169   
   118   ChromeSnippet *ChromeDOM::getSnippet(const QString &docElementId, QGraphicsItem* parent) {
   170   ChromeSnippet *ChromeDOM::getSnippet(const QString &docElementId, QGraphicsItem* parent) {
   119     
   171     Q_UNUSED(parent)
   120     ChromeSnippet * result = 0;
   172 
       
   173     ChromeSnippet * snippet = 0;
   121     QWebElement doc = m_page->mainFrame()->documentElement();
   174     QWebElement doc = m_page->mainFrame()->documentElement();
   122     QWebElement element = doc.findFirst("#" + docElementId);
   175     QWebElement element = doc.findFirst("#" + docElementId);
   123     QRect rect = getElementRect(docElementId);
   176     QRect rect = element.geometry();
       
   177     //TODO: This may not be accurate since final heights may not have been computed at this point!!
   124     m_height += rect.height();
   178     m_height += rect.height();
   125     //m_bytes += rect.width() * rect.height() * 3; //Calculate total rendered area at 24 bit depth
   179     
   126     //qDebug() << "Chrome total rects at 24 bits: " << m_bytes;
   180     //    qDebug() << "Snippet: ID: " << docElementId << " Owner Area: " << rect << " Element Rect: " << element.geometry();
   127     //qDebug() << "Snippet: ID: " << docElementId << " Owner Area: " << rect << " Element Rect: " << element.geometry();
   181   
   128     if(!rect.isNull()){
   182     if (!rect.isNull()) {
   129       QString className = element.attribute("data-GinebraNativeClass", "__NO_CLASS__");
   183         QString className = element.attribute("data-GinebraNativeClass", "__NO_CLASS__");
   130       if(className == "__NO_CLASS__")
   184         if (className == "__NO_CLASS__") {
   131 	if(element.attribute("data-GinebraContainer", "false") == "true" ){
   185             if (element.attribute("data-GinebraContainer", "false") == "true") {
   132           
   186                 snippet = new WebChromeContainerSnippet(docElementId, m_chrome, element);
   133           QString type = element.attribute("data-GinebraItemType", "normal");
   187                 snippet->setChromeWidget(new ChromeItem(snippet));
   134           if (type == "contenttoolbar" ) {
   188             }
   135             ContentToolbarChromeItem * widget = new ContentToolbarChromeItem();
   189             else {
   136             result = new WebChromeContainerSnippet(docElementId, m_chrome, rect, element, widget);
   190                 snippet = new WebChromeSnippet(docElementId, m_chrome, element);
   137             widget->setSnippet((WebChromeContainerSnippet*)result);
   191                 m_renderer->addRenderItem((static_cast<WebChromeSnippet*> (snippet))->item());
   138           }
   192             }
   139           else if (type == "toolbar" ) {
       
   140             ToolbarChromeItem * widget = new ToolbarChromeItem();
       
   141             result = new WebChromeContainerSnippet(docElementId, m_chrome, rect, element, widget);
       
   142             widget->setSnippet((WebChromeContainerSnippet*)result);
       
   143           }
       
   144           else {
       
   145             result = new WebChromeContainerSnippet(docElementId, m_chrome, rect, element, new QGraphicsWidget());
       
   146           }
       
   147 	}
       
   148 	else {
       
   149 	  result = new WebChromeSnippet(docElementId, m_chrome, rect, element);
       
   150 	  m_renderer->addRenderItem((static_cast<WebChromeSnippet*>(result))->item());
       
   151         }
   193         }
   152       else {
   194         else {
   153 	QGraphicsWidget * w = 0; 
   195             snippet = nativeSnippetForClassName(className, docElementId, element);
   154     if (className == "IconSnippet") {
   196             //TODO: Is the following still needed?
   155         result = new IconSnippet(docElementId, m_chrome, 0, element);
   197             QGraphicsWidget * widget = snippet->widget();
   156         w = new IconWidget(result);
   198             //Have snippet determine its own size when in anchor layout. Again, these will not
   157     } else if (className == "MostVisitedPagesWidget") {
   199             //necessarily be accurate at this point.
   158         result = new MostVisitedSnippet(docElementId,m_chrome,0,element);
   200             widget->resize(rect.width(), rect.height());
   159         MostVisitedPagesWidget* mostVisited;
   201             widget->setPreferredSize(rect.width(), rect.height());
   160         mostVisited = new MostVisitedPagesWidget(result,m_chrome);
   202             widget->setSizePolicy(QSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred));
   161         mostVisited->hide();
   203             //Have snippet determine its own location when NOT in anchor layout
   162         w = mostVisited;
   204             widget->setPos(rect.x(), rect.y());
   163     } else if (className == "ActionButton") {
   205             
   164         result = new ActionButtonSnippet(docElementId, m_chrome, 0, element);
   206         }
   165         w = new ActionButton(result);
   207 
   166     } else {
   208         QWebElement parentElem;
   167 	  //Chrome snippet takes ownership of w
   209 
   168 	  result = new ChromeSnippet(docElementId, m_chrome, 0, element);
   210         if (!(parentElem = findChromeParent(element)).isNull()) {
   169 	  if (className == "ScrollZoomWidget")
   211             snippet->setParentId(parentElem.attribute("id"));
   170 	    w = new ScrollZoomWidget(result);
   212         }
   171           else if (className == "UrlSearchSnippet")
   213         //Set auto-layout attributes
   172 	    w = new UrlSearchSnippet(result, m_chrome);
   214         snippet->setAnchor(element.attribute("data-GinebraAnchor", "AnchorNone"), false);
   173 	  else if (className == "ProgressSnippet")
   215         snippet->setAnchorOffset(element.attribute("data-GinebraAnchorOffset", "0").toInt());
   174 	    w = new ProgressSnippet(result);
   216         snippet->setInitiallyVisible(element.attribute("data-GinebraVisible", "false") == "true");
   175 	  else if (className == "TextEditSnippet"){
   217         snippet->setHidesContent(element.attribute("data-GinebraHidesContent", "false") == "true");
   176 	    w = new TextEditItem(result);
       
   177 	  }
       
   178 	  else { 
       
   179 	    w= new GreenChromeSnippet();
       
   180 	  }
       
   181 	}
       
   182         result->setWidget(w);
       
   183         //Have snippet deterimine its own size when in anchor layout
       
   184         w->resize(rect.width(), rect.height());
       
   185 	w->setPreferredSize(rect.width(), rect.height());
       
   186 	w->setSizePolicy(QSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred));
       
   187         //Have snippet determine its own location when NOT in anchor layout
       
   188         w->setPos(rect.x(), rect.y());	
       
   189       }
       
   190 
       
   191       if(element.parent().attribute("class") == "GinebraSnippet") {
       
   192 	result->setParentId(element.parent().attribute("id"));
       
   193       }
       
   194       //Set auto-layout attributes
       
   195       result->setAnchor(element.attribute("data-GinebraAnchor", "AnchorNone"), false);
       
   196       result->setAnchorOffset(element.attribute("data-GinebraAnchorOffset", "0").toInt());
       
   197       result->setInitiallyVisible(element.attribute("data-GinebraVisible", "false") == "true" );
       
   198       result->setHidesContent( element.attribute("data-GinebraHidesContent", "false") == "true" );      
       
   199     }
   218     }
   200     return result;
   219     return snippet;
   201   }
   220   }
   202   
   221   
       
   222   QWebElement ChromeDOM::findChromeParent(QWebElement element)
       
   223   {
       
   224     while(!(element = element.parent()).isNull()){
       
   225       if (element.attribute("class") == "GinebraSnippet"){
       
   226 	return element;
       
   227       }
       
   228     }
       
   229     return element;
       
   230   }
       
   231 
   203   QList <QWebElement> ChromeDOM::getInitialElements()
   232   QList <QWebElement> ChromeDOM::getInitialElements()
   204   { 
   233   {
   205     m_renderer->clearRenderList();
   234     m_renderer->clearRenderList();
   206     QWebElement test = getElementById("TestTableCell9");
   235     QWebElement test = getElementById("TestTableCell9");
   207     //qDebug() << "TEST ELEMENT:" << test.toPlainText();
   236     //qDebug() << "TEST ELEMENT:" << test.toPlainText();
   208     m_height = 0;
   237     m_height = 0;
   209     QWebElement doc = m_page->mainFrame()->documentElement();
   238     QWebElement doc = m_page->mainFrame()->documentElement();
   210 #if QT_VERSION < 0x040600 //TBD: Do we care, given that the dom api is not officially supported before 4.6?
   239 #if QT_VERSION < 0x040600 //TBD: Do we care, given that the dom api is not officially supported before 4.6?
   211     return doc.findAll(".GinebraSnippet");
   240     return doc.findAll(".GinebraSnippet");
   212 #else
   241 #else
   213     return doc.findAll(".GinebraSnippet").toList();
   242     return doc.findAll(".GinebraSnippet").toList();
   214 #endif
   243 #endif
   215   } 
   244   }
   216   
   245 
   217 } // end of namespace GVA
   246 } // end of namespace GVA