23.06.2015 Views

Exercises Lecture 4 – Datatypes, Collections and Files - SAIM

Exercises Lecture 4 – Datatypes, Collections and Files - SAIM

Exercises Lecture 4 – Datatypes, Collections and Files - SAIM

SHOW MORE
SHOW LESS

You also want an ePaper? Increase the reach of your titles

YUMPU automatically turns print PDFs into web optimized ePapers that Google loves.

<strong>Exercises</strong> <strong>Lecture</strong> 4 – <strong>Datatypes</strong>, <strong>Collections</strong> <strong>and</strong> <strong>Files</strong><br />

Qt in Education<br />

Aim:<br />

Duration:<br />

This exercise will take you through the process of loading <strong>and</strong> saving<br />

files, including custom data types <strong>and</strong> Qt collections.<br />

1h<br />

© 2010 Nokia Corporation <strong>and</strong> its Subsidiary(-ies).<br />

The enclosed Qt Materials are provided under the Creative Commons Attribution-Non-Commercial-Share Alike 2.5 License<br />

Agreement.<br />

The full license text is available here: http://creativecommons.org/licenses/by-nc-sa/2.5/legalcode.<br />

Nokia, Qt <strong>and</strong> the Nokia <strong>and</strong> Qt logos are the registered trademarks of Nokia Corporation in Finl<strong>and</strong> <strong>and</strong> other countries worldwide.<br />

© Nokia Corporation. All rights reserved.


Strings <strong>and</strong> Numbers<br />

Qt in Education<br />

Start from the calculator project. The project is implement to the extent that the user interface<br />

shows up <strong>and</strong> the CalculatorWidget::valueChanged slot is called when either of the value entry fields<br />

are altered.<br />

Complete the slot so that the sum of the values entered in m_firstValue <strong>and</strong> m_secondValue is shown<br />

in the m_result label. The calculator only needs to h<strong>and</strong>le integer values.<br />

If either of the value field does not contains a number, the result should say “no result”.<br />

Reading <strong>and</strong> Writing <strong>Files</strong><br />

Start from the fileaccess project. The project provides a user interface that lets the user edit a list<br />

of items. Your task is to implement the slots FileListWidget::saveClicked <strong>and</strong><br />

FileListWidget::loadClicked.<br />

The slots shall save the list as a text file using QTextStream. Each item of the list shall be given a<br />

line in the text file. This lets you verify the results using a plain text editor.<br />

Start by implementing the saveClicked slot. The code shall perform the following steps:<br />

1. Create a QFile object for the file name listitems.txt <strong>and</strong> open that file object for writing.<br />

2. When the file has been opened, create a QTextStream object for that file.<br />

3. Write the items to the stream using the item(i)->text());<br />

4. When all items have been written, close the file object using QFile::close.<br />

Before continuing, verify that the file does contain the items of the list, one item per line.<br />

The next step is to implement the loadClicked slot. The code shall be implemented much like the<br />

save slot, but read the file. Use the QTextStream::atEnd function to determine whether all lines of<br />

the file have been read. Use the QTextStream::readLine function to read a complete line of the file.<br />

Do not forget to close the file object when the entire file has been read.<br />

Now verify that the program loads <strong>and</strong> saves as expected. Also, ensure that you can load the<br />

© Nokia Corporation. All rights reserved.


same file repeatedly correctly, i.e. press the Load button several times in a row.<br />

Binary <strong>Files</strong> <strong>and</strong> Custom Data Types<br />

Qt in Education<br />

Start from the customtype project. You will use this project through exercise steps 3-5. The project<br />

contains a main.cpp file, which you will work in, <strong>and</strong> the class Person. Through out these exercise<br />

steps, you will use the Person class in different settings. For this to work, you need to take<br />

measures to give Qt the needed tools.<br />

To underst<strong>and</strong> the first task, simply build the project. The compiler will complain about missing the<br />

two > operators for streaming objects of the type Person to <strong>and</strong> from a QDataStream. In the<br />

documentation for the QDataStream class you can find out more about the required functions. The<br />

functions to implement are declaration as shown below.<br />

QDataStream &operator(QDataStream &, Person &);<br />

Implement the functions at the designated location in the source code (look for it in main.cpp). Build<br />

<strong>and</strong> run the application. Verify that the output reads as follows, i.e. that the original list can be<br />

saved <strong>and</strong> reloaded properly.<br />

Original people<br />

John Doe<br />

Jane Doe<br />

Albert A Einstein<br />

Loaded people<br />

John Doe<br />

Jane Doe<br />

Albert A Einstein<br />

Hashing Custom Data Types<br />

Continuing from the last step, uncomment the body of the hashOfPeople function in main.cpp, then<br />

build the project. The newly uncommented code tries to use the Person class as the key in a QHash<br />

collection. This requires a hashing function <strong>and</strong> a comparison operator. As expected, the compiler<br />

complains about a missing qHash(const Person&) function <strong>and</strong> an == operator for the Person class.<br />

Add such a function at the designated location in the source code (look for it in main.cpp). From the<br />

documentation for the QHash class, you will find the proper return type of such a function.<br />

A hashing function is often based on knowledge about the situation. Given our data type, we know<br />

that the first name <strong>and</strong> initials are usually more unique than the family name. Thus, base your<br />

return value on the qHash(const QString&) function <strong>and</strong> these two properties.<br />

The == operator, outlined below, needs to take all properties of the Person class into account.<br />

Complete the operator to return true only if the given Person objects are identical.<br />

bool operator==(const Person &p1, const Person &p2)<br />

Now build <strong>and</strong> run the application. If something is wrong, the output of the application will tell you<br />

(by printing “Something is wrong with...”).<br />

QVariant <strong>and</strong> Custom Data Types<br />

Continuing from the last step, uncomment the body of the variantsOfPeople function in main.cpp.<br />

This function will put Person object into QVariant objects <strong>and</strong> then try to retrieve them.<br />

© Nokia Corporation. All rights reserved.


Qt in Education<br />

Compiling the project with the function body uncommented, the compiler will complain about a<br />

QMetaTypeId for the Person class. This is a clue, but does not lead you all the way to the solution.<br />

The documentation for the QVariant class reads as follows.<br />

“QVariant can be extended to support other types than those mentioned in the Type<br />

enum. See the QMetaType documentation for details.”<br />

Read the documentation on the QMetaType class <strong>and</strong> add the single line type registration at the<br />

designated location in the source code (look for it in main.cpp).<br />

Building <strong>and</strong> running the application, the end of the output should now read as follows. This means<br />

that the Person objects has been properly passed through the QVariant objects.<br />

Original variants of people<br />

John Doe<br />

Jane Doe<br />

Albert A Einstein<br />

People after variants<br />

John Doe<br />

Jane Doe<br />

Albert A Einstein<br />

© Nokia Corporation. All rights reserved.


Qt in Education<br />

Solution Tips<br />

Step 1<br />

Use the following line to read the text from one of the QLineEdit widgets.<br />

QString firstValueText = m_firstValue->text();<br />

Convert a string to an integer using the toInt method.<br />

bool ok;<br />

int firstValue = firstValue.toInt(&ok);<br />

Use the setText method to update the result.<br />

m_result->setText("no result");<br />

Use the QString::number method to convert a number to a QString.<br />

Step 2<br />

Create a file object using the following line.<br />

QFile file("listitems.txt");<br />

Do not forget to open file object with the argument QIODevice::ReadOnly or QIODevice::WriteOnly<br />

depending on what you are trying to achieve.<br />

When writing to the file, use the following loop to retrieve the items.<br />

for(int i=0; icount(); ++i)<br />

// The item's text is available from m_list->item(i)->text()<br />

Add a line break at the end of each line by adding endl to the stream.<br />

When loading from the file, use m_list->addItem to add each line to the list.<br />

Step 3<br />

When implementing a stream operator for a type built on existing types, e.g. a class containing<br />

strings <strong>and</strong> integers, simply use the existing stream operators in your implementation. For<br />

instance:<br />

QDataStream &operator


Qt in Education<br />

{<br />

QString t;<br />

stream >> t; t.setString(t);<br />

...<br />

Step 4<br />

The qHash function returns a uint.<br />

For hashing the first name <strong>and</strong> initials, either join the strings <strong>and</strong> hash them, or join the hash<br />

values of each string.<br />

The operator== simply compares the first name, initials <strong>and</strong> family name of two given objects.<br />

Unless all match, the operator should return false.<br />

Step 5<br />

Use the Q_DECLARE_METATYPE macro.<br />

© Nokia Corporation. All rights reserved.

Hooray! Your file is uploaded and ready to be published.

Saved successfully!

Ooh no, something went wrong!