diff -r b0dd75e285d2 -r 0f2326c2a325 ginebra2/ContentToolbarSnippet.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ginebra2/ContentToolbarSnippet.cpp Wed Jun 23 17:59:43 2010 +0300 @@ -0,0 +1,550 @@ +/* +* Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies). +* All rights reserved. +* +* This program is free software: you can redistribute it and/or modify +* it under the terms of the GNU Lesser General Public License as published by +* the Free Software Foundation, version 2.1 of the License. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU Lesser General Public License for more details. +* +* You should have received a copy of the GNU Lesser General Public License +* along with this program. If not, +* see "http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html/". +* +* Description: +* This class extends WebChromeContainerSnippet class to hold the +* content view toolbar buttons +* Note: Showing/Hiding of the sub-chrome snippets in response to +* the button selection is not entirely done here as we have a +* a hybrid html-native design. +* MostVisited: Show/Hide is handled in handleMVButton. +* Menu: Show is handled in Javascript. Hide is handled here. +* Zoom: Show/Hide is handled here +* Note: Most Visited is native while Menu and Zoom are html based. All three of them need to +* be dismissed if the user taps anywhere else on the screen. Since mv is native, it handles +* all mouse events and dismisses itself. Zoom/Menu are created as PopupChromeItem which receives +* the mouse events in its event filter and emits a signal if the user taps anywhere on the screen +* other than itself. This signal is handled here. +* +*/ + +#include "ContentToolbarSnippet.h" +#include "ContentToolbarChromeItem.h" +#include "mostvisitedsnippet.h" +#include "Toolbar.h" +#include "ViewStack.h" +#include "webpagecontroller.h" + +#include + + +namespace GVA { + + + ContentToolbarSnippet::ContentToolbarSnippet(const QString& elementId, ChromeWidget * chrome, const QRectF& ownerArea, const QWebElement & element, QGraphicsWidget * widget) + : ToolbarSnippet(elementId, chrome, ownerArea, element, widget), + m_middleSnippet(NULL), + m_subChromeSnippet(NULL) + { + + m_type = TOOLBAR_WEB_VIEW; + m_subChromeInactiveTimer = new QTimer(this); + connect(m_subChromeInactiveTimer, SIGNAL(timeout()), this, SLOT(onInactivityTimer())); + + } + + ContentToolbarSnippet::~ContentToolbarSnippet() + { + delete m_subChromeInactiveTimer; + } + + void ContentToolbarSnippet::updateSize(QSize size) { + //qDebug() << "ContentToolbarSnippet::updateSize" << size.width() ; + setWidth(size.width()); + ToolbarSnippet::updateSize(size); + + } + + void ContentToolbarSnippet::updateOwnerArea() { + + + //qDebug() << "ContentToolbarSnippet::updateOwnerArea" << m_chrome->width() ; + setWidth(m_chrome->width()); + ToolbarSnippet::updateOwnerArea(); + + //qDebug() << "------------Relayout "<< elementId() << hidesContent(); + // If hidesContent is true, it means that the snippet is tied to the chrome's layout. Hence, we + // should invalidate and activate the layout here so that the layout and recalculate all + // edges (we don't want to wait for the asynchronous layout request to be handled as + // that would cause the this snippet to be painted in incorrect position before the layoutRequest + // is handled + if (hidesContent() ) { + chrome()->layout()->invalidate(); + chrome()->layout()->activate(); + } + } + + void ContentToolbarSnippet::setWidth(int width ){ + + QGraphicsLinearLayout* l = layout(); + + // We are using the width of the first element as the first and last elements are the same width + if (l && l->itemAt(0)) { + + qreal snippetWidth = width -(2 * l->itemAt(0)->geometry().width()); + m_middleSnippet->setLayoutWidth(snippetWidth, true); + + } + + } + + void ContentToolbarSnippet::childAdded(ChromeSnippet* child) { + + addActionInfo(child->elementId()); + } + + void ContentToolbarSnippet::addActionInfo(QString id) { + + ToolbarActions_t* t = new ToolbarActions_t(); + if (id == "BackButtonSnippet" ) { + t->actionId = CONTENT_VIEW_ACTION_BACK; + t->actionName = CONTENT_TOTOLBAR_BACK; + t->activeImg = ":/chrome/bedrockchrome/toolbar.snippet/icons/icon_back.png"; + t->disabledImg = ":/chrome/bedrockchrome/toolbar.snippet/icons/icon_back_disabled.png"; + t->selectedImg = ":/chrome/bedrockchrome/toolbar.snippet/icons/icon_back_pressed.png"; + } + else if (id == "ZoomButtonSnippet" ) { + t->actionId = CONTENT_VIEW_ACTION_ZOOM; + t->actionName = CONTENT_TOTOLBAR_ZOOM; + t->activeImg = ":/chrome/bedrockchrome/toolbar.snippet/icons/icon_zoom.png"; + t->disabledImg = ":/chrome/bedrockchrome/toolbar.snippet/icons/icon_zoom_disabled.png"; + t->selectedImg = ":/chrome/bedrockchrome/toolbar.snippet/icons/icon_zoom_pressed.png"; + } + else if (id == "MenuButtonSnippet" ) { + t->actionId = CONTENT_VIEW_ACTION_MENU; + t->actionName = CONTENT_TOTOLBAR_MENU; + t->activeImg = ":/chrome/bedrockchrome/toolbar.snippet/icons/icon_menu.png"; + t->disabledImg = ""; + t->selectedImg = ":/chrome/bedrockchrome/toolbar.snippet/icons/icon_menu_pressed.png"; + } + else if (id == "MostVisitedButtonSnippet" ) { + t->actionId = CONTENT_VIEW_ACTION_MOSTVISITED; + t->actionName = CONTENT_TOTOLBAR_MOSTVISITED; + t->activeImg = ":/chrome/bedrockchrome/toolbar.snippet/icons/icon_mostvisited.png"; + t->disabledImg = ""; + t->selectedImg = ":/chrome/bedrockchrome/toolbar.snippet/icons/icon_mostvisited_pressed.png"; + } + else if (id == "ToggleTBButtonSnippet" ) { + t->actionId = CONTENT_VIEW_ACTION_TOGGLETB; + t->actionName = CONTENT_TOTOLBAR_TOGGLETB; + t->activeImg = ":/chrome/bedrockchrome/toolbar.snippet/icons/icon_toggleTB.png"; + t->disabledImg = ""; + t->selectedImg = ":/chrome/bedrockchrome/toolbar.snippet/icons/icon_toggleTB_pressed.png"; + } + t->id = id; + m_actionInfo.append(t); + } + + void ContentToolbarSnippet::addChild(ChromeSnippet* child) { + + WebChromeContainerSnippet * s = dynamic_cast(child); + if (s) { + connect(child, SIGNAL(childAdded(ChromeSnippet*)), this, SLOT(childAdded(ChromeSnippet*))); + m_middleSnippet = s; + // Set the snippet width + setWidth(m_chrome->width()); + } + else { + addActionInfo(child->elementId()); + } + + WebChromeContainerSnippet::addChild(child); + + } + + void ContentToolbarSnippet::onChromeComplete() { + + ChromeItem * item = static_cast(widget()); + manageChildren(item); + + // Connect back to initialLayoutCompleted signal + ActionButtonSnippet * button = getActionButtonSnippet(CONTENT_VIEW_ACTION_BACK); + connect(WebPageController::getSingleton(), SIGNAL(initialLayoutCompleted()), button->widget(), SLOT(onHidden())); + + connect(m_chrome, SIGNAL(aspectChanged(int)) , this, SLOT(onAspectChanged())); + + } + + void ContentToolbarSnippet::manageChildren(ChromeItem * it) { + + + /*! + * Content toolbar needs to listen to mouse events of each of the toolbar + * buttons as well as the snippets that pop-up on selecting these + * buttons. Some of these buttons are not direct children of content toolbar + * but placed within another container. Also, the pop-ups are not directly + * linked to content toolbar. Here, all these snippets are determined to connect to the + * widget's mosueEvent signal + */ + QList items = it->childItems(); + ContentToolbarChromeItem * w = static_cast(widget()); + //qDebug() << " ------------------- Num of children " << items.count(); + for (int i = 0; i < items.count() ; i++) { + + // Can't use qobject_cast since QGraphicsWdiget is not a QObject + ChromeItem * item = dynamic_cast(items.at(i)); + if (item ) { + + WebChromeContainerSnippet * s = dynamic_cast(item->snippet()); + // If it is a container, need to connect to it's child items, so recurse + if (s ) { + manageChildren(item); + } + else { // Individual item + //qDebug() << "Item: " << item->snippet()->elementId(); + if (w->autoHideToolbar()) { + connect(item, SIGNAL(mouseEvent(QEvent::Type)), w, SLOT(onSnippetMouseEvent(QEvent::Type))); + } + // Connect to the mouse event to show selected image on key press + //connect(item, SIGNAL(mouseEvent( QEvent::Type )), this, SLOT(onMouseEvent(QEvent::Type))); + setAction(item->snippet()); + + + ChromeSnippet * link = item->snippet()->linkedSnippet(); + + if (link) { + ChromeItem* it = dynamic_cast (link->widget()); + if (it ) { + connect(it, SIGNAL(mouseEvent(QEvent::Type)), this, SLOT(onSnippetMouseEvent(QEvent::Type))); + // Save the linked children to be used later for hiding + w->addLinkedChild(link); + + // In case it has more children, recurse + manageChildren(it); + } + } + } + } + } + + } + + + void ContentToolbarSnippet::setAction(ChromeSnippet * s) { + + //qDebug() << "setAction: " << s->elementId(); + ToolbarSnippet::setAction(s); + ActionButtonSnippet * button = static_cast (s); + int index = getIndex(s); + + if (index != -1) { + QAction * action = button->getDefaultAction(); + ToolbarActions_t * t = m_actionInfo.at(index); + + switch (t->actionId) { + + case CONTENT_VIEW_ACTION_ZOOM: + addZoomButton(action, button); + break; + case CONTENT_VIEW_ACTION_MENU: + addMenuButton(action, button); + break; + case CONTENT_VIEW_ACTION_MOSTVISITED: + addMostVisitedButton(action, button); + break; + case CONTENT_VIEW_ACTION_TOGGLETB: + addToggleTBButton(action, button); + break; + default: + break; + } + } + + } + + void ContentToolbarSnippet::addZoomButton(QAction * action, ActionButtonSnippet* button) { + + assert(action); + assert(button); + connect(action, SIGNAL(triggered()), this, SLOT(handleZoomButton())); + + + // Connect to hide and show signals of the linked snippet + connectHideShowSignals(button); + connect( button->linkedSnippet(), SIGNAL(externalMouseEvent(int, const QString , const QString )), this, SLOT(onExternalMouse(int, const QString , const QString))); + + } + + void ContentToolbarSnippet::addMenuButton(QAction * action, ActionButtonSnippet* button) { + + assert(action); + assert(button); + + connect(action, SIGNAL(triggered()), this, SLOT(handleMenuButton())); + + // Connect to hide and show signals of the linked snippet + connectHideShowSignals(button); + connect( button->linkedSnippet(), SIGNAL(externalMouseEvent(int, const QString , const QString )), this, SLOT(onExternalMouse(int, const QString , const QString))); + + } + + void ContentToolbarSnippet::addMostVisitedButton(QAction * action, ActionButtonSnippet* button) { + + assert(action); + assert(button); + + connect(action, SIGNAL(triggered()), this, SLOT(handleMVButton())); + + // Connect to hide and show signals of the linked snippet + connectHideShowSignals(button); + } + + void ContentToolbarSnippet::addToggleTBButton(QAction * action, ActionButtonSnippet* button) { + + assert(action); + assert(button); + + connect(action, SIGNAL(triggered()), this, SLOT(handleToggleTBButton())); + } + + + void ContentToolbarSnippet::handleZoomButton() { + + ActionButtonSnippet * button = getActionButtonSnippet(CONTENT_VIEW_ACTION_ZOOM); + ChromeSnippet * zoomSnippet = button->linkedSnippet(); + + //qDebug() << "ContentToolbarSnippet::handleZoomButton() : Show flag: " << zoomSnippet->getDontShowFlag() << "Checked " << button->isChecked(); + + // Zoom bar is dismissed if the user taps anywhere on the screen. We get externalMouseEvent + // if the user presses the button also. In addition to that the action is triggered and the + // handler is called. In this case, we don't need to do anything, so we use the DontShowFlag + // to determine if there is any action needed. + if (zoomSnippet->getDontShowFlag() ){ + // Set selected state to false as it gets enabled in ActionButton mousePressEvent handling + button->setLatched(false); + zoomSnippet->setDontShowFlag(false); + } + else { + hideOtherPopups(button->elementId()); + zoomSnippet->show(); + } + + } + + void ContentToolbarSnippet::handleMenuButton() { + + ActionButtonSnippet * button = getActionButtonSnippet(CONTENT_VIEW_ACTION_MENU); + ChromeSnippet * menuSnippet = button->linkedSnippet(); + + //qDebug() << "ContentToolbarSnippet::handleMenuButton() : Show flag: " << button->linkedSnippet()->getDontShowFlag() << "Checked: " << button->isChecked(); + if (menuSnippet ) { + //qDebug() << "ContentToolbarSnippet::handleMenuButton() : Dont show flag " << menuSnippet->getDontShowFlag(); + if (menuSnippet->getDontShowFlag() ){ + // Set selected state to false as it gets enabled in ActionButton mousePressEvent handling + button->setLatched(false); + menuSnippet->setDontShowFlag(false); + } + else { + // Hide other pop-ups if any. Showing the menu is handled in + // javascript + emit menuButtonSelected(); + hideOtherPopups(button->elementId()); + } + } + + } + + void ContentToolbarSnippet::handleMVButton() { + + //qDebug() << "ContentToolbarSnippet::handleMVButton() "; + ActionButtonSnippet * button = getActionButtonSnippet(CONTENT_VIEW_ACTION_MOSTVISITED); + hideOtherPopups(button->elementId()); + button->linkedSnippet()->toggleVisibility(); + } + + void ContentToolbarSnippet::handleToggleTBButton() { + ActionButtonSnippet * button = getActionButtonSnippet(CONTENT_VIEW_ACTION_TOGGLETB); + ContentToolbarChromeItem * w = static_cast(widget()); + + w->toggleMiddleSnippet(); + button->updateButtonState(false); + } + + + void ContentToolbarSnippet::hideOtherPopups(QString id) { + + + for (int i = 0; i < m_actionInfo.size() ; i++ ) { + + ToolbarActions_t * t = m_actionInfo.at(i); + if (t->id != id ) { + ActionButtonSnippet * buttonSnippet = static_cast ( m_chrome->getSnippet(t->id)); + ChromeSnippet * linkedSnippet = buttonSnippet->linkedSnippet(); + + // If there is another sub-chrome visible, hide it + if (linkedSnippet ) { + if ( linkedSnippet->isVisible()) { + linkedSnippet->hide(); + } + else { + // When the user selects the menu button, menu is displayed after certain timeout + // and it is possible that the user can select another button. So cancel it if the + // button is 'checked' if we get another action trigger + + //qDebug() << "ContentToolbarSnippet::hideOtherPopups: " << id << "Button: " << t->id << buttonSnippet->isChecked(); + + if ( (buttonSnippet->elementId() == "MenuButtonSnippet" ) && (buttonSnippet->isChecked() )) { + emit menuButtonCanceled(); + buttonSnippet->updateButtonState(false); + } + } + } + } + + } + + + } + + void ContentToolbarSnippet::connectHideShowSignals(ActionButtonSnippet * button) { + + // Connect to hide and show signals of the linked snippet + ChromeSnippet * snippet = button->linkedSnippet(); + ActionButton * actionButton = static_cast(button->widget()); + connect(snippet, SIGNAL(hidden()), actionButton, SLOT(onHidden())); + connect(snippet, SIGNAL(shown()), actionButton, SLOT(onShown())); + + connect(snippet, SIGNAL(hidden()), this, SLOT(onHidden())); + connect(snippet, SIGNAL(shown()), this, SLOT(onShown())); + + } + + void ContentToolbarSnippet::onAspectChanged( ) { + + // Hide any pop-up that is visible + hideOtherPopups(QString()); + } + + void ContentToolbarSnippet::onSnippetMouseEvent( QEvent::Type type) { + + //qDebug() << "ContentToolbarSnippet::onSnippetMouseEvent : Type" << type; + if (type == QEvent::GraphicsSceneMousePress || type == QEvent::MouseButtonPress ) { + resetTimer(false); + } + else if (type == QEvent::GraphicsSceneMouseRelease || type == QEvent::MouseButtonRelease ) { + resetTimer(); + } + } + + void ContentToolbarSnippet::onMouseEvent( QEvent::Type type) { + + ActionButton* button = static_cast ( sender()); + ActionButtonSnippet * buttonSnippet = static_cast( button->snippet()); + ChromeSnippet * linkedSnippet = buttonSnippet->linkedSnippet(); + //qDebug() << "ContentToolbarSnippet::onMouseEvent : Button : " << buttonSnippet->elementId() << " type: " << type << "Is Enabled " << button->defaultAction()->isEnabled(); + + // Set the action button state to active so that we can show a selected image before the + // action is acted upon + if (button->defaultAction()->isEnabled() && type == QEvent::GraphicsSceneMousePress ) { + + // Set active flag if there is no linked snippet (the button acts as toggle if it + // has a linked snippet. If there is linked snippet, set active flag if the linked snippet + // is not visible and dont show flag is false + if (!linkedSnippet || (linkedSnippet && (!linkedSnippet->isVisible() && !linkedSnippet->getDontShowFlag()))){ + buttonSnippet->setActive(true); + } + } + } + + void ContentToolbarSnippet::onHidden() { + + ChromeSnippet * snippet = static_cast (sender()); + //qDebug() << "ContentToolbarSnippet::onHidden" << snippet->elementId(); + if (snippet == m_subChromeSnippet ) { + + //qDebug() << "ContentToolbarSnippet::onHidden hide shown snippet" << snippet->elementId(); + resetTimer(false); + m_subChromeSnippet = NULL; + } + + } + + void ContentToolbarSnippet::onShown() { + + // If one sub-chrome is being displayed when another is requested to be launched by the user, to avoid + //depending on the order of receiving hidden and shown signals for each of those, we save the snippet + // being shown and then later when hidden signal is received, the sender is compared to the + // snippet for which we started the timer so that the timer is started and stopped for the + // correct snippet. If 'shown' signal for the second is received before hidden for the second, the timer + // is stopped and restarted and the sub-chrome snippet is set to the new one. When 'hidden' is received + // for the first, it is ignored as it doesn't match our saved snippet value. + m_subChromeSnippet = static_cast (sender()); + //qDebug() << "ContentToolbarSnippet::onShown" << m_subChromeSnippet->elementId(); + + resetTimer(); + + } + + + void ContentToolbarSnippet::onInactivityTimer() { + + //qDebug() << "ContentToolbarSnippet::onInactivityTimer" << m_subChromeSnippet->elementId(); + if (m_subChromeSnippet->elementId() == "MostVisitedViewId" ) { + MostVisitedSnippet * mv = static_cast(m_subChromeSnippet); + mv->close(); + // Stop the timer here as there is animation to complete before hide is received + resetTimer(false); + m_subChromeSnippet = NULL; + } + else { + + // Hide the snippet. onHidden slot will be called when the snippet is hidden + // and there we will stop the timer and reset m_subChromeSnippet + m_subChromeSnippet->hide(); + } + } + + + void ContentToolbarSnippet::resetTimer(bool start) { + + int duration = TOOLBAR_POPUP_INACTIVITY_DURATION; + if (m_subChromeInactiveTimer->isActive() ) { + //qDebug() << " Stop timer for " << m_subChromeSnippet->elementId(); + m_subChromeInactiveTimer->stop(); + } + + if (start) { + if (m_subChromeSnippet->elementId() == "ZoomBarId" ) { + duration = TOOLBAR_ZOOMBAR_INACTIVITY_DURATION; + } + //qDebug() << " Start timer for " << m_subChromeSnippet->elementId(); + m_subChromeInactiveTimer->start(duration); + } + + } + void ContentToolbarSnippet::onExternalMouse( int type, + const QString & name, + const QString & description) { + + Q_UNUSED(type); + Q_UNUSED(description); + ChromeSnippet * snippet = static_cast (sender()); + //qDebug() << "ContentToolbarSnippet::onExternalMouse" << snippet->elementId() << name; + + if (name == "QGraphicsSceneMousePressEvent" || name == "QGraphicsSceneResizeEvent" ) { + snippet->hide(); + snippet->setDontShowFlag(true); + QTimer::singleShot(500, snippet, SLOT(disableDontShowFlag())); + } + + + } + + +} // end of namespace GVA + +