listview.cpp

来自「《UIQ 3 The Complete Guide》书的源代码」· C++ 代码 · 共 772 行 · 第 1/2 页

CPP
772
字号
//
// ListView.cpp - The ListView in the example signed app
//
// Copyright (C) UIQ Technology AB, 2007
//
// This material is provided "as is" without any warranty to its performance or functionality. 
// In no event shall UIQ Technology be liable for any damages whatsoever arising out of the
// use or inabilty to use this material. 
//

#include "ListView.h"
#include "SignedAppUids.h"
#include "SignedApp.hrh"
#include <SignedApp_0x20000462.rsg>

#include <QikCommand.h>
#include <QikEditCategoriesDlg.h>
#include <QikZoomDlg.h>
#include <QikSendAsLogic.h>
#include <QikSendAs.h>
#include <MtmUids.h>

#include <QikSimpleDialog.h>
#include <QikViewDialog.h>
#include <eikchlst.h>
#include <eiklbx.h>
#include <QikCameraCaptureDlg.h>

//////////////////////////////////////////////////////////////////////////////
class CCreateNewDialog : public CQikViewDialog, public MQikListBoxObserver
    {
protected:
	// from CQikViewBase
	void HandleCommandL(CQikCommand& aCommand);
	void ViewConstructL();

	// from MQikListBoxObserver
	void HandleListBoxEventL(CQikListBox* aListBox,TQikListBoxEvent aEventType,TInt aItemIndex,TInt aSlotId);

    };

void CCreateNewDialog::HandleListBoxEventL(
//
// List box event occured - its reporting back what that might be.
//
	CQikListBox* aListBox,
	TQikListBoxEvent aEventType,
	TInt aItemIndex,
	TInt aSlotId)
	{
	switch (aEventType)
		{
	case EEventItemConfirmed:
	case EEventItemTapped:
		CloseDialog(aItemIndex);
		break;
	default:
		break;
		}
	}

void CCreateNewDialog::ViewConstructL()
// Construct the 'Create new' dialog. Set the list box entries to contain the type of 
// entities we can construct.
	{
	ViewConstructFromResourceL(R_CREATE_NEW_DIALOG_CONFIGURATIONS);

	// setup list box content
	CQikListBox* listbox=LocateControlByUniqueHandle<CQikListBox>(ECreateNewListId);
	MQikListBoxModel& model(listbox->Model());
	model.ModelBeginUpdateLC();
	TBuf<64>bb;
	const TInt KMaxCreateNewTypes=2;
	for (TInt i=0;i<KMaxCreateNewTypes;i++)
		{
		MQikListBoxData* lbData=model.NewDataL(MQikListBoxModel::EDataNormal);
		CleanupClosePushL(*lbData);
		iEikonEnv->ReadResourceL(bb,R_STR_CREATE_SOUND_CLIP+i);
		lbData->AddTextL(bb,EQikListBoxSlotText1);
		CleanupStack::PopAndDestroy(lbData);
		}
	model.ModelEndUpdateL();

	// we want to HandleListBoxEventL() - so observe the listbox
	listbox->SetListBoxObserver(this); 

	iEikonEnv->ReadResourceL(bb,R_STR_CREATE_NEW_TITLE);
	ViewContext()->AddTextL(1,bb); // without this ChangeTextL() will panic !!
	}

void CCreateNewDialog::HandleCommandL(CQikCommand& aCommand)
	{
	switch (aCommand.Id())
		{
	case EAppCmdContinue:
		CloseDialog(LocateControlByUniqueHandle<CQikListBox>(ECreateNewListId)->CurrentItemIndex());
		break;

	default: // e.g. the back button...
		CQikViewBase::HandleCommandL(aCommand);
		break;
		}
	}

//////////////////////////////////////////////////////////////////////////////////
CListView::~CListView()
	{
	TidyUpSoundPlayer();	
	}

CListView::CListView(CQikAppUi& aAppUi,CAppEngine* aEngine) :
	CQikViewBase(aAppUi,KNullViewId),iEngine(aEngine)
	{}

TVwsViewId CListView::ViewId() const
//
// All views are uniquely identified within the entire system. A TVwsViewId consists of 
// the application uid (uid3) and app specific view uid
//
	{
	return(KViewIdListView);
	}

void CListView::UpdateListBoxL()
//
// Build the list of items to be displayed given the current user preferences, e.g. of 
// selected category
//
	{
	CQikListBox* listbox=LocateControlByUniqueHandle<CQikListBox>(EListViewListId);

	// Since we are going to update the model it is preferable to remove all items in the
	// model rather than  listbox->RemoveAllItemsL() as its more efficient and remove a 
	// screen redraw/reduces flicker. 

	// Get the listbox model
	MQikListBoxModel& model(listbox->Model());

	// rather than calling listbox->RemoveAllItemsL() we can use the model to remove all the
	// items. This is more efficient and eliminates a screen redraw
	model.RemoveAllDataL();

	model.ModelBeginUpdateLC();

	// create an entry in the listbox for each entry the engine reports as existing
	const TInt count=iEngine->EntryCount();
	for (TInt i=0;i<count;i++)
		{
		MQikListBoxData* lbData=model.NewDataL(MQikListBoxModel::EDataNormal);
		CleanupClosePushL(*lbData);

		lbData->AddTextL(iEngine->Entry(i).EntryName(),EQikListBoxSlotText1);
		lbData->SetItemId(i);

		// Removes the listboxData from the stack and calls close on lbData
		CleanupStack::PopAndDestroy(lbData);
		}

	// weve now finished all updates so commit changes
	model.ModelEndUpdateL();
	}

void CListView::SetCurrentEntry()
//
// Update the current entry recorded by the engine to be that within the UI.
//
	{
	iEngine->SetCurrentEntry(LocateControlByUniqueHandle<CQikListBox>(
													EListViewListId)->CurrentItemIndex());
	}

void CListView::HandleListBoxEventL(
//
// List box event occured - its reporting back what that might be.
//
	CQikListBox* aListBox,
	TQikListBoxEvent aEventType,
	TInt aItemIndex,
	TInt aSlotId)
	{
	switch (aEventType)
		{
	case EEventItemConfirmed:
	case EEventItemTapped:
		iEngine->SetCurrentEntry(aItemIndex);
		iQikAppUi.ActivateViewL(KViewIdDetailsView);
		break;

	// whilst tempting to use this to simply update the current entry, there are numerous 
	// cases where its not the right thing to do, e.g. if we call UpdateListBoxL() then the
	// hlight gets moved.. so in general its not the correct place to inform engine of currentEntry
	case EEventHighlightMoved:

	default:
		break;
		}
	}

void CListView::UpdateCommandAvailability()
//
// Adjust the availabilty of commands based on our internal state. E.g. if we dont have any
// entries then Open, Delete, SendAs as unavailable
//
	{
	// if we have no items in the list box we disable the delete menu option
	CQikCommandManager& cm=CQikCommandManager::Static();

	TBool avail=EFalse;
	if (iEngine->EntryCount()>0)
		avail=ETrue; // some entries exist in the current filtered list

	cm.SetAvailable(*this,EAppCmdOpen,avail);
	cm.SetAvailable(*this,EAppCmdDelete,avail);
	cm.SetAvailable(*this,EAppCmdDelete2,avail);
	cm.SetAvailable(*this,EAppCmdSendAs,avail);
	cm.SetAvailable(*this,EAppCmdSortCascade,avail);
	}

TBool CListView::OkToAddCategory() const
//
// Report whether it is acceptable to add a category.
//
	{
	return(ETrue); // ok to add a category
	}

TBool CListView::DoAddCategoryL(TInt& aHandle)
//
// Called when the user added a new category. aHandle can be updated if the model has a preferred 
// way of linking handles to categories.
//
	{
	TQikCategoryName name(CategoryModel()->CategoryNameByHandle(aHandle));
	iEngine->AddCategoryL(aHandle,name);
	return(ETrue); // added ok
	}

TBool CListView::OkToRenameCategory(TInt aHandle,const TDesC& aNewName) const
//
// Report whether it is acceptable to rename a category. This is not called for 
// entries marked as EQikCategoryCantBeRenamed within the resource. It already knows the category
// cannot be renamed.
//
	{
	return(ETrue); // ok to rename a category
	}

TBool CListView::DoRenameCategoryL(TInt aHandle,const TDesC& aNewName)
//
// The indicated category has been renamed. We need to store the updated category name.
//
	{
	iEngine->UpdateCategoryName(aHandle,aNewName);
	return(ETrue);
	}

TBool CListView::OkToMergeCategories(TInt aSourceHandle,TInt aTargetHandle) const
//
// Report whether it is reasonable to merge the two categories indicated.
//
	{
	return(EFalse); // not ok to merge.
	}

TBool CListView::DoMergeCategoriesL(TInt aSourceHandle,TInt aTargetHandle)
//
// Merge the indicated categories. The UI does not actually support this so we dont actually 
// need to support this
//
	{
	return(EFalse);
	}

TBool CListView::OkToDeleteCategory(TInt aHandle) const
//
// Report whether it is reasonable to delete the category indicated. This is not called for 
// entries marked as EQikCategoryCantBeDeleted within the resource. It already knows the category
// cannot be deleted.
//
	{
	return(ETrue); // ok to delete the category
	}

TBool CListView::DoDeleteCategoryL(TInt aHandle)
//
// Delete the indicated category.
//
	{
	// record which is the current list box entry - so we can track it if appropriate
	SetCurrentEntry();

	if (iEngine->DeleteCategoryL(aHandle))
		{ // either the current category been deleted OR some entries have been moved
		// into the current category due to the deletion of the catgory they originally belonged to
		SelectCategoryL(iEngine->CurrentCategory());

		// rebuild listbox to display new entries
		UpdateListBoxL();
		LocateControlByUniqueHandle<CQikListBox>(EListViewListId)->
							SetCurrentItemIndexL(iEngine->CurrentEntryIndex(),ETrue,EDrawNow);
		UpdateCommandAvailability();
		}
	return(ETrue);
	}

TBool CListView::IsCategoryEmpty(TInt aHandle) const
//
// Report if the category is empty or not. If we lie and claim it is empty this enables deletion
// of categories that contain items. Items within a category that gets deleted are set to belong to 
// the Unfiled category.
//
	{
	return(ETrue); // allow deletion of category even if still contains items
	}

void CListView::SortListL(const TFolderEntrySortType aType,const TFolderEntrySortOrder aOrder,const TInt aCmdId)
//
// Attempt to change the list sort order.
// Error handling is more than simply leaving + perhaps telling the user something has gone wrong.
// Your application MUST ensure it remains in some kind of self consistent state allowing the
// user to attempt the same operation at a later time without crashing. Most problems are caused
// not by the initial error but by attempting to continue after the error as the various parts of 
// an application are not in sync with each other. 
//
	{
	// record current settings incase we need to roll back
	TFolderEntrySortType oldType=iEngine->SortType();
	TFolderEntrySortOrder oldOrder=iEngine->SortOrder();

	// update the list
	SetCurrentEntry();
	iEngine->SortEntries(aType,aOrder);

	// attempt to update the listbox display, track the current entry...
	TRAPD(err,
		UpdateListBoxL();
		LocateControlByUniqueHandle<CQikListBox>(EListViewListId)->
							SetCurrentItemIndexL(iEngine->CurrentEntryIndex(),ETrue,EDrawNow);
		);

	// if the listbox display fails, roll back to previous sort order
	if (err!=KErrNone)
		{
		iEngine->SortEntries(oldType,oldOrder);

		// now roll back the UI so the list box data, UI and engine are all in same state.
		CQikCommandManager& cm=CQikCommandManager::Static();

		// restore the Radio button state within the UI
		if (oldType!=aType)
			{
			TInt commandId=EAppCmdSortByName;
			if (oldType==EFolderEntrySortBySize)
				commandId=EAppCmdSortBySize;
			else if (oldType==EFolderEntrySortByModified)
				commandId=EAppCmdSortByDate;
			else if (oldType==EFolderEntrySortByType)
				commandId=EAppCmdSortByType;
			if (commandId!=aCmdId)
				{ // swap back the radio button state
				cm.SetChecked(*this,aCmdId,EFalse);
				cm.SetChecked(*this,commandId,ETrue);
				}
			}

		// restore the Ascending check box within the UI
		if (oldOrder!=aOrder)
			{
			TBool val=EFalse;
			if (oldOrder==ESortOrderAscending)
				val=ETrue;
			cm.SetChecked(*this,EAppCmdSortOrder,val);
			}

		LocateControlByUniqueHandle<CQikListBox>(EListViewListId)->
							SetCurrentItemIndexL(iEngine->CurrentEntryIndex(),ETrue,EDrawNow);
		// inform user via a system type dlg
		User::Leave(err); 
		}
	}

void CListView::SendFileAsL()
//
// Send the file, via a user chosen transport. 
//
	{

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?