wlanutilities/wlansniffer/wlansnifferapplication/src/wlansnifferlistview.cpp
author Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
Fri, 17 Sep 2010 08:35:49 +0300
changeset 58 301aeb18ae47
parent 56 de27cc8389dd
child 61 e1d68407ed06
permissions -rw-r--r--
Revision: 201035 Kit: 201037

/*
* Copyright (c) 2009-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:
* WLAN Sniffer List View. 
*/

// System includes

#include <QGraphicsWidget>
#include <QSharedPointer>
#include <QObjectList>

#include <HbLabel>
#include <HbPushButton>
#include <HbMenu>
#include <HbAction>
#include <HbListWidget>
#include <HbListWidgetItem>
#include <HbDocumentLoader>
#include <HbInstance>
#include <HbMessageBox>
#include <HbParameterLengthLimiter>

#include <xqserviceutil.h>

// User includes

#include "wlanqtutils.h"
#include "wlanqtutilsap.h"

#include "wlansnifferengine.h"
#include "wlansniffermainwindow.h"
#include "wlansnifferlistview.h"
#include "wlansnifferlistitem.h"
#include "wlansnifferlistwidget.h"

#include "OstTraceDefinitions.h"
#ifdef OST_TRACE_COMPILER_IN_USE
#include "wlansnifferlistviewTraces.h"
#endif

/*!
    \class WlanSnifferListView
    \brief WLAN Sniffer application's list view implementation.
*/

// External function prototypes

// Local constants

//! WLAN Sniffer list view docml file location
static const QString WlanSnifferListViewDocml(":/docml/wlansnifferlistview.docml");

//! WLAN Sniffer list view object name
static const QString WlanSnifferListViewName("occ_list");

// ======== LOCAL FUNCTIONS ========

// ======== MEMBER FUNCTIONS ========

/*!
    Constructor.
    
    @param [in] engine WLAN Sniffer application engine.
    @param [in] mainWindow WLAN Sniffer main window.
*/

WlanSnifferListView::WlanSnifferListView(
    WlanSnifferEngine *engine,
    WlanSnifferMainWindow *mainWindow) :
    HbView(),
    mDocLoader(new HbDocumentLoader(mainWindow)),
    mWlanListWidget(),
    mContextMenu(),
    mContextMenuData(),
    mWlanEnableDialog(),
    mIgnoreWlanScanResults(false),
    mConnectingIapId(WlanQtUtils::IapIdNone),
    mEngine(engine),
    mSwitchWlanAction(0),
    mAddWlanAction(0),
    mWlanList(0),
    mStatusLabel(0),
    mWlanButton(0)
{
    OstTraceFunctionEntry0(WLANSNIFFERLISTVIEW_WLANSNIFFERLISTVIEW_ENTRY);

    // Initialize UI from the docml based on standalone/embedded status
    loadDocml(mEngine->isEmbedded());

    if (mEngine->isEmbedded()) {
        // We need to create a custom navigation action and handle exiting
        // from the application differently in case the application was
        // launched as embedded via QtHighway
        HbAction *completeAction = new HbAction(Hb::BackNaviAction, this);
        setNavigationAction(completeAction);
        bool connectStatus = connect(
            completeAction,
            SIGNAL(triggered(bool)),
            mEngine,
            SLOT(completeService()));
        Q_ASSERT(connectStatus);
    }
    
    // Connect WLAN network open & close signals
    bool connectStatus = connect(
        mEngine->wlanQtUtils(),
        SIGNAL(wlanNetworkOpened(int)),
        this,
        SLOT(updateConnectionOpened(int)));
    Q_ASSERT(connectStatus);
    connectStatus = connect(
        mEngine->wlanQtUtils(),
        SIGNAL(wlanNetworkClosed(int, int)),
        this,
        SLOT(updateConnectionClosed(int))); // "reason" parameter ignored
    Q_ASSERT(connectStatus);
    
    // Connect WLAN ON/OFF setting change signal
    connectStatus = connect(
        mEngine,
        SIGNAL(masterWlanStatus(bool)),
        this,
        SLOT(updateWlanEnabled()));
    Q_ASSERT(connectStatus);
    
    // Connect Force Disable WLAN setting change signal
    connectStatus = connect(
        mEngine,
        SIGNAL(forceDisableWlanStatus(bool)),
        this,
        SLOT(updateWlanEnabled()));
    Q_ASSERT(connectStatus);

    // Connect signals to catch user interaction with the WLAN network list
    connectStatus = connect(
        mWlanList,
        SIGNAL(activated(HbListWidgetItem *)),
        this,
        SLOT(handleListItemActivated(HbListWidgetItem *)));
    Q_ASSERT(connectStatus);
    connectStatus = connect(
        mWlanList,
        SIGNAL(longPressed(HbListWidgetItem *, QPointF)),
        this,
        SLOT(handleListItemLongPressed(HbListWidgetItem *, QPointF)));
    Q_ASSERT(connectStatus);

    // Connect signals to catch user interaction with WLAN ON/OFF switching
    connectStatus = connect(
        mWlanButton,
        SIGNAL(clicked(bool)),
        this,
        SLOT(handleWlanToggled()));
    Q_ASSERT(connectStatus);
    connectStatus = connect(
        mSwitchWlanAction,
        SIGNAL(triggered(bool)),
        this,
        SLOT(handleWlanToggled()));
    Q_ASSERT(connectStatus);

    // Connect adding WLAN manually
    connectStatus = connect(
        mAddWlanAction,
        SIGNAL(triggered(bool)),
        this,
        SLOT(startWlanWizard()));
    Q_ASSERT(connectStatus);
    
    // Connect WLAN scan results signal
    connectStatus = connect(
        mEngine,
        SIGNAL(wlanScanReady()),
        this,
        SLOT(updateListContent()));
    Q_ASSERT(connectStatus);

    // Set the initial value of WLAN state
    updateWlanEnabled();

    OstTraceFunctionExit0(WLANSNIFFERLISTVIEW_WLANSNIFFERLISTVIEW_EXIT);
}

/*!
    Destructor.
*/

WlanSnifferListView::~WlanSnifferListView()
{
    OstTraceFunctionEntry0(WLANSNIFFERLISTVIEW_WLANSNIFFERLISTVIEWDESTR_ENTRY);
    OstTraceFunctionExit0(WLANSNIFFERLISTVIEW_WLANSNIFFERLISTVIEWDESTR_EXIT);
}

/*!
    Loading of WLAN Sniffer List View docml.
    
    @param [in] isEmbedded TRUE if WLAN Sniffer is launched as embedded. 
*/

void WlanSnifferListView::loadDocml(bool isEmbedded)
{
    OstTraceFunctionEntry0(WLANSNIFFERLISTVIEW_LOADDOCML_ENTRY);

    // Pass the view to the document loader. Document loader uses this view
    // when docml is parsed, instead of creating a new view.
    setObjectName(WlanSnifferListViewName);
    QObjectList objectList;
    objectList.append(this);
    mDocLoader->setObjectTree(objectList);

    // First load the common section
    bool ok = false;
    mDocLoader->load(WlanSnifferListViewDocml, &ok);
    Q_ASSERT(ok);
    
    // Then load the mode specific section
    if (isEmbedded) {
        mDocLoader->load(WlanSnifferListViewDocml, "embedded", &ok);
    } else {
        mDocLoader->load(WlanSnifferListViewDocml, "standalone", &ok);
    }
    Q_ASSERT(ok);
    
    // Load the view by name from the xml file
    QGraphicsWidget *widget = mDocLoader->findWidget(WlanSnifferListViewName);
    Q_ASSERT(widget);

    // Set view menu
    HbMenu *viewMenu = qobject_cast<HbMenu *>(mDocLoader->findWidget("viewMenu"));
    Q_ASSERT(viewMenu);
    setMenu(viewMenu);

    // WLAN Sniffer list widget takes responsibility of the list widget behaviour
    mWlanList = qobject_cast<HbListWidget *>(mDocLoader->findWidget("listWidget"));
    Q_ASSERT(mWlanList);
    mWlanListWidget = QSharedPointer<WlanSnifferListWidget>(new WlanSnifferListWidget(mWlanList));

    // Retrieve pointers to widgets we need to access from the code
    mSwitchWlanAction = qobject_cast<HbAction *>(mDocLoader->findObject("switchWlanAction"));
    Q_ASSERT(mSwitchWlanAction);

    mAddWlanAction = qobject_cast<HbAction *>(mDocLoader->findObject("addWlanAction"));
    Q_ASSERT(mAddWlanAction);

    mWlanButton = qobject_cast<HbPushButton *>(mDocLoader->findWidget("wlanButton"));
    Q_ASSERT(mWlanButton);
    
    mStatusLabel = qobject_cast<HbLabel *>(mDocLoader->findWidget("statusLabel"));
    Q_ASSERT(mStatusLabel);
    
    OstTraceFunctionExit0(WLANSNIFFERLISTVIEW_LOADDOCML_EXIT);
}

/*!
    Updates WLAN status label based on current WLAN status.
    
    @param [in] enabled True if WLAN is enabled.
*/

void WlanSnifferListView::updateWlanStatusLabel(bool enabled)
{
    OstTraceFunctionEntry0(WLANSNIFFERLISTVIEW_UPDATEWLANSTATUSLABEL_ENTRY);
    
    QString status;
    if (!enabled) {
        // WLAN is OFF
        status = hbTrId("txt_occ_grid_wlan_is_switched_off");
    } else {
        int iapId = mEngine->wlanQtUtils()->activeIap();
        
        switch (mEngine->wlanQtUtils()->connectionStatus()) {
        case WlanQtUtils::ConnStatusConnecting:
            // WLAN is connecting
            Q_ASSERT(iapId != WlanQtUtils::IapIdNone);
            status = HbParameterLengthLimiter(
                "txt_occ_grid_connecting_to_1").arg(
                    mEngine->wlanQtUtils()->iapName(iapId));
            break;
            
        case WlanQtUtils::ConnStatusConnected:
            // WLAN is connected
            Q_ASSERT(iapId != WlanQtUtils::IapIdNone);
            status = HbParameterLengthLimiter(
                "txt_occ_grid_connected_to_1").arg(
                    mEngine->wlanQtUtils()->iapName(iapId));
            break;
            
        default:
            // WLAN is disconnected
            status = hbTrId("txt_occ_grid_not_connected");        
            break;
        }
    }
    mStatusLabel->setPlainText(status);

    OstTraceFunctionExit0(WLANSNIFFERLISTVIEW_UPDATEWLANSTATUSLABEL_EXIT);
}

/*!
    Handles a "Connect" action for the selected IAP or AP item.
    
    @param data IAP ID (int), or AP class (WlanQtUtilsAp) to connect.
*/

void WlanSnifferListView::handleConnect(QVariant data)
{
    OstTraceFunctionEntry0(WLANSNIFFERLISTVIEW_HANDLECONNECT_ENTRY);

    // Check whether we need to disconnect a previous connection first
    int activeWlanId = mEngine->wlanQtUtils()->activeIap();
    
    // Get IAP ID if IAP is available
    int iapId = WlanQtUtils::IapIdNone;
    if (data.canConvert<int>()) {
        iapId = data.toInt();
    }
    OstTraceExt2(
        TRACE_NORMAL,
        WLANSNIFFERLISTVIEW_HANDLECONNECT,
        "WlanSnifferListView::handleConnect;activeWlanId=%d;iapId=%d",
        activeWlanId,
        iapId);
    
    // Skip connecting if the IAP is already connected
    if (activeWlanId != WlanQtUtils::IapIdNone && iapId == activeWlanId) {
        return;
    }
    
    if (activeWlanId != WlanQtUtils::IapIdNone) {
        mEngine->wlanQtUtils()->disconnectIap(activeWlanId);
        
        // Update list widget so that the IAP is no longer connected
        updateListContent();
    }
    
    if (iapId != WlanQtUtils::IapIdNone) {
        // Item was an IAP, connect it.
        mConnectingIapId = iapId;
        mStatusLabel->setPlainText(
            HbParameterLengthLimiter(
                "txt_occ_grid_connecting_to_1").arg(
                    mEngine->wlanQtUtils()->iapName(iapId)));
        mEngine->wlanQtUtils()->connectIap(iapId);
    } else {
        // Item is a WLAN AP. Summon the Wlan Wizard to handle creation
        // of the IAP and connecting it.
        Q_ASSERT(data.canConvert<WlanQtUtilsAp>());
        WlanQtUtilsAp ap = data.value<WlanQtUtilsAp>();
        emit wizardTriggered(&ap);
    }

    OstTraceFunctionExit0(WLANSNIFFERLISTVIEW_HANDLECONNECT_EXIT);
}

/*!
    Updates WLAN list widget with new WLAN scan results. 
*/

void WlanSnifferListView::updateListContent()
{
    OstTraceFunctionEntry0(WLANSNIFFERLISTVIEW_UPDATELISTCONTENT_ENTRY);

    if (!mIgnoreWlanScanResults) {
        // Get the latest scan results
        QList< QSharedPointer<WlanQtUtilsAp> > iaps;
        QList< QSharedPointer<WlanQtUtilsAp> > aps;
        mEngine->wlanQtUtils()->availableWlans(iaps, aps);
    
        // Check for connected IAP
        int iapId = WlanQtUtils::IapIdNone;
        if (mEngine->wlanQtUtils()->connectionStatus() ==
            WlanQtUtils::ConnStatusConnected) {
            iapId = mEngine->wlanQtUtils()->activeIap();
        }
    
        // Let the list widget class update the list content
        mWlanListWidget->updateContent(iaps, aps, iapId);
    }

    OstTraceFunctionExit0(WLANSNIFFERLISTVIEW_UPDATELISTCONTENT_EXIT);
}

/*!
    WLAN state settings change handler. This slot handles both the
    WLAN ON/OFF setting and WLAN forced OFF setting.
    Updates all WLAN ON/OFF related (UI) elements.
*/

void WlanSnifferListView::updateWlanEnabled()
{
    OstTraceFunctionEntry0(WLANSNIFFERLISTVIEW_UPDATEWLANENABLED_ENTRY);
    
    // Check the updated setting status
    bool forcedOff = mEngine->forceDisableWlan();
    bool enabled = mEngine->masterWlan() && !forcedOff;
    
    // Update the WLAN status label
    updateWlanStatusLabel(enabled);

    // Set the WLAN ON/OFF button state
    mWlanButton->setChecked(enabled);

    // Select the right WLAN button icon and menu action text
    if (enabled) {
        mWlanButton->setIcon(HbIcon("qtg_mono_wlan"));
        mSwitchWlanAction->setText(hbTrId("txt_occ_opt_switch_wlan_off"));
    } else {
        mWlanButton->setIcon(HbIcon("qtg_mono_wlan_offline"));
        mSwitchWlanAction->setText(hbTrId("txt_occ_opt_switch_wlan_on"));
    }

    // Set triggable WLAN UI elements disabled if WLAN is forced OFF
    mWlanButton->setEnabled(!forcedOff);
    mSwitchWlanAction->setEnabled(!forcedOff);

    // Disable manual WLAN IAP creation when WLAN is switched OFF
    mAddWlanAction->setEnabled(enabled);

    // Switch WLAN scanning ON/OFF
    if (enabled) {
        mEngine->startWlanScanning();
    } else {
        mEngine->stopWlanScanning();
        // Clear the network list when going to offline
        mWlanList->clear();
    }

    OstTraceFunctionExit0(WLANSNIFFERLISTVIEW_UPDATEWLANENABLED_EXIT);
}

/*!
    Connection opened slot. Updates connection status.
    
    @param [in] iapId IAP ID of the connected WLAN IAP. 
*/

void WlanSnifferListView::updateConnectionOpened(int iapId)
{
    OstTraceFunctionEntry0(WLANSNIFFERLISTVIEW_UPDATECONNECTIONOPENED_ENTRY);
    
    mConnectingIapId = WlanQtUtils::IapIdNone;
    mStatusLabel->setPlainText(
        HbParameterLengthLimiter(
            "txt_occ_grid_connected_to_1").arg(
                mEngine->wlanQtUtils()->iapName(iapId)));
    
    // Update the list widget content
    updateListContent();

    // Scroll to the top of the list
    mWlanListWidget->scrollTo(0);
    
    OstTraceFunctionExit0(WLANSNIFFERLISTVIEW_UPDATECONNECTIONOPENED_EXIT);
}

/*!
    Connection closing handler. Updates connection status.
    
    @param [in] iapId Disconnected IAP ID. 
*/

void WlanSnifferListView::updateConnectionClosed(int iapId)
{
    OstTraceFunctionEntry0(WLANSNIFFERLISTVIEW_UPDATECONNECTIONCLOSED_ENTRY);
    
    if (mEngine->masterWlan() && !mEngine->forceDisableWlan()) {
        // Check whether we can update the status text to "Not connected"
        if (mConnectingIapId == WlanQtUtils::IapIdNone ||
            mConnectingIapId == iapId) {
            mStatusLabel->setPlainText(hbTrId("txt_occ_grid_not_connected"));
        }
        // else: we are already connecting to another network so don't touch
        // the status label
        
        // Update the list widget content
        updateListContent();
    }

    if (mConnectingIapId == iapId) {
        // Not connecting to this network anymore
        mConnectingIapId = WlanQtUtils::IapIdNone;
    }

    OstTraceFunctionExit0(WLANSNIFFERLISTVIEW_UPDATECONNECTIONCLOSED_EXIT);
}

/*!
    Context menu closing handler.
*/

void WlanSnifferListView::handleContextMenuClosed()
{
    OstTraceFunctionEntry0(WLANSNIFFERLISTVIEW_HANDLECONTEXTMENUCLOSED_ENTRY);

    // Let list updating start again
    mIgnoreWlanScanResults = false;
    
    OstTraceFunctionExit0(WLANSNIFFERLISTVIEW_HANDLECONTEXTMENUCLOSED_EXIT);
}

/*!
    List item activation handler. Connects the WLAN network, and if there
    is no IAP yet for it, starts WLAN Wizard.
    
    @param [in] item Selected WLAN network list item. 
*/

void WlanSnifferListView::handleListItemActivated(HbListWidgetItem *item)
{
    OstTraceFunctionEntry0(WLANSNIFFERLISTVIEW_HANDLELISTITEMACTIVATED_ENTRY);
    
    handleConnect(item->data());

    OstTraceFunctionExit0(WLANSNIFFERLISTVIEW_HANDLELISTITEMACTIVATED_EXIT);
}

/*!
    WLAN List item long press handler.
    The long press of a list item (i.e. WLAN IAP) opens a context menu that
    is populated depending on the state of the WLAN network in case.
    
    @param [in] item Selected list item.
    @param [in] coords Coordinates of the long press.
*/

void WlanSnifferListView::handleListItemLongPressed(
    HbListWidgetItem *item,
    const QPointF &coords)
{
    OstTraceFunctionEntry0(WLANSNIFFERLISTVIEW_HANDLELISTITEMLONGPRESSED_ENTRY);

    mContextMenu = QSharedPointer<HbMenu>(new HbMenu());

    int activeIap = mEngine->wlanQtUtils()->activeIap();
    
    // Remember the item that was long pressed
    mContextMenuData = item->data();
    if (mContextMenuData.canConvert<int>()
        && mContextMenuData.toInt() == activeIap) {
        // Connected IAP, add "Disconnect" action
        mContextMenu->addAction(
            hbTrId("txt_common_menu_disconnect"),
            this,
            SLOT(handleListItemDisconnect()));
    } else {
        // Not connected IAP or AP, add "Connect" action
        mContextMenu->addAction(
            hbTrId("txt_common_menu_connect"),
            this,
            SLOT(handleListItemConnect()));
    }
    
    // Show the menu and connect closure signal (to re-enable list refreshing)
    bool connectStatus = connect(
        mContextMenu.data(),
        SIGNAL(aboutToClose()),
        this,
        SLOT(handleContextMenuClosed()));
    Q_ASSERT(connectStatus);
    mContextMenu->setTimeout(HbPopup::ContextMenuTimeout);
    mContextMenu->setPreferredPos(coords);
    mContextMenu->show();
    
    // Skip WLAN scan result updates during context menu handling
    mIgnoreWlanScanResults = true;
    
    OstTraceFunctionExit0(WLANSNIFFERLISTVIEW_HANDLELISTITEMLONGPRESSED_EXIT);
}

/*!
    Handles the "Connect" action selected from the context menu for a list item.
*/

void WlanSnifferListView::handleListItemConnect()
{
    OstTraceFunctionEntry0(WLANSNIFFERLISTVIEW_HANDLELISTITEMCONNECT_ENTRY);

    handleConnect(mContextMenuData);
    
    OstTraceFunctionExit0(WLANSNIFFERLISTVIEW_HANDLELISTITEMCONNECT_EXIT);
}

/*!
    Handles the "Disconnect" action selected from the context menu for a list item.
*/

void WlanSnifferListView::handleListItemDisconnect()
{
    OstTraceFunctionEntry0(WLANSNIFFERLISTVIEW_HANDLELISTITEMDISCONNECT_ENTRY);

    // "Disconnect" was only added, if the item was an IAP and data was
    // the IAP ID.
    Q_ASSERT(mContextMenuData.canConvert<int>());
    mEngine->wlanQtUtils()->disconnectIap(mContextMenuData.toInt());
    
    OstTraceFunctionExit0(WLANSNIFFERLISTVIEW_HANDLELISTITEMDISCONNECT_EXIT);
}

/*!
    Function for handling WLAN ON/OFF switch initiation.
*/

void WlanSnifferListView::handleWlanToggled()
{
    OstTraceFunctionEntry0(WLANSNIFFERLISTVIEW_HANDLEWLANTOGGLED_ENTRY);
    
    // Toggle the new WLAN ON/OFF value
    bool wlanOn = mEngine->masterWlan(); 
    OstTraceExt1(
        TRACE_NORMAL,
        WLANSNIFFERLISTVIEW_HANDLEWLANTOGGLED,
        "WlanSnifferListView::handleWlanToggled;wlan=%hhu",
        wlanOn);
    
    // We have to check whether the offline mode is ON. If it is, then the
    // user needs to be queried whether WLAN will be used in offline mode.
    if (!wlanOn && mEngine->offlineMode()) {
        // Show the dialog and wait for user input.
        mWlanEnableDialog = QSharedPointer<HbMessageBox>(
            new HbMessageBox(HbMessageBox::MessageTypeQuestion)); 
        mWlanEnableDialog->setTimeout(HbPopup::StandardTimeout);
        mWlanEnableDialog->setText(hbTrId("txt_occ_info_activate_wlan_in_airplane_mode"));
        mWlanEnableDialog->setStandardButtons(HbMessageBox::Yes | HbMessageBox::No);
        // Open the dialog and connect the result to the handleWlanEnableDialogClosed slot
        mWlanEnableDialog->open(this, SLOT(handleWlanEnableDialogClosed(int)));
    } else {
        // Stop WLAN scanning immediately when switching WLAN OFF.
        // WLAN might have sent scan results just before disabling WLAN.
        if (wlanOn) {
            mEngine->stopWlanScanning();
        }
        mEngine->setMasterWlan(!wlanOn);
    }

    OstTraceFunctionExit0(WLANSNIFFERLISTVIEW_HANDLEWLANTOGGLED_EXIT);
}

/*!
    Function for handling WLAN Wizard starting when adding WLAN manually.
*/

void WlanSnifferListView::startWlanWizard()
{
    OstTraceFunctionEntry0(WLANSNIFFERLISTVIEW_STARTWLANWIZARD_ENTRY);

    emit wizardTriggered(NULL);

    OstTraceFunctionExit0(WLANSNIFFERLISTVIEW_STARTWLANWIZARD_EXIT);
}

/*!
    Function to handle the input received when the wlan enabling 
    query is closed.
    
    @param [in] action The user action received from the dialog.
*/

void WlanSnifferListView::handleWlanEnableDialogClosed(int action)
{
    OstTraceFunctionEntry0(WLANSNIFFERLISTVIEW_HANDLEWLANENABLEDIALOGCLOSED_ENTRY);

    // The dialog must exist
    Q_ASSERT(mWlanEnableDialog);

    // If the user selected yes, then the wlan value is toggled,
    // otherwise nothing needs to be done.
    if (action == HbMessageBox::Yes) {
        mEngine->setMasterWlan(true); 
    }

    OstTraceFunctionExit0(WLANSNIFFERLISTVIEW_HANDLEWLANENABLEDIALOGCLOSED_EXIT);
}