COS3711 Summary - An Introduction to Design Patterns in C++ with Qt PDF

Title COS3711 Summary - An Introduction to Design Patterns in C++ with Qt
Author Wilco Breedt
Course Advanced Programming
Institution University of South Africa
Pages 22
File Size 436.1 KB
File Type PDF
Total Downloads 418
Total Views 942

Summary

COS3711 Summary For: An Introduction to Design Patterns in with Qt : Wilco Breedt 1. Reflection 2 2. Validation 5 3. XML 7 4. Model View Architecture 8 5. Momento 13 6. Concurrency 15 7. Singleton 17 8. UML 18 9. Factory Method 19 10. Notes 20 COS3711 Wilco Breedt 1 G const QMetaProperty metaProp CO...


Description

       

COS3711 Summary For: An Introduction to Design Patterns in C++ with Qt By: Wilco Breedt 





1. Reflection

2

2. Validation

5

3. XML

7

4. MV/MVC - Model View Architecture

8

5. Momento

13

6. Concurrency

15

7. Singleton

17

8. UML

18

9. Factory Method

19

10. Notes

20

                                       

COS3711

Wilco Breedt 1

1. Reflection 1. 2. 3. 4. 5. 6.

Inherit QObject Q_OBJECT Macro Q_PROPERTY(int size READ getSize WRITE setSize) Q_PROPERTY(type name READ getter WRITE setter) MOC (Meta Object Compiler) Looks for QOBJECT Macro and compiles a meta object file. Before RUNTIME. Dynamic Properties (When you use setProperty and the property you are trying to set was NOT in the class Q_PROPERTY declared by yourself. This means you cannot use the QMetaProperty to get these values because Dynamic properties are created at RUNTIME where static properties are created BEFORE RUNTIME when the MOC generates the MetaObject for the class 7. QMetaObject - Object that carries meta data about another object (QObject) Used for reflection 8. Static Properties - Defined in the class - Information about static properties are created at compile time and exist within QMetaObject 9. Dynamic Properties- Defined outside the class - created at runtime and you cannot obtain information about them using the QMetaObject

  ===================================image.h=================================== #ifndef IMAGE_H #define IMAGE_H #include   class Image: public  Q  Object / / Inherit   from   QObject { Q_OBJECT // QOBJECTMacro (MOC) Q_PROPERTY(i nt size READ getSize WRITE setSize) // Q_PROPERTY (MOC) Q_PROPERTY(QString   name READ getName WRITE setName) // Q_PROPERTY (MOC)  public: Image(); int getSize(); void setSize(int s); QString getName(); void setName(QString s);  private: int length; // Q_PROPERTY(int size ...) This does not have to be the same as the Q_PROPERTY that gets its value QString name; }; #endif // IMAGE_H      ===================================image.cpp=================================== #include "image.h"  Image::Image() {} void Image::setSize(int s ) {  length = s; } int Image::getSize() {  r eturn length; } void Image::setName(QString s) {   ame = s; n } QString Image  ::getName() {  r eturn name; } 

COS3711

Wilco Breedt 2

====================================main.cpp===================================  #include  #include  #include  #include "image.h"  void printObject(Q  Object *obj)   { / / Method   that uses reflective techniques c onst QMetaObject *meta = obj->metaObject( ); QString className = meta->className(); QString result = "";  // Static Properties ( Was declared by yourself in the Q_PROPERTY of the class ) (Declared at compile time) // for (int i = meta->propertyOffset(); i propertyCount(); i++) Get rid of properties in base class for (int i = 0;  i propertyCount(); i++) { // First method to get value of meta property const QMetaProperty metaProp = meta->property(i); const char *name = metaProp.name(); // Get the name of the meta property QVariant value = obj->property(name); / / Get the value of the meta property  // Convert meta property name to QString if you have to // QString name = QString(metaProp.name());  // Second method to get value of meta property // const QMetaProperty metaProp = meta->property(i); // QVariant value = metaProp.read(obj); result += QString(" %1 %2 ").arg(name).arg(value.toString()); } // Dynamic Properties (Wasn’t declared in the Q_PROPERTY/ Declared at RUNTIME) foreach(QByteArray dynamicPropName, obj->dynamicPropertyNames()) { QVariant value = obj->property(dynamicPropName); result += QString(" %1 %2 ") .arg(Q  String(dynamicPropName)) .arg(value.toString()); } qDebug() dynamicPropertyNames()) { QVariant value = i->property(dynamicPropName); merge.append(QString("DName %1, Value %2").arg(QString(dynamicPropName)).arg(value.toString())); } } // If   the Object is not   a pointer (Image *i)   -> Image i // f oreach(Image i, list)   { // const QMetaObject metaObj   = i.metaObject(); // for (int in   = 0;   in   setProperty("name2", "Wilco2.png"); // Dynamic Property // Getting Values int imageSize = img->property(" size").toInt(); // ->property returns QVariant // OR QVariant name = img->property("name"); // ->property returns QVariant QString imageName = name.toString(); // Convert to QString qDebug() getName()); name.appendChild(nameText); } QString xml = doc.toString(); } 

COS3711

Wilco Breedt 7

4. MV/MVC - Model View Architecture 1.

Views - ONLY displays the data, declare one instance and set the Model (that is basically the only thing you do with it) The rest of the things comes from the Model (use setModel to set the view) a.

QTableView (Model Based)

b. QListView (Model Based) c.

QTreeView (Model Based)

d. QTableWidget (Item Based/ Convenience class) e.

QListWidget (Item Based/ Convenience class)

f.

QTreeWidget (Item Based/ Convenience class)

2. Models - Serve the DATA to the Views (Remember Abstract means you cannot use it, you can not make an instance of it, you cannot instantiate it ! you need to inherit it and then you can use it !!! QAbstractItemModel, QAbstractTableModel, QAbstractListModel) Concrete models are models of which you can make a instance of



Objectives when using a QAbstractTableModel (Nothing is done on the View, everything is done on the MODEL!) : 1.

Headers

2. Edit table data (Double click on row and edit it)

COS3711

Wilco Breedt 8

3.

Add table data (Add rows)

4.

Remove / Delete data (Delete rows)

 How to implement a QAbstractTableModel (subclassing it): ●

Functions YOU MUST IMPLEMENT !!!!!!! ○

rowCount() (pure virtual)→ How many rows are in your data



columnCount() (pure virtual) → How many columns are there in your data



data() (pure virtual) → To return the actual value / data (provides the data for each and every CELL in



headerData() (This is just to make it a WELL behaved model)

your table) ●

Functions to implement if you want your model to be EDITABLE ! ○

setData() (If you want your table to be editable)



flags() that returns a value containing Qt::ItemIsEditable / Qt::ItemIsSelectable / Qt::ItemIsEnabled

 int MyModel::rowCount(const Q  QModelIndex &parent) const  { // Q_UNUSED(parent); // Sodat jy nie warnings kry vir goed wat nie gebruik word nie. return list.count(); // list.length - 1 ?? }  int MyModel::columnCount(const Q  QModelIndex &parent)   const  { // Q_UNUSED(parent); // Sodat jy nie warnings kry vir goed wat nie gebruik word nie. return headers.count(); // headers.length - 1 ?? }  // Get   the   header   data QVariant MyModel::headerData(int section,   Qt::Orientation orientation, i nt role)   const // MUST   IMPLEMENT  { if (role != Qt::DisplayRole) // If it is not for display purposes don't return QVariant {

// Readonly return QVariant();

} if (orientation == Qt::Vertical) // orientation != Qt::Horizontal { return QVariant(); } return headers.at(section); // Headers are stored in QList || QStringList; // return headers[section]; }    // Get the data for each   cell QVariant MyModel::data(const QModelIndex  &  index, int role)   const / / MUST IMPLEMENT {

COS3711

Wilco Breedt 9

if (!index.isValid()) // Check if the index is VALID ! { return QVariant(); } if (role == Qt::DisplayRole || role == Qt::EditRole) // Important { // int row = index.row(); // int col = index.column(); // QObject *object = list[row]; // QString columnName = headers[col]; / / QVariant value = object->property(columnName.toStdString().c_str()); // Return const char // return value; r eturn list[index.row()]->property(headers[index.column()].toStdString().c_str()); // Return the data requested. } return QVariant(); }  void MyModel::insert() / / Do   not   have   to   implement, just   for   fun. { QObject *object = new QObject(); foreach(QString header, headers) { object->setProperty(header.toStdString().c_str(), "MyTest"); } list.append(object); }                    a cell // Must   be   here to   edit the   MODEL   !! // Set the data for bool MyModel::setData(const Q  ModelIndex &  index, const Q  Variant &  value, int   r ole) / / MUST   I MPLEMENT EDITABLE {

COS3711

Wilco Breedt 10

if (role == Qt::EditRole && index.isValid()) { int row = index.row(); int col = index.col(); // list[row]->setProperty(headers[col].toStdString().c_str(), value); l ist.at(row)->setProperty(headers.at(col).toStdString().c_str(), value); emit dataChanged(index, index); // Signal the view that the data changed. return true; } return false; }   // Must   be here   to edit   the MODEL   !! Qt::ItemFlags M  yModel::flags(const QModelIndex &  index)  // MUST   IMPLEMENT EDITABLE { // Do some check here to see if you are allowed to edit it ? // If everything is editable then return everything ! return (Qt::ItemIsEditable | Qt::ItemIsSelectable | Qt::ItemIsEnabled); }  MVC M: Model → Application object / data V: View → Presentation C: Controller → Controls data flow from the model to the view or from the view to the model. Notifies everyone of what is happening.  MV Delegate: Renders items for editing (QSpinBox, QLineEdit etc.) Sits between the Model and View  Transition from MVC to MV (Why MV is a good example of MVC): ●

Do not see the C (Controller)



View and Controller are merged together



If something changes in the model, the view is notified, if something changes on the view the model is notified

 The controller is like an observer (it observes the changes on the model & view).  What is the relationship between MVC and observer pattern ●

In the observer pattern the observer automatically respond to events occurring in the subject/ its subjects



In the same way the model, view and controller automatically respond to data changes within each other.



This can hence be seen as they are observing each other

   MV vs MVC

COS3711

Wilco Breedt 11

In the MV pattern there is no controller, there is however a delegate, which is used to render items for editing on the view and update the model with values from the view when editing is done from the view. A delegate can therefore be seen as playing the role of a controller in the MV vs MVC architecture.  Difference between QTableView/QAbstractItemModel and QTableWidget (What is the difference between item based and model based views) ●

QTableWidget (Item based) handles the data for you/data is stored in the widget (This is a convenience class)



QTableView (Model based) requires a model to handle the data for you



Item based Less flexible ○

In Model based the view and the model are separated, this makes it more flexible because you can have multiple views for the same model, or multiple models for the same view.



Model and View are tightly coupled together in the item based.



Item based is not reusable because the data is stored within the widget (the view moves with the data)

                   

       COS3711

Wilco Breedt 12

5. Momento ●

When you want to serve the state of an object (state = data within the class) in a previous time frame (basically it is used to restore data)



3 classes involved ○

Originator → Class that has the state that you want to serve (The class you want to backup) The originator must handle the back-up logic (So all the logic basically comes here)





Memento → Copy the state of the Originator (This is where the backup is stored)



Caretaker → Stores the memonto’s

Momento class (Backup class) → Only has the state + a getter and a setter to set the data

 // Originator  class ImageList { public: ImageList(); Backup getBackup(); void restore(Backup b); private: QList list; };  // Implementation of the getters and setters within the ImageList Backup ImageList::getBackup() { Backup b; b.setList(l ist); return b; }  void ImageList::restore(Backup b) { list = b.getList(); }   // Memento  class Backup { public: Backup(); void setList(Q  List l); QList getList(); private:

COS3711

Wilco Breedt 13

QList list; }; // Caretaker class BackupList: public Q  List { public: BackupList(); }; Basic steps of the client: 1.

Backup a.

Get an instance from the originator using the getter you declared

b. Store that backup instance in the caretaker. 2. Restore a.

Get the instance of the backup in the caretaker

b. Use the setter you declared in the originator to restore the backup // CLIENT  I mageList i; BackupList bl; // Backup Backup b = i.getBackup(); // Get a instance from originator. bl.append(b); // Store the backup in the caretaker  // Restore Backup r = bl.at(0  ); // bl[0] // Get the backup from the caretaker. i.restore(r); // Restore the backup in the originator.  Encapsulation REQUIREMENT Should always satisfy this ! ●

Caretaker must NOT be able to modify the memento



Make everything private and make the originator a friend class



See below how to do this !

 // Memento  class Backup { private: friend class ImageList; Backup();   List l); void s etList(Q QList getList(); QList list; };    

COS3711

Wilco Breedt 14

6. Concurrency ●

The ability to run multiple processes at the same time (Threads)



Example: You want to loop a 900 times over 0 - 900. Then check if the numbers are prime numbers. Imagine if it took 1 second for a check, this means your program will be busy for 900 seconds. But if you split it into threads [0 - 300, 301 - 600, 601 - 900] and execute those loops at the same time, then it will take a ⅓ of the time to complete the 900 loop.

 Have two things involved in threads (Two classes involved) 1.

Worker → Does the actual work (Does the loop) a.

Must be a QObject

b. Use signals to communicate with the Client 2. Client → The one telling the worker to do its stuffies  // Worker, USING THE QOBJECT is the RECOMMENDED APPROACH !! class SearchImages: public  Q  Object { Q_OBJECT public: SearchImages(); // QList search(QList list, int size); void search(QList list, int size); // Changed the above to this to make it use signals and slots signals: void imageFound(Image); // Signal for when a image is found to emit outside the thread. void finished(); };  // Client QList imgList; QThread *thread = new QThread(); SearchImages *s = new SearchImages(); // Move the Q  Object t o t hread, moveToThread e  xists o  n Q  Object c lass s->moveToThread(thread); // connect(senderObject, signalOnSenderObject, receiverObject, slotOnReceiverObject) Connect Basic Params // When the thread starts, start the search function in SearchImage Class connect(thread, SIGNAL(started()), s, SLOT(search(imgList, 300))); // Connect when the SearchImage finds an image and emits it and then sends the image to the handleImage function. connect(s, SIGNAL(imageFound(I mage)), this, SLOT(handleImage(I mage))); // The following 3 steps ARE FOR CLEANUP !! connect(s, SIGNAL(finished()), thread, SLOT(quit()); // When done, quit the thread, CLEANUP connect(thread, SIGNAL(finished()), thread, SLOT(deleteLater()); // Delete the thread nicely, CLEANUP connect(thread, SIGNAL(finished()), si, SLOT(deleteLater())); // Delete the worker nicely, CLEANUP thread->start(); // Emits the signal started ... and then the above search(size) SIGNAL SLOT gets handled, 

COS3711

Wilco Breedt 15

   QProcess ●

Run an exe



readyReadStandardOutput - Signal that gets emitted when something is printed to the CONSOLE !!!

 QProcess *process =  n  ew QProcess  (); connect(process, SIGNAL(readyReadStandardOutput()), this, SLOT(manage()); process->start("image.exe");  void manage() { QByteArray ba = process->readAllStandardOutput(); // Readline QString output = QString(ba); QStringList lines = output.split("/n"); }    

              COS3711

Wilco Breedt 16

7. Singleton ●

ONE instance



Can be asked with Memento



Steps ○

1. Hide the constructor → Move the constructor to the private members



2. Create a method on the class to get an instance. (getInstance)



3. Make that method that you created (getInstace) a static method, this makes it easier so you can call it like so. BookList bl = BookList::getInstance();



This makes the getInstance function INSTANCE INDEPEN...


Similar Free PDFs