Exercises Lecture 4 â Datatypes, Collections and Files - SAIM
Exercises Lecture 4 â Datatypes, Collections and Files - SAIM
Exercises Lecture 4 â Datatypes, Collections and Files - SAIM
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.