piprofilerui/ui/hb/src/pimainview.cpp
author Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
Tue, 14 Sep 2010 21:20:12 +0300
branchRCL_3
changeset 21 f8280f3bfeb7
parent 20 fad26422216a
permissions -rw-r--r--
Revision: 201033 Kit: 201035

/*
* Copyright (c) 2010 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: 
*
*/


#include <hbdocumentloader.h>
#include <hbmainwindow.h>
#include <hbapplication.h>
#include <hbaction.h>
#include <qgraphicslayout.h>
#include <qvariant.h>
#include <qobject.h>
#include <qlist.h>
#include <hbmessagebox.h>
#include <hblabel.h>
#include <hbwidget.h>
#include <qstringlist.h>
#include <qsignalmapper.h>
#include <hblistwidget.h>
#include <hblistwidgetitem.h>
#include <hbmenu.h>
#include <hbtoolbar.h>
#include <hbdialog.h>
#include <hbprogressdialog.h>
#include <hbtextitem.h>
#include <hbindicator.h>
#include <qdebug.h>

#include "pimainview.h"
#include "piprofilerengine.h"
#include "notifications.h"
#include "pimainwindow.h"

const char *INVALIDCONFIGURATIONFILE = "Invalid configuration file";
const char *APPLICATIONNAME = "PI Profiler";

// actions that are found from xml
const char *ACTIONEXIT = "actionExit";
const char *ACTIONSTARTPROFILING = "actionStartProfiling";
const char *ACTIONSTARTTIMEDPROFILING = "actionStartTimedProfiling";
const char *ACTIONSETTINGS = "actionSettings";
const char *ACTIONABOUT = "actionAbout";

// UI components that are found from xml

const char *LISTWIDGETPLUGINS = "listPlugins";
const char *TEXTMANDATORYPLUGINS = "Mandatory plug-ins:";
const char *TEXTOPTIONALPLUGINS = "Optional plug-ins:";

// ---------------------------------------------------------------------------

PIMainView::PIMainView() :
    application(0), mMainWindow(0), mEngine(0), mPluginList(0), mContextMenu(0), mActionExit(0),
        mActionExitAndLeaveProfilingOn(0), mActionAbout(0), mActionStartTimedProfiling(0),
        mActionSettings(0), mActionStopProfiling(0), mListPlugins(0), mProfilingNote(0)
{

}

// ---------------------------------------------------------------------------

PIMainView::~PIMainView()
{
}

// ---------------------------------------------------------------------------

void PIMainView::init(PIMainWindow *mainWindow, HbApplication* app, HbDocumentLoader &loader,
    PIProfilerEngine *engine)
{

    application = app;
    mMainWindow = mainWindow;

    // Load items from xml file
    loadItemsFromResources(loader);

    // Set list widget items
    mListPlugins->setClampingStyle(HbScrollArea::BounceBackClamping);
    mListPlugins->setFrictionEnabled(true);

    // Create stop profiling action
    mActionStopProfiling = new HbAction("Stop Profiling", this);

    // Create exit and leave profiling on action
    mActionExitAndLeaveProfilingOn = new HbAction("Close UI\n(Continue profiling)", this);

    mEngine = engine;

    // Connect signals and slots
    this->connectSignalsAndSlots(app);

    // Create icons
    mIconDisabled = HbIcon(":/gfx/disabled.svg");
    mIconEnabled = HbIcon(":/gfx/enabled.svg");

    // update timed profiling text according to settings
    updateTimedProfilingText();
}

// ---------------------------------------------------------------------------


void PIMainView::connectSignalsAndSlots(HbApplication* app)
{

    // Menu items:
    connect(mActionExit, SIGNAL(triggered()), app, SLOT( quit() ));
    connect(mActionSettings, SIGNAL(triggered()), this, SLOT( openSettingsView() ));
    connect(mActionAbout, SIGNAL(triggered()), this, SLOT( showAboutPopup() ));
    connect(mActionStartProfiling, SIGNAL(triggered()), this, SLOT( startProfiling() ));
    connect(mActionStartTimedProfiling, SIGNAL(triggered()), this, SLOT( startTimedProfiling() ));

    // List widget actions
    connect(mListPlugins, SIGNAL(activated(HbListWidgetItem*)), this,
        SLOT(enableOrDisablePlugin(HbListWidgetItem*)));
    connect(mListPlugins, SIGNAL(longPressed(HbListWidgetItem*, QPointF)), this,
        SLOT(showContexMenu(HbListWidgetItem*, QPointF)));

    connect(
        mEngine,
        SIGNAL(profilingStatusChanged(ProfilerEngineStatus, const QString&, ProfilingMode, ProfilingOutput)),
        this,
        SLOT(profilingStatusChanged(ProfilerEngineStatus, const QString&, ProfilingMode, ProfilingOutput)));

    connect(mMainWindow, SIGNAL(returnedFromSettings()), this, SLOT( updateTimedProfilingText() ));
    connect(mActionExitAndLeaveProfilingOn, SIGNAL(triggered()), this,
        SLOT( exitAndLeaveProfilingOn() ));
    connect(mActionStopProfiling, SIGNAL(triggered()), this, SLOT( stopProfiling() ));

}

// ---------------------------------------------------------------------------


void PIMainView::loadItemsFromResources(HbDocumentLoader &loader)
{

    // ACTIONS:

    // Exit
    QObject *object = loader.findObject(ACTIONEXIT);
    Q_ASSERT_X((object != 0), APPLICATIONNAME, INVALIDCONFIGURATIONFILE);
    this->mActionExit = qobject_cast<HbAction *> (object);

    // About
    object = loader.findObject(ACTIONABOUT);
    Q_ASSERT_X((object != 0), APPLICATIONNAME, INVALIDCONFIGURATIONFILE);
    this->mActionAbout = qobject_cast<HbAction *> (object);

    // Settings
    object = loader.findObject(ACTIONSETTINGS);
    Q_ASSERT_X((object != 0), APPLICATIONNAME, INVALIDCONFIGURATIONFILE);
    this->mActionSettings = qobject_cast<HbAction *> (object);

    // Start profiling
    object = loader.findObject(ACTIONSTARTPROFILING);
    Q_ASSERT_X((object != 0), APPLICATIONNAME, INVALIDCONFIGURATIONFILE);
    this->mActionStartProfiling = qobject_cast<HbAction *> (object);

    // Start timed profiling
    object = loader.findObject(ACTIONSTARTTIMEDPROFILING);
    Q_ASSERT_X((object != 0), APPLICATIONNAME, INVALIDCONFIGURATIONFILE);
    this->mActionStartTimedProfiling = qobject_cast<HbAction *> (object);

    QGraphicsWidget *widget = loader.findWidget(LISTWIDGETPLUGINS);
    Q_ASSERT_X((widget != 0), "Launcher", "Invalid launcher.xml file");
    this->mListPlugins = qobject_cast<HbListWidget *> (widget);
}

// ---------------------------------------------------------------------------

void PIMainView::showAboutPopup()
{

    Notifications::showMessageBox("Version 2.2.1 - 10th August 2010. \n"
            "Copyright © 2010 Nokia Corporation "
            "and/or its subsidiary(-ies). "
            "All rights reserved.");

}
// ---------------------------------------------------------------------------

void PIMainView::setPluginList(QList<PluginAttributes> *pluginList)
{

    this->mPluginList = pluginList;
    this->updatePlugInLists();

}

// ---------------------------------------------------------------------------

void PIMainView::openSettingsView()
{
    mMainWindow->activateSettingsView();
}

// ---------------------------------------------------------------------------

void PIMainView::updatePlugInLists()
{

    mListPlugins->clear();

    // Create Compulsory and Optional labels into list widget:
    HbListWidgetItem *compulsory = new HbListWidgetItem();
    compulsory->setText(TEXTMANDATORYPLUGINS);
    mListPlugins->addItem(compulsory);

    HbListWidgetItem *optional = new HbListWidgetItem();
    optional->setText(TEXTOPTIONALPLUGINS);
    mListPlugins->addItem(optional);

    HbIcon *icon;

    // Go thru pluginlist and add list item for each plug-in into list widget 
    for (int index = 0; index < mPluginList->size(); index++) {
        QString plugInName = mPluginList->at(index).mName;

        // get icon for item 
        if (mPluginList->at(index).mEnabled) {
            icon = &mIconEnabled;
        }
        else {
            icon = &mIconDisabled;
        }

        // Create list widget item
        // TODO ensure that this does not leak memory
        HbListWidgetItem *newItem = new HbListWidgetItem();
        newItem->setIcon(*icon);
        newItem->setText(plugInName);
        newItem->setData(mPluginList->at(index).mUid);

        // check if plug-in is compulsory or optional
        if (mPluginList->at(index).mIsHidden) {
            mListPlugins->insertItem(mListPlugins->row(optional), newItem);
        }
        else {
            mListPlugins->addItem(newItem);

        }
    }

}
// ---------------------------------------------------------------------------

void PIMainView::enableOrDisablePlugin(HbListWidgetItem *widget)
{

    // if widget is not found, set currently highlighted item as widget
    // (in that case this method is called from context menu)
    if (widget == 0) {
        widget = mListPlugins->currentItem();
    }

    // if this method is called from list widget's activated signal, do nothing
    // if context menu is open.
    else {
        if (mContextMenu != 0) {
            return;
        }
    }
    bool ok = false;
    int widgetUid = widget->data().toInt(&ok);
    if (!ok) {
        qWarning("PIProfiler: Unable to find plug-in uid");
        return;
    }

    // go thru plug-in array and find checked plug-in
    for (int index = 0; index < mPluginList->size(); index++) {

        if (mPluginList->at(index).mUid == widgetUid) {
            PluginAttributes pluginAttributes = mPluginList->at(index);

            // if plug-in is hidden it cannot be disabled
            if (pluginAttributes.mIsHidden) {
                return;
            }

            // change enable status and set icon correct
            if (pluginAttributes.mEnabled) {
                pluginAttributes.mEnabled = false;
                widget->setIcon(mIconDisabled);
            }
            else {
                pluginAttributes.mEnabled = true;
                widget->setIcon(mIconEnabled);
            }

            // save plug-in settings
            if (mEngine->savePluginSettings(pluginAttributes)) {
                mPluginList->replace(index, pluginAttributes);
            }
            else {
                // if saving operation failed, revert icon back
                if (pluginAttributes.mEnabled) {
                    widget->setIcon(mIconEnabled);
                }
                else {
                    pluginAttributes.mEnabled = true;
                    widget->setIcon(mIconDisabled);
                }
                Notifications::showErrorNote(
                    "Error occured while saving settings to Profiler engine.");
            }
            break;
        }

    }

}

// ---------------------------------------------------------------------------

void PIMainView::showContexMenu(HbListWidgetItem *widget, const QPointF &point)
{

    bool ok = false;
    int uid = widget->data().toInt(&ok);

    if (!ok) {
        return;
    }

    for (int index = 0; index < mPluginList->size(); index++) {

        if (mPluginList->at(index).mUid == uid) {

            // Create Context menu:
            mContextMenu = new HbMenu();
            mContextMenu->setPreferredPos(point, HbPopup::TopLeftCorner);
            mContextMenu->setDismissPolicy(HbPopup::TapOutside);
            mContextMenu->setAttribute(Qt::WA_DeleteOnClose);

            // Enable/disable plug-in
            if (!mPluginList->at(index).mIsHidden) {
                HbAction *enableAction;
                if (mPluginList->at(index).mEnabled) {
                    enableAction = mContextMenu->addAction(QString("Disable"));
                }
                else {
                    enableAction = mContextMenu->addAction(QString("Enable"));
                }
                connect(enableAction, SIGNAL(triggered()), this, SLOT( enableOrDisablePlugin() ));
            }

            //FIXME take these into use once expanding and collapsing data form groups works. 
            // Plug-in specific settings 
            /*if (mPluginList->at(index).mItemCount != 0 || mPluginList->at(index).mSampleRate != -1) {
             HbAction *pluginSettingsAction = mContextMenu->addAction(QString(
             "Plug-in settings"));
             connect(pluginSettingsAction, SIGNAL(triggered()), this,
             SLOT(openPluginSpecificSettings()));
             }*/

            // Plug in info
            HbAction *infoAction = mContextMenu->addAction(QString("Plug-in info"));
            connect(infoAction, SIGNAL(triggered()), this, SLOT( openSampleInfo() ));

            connect(mContextMenu, SIGNAL(aboutToClose()), this, SLOT( contextMenuClosed() ));
            mContextMenu->open(this, SLOT(contextMenuClosed()));
            break;
        }
    }

}

// ---------------------------------------------------------------------------

void PIMainView::openSampleInfo()
{

    // Show plug-in specific info
    bool ok = false;
    int uid = mListPlugins->currentItem()->data().toInt(&ok);
    if (!ok) {
        return;
    }
    Notifications::showInformationNote(this->getPluginAttributes(uid).mDescription);
}
// ---------------------------------------------------------------------------

PluginAttributes PIMainView::getPluginAttributes(int uid)
{
    // Get plug-in attributes from the plug-in list based on uid number
    for (int index = 0; index < mPluginList->size(); index++) {
        if (mPluginList->at(index).mUid == uid) {
            return mPluginList->at(index);
        }
    }
    return PluginAttributes();
}

// ---------------------------------------------------------------------------

void PIMainView::contextMenuClosed()
{
    mContextMenu = 0;
}

// ---------------------------------------------------------------------------

void PIMainView::startProfiling()
{

    showProfilingNote();
    if (!mEngine->startProfiling()) {
        Notifications::showErrorNote("Unable to start profiling");
        mProfilingNote->close();
        mProfilingNote = 0;
    }
}

// ---------------------------------------------------------------------------
void PIMainView::startTimedProfiling()
{
    showProfilingNote();
    if (!mEngine->startTimedProfiling()) {
        Notifications::showErrorNote("Unable to start profiling");
        mProfilingNote->close();
        mProfilingNote = 0;
    }
}

// ---------------------------------------------------------------------------


void PIMainView::stopProfiling()
{
    mProfilingNote = 0;
    mEngine->stopProfiling();
}

// ---------------------------------------------------------------------------

void PIMainView::profilingStatusChanged(ProfilerEngineStatus status, const QString &text,
    ProfilingMode profilingMode, ProfilingOutput outputMode)
{

    if (status == PI_FINISHED_SUCCEFULLY) {
        // Profiling finished successfully

        // close profiling note
        if (mProfilingNote != 0) {
            mProfilingNote->close();
            mProfilingNote = 0;
        }

        // Show info text
        Notifications::showInformationNote(text);
        return;
    }

    if (mProfilingNote == 0) {
        // if profiling note is not yet shown, create it
        showProfilingNote();
    }

    if (status == PI_ERROR) {
        // if errors occured, close profiling note and show error message
        if (mProfilingNote != 0) {
            mProfilingNote->close();
            mProfilingNote = 0;
        }
        Notifications::showErrorNote(text);
    }

    else if (status == PI_PROFILING) {
        // if profiling is on-going, update info text according to output:

        HbLabel *titleLabel = new HbLabel("Profiling...", mProfilingNote);
        titleLabel->setAlignment(Qt::AlignCenter);

        HbTextItem *textItem = new HbTextItem(text, mProfilingNote);
        textItem->setAlignment(Qt::AlignCenter);

        mProfilingNote->setHeadingWidget(titleLabel);
        mProfilingNote->setContentWidget(textItem);
    }

}

// ---------------------------------------------------------------------------

void PIMainView::showProfilingNote()
{
    // Create new dialog 
    mProfilingNote = new HbDialog();
    mProfilingNote->setAttribute(Qt::WA_DeleteOnClose);

    // Make it modal.
    mProfilingNote->setModal(true);

    // set dismiss policy
    mProfilingNote->setDismissPolicy(HbPopup::NoDismiss);
    mProfilingNote->setTimeout(0); //
    mProfilingNote->setBackgroundFaded(true);

    // create label and text item for popup
    HbTextItem *titleLabel = new HbTextItem("Profiling...", mProfilingNote);
    HbTextItem *label = new HbTextItem("Starting to profile", mProfilingNote);

    label->setAlignment(Qt::AlignCenter);
    titleLabel->setAlignment(Qt::AlignCenter);
    mProfilingNote->setHeadingWidget(titleLabel);
    mProfilingNote->setContentWidget(label);

    // set actions
    mProfilingNote->setPrimaryAction(mActionStopProfiling);
    mProfilingNote->setSecondaryAction(mActionExitAndLeaveProfilingOn);

    mProfilingNote->open();
}

// ---------------------------------------------------------------------------

void PIMainView::updateTimedProfilingText()
{
    QString text = "Start timed profiling(";
    QString number;
    number.setNum(mEngine->getTimeLimit(), 10);
    text.append(number);
    text.append("s)");
    mActionStartTimedProfiling->setText(text);

}

// ---------------------------------------------------------------------------

void PIMainView::exitAndLeaveProfilingOn()
{
    mEngine->leaveProfilingOnAfterClosing();
    application->quit();
}
// ---------------------------------------------------------------------------

void PIMainView::openPluginSpecificSettings()
{
    HbListWidgetItem *listItem = mListPlugins->currentItem();
    bool ok = false;
    int uid = listItem->data().toInt(&ok);
    if (ok) {
        mMainWindow->activateSettingsView(uid);
    }
}

// ---------------------------------------------------------------------------
// ---------------------------------------------------------------------------