Qt for s60 (Part II) -Mrudul V. Pendharkar
Learning Qt - Intermediate
• • • • • • • •
I/O (File) Dialogs Layouts Xml Events Timers Container Classes Iterators Qt for s60(Part II )
I/O • •
Qt offers general input/output classes that offer platform independent way to handle data. The following targets & sources are supported: – – – –
• •
Normal file Buffers Process ( IPC communication) TCP & UDP sockets
File Handling Files can be either text or binary. Qt offers convinient way to handle both types of files. –
Text: Following snippet shows how text files are written/created. QFile f(“myTxtFile.txt”); f.open(QIODevice::WriteOnly); QTextStream out(&f); out << “ Writing to Text File”; f.close();
–
Similarly files can be read by >> operator.
–
Binary: Working with binary files only differs with the class which is used to access file. Here we use QDataStream instead of QTextStream. QFile f(“myTxtFile.txt”); f.open(QIODevice::WriteOnly); QDataStream out(&f); out << “ Writing to Text File”; f.close();
–
As with text files, files can be read by >> operator.
NOTE: While reading using redirection operator, only a word is read at a time.
Qt for s60(Part II )
Dialogs • • • •
Dialog window is a top-level window mostly used for short-term tasks and brief communications with the user. Dialogs can be both modal ( User needs to respond before proceeding to do any GUI component for the application ) or modeless. In Qt QDialog is the base class of dialog windows. Modal Dialogs: – – – –
•
When an application modal dialog is opened, the user must finish interacting with the dialog and close it before they can access any other window in the application. Window modal dialogs only block access to the window associated with the dialog, allowing the user to continue to use other windows in an application. The most common way to display a modal dialog is to call its exec() function. An alternative is to call setModal(true) or setWindowModality(), then show().
Modeless Dialogs: – –
A modeless dialog is a dialog that operates independently of other windows in the same application. Modeless dialogs are displayed using show(), which returns control to the caller immediately.
•
Qt provides wide range of Dialogs like QProgressDialog, QDialogButtonBox, QFileDialog, QPrintPreviewDialog etc.
•
Lets look at code example to create dialogs:
•
Modal Dialog void EditorWindow::countWords() { WordCountDialog dialog(this); dialog.setWordCount(document().wordCount()); dialog.exec(); }
•
Modeless void EditorWindow::find() { if (!findDialog) { findDialog = new FindDialog(this); connect(findDialog, SIGNAL(findNext()), this, SLOT(findNext())); }
findDialog->show(); findDialog->raise(); findDialog->activateWindow(); }
Qt for s60(Part II )
Layouts
• Layouts help in arranging/ grouping various controls. • Qt includes a set of layout management classes that are used to describe how widgets are laid out in an application's user interface. • These layouts automatically position and resize widgets when the amount of space available for them changes, ensuring that they are consistently arranged and that the user interface as a whole remains usable. • Base class for Layouts in Qt is QLayout which in turn derives from QObject. • One can have layouts horizontally, vertically, in grid format or have two column layouts. • Here is the list of layouts used in Qt Qt for s60(Part II )
Layouts contd…
• A QHBoxLayout lays out widgets in a horizontal row, from left to right (or right to left for right-toleft languages). • A QVBoxLayout lays out widgets in a vertical column, from top to bottom. • A QGridLayout lays out widgets in a twodimensional grid. Widgets can occupy multiple cells. • A QFormLayout lays out widgets in a 2-column descriptive label-field style. • One can also create custom layouts in Qt. But would advice against creating one unless is really essential for your application. • Lets look at the code in next slide. Qt for s60(Part II )
Layouts contd…
QWidget *window = new QWidget; QPushButton *button1 = new QPushButton("One"); QPushButton *button2 = new QPushButton("Two"); QPushButton *button3 = new QPushButton("Three"); QPushButton *button4 = new QPushButton("Four"); QPushButton *button5 = new QPushButton("Five"); //Choose either of the layouts QHBoxLayout *layout = new QHBoxLayout; Or QVBoxLayout *layout = new QVBoxLayout; layout->addWidget(button1); layout->addWidget(button2); layout->addWidget(button3); layout->addWidget(button4); layout->addWidget(button5); window->setLayout(layout); window->show(); Example & Pics are taken from following link
Qt for s60(Part II )
Layouts contd…
QWidget *window = new QWidget; QPushButton *button1 = new QPushButton("One"); QPushButton *button2 = new QPushButton("Two"); QPushButton *button3 = new QPushButton("Three"); QPushButton *button4 = new QPushButton("Four"); QPushButton *button5 = new QPushButton("Five"); //Creating grid layout QGridLayout *layout = new QGridLayout; layout->addWidget(button1, 0, 0);//row 1, col 1 layout->addWidget(button2, 0, 1); //row 1, col 2 layout->addWidget(button3, 1, 0, 1, 2); //row 2, col 1 & 2 layout->addWidget(button4, 2, 0); //row 2, col 1 layout->addWidget(button5, 2, 1); //row 2, col 2
window->setLayout(layout); window->show(); Example & Pics are taken from following link
Qt for s60(Part II )
XML
• The two most popular XML handling APIs are supported by Qt: – SAX (Simple API for XML) for parsing event based handling. – DOM (Document Object Model) for creating a tree object of an XML file.
• In order to use these features one must add QtXML module to the .pro file. Syntax is as follows: – QT +=xml
• Lets look at an example each of SAX and DOM way of accessing xml file in the next slide. Qt for s60(Part II )
Xml – Understanding the models
•
DOM (Document Object Model) – – A xml file is read, and a tree based model is retrieved. – One can access any element in the tree using the id/name/parent-child relationship associated with the element. – It’s a very convenient way to access and modify xml elements, but can become quiet heavy on memory in case the xml file is of large size. – Qt supports DOM level 2 structure as recommended by W3C. – DOM can be used for reading, writing or modifying xml files.
•
SAX (Simple API for XML) – – Unlike DOM, SAX does not have a default object model. – A SAX parser is only required to read in your XML document and fire events based on the things it encounters in your XML document. Events are fired when the following things happen: • • • •
open element tags are encountered in your document close element tags are encountered in your document #PCDATA and CDATA sections are encountered in your document processing instructions, comments, entity declarations, are encountered in your document.
– Since SAX does not keep any object/tree in memory it becomes difficult to access and modify elements on the fly. – But this drawback, comes with an advantage of less memory consumption compared to DOM model – Qt supports deisgn of SAX2 Java implementation. The naming scheme is adapted to fit in Qt. – SAX apis generally provide a way to only read XML files. Qt for s60(Part II )
Qt-DOM •
DOM Example – – –
We will create a personal details xml file using DOM API. Following things need to be done for it • • • • •
Create a document element using QDomDocument. Create a root ( starting point of tree) element using QDomDocument::CreateElement Insert personal detail Information using QDomDocument::CreateElement and QDomElement::setAttribute. Write to file using QtTextStream. We will have xml file in following format at the end.
John 40
•
The code for it is as follows //Create document. QDomDocument d; //Create All the nodes on the tree. QDomElement root = d.createElement(“personal”); QDomElement personNode = d.createElement(“person”); QDomElement nameNode = d.createElement(“name”); QDomElement ageNode = d.createElement(“age”); QDomText nameData = d.createTextNode(“John”); QDomText ageData = d.createTextNode(“40”); //Create Attribute and add information to the attribute. personNode.setAttribute(“id”,”123”); //Now connect each node in the tree as required. d.appendChild(root); root.appendChild(personNode); personNode.appendChild(nameNode); personNode.appendChild(ageNode); nameNode.appendChild(nameData); ageNode.appendChild(ageData); //Now write the dom to file. QFile file(“personals.xml”); file.open(QIODevice::WriteOnly); QTextStream out(&file);
Qt for s60(Part II )
QtXml - SAX //Save document using the streaming object. Also specify the indent value(3 in our case). d.save(out,3); • • •
Lets now read the xml file generated in the previous slide. Since SAX informs about various xml events, we need to observe/override default events. Qt provides QXmlDefaultHandler class which contains methods which should be overridden. Here is the code. //ExampleSAXHandler.h #ifndef _EXAMPLESAXHANDLER_H_ #define _EXAMPLESAXHANDLER_H_ #include
Class ExampleSaxHandler: public QXmlDefaultHandler { public: ExampleSaxHandler(); bool startElement(const QString &nsURI, const QString &localname, const QString &qName, const QXmlAttributes &attrs); bool endElement(const QString &nsURI, const QString &localname, const QString &qName, const QXmlAttributes &attrs); bool characters(const QString &str); bool fatalError(const QXmlParseException &e); }; #endif //ExampleSAXHandler.cpp #include “ExampleSAXHandler.h” #include using namespace std; ExampleSAXHandler::ExampleSAXHandler(){ cout << “parse created” << endl; } bool ExampleSAXHandler::startElement(const QString &nsURI, const QString &localname, const QString &qName, const QXmlAttributes &attrs){ cout << qName.toStdString() << “\t”; return true; } bool ExampleSAXHandler::endElement(const QString &nsURI, const QString &localname, const QString &qName, const QXmlAttributes &attrs){ cout << endl; return true; Qt for s60(Part II ) }
QtXml-SAX contd… bool ExampleSAXHandler::characters(const QString &str){
If(!str.isEmpty()) cout << str.toStdString() << “ “; return true; } bool ExampleSAXHandler::fatalError(const QXmlParseException &e){
cout << “Error!” << endl; return true; } //main.cpp #include #include “ExampleSAXHandler.h” #include using namespace std; Int main ( int argc, char* argv[]){
QFile file(“personal.xml”); QXmlInputSource inputsource(&file); QXmlSimpleReader reader; ExampleSaxHandler handler; reader.setContentHandler(&handler); reader.setErrorHandler(&handler); reader.parse(inputsource); } Qt for s60(Part II )
Container Classes
• Qt provides a template-based (generic) container classes. • Qt container classes are designed to be lighter, safer & easier to use compared to STL. • Container classes are implicitly shared(Implicit sharing automatically detaches the object from a shared block if the object is about to change and the reference count is greater than one.) and reentrant (A reentrant function can be called simultaneously by multiple threads provided that each invocation of the function references unique data. ), and they are optimized for speed, low memory consumption, and minimal inline code expansion, resulting in smaller executables. • Containers bring in the benefit of writing less code for repetitive tasks like Creating List of items, Linked Lists etc. • We have two kinds of containers: Sequential & Associative. Qt for s60(Part II )
Container Classes – Sequential Containers •
Following classes are provided by Qt – –
QVector • •
–
QLinkedList • • •
–
This is a subclass on QList. This provides few extra functions for string handling.
QStack , QQueue • •
•
Internally this is implemented using arrays. As a result random access to elements is faster compared to QLinkedList.
QStringList • •
–
It provides a linked list. Adding elements anywhere in the list is quicker than QVector. Random access of elements is slower QList.
QList • •
–
It is resizeable and fast to the end of the container. Adding in the middle or to the start is slow.
QStack is a vector that provides push(), pop() & top() functions. QQueue is a list providing enqueue, dequeue() & head() functions.
Example: QVector vect(5); vect[0]= 1; vect.append(2); vect << 3 << 4 <<5; Int sum =0; for ( int i=0; i<5; i++){ sum+=vect[i]; }
Qt for s60(Part II )
Container Classes – Associative Containers
• • •
Associative Containers are containers which have one key associated with one ( QMap) or more values ( QMultiMap). Qt provides following Associative Containers: QMap: – It provides a dictionary that maps keys of type Key(K) to values of type(T). – Normally each key is associated with a single value. – The data is stored in a Key order.
•
QHash: – It is similar to QMap but provides significant faster lookups than QMap. – The data stored is in unordered manner.
•
QMultiMap: – This is a subclass of QMap and provides interface for multi-valued maps.
•
QMultiHash: – This is a subclass of QHash and provides interface for multi-valued hashes.
•
QSet – This provides a single valued mathematical set with fast lookups.
Example : QMap dict; dict.insert(“One”, 1); dict[“Two”]=2; int num = map.value(“Two”); Qt for s60(Part II )
Container Classes – Associative Containers QSet set; set.insert(“one”); set << “two”; QString concStr=“”; foreach(QString val, set){ concStr+= val; } QMultiMap map1, map2, map3; map1.insert(“quantity”,100); // map1.size() == 1 map2.insert(“quantity”,1000); // map2.size() == 1 map3 = map1 + map2; // map3.size() == 1 QList values = map.values("plenty"); for (int i = 0; i < values.size(); ++i) cout << values.at(i) << endl; QHash hash; hash[“three"] = 3; hash[“one"] = 1; hash["seven"] = 7; int num1 = hash[“three"]; int num2 = hash.value(“one"); Qt for s60(Part II )
Iterators
• Iterators provide a uniform means to access items in a container. • Qt's container classes provide two types of iterators: Javastyle iterators and STL-style iterators. • Java-style iterators are more convinient to use but are less efficient when compared to STL ones. • Java-style iterators point between elements • STL-style iterators point directly at the item. • As a result end() function of a container returns an iterator to the imaginary item one position past the last item in the container. end() marks an invalid position, hence it should never be dereferenced. • Both Java & STL style iterators offer read only and read/write iterators. Lets look at the code in the next slide. Qt for s60(Part II )
Iterators •
Java-Style Iterators: –
Read-Only Iterators• •
–
Here are the class names of read only iterators:- QListIterator (for QList), QLinkedListIterator (for QLinkedList), QVectorIterator (for QVector), QSetIterator (for QSet), QMapIterator(works on both QMap & QMultiMap), QHashIterator (works on both QHash & QMultiHash class) Example:QList list; list << "A" << "B" << "C" << "D"; QString concStr=“”; QListIterator i(list); //Read-only Iterator declaration while (i.hasNext()) { concStr+=i.next(); //i.remove(); //Not allowed compiler will complain. //i.insert(“M”); // Not allowed compiler will complain. } //concStr == “ABCD” after while loop
Read/Write Iterators• •
Name of read/write & read-only iterators differs only by word “Mutable” contained in the class name. Like QMutableListIterator, QMutableVectorIterator QMutableHashIterator etc… Example:QList list; list << "A" << "B" << "C" << "D"; QString concStr=“”; int j=0; QMutableListIterator i(list); //Read/Write Iterator declaration while (i.hasNext()) { if(j==2) i.setValue(“M”); // Note we are modifying 3rd element in the list using Iterator concStr+=i.next(); j++; }
//concStr == “ABMD” after while loop
Qt for s60(Part II )
Iterators •
STL-Style Iterators: –
Read-Only Iterators•
•
–
Here are the class names of read only iterators:- QList::const_iterator(for QList), QLinkedList::const_iterator (for QLinkedList), QVector::const_iterator (for QVector), QSet::const_iterator (for QSet), QMap::const_iterator (works on both QMap & QMultiMap), QHash::const_iterator (works on both QHash & QMultiHash class) Example:QList list; list << "A" << "B" << "C" << "D"; QString concStr=“”; QList::const_iterator i; //Read-only Iterator declaration for (i = list.begin(); i != list.end(); ++i) { concStr+=*i; //i.remove(); //Not allowed compiler will complain. } //concStr == “ABCD” after while loop
Read/Write Iterators• •
Name of read/write & read-only iterators differs only by word “Mutable” contained in the class name. Like QMutableListIterator, QMutableVectorIterator QMutableHashIterator etc… Example:QList list; list << "A" << "B" << "C" << "D"; QString concStr=“”; int j=0; QList::iterator i(list); //Read/Write Iterator declaration for (i = list.begin(); i != list.end(); ++i) { if(j==2) i.setValue(“M”); // Note we are modifying 3rd element in the list using Iterator concStr+=*i; j++; }
//concStr == “ABMD” after while loop
Qt for s60(Part II )
References • • • •
Independent Qt tutorials http://cartan.cas.suffolk.edu/oopdocbook/html/ http://thelins.se/learnqt/2009/04/the-qt-build-sy http://cartan.cas.suffolk.edu/qtdocs/index.html
Qt for s60(Part II )