×
Namespaces

Variants
Actions

Native Symbian Dialogs in Qt Apps

From Nokia Developer Wiki
Jump to: navigation, search

This article explains how to launch native Symbian C++ dialogs from within a Qt QWidget based application.

Article Metadata
Code ExampleArticle
Created: ajakl (15 Dec 2010)
Last edited: hamishwillee (30 May 2013)

Contents

Overview

Not every Symbian native dialog is present in the standard Qt widget library, and in any case these dialogs do not always sufficiently match the look and feel of the Symbian native dialogs. If the native widget is not available or suitable, one alternative is to directly launch the native Symbian dialog from your Qt code.

Note.pngNote: We recommend that you use Qt Quick where possible. The Symbian Qt Quick Components make it relatively easy to match the native look and feel in the latest devices.

Showing a standard native Symbian note dialog is easy, as those can be setup and instantiated only from the source code - this article explains how to do that through the example of a confirmation note dialog.

If a definition in a Symbian resource file is required or recommended (e.g., for progress dialogs), several steps are necessary to make it work - this article will guide you through the necessary steps.

Download the attached example, which demonstrates showing a Symbian progress / wait dialog from a Qt Hello World app. The key steps are explained here. The example can be self-signed. Use at least Qt SDK 1.1 (final) and ensure you enable the "Native API Support" in the Symbian Toolchains section of the Qt SDK Maintenance tool.

NativeSymbianDialogQt.png

Symbian Resource File

Create a new file in your project, e.g. “dialogs_<UID>.rss”. Adding the Symbian UID3 to the filename is recommended, as the standard directory for resource files is shared between all installed apps. As your UID is unique on the system, you avoid any potential filename conflicts. In this example, the UID3 of the app is 0xee0861b3 (as defined in the .pro file as TARGET.UID3).

The file needs to have certain elements defined at the top to make it a valid Symbian resource file (NAME, RSS_SIGNATURE, TBUF16). Add your own definition of the dialog below. Here, our dialog definition is called: r_wait_note_softkey_cancel

 NAME QTDL
#include <eikon.rh>
#include <avkon.rsg>
#include <avkon.rh>
#include <avkon.mbg>
#include "nativesymbiandlg.hrh"
// Don't forget those two resources, which are required to make this
// file a valid Symbian resource file. These have to be defined before
// you define any own resources!
RESOURCE RSS_SIGNATURE
{
}
RESOURCE TBUF16
{
buf = "";
}
 
// The definition of our own wait dialog with a cancel softkey
// Read the Symbian documentation for more details on the dialog definitions.
RESOURCE DIALOG r_wait_note_softkey_cancel
{
flags = EAknWaitNoteFlags;
buttons = R_AVKON_SOFTKEYS_CANCEL;
items =
{
DLG_LINE
{
type = EAknCtNote;
id = EMyAppWaitNote;
control= AVKON_NOTE
{
layout = EWaitLayout;
singular_label = "Wait...";
animation = R_QGN_GRAF_WAIT_BAR_ANIM;
};
}
};
}

hrh file

The hrh file contains control ids, so that they can be referenced from both the source code as well as the resource file (if needed). Here, we define only one control in a new file called nativesymbiandlg.hrh. In this example, we don't access the control id from the source code, as we don't need to dynamically adapt the dialog or to retrieve user entered content from it.

// Define the ID of the control
enum TQtDlgExControlIds
{
EMyAppWaitNote = 0x100
};


Qt .pro file

In the project file, several additions are needed when compiling for Symbian:

  1. Add native Symbian libs required for calling the dialogs
  2. Add code so that the resource file gets compiled by the Symbian resource compiler
  3. Deploy the compiled resource file from the Nokia Qt SDK to the \resource\apps\ folder on the device (the ! as the drive letter means that the file is going to be copied to the drive the user / Nokia Store selects for installation – usually, either C: or E:)
  4. Also include the .hrh file for the compilation
symbian {
TARGET.UID3 = 0xee0861b3
LIBS += -lcone \
-leikcore \
-lavkon \
-leikcdlg \
-laknnotify
 
rssresources = "SOURCEPATH ." \
"START RESOURCE dialogs_ee0861b3.rss" \
"HEADER" \
"TARGETPATH resource\apps" \
"END"
MMP_RULES += rssresources
 
addFiles.pkg_postrules = "\"/NokiaQtSDK/Symbian/SDK/epoc32/data/z/resource/apps/dialogs_ee0861b3.rsc\" - \"!:\\resource\\apps\\dialogs_ee0861b3.rsc\""
DEPLOYMENT += addFiles
 
OTHER_FILES += nativesymbiandlg.hrh
}

Load the resource file

In the main(), you need to load your additional resource file so that its contents can be utilized from your app. In the .pro file, we specified that the resource file should be deployed to the drive the user / Nokia Store selects during installation. Therefore, we need to dynamically retrieve the installation drive and make sure we load the file from the correct drive. The code to add the correct path and drive to the resource file name, plus to load the file has been written in a new loadSymbianResourceFile() method:

 #include <COEMAIN.H>
#include <eikenv.h>
#include <eikapp.h>
#include <eikappui.h>
 
void loadSymbianResourceFile(const QString& resFileName)
{
// Convert the QString parameter to a descriptor
TPtrC resFileNameDescriptor (reinterpret_cast<const TText*>(resFileName.constData()), resFileName.length());
// Resource file path (drive letter will be replaced if necessary)
_LIT(KResourcePath, "c:\\resource\\apps\\");
// Get the full path and name of the executable - using this to determine the resource file
// path. Assumes that resource files are installed to the same dir as the exe.
TFileName appNamePath = CEikonEnv::Static()->EikAppUi()->Application()->AppFullName();
// Convert the path to a modifiable descriptor
TFileName resFile(KResourcePath);
// Replace the drive letter with the letter from the app path
resFile[0] = appNamePath[0];
//resFile.Replace(0, 1, appNamePath[0]);
// Add the actual filename of the resource file to the path
resFile.Append(resFileNameDescriptor);
// Want to see the filename that will be loaded? Uncomment the following two lines
// to convert the descriptor to a QString and output it to the debug stream.
// Don't forget to also uncomment the QDebug include statement at the top of this file.
//QString resFileQt((QChar*)resFile.Ptr(),resFile.Length());
//qDebug() << resFileQt;
// Load the resource file and convert the potential leave to a exception
QT_TRAP_THROWING(CCoeEnv::Static()->AddResourceFileL(resFile));
}
 
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
// Load the Symbian resource file - only specify the name of the compiled resource file
// Don't forget to add the deployment to the .pro file to actually copy the file
// to the right directory on the device.
loadSymbianResourceFile("dialogs_ee0861b3.rsc");
MainWindow w;
#if defined(Q_WS_S60)
w.showMaximized();
#else
w.show();
#endif
return a.exec();
}


Showing the dialog on the screen

In the main window class, we now load the dialog definition from the resource file and show it on the screen. The m_waitDialog variable is defined as an instance variable in the header file (not visible here). Note the dialog ID specified when executing the dialog is the same as specified in the resource file - the only difference is that it's now written in uppercase letters. This transformation is automatically applied by the resource compiler. If you're interested, you can take a look at the id definition if you search for the dialogs_<UID>.rsg file, which is automatically created in the SDK directory during compilation.

 #include <aknwaitdialog.h>
#include <dialogs_ee0861b3.rsg>
#include "nativesymbiandlg.hrh"
 
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
// Create a new instance of the S60 wait dialog class
m_waitDialog = new CAknWaitDialog(REINTERPRET_CAST(CEikDialog**, &m_waitDialog));
// If creation was successful...
// (we don't use the (ELeave) here, as the only reason for it would be to check if
// creating the instance was successful and if not throwing a Symbian Leave.
// In a Qt app, this would then have to be converted to a C++ exception and handled
// somewhere as well. Far easier in this simple case to just check manually if
// creation was successful.)
if (m_waitDialog)
{
// Execute the dialog, specifying the resource ID that is defined in the .rss
// file (here written in uppercase, as it's converted to by the resource compiler.
// See the real ID that's used here in dialogs_ee0861b3.rsg)
// The D at the end of this call means that the dialog will be destroyed
// automatically after it's dismissed.
m_waitDialog->ExecuteLD(R_WAIT_NOTE_SOFTKEY_CANCEL);
}
}
MainWindow::~MainWindow()
{
if (m_waitDialog)
{
// If the dialog is still active, finish it so that it's automatically deleted.
m_waitDialog->ProcessFinishedL();
}
delete ui;
}


Postconditions

When you launch the app, it will load the UI (in the example app simply a label with the “Hello World” text) and show an indefinite progress dialog on top. The dialog can either be cancelled by the user, or will also be dismissed when the window is destructed. Note that this example only works when executed on a Symbian device - you can not use the simulator to test it, as the simulator isn't based on the Symbian OS. The downloadable example contains additional #ifdefs so that you can compile the app also for the simulator (the dialog won't be shown then) - these have been omitted in the code snippets shown above.


Test application

Import the test app to your Qt Creator as part of the Qt SDK. If needed, adapt the source location of the resource file in the Qt .pro to the installation directory of your Nokia Qt SDK. File:NativeSymbianDlg.zip

This page was last modified on 30 May 2013, at 09:34.
67 page views in the last 30 days.