mpviewplugins/mpdetailsviewplugin/src/mpdetailssharedialog.cpp
changeset 36 a0afa279b8fe
parent 35 fdb31ab341af
child 45 612c4815aebe
--- a/mpviewplugins/mpdetailsviewplugin/src/mpdetailssharedialog.cpp	Fri May 14 18:54:37 2010 -0500
+++ b/mpviewplugins/mpdetailsviewplugin/src/mpdetailssharedialog.cpp	Fri May 28 19:46:01 2010 -0500
@@ -1,3 +1,20 @@
+/*
+* Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of "Eclipse Public License v1.0"
+* which accompanies this distribution, and is available
+* at the URL "http://www.eclipse.org/legal/epl-v10.html".
+*
+* Initial Contributors:
+* Nokia Corporation - initial contribution.
+*
+* Contributors:
+*
+* Description: Implementation for share player.
+*
+*/
+
 #ifdef SHARE_FUNC_ENABLED
 
 #include "mpdetailssharedialog.h"
@@ -11,12 +28,19 @@
 #include <QWebFrame>
 #include <QNetworkAccessManager>
 #include <QNetworkDiskCache>
+#include <QNetworkReply>
 #include <QDesktopServices>
 #include <QNetworkProxyFactory>
+#include <QTimer>
 #include <hbmessagebox.h>
 #include <QFile>
 #include <QTextStream>
+#include <qsysteminfo.h>
+#include <hbmainwindow.h>
+#include <hbstyleloader.h>
+#include <hbprogressdialog.h>
 
+QTM_USE_NAMESPACE
 
 // SHARE_INDEX_FILE defines where the index.html file is loaded from.
 #define SHARE_INDEX_URL "qrc:///shareview/index.html"
@@ -27,11 +51,9 @@
 // For R&D testing, index.html may be loaded from E: drive.
 // User must manually place index.html in the correct location.
 // If the RND file does not exist, then SHARE_INDEX_URL will be used.
-#define RND_SHARE_INDEX_URL "file:///e:/index.html"
-#define RND_SHARE_INDEX_FILE "e:\\index.html"
-#define RND_OVI_LOGIN_FILE "e:\\ovicredentials.txt"
-#define RND_DEFAULT_USER "hipsu"
-#define RND_DEFAULT_PASS "hipsupass"
+#define RND_SHARE_INDEX_URL "file:///f:/index.html"
+#define RND_SHARE_INDEX_FILE "f:\\index.html"
+#define RND_OVI_LOGIN_FILE "f:\\ovicredentials.txt"
 #endif
 #else
 // Assume Windows target.
@@ -41,27 +63,73 @@
 
 #endif
 
-// For allowing local caching of javascript files loaded by popup
+// Default language in case QSystemInfo does not work.
+#define DEFAULT_LANGUAGE "en-US"
+
+// Default error message.
+#define ERROR_MESSAGE "An error occured. Sharing is not currently available"
+
+
+/*!
+ MpNetworkAccessManager allows local caching of publishing player files
+ in order to minimize network traffic.
+ The files will be cached to the private directory of the application,
+ i.e. in the music player's case, this is C:\Private\10207C62\Cache.
+ */
 class MpNetworkAccessManager : public QNetworkAccessManager
 {
 public:
-    MpNetworkAccessManager() { };
+    MpNetworkAccessManager( QObject* parent = 0 )
+        : QNetworkAccessManager( parent )
+    {
+        proxyFactory()->setUseSystemConfiguration( true );
+        QNetworkDiskCache* diskCache = new QNetworkDiskCache( this );
+        QString location = QDesktopServices::storageLocation( QDesktopServices::CacheLocation );
+        diskCache->setCacheDirectory( location );
+        setCache( diskCache );
+    }
 
 private:
-    QNetworkReply *createRequest( Operation op,
-                                 const QNetworkRequest &request,
-                                 QIODevice *outgoingData = 0 )
+    QNetworkReply* createRequest( Operation op,
+                                  const QNetworkRequest &request,
+                                  QIODevice* outgoingData = 0 )
     {
         TX_ENTRY
+        TX_LOG_ARGS( "share: createRequest URL=" << request.url().toString() )
+
         QVariant val = request.attribute( QNetworkRequest::CacheLoadControlAttribute );
-        qDebug() << "request cachecontrol - " << val.typeName() << val.toInt();
 
          // Change the cache load control attrbute!
         QNetworkRequest req = request;
         req.setAttribute( QNetworkRequest::CacheLoadControlAttribute,
-                           QVariant( QNetworkRequest::PreferCache ) ); // was PreferNetwork
+                          QVariant( QNetworkRequest::PreferCache ) );
+        QNetworkReply* result = QNetworkAccessManager::createRequest( op, req, outgoingData );
         TX_EXIT
-        return QNetworkAccessManager::createRequest( op, req, outgoingData );
+        return result;
+    }
+};
+
+/*!
+ MpShareWebView derives from QGraphicsWebView in order to override it's
+ contextMenuEvent method to prevent the background context menu from
+ being displayed when user makes long click in the web view.
+ */
+class MpShareWebView : public QGraphicsWebView
+{
+public:
+    MpShareWebView( QGraphicsItem * parent = 0 )
+        : QGraphicsWebView( parent )
+    {
+        settings()->setAttribute( QWebSettings::LocalContentCanAccessRemoteUrls, true );
+        settings()->setAttribute( QWebSettings::LocalStorageDatabaseEnabled, true );
+        settings()->enablePersistentStorage();
+    }
+
+protected:
+    void contextMenuEvent( QGraphicsSceneContextMenuEvent* /*ev*/ ) // Override QGraphicsWebView::contextMenuEvent
+    {
+        // Fix to prevent "Stop" and "Reload" buttons in page background.
+        // Do not respond to the contextMenuEvent.
     }
 };
 
@@ -71,11 +139,22 @@
  */
 MpDetailsShareDialog::MpDetailsShareDialog()
     : mShareWebView( 0 ),
-      mShareNetAccMan( 0 )
+      mShareNetAccMan( 0 ),
+      mProgressbar ( 0 ),
+      mIsInitialized( false )
 {
+    // DeleteOnClose attribute prevents crash when user presses Cancel
+    // before publishing player is fully loaded.
+    setAttribute( Qt::WA_DeleteOnClose, true );
 }
 
-void MpDetailsShareDialog::initialize( MpSongData* aSongData )
+/*!
+ Initialize the share dialog.
+ When fully initialized we set our mIsInitialized flag to true.
+ Our isInitialized() method can be called to determine whether
+ initialization was successful.
+ */
+void MpDetailsShareDialog::initialize( MpSongData* aSongData, const QString& aUnknownTr )
 {
     TX_ENTRY
     if ( !initUser() )
@@ -83,7 +162,8 @@
         emit closeShareDialog();
         return;
     }
-    initShareData( aSongData );
+    initShareData( aSongData, aUnknownTr );
+    initLanguage();
     initNetworkAccessManager();
     initWebView();
     initSignalSlots();
@@ -109,68 +189,136 @@
         TX_LOG_ARGS( "share: Use QRC index.html file " << SHARE_INDEX_URL )
         mShareWebView->load( QUrl( SHARE_INDEX_URL ) );
     }
+
+    // Flag that the dialog is now fully initialized.
+    mIsInitialized = true;
+
+    // Show progress dialog in .3 second if loading not finished.
+    QTimer::singleShot(300, this, SLOT(showProgressDialog()));
+
     TX_EXIT
 }
 
-
 /*!
  Destructor.
  */
 MpDetailsShareDialog::~MpDetailsShareDialog()
 {
     TX_ENTRY
+    if ( mShareData.songData() )
+    {
+        // Ensure that we remove the temporary album art file when we close the dialog.
+        // TODO this should be removed when base64 issue is solved.
+        TX_LOG_ARGS( "share: remove album art file" )
+        mShareData.songData()->removeAlbumArtFile();
+    }
     logoutPlayer();
-    delete mShareNetAccMan;
+    // Probably mShareNetAccMan should not be deleted but qt documentation
+    // does not indicate whether QWebPage takes ownership of the object or not.
+    // See http://doc.qt.nokia.com/4.6/qwebpage.html
+    //delete mShareNetAccMan;
     TX_EXIT
 }
 
-void MpDetailsShareDialog::initShareData( MpSongData* aSongData )
+/*!
+ Initialize share data.
+ */
+void MpDetailsShareDialog::initShareData( MpSongData* aSongData, const QString& aUnknownTr )
 {
     TX_ENTRY
     // Set information for the share data.
     mShareData.setOwner( this );
     mShareData.setSongData( aSongData );
-    // TODO need localized error message.
-    mShareData.setErrorMessage( "An error occured. Sharing is not currently available" );
-    // TODO need language setting.
-    mShareData.setLanguage( "en" );
+    mShareData.setErrorMessage( tr( ERROR_MESSAGE ) );
+    mShareData.setUnknownTr( aUnknownTr );
     TX_EXIT
 }
 
+/*!
+ Initialize language.
+ Language string is formatted like "en-US", where "en" is the ISO-639-1 language code,
+ and "US" is the ISO-3166-1 country code.
+ We use the QT Mobility API (systeminfo) to obtain the settings from the device.
+ In the event that we cannot construct the QSystemInfo variable then we will fallback
+ to some DEFAULT_LANGUAGE setting.
+ */
+void MpDetailsShareDialog::initLanguage()
+{
+    TX_ENTRY
+    // Set language string, example "en-US".
+    QString language;
+    QSystemInfo* sysInfo = new QSystemInfo( this );
+    if ( sysInfo )
+    {
+        language += sysInfo->currentLanguage(); // ISO-639-1 language code.
+        language += "-";
+        language += sysInfo->currentCountryCode(); // ISO-3166-1 country code.
+        delete sysInfo;
+    }
+    else
+    {
+        // Fallback to the default language.
+        language = DEFAULT_LANGUAGE;
+    }
+    TX_LOG_ARGS( "share: language '" << language << "'" )
+    mShareData.setLanguage( language );
+    TX_EXIT
+}
+
+/*!
+ Initialize network access manager.
+ */
 void MpDetailsShareDialog::initNetworkAccessManager()
 {
     TX_ENTRY
-    // Make our own network access manager to allow JS retrieval from local cache,
+    // Make our own network access manager to allow file retrieval from local cache,
     // since configuration for the default network access manager seems to be
     // to always redownload from network.
-    mShareNetAccMan = new MpNetworkAccessManager();
-    mShareNetAccMan->proxyFactory()->setUseSystemConfiguration( true );
-    QNetworkDiskCache* diskCache = new QNetworkDiskCache( this );
-    QString location = QDesktopServices::storageLocation( QDesktopServices::CacheLocation );
-    diskCache->setCacheDirectory( location );
-    mShareNetAccMan->setCache( diskCache );
+    if ( !mShareNetAccMan )
+    {
+        TX_LOG_ARGS( "share: construct network access manager" )
+        mShareNetAccMan = new MpNetworkAccessManager( this );
+    }
     TX_EXIT
 }
 
+/*!
+ Initialize the web view.
+ */
 void MpDetailsShareDialog::initWebView()
 {
     TX_ENTRY
-    mShareWebView = new QGraphicsWebView();
-    mShareWebView->settings()->setAttribute( QWebSettings::LocalContentCanAccessRemoteUrls, true );
-    mShareWebView->settings()->setAttribute( QWebSettings::LocalStorageDatabaseEnabled, true );
-    mShareWebView->settings()->enablePersistentStorage();
-    mShareWebView->page()->setNetworkAccessManager( mShareNetAccMan );
-    setContentWidget( mShareWebView );
+    if ( !mShareWebView )
+    {
+        TX_LOG_ARGS( "share: construct share web view" )
+        mShareWebView = new MpShareWebView( this );
+        mShareWebView->page()->setNetworkAccessManager( mShareNetAccMan );
+        mShareWebView->page()->mainFrame()->setScrollBarPolicy(Qt::Horizontal, Qt::ScrollBarAlwaysOff);
+        mShareWebView->page()->mainFrame()->setScrollBarPolicy(Qt::Vertical, Qt::ScrollBarAsNeeded);
+        setContentWidget( mShareWebView );
+        addContext();
+        mProgressbar = new HbProgressDialog(HbProgressDialog::WaitDialog);
+        mProgressbar->setText(tr("Loading"));
+    }
     TX_EXIT
 }
 
+/*!
+ Initialize signals and slots.
+ */
 void MpDetailsShareDialog::initSignalSlots()
 {
     TX_ENTRY
+    // Connect various signals to slots for networking.
+    connect( mShareNetAccMan, SIGNAL( sslErrors( QNetworkReply*, const QList< QSslError >& ) ),
+             this, SLOT( handleRequestSSLErrors( QNetworkReply*, const QList< QSslError >& ) ) );
+    connect( mShareNetAccMan, SIGNAL( finished( QNetworkReply* ) ), this, SLOT( handleRequestFinished( QNetworkReply* ) ) );
+
     // Connect various signals to slots for interface to webview.
     connect( mShareWebView, SIGNAL( loadFinished( bool ) ), SLOT( onIndexLoad( bool ) ) );
     connect( mShareWebView->page()->mainFrame(), SIGNAL( javaScriptWindowObjectCleared() ), this, SLOT( addContext() ) );
     connect( mShareWebView->page(), SIGNAL( windowCloseRequested() ), this, SIGNAL( closeShareDialog() ) );
+    connect( mProgressbar, SIGNAL(cancelled()), this, SIGNAL( closeShareDialog() ) );
     TX_EXIT
 }
 
@@ -186,10 +334,9 @@
     QFile file( RND_OVI_LOGIN_FILE );
     if ( !file.open( QFile::ReadOnly ) )
     {
-//        errorHandler( "share", QString( RND_OVI_LOGIN_FILE ) + " missing" );
-        mShareData.setUsername( RND_DEFAULT_USER );
-        mShareData.setPassword( RND_DEFAULT_PASS );
-        result = true;
+        // There must be e:ovicredentials.txt in the filesystem but don't show error dialog
+        // otherwise it will appear as soon as detailsview is created.
+        result = false;
     }
     else
     {
@@ -217,12 +364,46 @@
 }
 
 /*!
+ Returns true if the dialog has been fully initialized.
+  */
+bool MpDetailsShareDialog::isInitialized() const
+{
+    return mIsInitialized;
+}
+
+/*!
+ Attempt to cache the publishing player files from internet
+ to improve user experience for first-time use.
+ If the files are already in the cache and have not expired,
+ then this should not do anything.
+ */
+void MpDetailsShareDialog::cachePublishingPlayerFiles()
+{
+    TX_ENTRY
+    // We need the network access manager, so make sure it is initialized.
+    if ( !mShareNetAccMan )
+    {
+        initNetworkAccessManager();
+    }
+    // Attempt to get the required publishing player files from the net in advance.
+    // We don't listen to any signal that the download succeeded or failed
+    // since we will let it silently fail at this stage.
+    // These URLs are also included in index.html resource, and the two must
+    // be kept the same.
+    mShareNetAccMan->get( QNetworkRequest( QUrl(
+            "http://hf.ci.wipsl.com/PleiXXPTsup/noheva-be/css/ovi.player.share.ui.css" ) ) );
+    mShareNetAccMan->get( QNetworkRequest( QUrl(
+            "http://hf.ci.wipsl.com/PleiXXPTsup/noheva-be/js/publishplayer.js" ) ) );
+    TX_EXIT
+}
+
+/*!
  Release resources from share player.
  */
 void MpDetailsShareDialog::logoutPlayer()
 {
     TX_ENTRY
-    if (mShareWebView)
+    if ( mShareWebView )
     {
         mShareWebView->page()->mainFrame()->evaluateJavaScript( "music.teardown();" );
     }
@@ -235,7 +416,7 @@
 void MpDetailsShareDialog::addContext()
 {
     TX_ENTRY
-    if (mShareWebView)
+    if ( mShareWebView )
     {
         mShareWebView->page()->mainFrame()->addToJavaScriptWindowObject( "context", &mShareData );
     }
@@ -248,9 +429,10 @@
 void MpDetailsShareDialog::updateSharedData()
 {
     TX_ENTRY
-    if (mShareWebView)
+    if ( mShareWebView )
     {
-        mShareWebView->page()->mainFrame()->evaluateJavaScript( "music.updateContextArea();" );
+        // We don't need to call updateContextArea when the track URL has been updated.
+        //mShareWebView->page()->mainFrame()->evaluateJavaScript( "music.updateContextArea();" );
         mShareWebView->page()->mainFrame()->evaluateJavaScript( "music.updateMetadata();" );
     }
     TX_EXIT
@@ -287,12 +469,23 @@
 /*!
  Slot to call for displaying an error message to the user.
  */
-void MpDetailsShareDialog::errorHandler( QString error, QString message )
+void MpDetailsShareDialog::errorHandler( QString aError, QString aMessage )
 {
     TX_ENTRY
-    TX_LOG_ARGS( "share: errorHandler: " << error << ": " << message )
-    HbMessageBox::warning( error + ": " + message ); // For week16 hbwidgets
-//    HbMessageBox::launchWarningMessageBox( error + ": " + message ); // For week12 hbwidgets
+    // If error argument ends with "_SUCCESS", then this should be an info message.
+    // If error argument ends with "_FAILED" or something else, then this should be a warning message.
+    TX_LOG_ARGS( "share: errorHandler: " << aError << ": " << aMessage )
+    if ( aError.endsWith( "_SUCCESS" ) )
+    {
+        // TODO this method seems to be deprecated?
+        HbMessageBox::information( tr( "%1" ).arg( aError ) + ": " + tr( "%1" ).arg( aMessage ) ); // For week16 hbwidgets
+    }
+    else
+    {
+        // TODO this method seems to be deprecated?
+        HbMessageBox::warning( tr( "%1" ).arg( aError ) + ": " + tr( "%1" ).arg( aMessage ) ); // For week16 hbwidgets
+        // HbMessageBox::launchWarningMessageBox( tr( "%1" ).arg( aError ) + ": " + tr( "%1" ).arg( message ) ); // For week12 hbwidgets
+    }
     TX_EXIT
 }
 
@@ -321,4 +514,55 @@
     TX_EXIT
 }
 
+/*!
+ Slot to show the publishing window after html elements are created in javascript.
+ */
+void MpDetailsShareDialog::showWindow()
+{
+    TX_ENTRY
+    if (mProgressbar)
+        mProgressbar->close();
+    show();
+    TX_EXIT
+}
+
+/*!
+ Slot to show progress dialog if the publishing window is not loaded in .3 sec.
+ */
+void MpDetailsShareDialog::showProgressDialog()
+{
+    TX_ENTRY
+    if (!isVisible())
+        mProgressbar->show();
+    TX_EXIT
+}
+
+/*!
+ Slot to SSL errors in network request. We will ignore any errors.
+ */
+void MpDetailsShareDialog::handleRequestSSLErrors( QNetworkReply* aReply, const QList< QSslError >& aErrors )
+{
+    TX_ENTRY
+    aReply->ignoreSslErrors();
+    for( int i = 0; i < aErrors.count(); i++ )
+    {
+        TX_LOG_ARGS( "SSL error " << aErrors.at( i ).errorString() );
+    }
+    TX_EXIT
+}
+
+/*!
+ Slot to handle network request completion.
+ */
+void MpDetailsShareDialog::handleRequestFinished( QNetworkReply* aReply )
+{
+    TX_ENTRY
+    if ( aReply->error() != QNetworkReply::NoError )
+    {
+        TX_LOG_ARGS( "Network request error " << aReply->error() << aReply->errorString() );
+        // TODO what to do now?
+    }
+    TX_EXIT
+}
+
 #endif // SHARE_FUNC_ENABLED