Libraries
Groups code modules, reusable
Pre-compiled programming codes
ready for use
Design Patterns
Efficient and elegant
solutions to common
problems
Structural = how organize objects + connect them
Behavioral = how organize code
Creational = how organize code to manage object creation
Serializer Pattern
Responsible reading and
writing objects
QTextStream = read + write human-readablefiles
QDataStream = read + write structured data binary
Client
Class1Reader Class1Writer
+read(Class1)
Class1
+writer(Class1)
ANTIPATTERNSCommon used programming practices/solutions to recurring
programming problems that is ineffective/inefficient
1) Software Design antiPattern
> Input kludge – failing handling invalid input
> Interface bloat – interface powerful/complicated, hard to reuse
> Race hazard – fail see consequence order of events
2) Object-oriented design antiPattern
> Circular dependency – mutual dependencies between objects
> God object – too much information/responsibility
3) Programming antiPattern
> Hard coding – embedding assumptions
> Magic numbers – unexplained numbers
> Magic strings – literal strings
4) Methodological antiPattern
> Copy + paste programming – existing code
> Reinvent the (square) wheel – existing solution
Included in project with directive #include
System program caller linker establish link between
program and library code at run time
lib file ease job of linker – contains compiled/object files,
ease linking process of library items and program codeFramework and
Design Pattern
Framework is large colletion components and
conventions documented public API
Qt is a framework – framework implemented with design
patterns
Design patterns efficient solution to common problems
QMetaObject Meta object describe structure of another object
MetaObject Pattern (Reflective pattern): information about properties and methods of QObject
Q_PROPERTY macro Describe QObject Properties
Access data members:
> Direct (getters and setters) – faster more efficient
> Indirect (QObject / QMetaObject interface) – more reusable code
Q_PROPERTY (type name READ getFunction [WRITE setfunction] [RESET resetFunction] [NOTIFY ntifySignal])
[. . . .]
Customer::Customer(const QString name, QObject * parent)
:QObject(parent){
setObjectName(name);
}
Void Customer::setId(const QString &newId){
if (newId !- m_id) {
Qstring oldId = m_id;
m_id = newId;
emit valueChanged( id newId, oldId);
}
Void Customer::setType(CustomerType theType){
if (m_Type != theType) {
CustomerType oldType = m_type;
m_Type = theType;
}
Void TestCustomerProps::test() {
Customer cust;
cust.setObjectName( Customer
cust.setName( Falafal
cust.setType( Government //enumproperty as string
QString originalId =
cust.setId(orifinalId);
QVariant V = cust.propert id
QString str = v.toString();
return;
}
Class Customer: public QObject{
Q_OBJECT
Q_PROPERTY (QString id READ getID WRITE setID NOTIFY valueChanged)
Q_PROPERTY (QString name READ getName WRITE setName)
Q_PROPERTY (CustomerType type READ getType WRITE setType)
Q_PROPERTY (Qdate dateEstablished READ getDateEstablished) //read-only
public:
enum CustomerType {Corporate, Individual,
Educational, Government};
Q_ENUMS(CustomerType);
explicit Customer (const QString name = QString(),
QObject * parent = 0);
QString getId() const {
return m_id;
}
QString getName() const {
return m_name;
}
CustomerType getType() const {
return m_type;
}
private:
QString m_id, m_name;
CustomerType m_type;
};
[. . . .]
Using reflective programming, can write general-purpose
operations work on classes of varied structures.
To make class reflective:
Inherit from QObject
Include Q_OBJECT macro
Q_PROPERY(QString name READ getName WRITE setName)
[. . . .]
/* Method for setting enum values from Strings */
Void Customer::setType (Qstring newType){ 1
static const QMetaObject* meta = metaObject(); 2
static int propindex = meta->indexOfProperty( type
static const QMetaProperty mp = meta->property(propindex);
QMetaEnum menum = mp.enumerator();
const char* ntype = newType.toAscii().data(); 3
CustomerType theType =
static_cast<CustomerType>(menum.keyToValue(ntyp));
if (theType != m_type) { 4
CustomerType oldType = m_type;
m_type = theType;
emit valueChanged( type theType, oldType);
}
}
1 Overloaded version accept string as argument. Set
value -1 if unknown.
2 Static locals, initializations happen only once.
3 Executed each time
4 Check if valueChanged signal needed
What kinds of information can you obtain from a QMetaObject?
className(), which returns the class name as a const char*
superClass(), which returns a pointer to the QMetaObject of the base class if there
is one (or 0 if there is not)
methodCount(), which returns the number of member functions of the class
method(index), which returns the meta-data for the method with the given index
propertyCount(), which returns the number of properties in this class, including base
class properties.
property(index), which returns the meta-data for the property with the given index.
What Qt classes are used to do data reflection?
QMetaObject, QMetaProperty, QSqlDatabase::tables, QSqlRecord, Qvariant
How does the QMetaObject code for each of your QObject-derived classes get generated?
moc generates QMetaObject classes to support properties, signals and slots.
Normally, you do not run moc directly. It is run automatically by make on the
header files listed in HEADERS which use the Q_OBJECT macro.
What are the advantages of using property() and setProperty() over direct getters and
setters?
Q_PROPERTY macros make it possible for moc to generate code for QObject's
property() and setProperty() member functions. The advantage of using these
functions is that client code can determine which properties are available by
iterating through QMetaProperty objects of the QMetaObject corresponding to that
class.
What does the property() function return? How do you obtain the actual stored value?
property() returns a QVariant, which is a union wrapper around every possible basic
type, and also several Qt classes/types. With QVariant, you can ask for its type()
and convert to the actual value<>(). Benefits are most apparent when implementing
script engines or developer tools. It becomes possible to define "handle anything"
kinds of functions without using anything but the QObject interface to read and
write values.
Explain how it is possible to add new properties, acquired at runtime, to a Qobject
setProperty("propName") sets a dynamic property for that object even if it is not
declared as a Q_PROPERTY
Explain how dynamic properties can be serialized
They are stored in a QVariantMap, which can be serialized via a QDataStream.
QDataStream out(...);
QVariant v(123); // The variant now contains an int
int x = v.toInt(); // x = 123
out << v; // Writes a type tag and an int to out
v = QVariant("hello"); // The variant now contains a QByteArray
v = QVariant(tr("hello")); // The variant now contains a QString
int y = v.toInt(); // y = 0 since v cannot be converted to an int
QString s = v.toString(); // s = tr("hello") (see QObject::tr())
out << v; // Writes a type tag and a QString to out
...
QDataStream in(...); // (opening the previously written stream)
in >> v; // Reads an Int variant
int z = v.toInt(); // z = 123
qDebug("Type is %s", // prints "Type is int"
v.typeName());
v = v.toInt() + 100; // The variant now hold the value 223
v = QVariant(QStringList());
QMetaObject
Qt support reflective programming via QMetaObject
Provides generic interface through which state of any Qobject
accessed and manipulated
Instance of QMetaObject class used as mirror reflect and
change stated of Qobjects without manupulating Qobject
directly
Qobject
Person
-name:Qstring -birthDate:QDate
+Person() +Person(QString, Qdate) +getName():Qstring +getBirthDate():Qdate +setName(Qstring) +setBirthDate(Qdate)
Product
-name:Qstring -price:double
+Product() +Product(QString, double) +getName():Qstring +getPrice():double +setName(Qstring) +setPrice(double)
writeToFile(Qobject*);
Class Person: public Qobject
{
Q_OBJECT
Q_PROPERTY(Qstring name READ getName WRITE setName)
Q_PROPERTY(Qdate birth READ getBirthDate WRITE setBirthDate)
public:
Person();
Person(Qstring n, Qdated);
Qstring getName()const;
Qdate getBirthDate()const;
void setName(Qstring n);
void setBirthDate(QDate d);
private:
QString name;
Qdate birthDate;
};
Person * person = newPerson;
writeToFile(person);
Product* product = new Product;
writeToFile(product);
writeToFile(Qobject *obj){
QFile file( dat.txt
file.open(QIODevide::Append);
QTextStreamtoFile(&file);
const QMetaObject *mo = obj->metaObject();
for (int i=mo->propertyOffset(); i<mo-propertyCount();i++)
{
const QMetaProperty prop = mo->property(i);
QString name = prop.name();
QVariant value = prop.read(obj);
Qstring valStr = value.toString();
toFile << name << valStr << endl;
}
file.close();
}
Models and Views Separate underlying data class (model) from GUI (view)
Data
View
Standard Widgets ->use data as part of widget
View class operate external data (model)
Model
View
setModel()
Data
• Separate model from view – reduces complexity
• Different maintenance imperatives – easier
maintain both kept separate
• Possible maintain different, consistent views of
same data
• Different, consistent views of same data
• Do not store data
• Do not know data structure
Standard Widgets:
• Two copies data: one outside widget, one inside
• Synchronize both
• Tight coupling present data, hard write unit test
Example QFileSystemModeluser QTreeView:
#include <QtGui>
int main(int argc, char *argv[]){
Qapplication app(argc, argv);
QFileSystemModel model;
model.setRootPath(
QTreeView tree;
tree.setModel(&model);
tree.setSortingEnabled(true);
tree.header()->setResizeModel(QHeaderView::
ResizeToContent);
tree.resize(640, 480);
tree.show();
return app.exec();
}
MVC consists of three kinds of objects.
1) Model = application object
2) View = screen presentation
3) Controller = defines way user interface reacts to user input
QFileSystemModel in a
QTreeView QFileSystemModel is already populated with data, so we can simply
create one, create a view, and view->setModel(model).
#include <QtGui>
int main(int argc, char *argv[]) {
QApplication app(argc, argv);
QFileSystemModel model;
model.setRootPath("/");
QTreeView tree;
tree.setModel(&model);
tree.setSortingEnabled(true); 1
tree.header()-
>setResizeMode(QHeaderView::ResizeToContents);
tree.resize(640, 480);
tree.show();
return app.exec();
}
//1 - Enable HeaderView sort buttons.
Qt provides its model-view architecture to separate models and view. In this architecture a number of abstract and concrete model and view classes are
provided. Though this architecture supports the separation of model/logic from the views, it does not provide controller classes like the classic MVC pattern.
Qt s model-view architecture uses signals and slots for the communication between models and views.
A model class in Qt either has the data or communicates with the data source. In order to make use of Qt s model-view architecture one has to either use
the built-in, concrete model or view classes or implement a model or view class derived from model/view interfaces provided in Qt. In order to make use of
the architecture the view has to be set up with a model. In other words, view has a model and not the other way around.
In a sense, Qt replaces the controller in its model-view architecture with delegates that are
responsible for the rendering/display and editing of model data in a view.
Validate Regular Expression
QLineEdit validate input:
A > ASCII alphabetic character
N > ASCII alphanumeric character
X > ASCII any character
D > ASCII nonzero digit
9 > ASCII digit
# > Hexadecimal digit
B > Binary digit
Validators = attached to input widgets
1) QDoubleValidator = floating point
2) QIntValidator = integer
3) QRegExpValidator = text regular expression
int main (int argc, char* argv[]){
QApplication app(argc, argv);
QLineEdit e;
e.setIntputMask( - - -
e.show();
return app.exec();
}
int main (int argc, char* argv[]){
QApplication app(argc, argv);
QLineEdit e;
QIntValidator *v = new QIntValidator(0,100);
e.setValidator(v);
e.show();
return app.exec();
}
Regular Expression
Special characters
. any character
\n newline
\f form feed
\t tab
\xhhhh hex
Quantifiers
+ 1 or more
? 0 or 1
* 0 or more
{i, j} at leat i, no more than j
Chracter Sets:
\S white space
\S non-whitepace
\d digital 0 to 9
\D non-digital
\w any word character (letter/
digit/underscore)
\W non-word character
[AEIOU] match A, E, I, O, U
[a-g] range from a to g
[^xyz] except x, y, z
QLineEdit e;
QRegExp re( a-zA-Z][_a-zA-Z0-9]+
QRegExpValidator *v = new QRegExpValidator(re);
e.setValidator(v);
e.show();
Consist 4 digits (0-9):
d{4}
Consist 6 character, forst 3 alphabetic, last 3
digits
A-Za-z]{3}[0-9]{3}
Minimum 4, max 6 characters, except0, z and Z
zZ]{4,6}
Parsing Xml
Each <tag> must have closing </tag>
Or selfclosing <br/> NB: Case-sensitive
Tags with attributes:
<library>
<book title = Computer Algorithm pages =
<book title = C++ unleashed pages =
</library>
Tags with text:
<library>
<book>
<title>Computer Algotithm</title>
<pages>688</pages>
</book>
<book>
<title>C++ unleashed</title>
<pages>918</pages>
</book>
</library>
• Event driven
• Low-level
• Sequential-access while parsing document
• Any file size
• Forward direction
QT+ - xml
QXmlReader
+parse()
QXmlSimpleReader
QXmlContentHandler
+startDocument()
+endDocument()
+startElement()
+endElement()
+characters
QXmlDefaultHandler
MyHandler
SAX
#include <QXmlDefaultHandler>
class Qstring;
class MyHandler:public QXmlDefaultHandler{
public:
bool startDocument();
bool startElement(const Qstring & namespaceURI,
const QString & LocalName,
const QString & qName,
const QXmlAttributes & atts);
bool characters (const QString & text);
bool endElement (const QString & namespaceURI,
const QString & localName,
const QString & qName);
private:
QString indents;
};
Myhandler.cpp
QTextStream cout(stdout);
bool MyHandler::startDocument(){
indent =
return TRUE;}
bool MyHandler::characters(const Qstring & text){
QString t = text;
cout << t.remove( n
Bool MayHandler::startElement(const Qstring & namespaceURI,
const QString & LocalName,
const QString & qName,
const QXmlAttributes & atts){
QString str = QString n%1\\%2).arg(indent).arg(qName);
cout << str;
if (atts.lenght()>0){
QString fildName = atts.qName(0);
cout << QString
.arg(fieldName).arg(fieldName);
}
cout <<
indent +=
return TRUE;
}
Three ways parse XML:
Qt s XML module:
1) SAX (Simple API for XML) – parse event-driven
2) DOM (Document Object Module) – tree-style parse
3) Stream-style parsing with QXmlStreamReader
DOM
• XML elements as objects in tree structure
• File in memory, limit RAM
• Random access
• Not handle parse errors
• Creating documents
Writing using DOM:
1) Create document (QDomDucument)
2) Create root element
3) for each contact, put in document
4) Write result to file
Write to file: (open filem create text stream, call toStrin() method of DOM document)
int main (int argc, char **argv){
QApplication a (argc, argv);
QDomDocument doc AdBookML
QDomElement root = doc.createElement adbook
doc.appendChild(root);
Contact c;
c.name = Kal
c.eMail = [email protected]
c.phone =
root.appendChaild(ContactToNode(doc, c));
QFile file c:/qt/text/xml
if (file.open(Qfile::WriteOnly))
return -1;
QTextStream ts(&file);
ts << doc.toString();
file.close();
return 0;
}
Reading using DOM:
1) Create DOM document from file
2) Find root
3) Find children (elements)
4) Find attributes
Reading file:
QDomDocument doc adBookML
Qfile file test.xml
if (!file.open(IO_ReadOnly)
return -1;
file.close;
Find root element:
QDomElement root = doc.documentElement();
if (root.tagNam() != adbook
return -3;
Find element, check attributes:
QDomNode n – root.firstChild();
while (!n.isNull()){
QDomElement e = n.toElement();
if (!e.isNull()){
if (e.tagName() == contact
Contact c;
c.name = e.attribute( name
c.phone = e.attribute( phone
c.eMail = e.attribute( email
}
}
n = n.nextSibling();
}
Create Document:
QDomDocument doc adBookML
Create root element:
root element point to start
root element called adbook
QDomElement root = doc.creeateElement( adbook
doc.appendChild(root);
Each contact put in document:
QDomElement ConstactToNode( QDomDocument &d, const Contact & c){
QDomElement cn = d.createElement( contract
cn.setAttribute( name c.name);
cn.setAttribute( phone c.phone);
cn.setAttribute( email c.eMail);
return cn;
}
Design Patterns
Creational Patterns: Manage object creation during runtime, manage object deletion
Factory Method
Product Factory
FactoryMethod(): Product
Operation()
ConcreteProduct
ConcreteFactory
FactoryMethod():product
. . .
Product = FactoryMethod()
. . .
return newConcreteProductcreate
Bread
WhiteBread
BrownBread
WholewheatBread
AbstractBreadFactory
BreadFactory
Client
+makeBread(QString):Bread
+ makeBread(Qstring):Bread
- Bread *myBread
+bake()
uses
create
uses
AbstractFactory
Abstract Factory Pattern
AbstractProductA Client
ProductA1 ProductA2
createProductA()
createProductB()
AbstractProductB
ProductB1 ProductB2
ConcreteFactory2
createProductA()
createProductB()
ConcreteFactory1
createPRoductA()
createProductB()
SingletonClass has only one instance, accessed via global access point
Make constructor Private, creating one instance
Class A {
public:
static A* getInstance();
private:
A();
static A* onlyInstance;
}
A*A::onlyInstance = NULL;
A::A(){}
A*A::getInstance(){
if(onlyInstance == 0)
onlyInstance = new A();
return onlyInstance;
}
Memento PatternObject storing snapshot of internal state of another object
Object state restored, allow undo/rollback operation
Originator
Memento
Caretaker
Object know how to save itself
Object written and read by originator
Object holds memento for originator
state = m -> getState()
Originator
setMemento(Memento m)
createMemento()
state
Memento
getState()
setState()
state
Caretaker
Return new Memento(state)
Memento Stares state of Originator
Caretaker Keep Memento
• Role of Caretaker store Memento, not allowed access state of Originator.
• Achieved by making getState(), setState() and constructor of Memento provate,
Caretaker cannot access state of Originator.
• Originator need able access construcotr, getState() and setState() of Memento.
Achieved making Originator friend of Memento.
Class Memento
{
public:
private: friend class Person;
Memento();
QStringList getState();
void setState(QStringList s);
QStringList state;
};
Memento Person::createMemento() const
{
QStringList state;
state << name << birthDate.toString();
Memento mem;
mem.setState(state);
return mem;
}
Void Person::setMemento(Memento m)
{
QStringList s = m.getState();
name = s.at(0);
birthDate = QDate::fromString(s.at(1));
}
int main(int argc, char *argv[])
{
Person p( John Qdate(1990,12,25));
//create memento
Memento caretaker = p.createMemento();
//change Person p
//restore Memento
p.setMemento(caretaler);
}
Façade Pattern
Unified interface to set of interfaces in subsystem
Defines higher-level interface making subsystem easier use
Concurrency
Similar in concept: start() function cause execution, fork (two things happening
QProcess Qthread
Runs different program Runs same process, share
In same process, separate code, share memory with
memery other threads
Communicate with child Share memory and code
Process via streams with peer threads. Sync
(stdin, stdout stderr) locks, wait conditions,
Pass data using command mutexes, semaphores
Line arguments
Managed by operating Managed by process
system
#include <QObject>
#include <QProcess>
class LogTail: public Qprocess {
Q_OBJECT
public: LogTail (Qstring fn=Qstring());
~LogTail();
signals: void LogString()
public slots: void LogOutPut();
};
LogTail::LogTail (Qstring fn){
connect (this SIGNAL (readyReadStandardOutput()), this SLOT (logOutput()));
QString argv;
argv << -f fn;
start tail argv);
}
LogTail::~LogTail(){
terminate();
}
QProcess: class for starting and controlling other process
Derived from QObject using signals and slots
QThread and
QtConcurrent
• QThread class provide platform-independent threads
• Qt support multi-threading and encapsulates threads using QThread class
• QObjects are thread safe and re-entrant, communicate across threads
• Only have one GUI thread (QApplication)
• Widgets inheritedfrom QWidget not thread safe
• Executing in run() method
• Start event loop calling exec
Thread has:
> Own stack pointer
> instruction (program) counter
> processor registers
> execution state
Access to:
> shared resources (memory, wait conditionsm nutual exclusive data blocks, semaphores
class MyThread: public QThread {
public: void run (); //execute end when return from run()
};
Void MyThread::run(){
QTcpSocket socket;
socket.connectToHost(hostName, portNumber);
exec();
}
Networking ConceptsWebKit: open source web content rendering and editing engine
QT += webkit
Main classes:
> QWebElement = access and edit QWebFrame DOM elements
> QWebFrame = data object represent frame in web page
> QWebHistory = history of visited links associated with QWebPage
> QWebHistoryItem = object represent one visited link in QWebHistory
> QWebPage = data object represent web page
> QWebSettings = data object holds settings used by QWebFrame or QWebPage
> QWebView = widget visualizes QWebPage
Only Widget in QWebKit is QWebView
QWebPage download web content behind scenes, process content, reflect results user interface
Viewing webpage:
QWebView *view = new QWebView();
View -> load(QUrl( www.unisa.ac.za
Networking Concepts
QWebView = widget used to view and edit web documents
QWebPage = object to view and edit web document
QUrl = interface for workin with URL s
QWebFrame = data object represent frame in web page
QWebElement = class eccess and edit QWebFrame DOM elements
Browsing web using HTTP protocol (hypertext transfer protocol)
HTTP built on top of TCP (transmission control protocol) which is built in IP (internet protocol)
QUrl class:
ftp://ftp.qt.nokia.com:2021
SchemeHost port
http://qt-project.org/documents#qt-other
fragment
http://qt-project.org/products/qt-for-mobile
path
ftp://person:[email protected]:2021
userName
password
TCP Sockets UDP Sockets
Guaranteed in-order delivery File and forget
Point-to-point only Point-to-pint or broadcast
Correct delivery important Time more important than delivery
QTcpSocket = represent a socket
QTcpServer = represent a server, listen incomming onnections generating
QToSocket instances for each connection
QT += network
Person
- name: QString
- birthDate: QDate
+ Person(QString, QDate)
+ setMemento(Memento)
+ createMemeonto(): Memento
Memento
- state: QStringList
- Memento()
- getState)_: QStringList
- setState(QStringList)
Caretaker
- person: Person
- memento: Memento