Queries

Series 60 applications use various queries to ask the user a question, which may determine how the application then proceeds. A response to a query may require the user to enter some data, select one or more items from a list or simply confirm an action. The basic types of query are a confirmation query, a data query, a list query and a global query.

A confirmation query poses a question to which there is only a positive or a negative response ”for example, confirming whether a saved game should be deleted. It is possible for a confirmation query to have a single answer. A data query requests that a user enter some text, for example, a player's name . The text can be plain or formatted as a password, PIN, phone number, date, time, duration, or floating-point number. Table 6-3 provides a more comprehensive list of the different types. A multiline data query can have two lines of text, each plain or formatted as per single-line data queries.

Table 6-3. Data Query Types

Type

Class

Layout

Control

Plain Text

CAknTextQueryDialog

EDataLayout

EDWIN

Phone Number

CAknTextQueryDialog

EPhoneLayout

EDWIN

PIN

CAknTextQueryDialog

EPinLayout

SECRETED

Password

CAknTextQueryDialog

ECodeLayout

SECRETED

Date

CAknTimeQueryDialog

EDateLayout

DATE_EDITOR

Time

CAknTimeQueryDialog

ETimeLayout

TIME_EDITOR

Duration

CAknDurationQueryDialog

EDurationLayout

DURATION_EDITOR

Float

CAknFloatingPointQueryDialog

EFloatingPointLayout

FLPTED

Multiline

CAknMultiLineDataQueryDialog

Each AVKON_DATA_QUERY has a value from EAknMultilineDataLayout depending on the type of control

Varies depending on usage. Up to two lines.

Number

CAknNumberQueryDialog

ENumberLayout

AVKON_INTEGER_EDWIN


A list query contains a menu list, from which one or more items can be selected. Items in the list can contain one or two lines of text, with or without an icon or heading. As with all lists, items must have the same type of content.

Queries can be local to the application or global. The three types mentioned earlier are all local. Series 60 hides local queries when another application switches to the foreground, but global queries are not hidden.

Global queries are not dialogs, strictly speaking, as they do not inherit from CEikDialog .


You can use global queries for servers or applications that are currently in the background. Do this only if the information to be conveyed to the user is very important. If you display a global query from your application, the user cannot switch away to another application until they dismiss it. Global queries can be used to confirm an action, display a message or request an item be selected from a list. The different types are listed in Table 6-4.

Table 6-4. Global Queries

Type of Global Query

Description

Confirmation

Poses a question in a global manner, such as confirming whether to delete all games . You can customize a global confirmation query so that it plays a tone, dismisses with any key rather than just the soft keys, or shows a different icon and animation.

Message

Displays a message with a header ”for example, informing that the current game will close. You can customize a global message query so that it plays a tone and/or shows a small icon in the top right-hand corner.

List

Contains a selection list from which you can select an item. The items can contain a single line of text only. The query focuses the first item of the list by default, but you can change this.


The following section discusses three example applications that deal with data queries ( DataQuery ), list queries ( ListQuery ), and global queries ( GlobalQuery ). A confirmation query is very similar to a data query and therefore is not covered explicitly here, although sample code can be found in DataQuery .

Data Queries

The example application DataQuery provides sample implementations of both a confirmation query and a data query. As you would expect, the techniques involved in creating these dialogs are similar, and therefore only the data query will be analyzed in detail here.

DataQuery has just one menu option, Exit . If the user chooses to exit the application, a dialog is shown asking if they would like to save the game. This dialog is a confirmation query with soft key options of Yes and No , as shown in Figure 6-23.

Figure 6-23. Confirmation query.


If the user decides to save the game, a data query is displayed, requesting a name for the saved game, as shown in Figure 6-24. This subsection describes how to define and execute the data query.

Figure 6-24. Data query.


Defining a Data Query in Resource

As a data query is a type of dialog, it should be defined in a DIALOG resource.

 RESOURCE DIALOG r_dataquery_data_query    {    flags = EGeneralQueryFlags;    buttons = R_AVKON_SOFTKEYS_OK_CANCEL;    items =       {       DLG_LINE          {          type = EAknCtQuery;          id = EDataQueryDlgCIdDataQuery;          control = AVKON_DATA_QUERY             {             layout = EDataLayout;             control =                EDWIN                   {                   width = KMaxGameNameLength;                   lines = 1;                   maxlength = KMaxGameNameLength;                   };             };          }       };    } 

The flags should be set to EGeneralQueryFlags or EAknGeneralQueryFlags ”both equate to the same thing. The dialog should contain a single dialog line, which contains the query control. An appropriate layout for the DataQuery example is EDataLayout ”other layouts are defined in avkon.hrh . An EDWIN control is used for the data entry. Optionally, it is possible to set the text for the control's label, but in DataQuery, the label text is set dynamically.

A heading can be set for a query, and this should be constructed as a dialog line. The exception to this is a multiline data query. This has two dialog lines, each of which must contain a query.


Table 6-3 shows the type of control to use for each type of query. Chapter 8 gives more details on EDWIN and other editor resources.

Constructing and Executing a Data Query

The general method for executing a data query is to construct it using the NewL() method and execute it using ExecuteLD() . In DataQuery this is performed in CDataQueryContainer::SaveGameL() . A descriptor representing the game's name is passed into the query on construction. This will be modified using the contents of the editor control.

 ... TBuf<KMaxGameNameLength> gameName; CAknTextQueryDialog* gameNameQuery = CAknTextQueryDialog::NewL(gameName); CleanupStack::PushL(gameNameQuery); HBufC* prompt = StringLoader::LoadLC(R_DATA_QUERY_PROMPT); gameNameQuery->SetPromptL(*prompt); CleanupStack::PopAndDestroy(prompt); CleanupStack::Pop(gameNameQuery); if (gameNameQuery->ExecuteLD(R_DATAQUERY_DATA_QUERY))    {    SaveGameToFileL(gameName);    } } ... 

CAknQueryDialog is the base class for all local queries. It provides overloaded NewL() methods , which construct an appropriate derived class based on the type of the argument.


After constructing the query, a prompt can be set that will be displayed with the control. This is done by calling the SetPromptL() method, passing in a constant reference to a descriptor containing the prompt. In DataQuery , a string is loaded from resource into the prompt descriptor. Because the method is not leave-safe, the query should be put onto the Cleanup Stack before it is called. However, before ExecuteLD() is called, it must be popped off the stack, because the query will put itself onto the Cleanup Stack as part of the execution.

List Queries

A list query contains a menu list, from which the user can select one or more items. Items in the list can contain one or two lines of text with or without an icon or heading. As with all lists, items must have the same type of content. This subsection gives details of how to construct a list query, with the application ListQuery providing the basis of the discussion. This application is very similar to the previous example, DataQuery , but instead of asking the user to enter a name for the saved game, it presents a list of names for the user to choose from, as shown in Figure 6-25.

Figure 6-25. List query.


List Query Resources

The resource type for a list query is an AVKON_LIST_QUERY resource. The resource should have a single dialog line, AVKON_LIST_QUERY_DLG_LINE , containing an AVKON_LIST_QUERY_CONTROL . The control should define the listtype field to indicate the type of list the query will contain. This could be one of the pop-up menu list types, but in ListQuery a single line of text is chosen . The listbox refers to an AVKON_LIST_QUERY_LIST resource. To define the list items statically, an array identifier can be specified. The array_id specified in the AVKON_LIST_QUERY_LIST resource structure can refer to another resource containing an array of static strings representing the list items. In the ListQuery example, the list items are going to be defined dynamically, so the resource is left blank.

 RESOURCE AVKON_LIST_QUERY r_listquery_list_query    {    items =       {       AVKON_LIST_QUERY_DLG_LINE          {          control = AVKON_LIST_QUERY_CONTROL             {             listtype = EAknCtSinglePopupMenuListBox;             heading = SELECT_GAME_TEXT;             listbox = AVKON_LIST_QUERY_LIST                {                // array of items will be defined dynamically                };             };          }       };    } 

The AVKON_LIST_QUERY has a flags field, which defaults to EGeneralQueryFlags , and a softkeys field, which defaults to Ok and Cancel . These values can be overridden for a custom list query.


Creating and Executing a List Query

In ListQuery , the query list is created in CListQueryContainer::SaveGameL() . The CAknListQueryDialog constructor takes a reference to a TInt . This represents the index of the selected item and can be set to a nonzero value to preselect a particular item in the list. The TInt passed in is updated by the control with the user selection.

 TInt index(0); CAknListQueryDialog* query = new (ELeave) CAknListQueryDialog(&index); 

As you might expect, the list query contains a list, which in turn contains an item array. In ListQuery , an item array is a set up in the local method SetupListQueryItemArrayL() , which is called from CListQueryContainer::ConstructL() . The item array is a standard list item array, which is covered further in Chapter 7.

Setting the item array is done once the construction of the query is completed by PrepareLC() . In ListQuery this is performed in CListQueryContainer::SaveGameL() by calling the query's SetItemTextArray() method.

 query->PrepareLC(R_LISTQUERY_LIST_QUERY); query->SetItemTextArray(iListQueryItemArray); query->SetOwnershipType(ELbmDoesNotOwnItemArray); 

To see which item was selected by the user, rather than just its index, the application should take ownership of the item array by calling SetOwnershipType() . The query destroys itself after execution, so if the application does not take ownership of the array, it will be destroyed too.

A list query is invoked in the same manner as other queries ”that is, using PrepareLC() and RunLD() or using ExecuteLD() . In ListQuery , PrepareLC() is used, so RunLD() is used for execution.

 if (query->RunLD())    {    SaveGameToFileL((*iListQueryItemArray)[index]);    } 

The execution methods return a TBool indicating whether the user closed the query by pressing Ok ( Etrue ) or Cancel ( EFalse ). Assuming the application owns the item array, it can obtain the selected item, by using the TInt passed to the query on construction, to index into the array of items. Here the resulting list item is passed to a local method called SaveGameToFileL() .

Multiselection List Queries

A multiselection list allows the user to choose more than one list item. A multiselection list query is created in the same way as a list query, with the following exceptions:

  • An AVKON_MULTISELECTION_LIST_QUERY_DLG_LINE is used rather than a AVKON_LIST_QUERY_DLG_LINE in the AVKON_LIST_QUERY.

  • The listbox in the AVKON_LIST_QUERY_LIST is set to be an AVKON_MULTISELECTION_LIST_QUERY_LIST.

  • The list items will need to contain an icon index to refer to the check box ”for example, " 1\tMy Item ". The list class supplies the bitmaps for the check boxes automatically, so unlike in multiselection lists, adding them to the list's icon array is not required.

  • The list query is constructed, passing in a TInt array ( CSelectionIndexArray ). This will contain the indices of the selected items, once the query is dismissed.

Using Global Queries

A global query always takes focus, even when the application that owns it is running in the background. The user cannot task away from a global query, they must dismiss it, and so this type of query should be used sparingly ”applications should not dominate the screen if the user has tasked away.

Global queries are slightly more complex than the queries seen so far. Their functionality relies on both the notifier framework and the Active Object mechanism. The notifier framework is an operating system facility that allows messages or dialogs to be displayed.

To produce a global query, an Active Object has to be constructed to handle the dismissal of the dialog.

The example application, GlobalQuery , implements a global query to inform the user that a game will be closed, as shown in Figure 6-26. This note is displayed when the application is opened.

Figure 6-26. Global query.


Creating a Global Message Query

GlobalQuery does nothing more than create a global query and then handle its dismissal ”no other processing takes place. The query is created by the container class, CGlobalQueryContainer , during its construction. An Active Object, CGlobalQueryQueryHandlerAO , handles the notification of the dialog's dismissal from the framework. Because the GlobalQuery example is trivial, the Active Object simply informs an observer class that the dialog has been closed.

Since the container launches the query, it is also defined as the observer. The container class therefore implements the interface, MGlobalQueryCloseGameObserver , which has one method, CloseGameL() . A reduced class definition for CGlobalQueryContainer , presenting only the parts involved in the query construction, is shown below:

 class CGlobalQueryContainer : public CCoeControl, MGlobalQueryCloseGameObserver    { public: // from MGlobalQueryCloseGameObserver    void CloseGameL(); private: // constructor    void ConstructL(const TRect& aRect); private: //data    CGlobalQueryQueryHandlerAO* iQueryHandlerAO;    CAknGlobalMsgQuery* iGlobalMsgQuery;    }; 

Before a global query can be executed, the Active Object ( CActive derived class) must be constructed and set active. As the query is shown upon startup of GlobalQuery , this is performed in CGlobalQueryContainer::ConstructL() .

 iQueryHandlerAO = CGlobalQueryQueryHandlerAO::NewL(*this); iQueryHandlerAO->Start(); 

The NewL() function of the Active Object takes a reference to a MGlobalQueryCloseGameObserver object. As the container class itself is the observer, a dereferenced this pointer is passed in.

In the GlobalQuery example, the Active Object's Start() method initiates the process. It simply sets it to be active using the SetActive() method.

The query itself is created in the container's ConstructL() method:

[View full width]
 
[View full width]
HBufC* header = StringLoader::LoadLC(R_GLOBALQUERY_HEADER_TEXT); HBufC* message = StringLoader::LoadLC(R_GLOBALQUERY_MESSAGE_TEXT); iGlobalMsgQuery = CAknGlobalMsgQuery::NewL(); iGlobalMsgQuery->ShowMsgQueryL(iQueryHandlerAO->iStatus, *message, R_AVKON_SOFTKEYS_OK_CANCEL, *header, KNullDesC); CleanupStack::PopAndDestroy(message); CleanupStack::PopAndDestroy(header);

A global message query is constructed via NewL() and is executed using the ShowMsgQueryL() method. ShowMsgQueryL() has a number of parameters, some of which have default values and so are optional:

  • TRequestStatus& aStatus ” The iStatus of the Active Object that will handle the query's dismissal. The message query will set this to the value of the soft key used to dismiss it, which in turn will cause the Active Object's RunL() method to run.

  • const TDesC& aMsgText ” The text the query will display.

  • TInt aSoftkeys ” The resource identity for the soft keys.

  • const TDesC& aHeaderText ” A heading for the query.

  • const TDesC& aHeaderImageFile ” The name of the file containing the icon to be displayed with the query. The file should be an .mbg file. Set this to an empty string using KNullDesC if an icon is not required.

  • TInt aImageId ” The ID of the icon to be used for the query. This is optional, but must be specified if a file name is given in the previous parameter.

  • TInt aImageMaskId ” The ID of the icon mask. This is optional, but it must be specified if a file name is given in the previous parameter.

  • CAknQueryDialog::TTone aTone ” Tone to play when the query displays (optional).

Handling Dismissal of a Global Message Query

When the query is dismissed by the user, it causes the Active Object's RunL() to be called:

 void CGlobalQueryQueryHandlerAO::RunL()    {    if (iStatus == EAknSoftkeyOk)       {       iCloseGameObserver.CloseGameL();       }    Cancel();    } 

Testing the value of iStatus will reveal which soft key dismissed the query, and appropriate action can be taken. (The soft key values are defined in avkon.hrh .) In the GlobalQuery example, if Ok is pressed, MGlobalQueryCloseGameObserver :: CloseGameL() is called, which is implemented in the container. The Active Object is then cancelled, using its Cancel() method.

It is very important that the RunL() method should complete quickly.

Other Global Queries

In addition to global message queries, global confirmation queries and global list queries can be created. Creating these types of queries is very similar to creating the global message query. A global confirmation query should be created using CAknGlobalConfirmationQuery::NewL() and executed using ShowConfirmationQueryL() , while a global list query is created using CAknGlobalListQuery::NewL() and executed with ShowListQueryL() .



Developing Series 60 Applications. A Guide for Symbian OS C++ Developers
Developing Series 60 Applications: A Guide for Symbian OS C++ Developers: A Guide for Symbian OS C++ Developers
ISBN: 0321227220
EAN: 2147483647
Year: 2003
Pages: 139

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net