Porting to the Qt C++ Framework :: Part 2

In this post I want to introduce the Qt code I’ve written so far. One of the strengths of the Qt framework is its well supported in NetBeans, but more importantly, by Nokia via the Qt Creator IDE. In fact, Nokia supplies a host of tools, from the IDE and language tools, an Interface Designer, and loads of examples.

At the end of this post we’ll have a shell ready for the actual porting process to being. In other words, a GUI that loads, reacts to button presses, and updates status text.

So here’s the code:

main.enc__cppqt

  1. #include
  2. #include "cleaner.h"
  3. int main(int argc, char *argv[])
  4. {
  5.     QApplication app(argc, argv);
  6.  
  7.     Cleaner cleaner;
  8.     cleaner.show();
  9.  
  10.     return app.exec();
  11. }

cleaner.enc__cppqt

  1. #include
  2. #include "cleaner.h"
  3. #include "worker.h"
  4.  
  5. Cleaner::Cleaner(QWidget *parent)
  6.     : QWidget(parent)
  7. {
  8.     statusLabel = new QLabel("Conversion Status:");
  9.     processPathLabel = new QLabel("Folder To Process…");
  10.  
  11.     processStatusText = new QTextEdit;
  12.     processStatusText->setDisabled(true);
  13.  
  14.     processPathQLineEdit = new QLineEdit;
  15.     processPathQLineEdit->setDisabled(true);
  16.  
  17.     loadButton = new QPushButton("Select Folder");
  18.     loadButton->setToolTip("Select a folder to load Prestige export data from…");
  19.     processButton = new QPushButton("Process Folder");
  20.     processButton->setDisabled(true);
  21.  
  22.     QGridLayout *mainLayout = new QGridLayout;
  23.     mainLayout->addWidget(statusLabel, 0, 0);
  24.     mainLayout->addWidget(processStatusText, 1, 0);
  25.     mainLayout->addWidget(processPathLabel, 2, 0);
  26.     mainLayout->addWidget(processPathQLineEdit, 3, 0);
  27.  
  28.     QVBoxLayout *buttonLayout1 = new QVBoxLayout;
  29.     buttonLayout1->addWidget(loadButton, Qt::AlignTop);
  30.     buttonLayout1->addWidget(processButton, Qt::AlignTop);
  31.  
  32.     mainLayout->addLayout(buttonLayout1, 1, 1, Qt::AlignTop);
  33.  
  34.     setLayout(mainLayout);
  35.     setWindowTitle("Prestige Export File Cleaner");
  36.  
  37.     // signal and slots
  38.     connect(loadButton, SIGNAL(clicked()), this, SLOT(loadAction()));
  39.     connect(processButton, SIGNAL(clicked()), this, SLOT(processAction()));
  40.  
  41. }
  42.  
  43. void Cleaner::loadAction()
  44. {
  45.  
  46.     // main folder name to use
  47.     processPath = QFileDialog::getExistingDirectory(this,
  48.                    "Prestige Export Folder", "",
  49.                    QFileDialog::ShowDirsOnly
  50.                    );
  51.  
  52.     processPathQLineEdit->setText(processPath);
  53.  
  54.     processButton->setDisabled(false);
  55.  
  56. }
  57.  
  58. void Cleaner::processAction()
  59. {
  60.     processStatusText->setText("Starting Process…");
  61.  
  62.     Worker *wk = new Worker();
  63.     processStatusText->setText(wk->cleanImages());
  64.  
  65. }

cleaner.h

  1. #ifndef CLEANER_H
  2. #define CLEANER_H
  3.  
  4. #include
  5.  
  6. class QLabel;
  7. class QLineEdit;
  8. class QTextEdit;
  9. class QPushButton;
  10.  
  11. class Cleaner : public QWidget
  12. {
  13.     Q_OBJECT;
  14.  
  15. public:
  16.     Cleaner(QWidget *parent = 0);
  17.  
  18. public slots:
  19.     void loadAction();
  20.     void processAction();
  21.  
  22. private:
  23.     QLineEdit *processPathQLineEdit;
  24.  
  25.     QLabel *statusLabel;
  26.     QLabel *processPathLabel;
  27.  
  28.     QTextEdit *processStatusText;
  29.     QPushButton *loadButton;
  30.     QPushButton *processButton;
  31.  
  32.     QString processPath;
  33.  
  34. };
  35.  
  36. #endif // CLEANER_H

worker.enc__cppqt

  1. #include "worker.h"
  2.  
  3. #include
  4.  
  5. Worker::Worker()
  6. {
  7.  
  8.     br = "";
  9.     rl = "\r";
  10.     nl = "\n";
  11.     rn = "\r\n";
  12.     openp = "<p>";
  13.     closep = "</p>";
  14.     doublebr = "<br/><br/>";
  15.  
  16. };
  17.  
  18. QString Worker::cleanImages(){
  19.     return"Done!";
  20. }
  21.  
  22. void Worker::cleanXMLStoryFiles()
  23. {
  24.  
  25. }

worker.h

  1. #ifndef WORKER_H
  2. #define WORKER_H
  3.  
  4. #include
  5.  
  6. class Worker
  7. {
  8.  
  9. public:
  10.  
  11.     Worker();
  12.     Worker(QString dir);
  13.  
  14.     // functions
  15.     QString cleanImages();
  16.     void cleanXMLStoryFiles();
  17.  
  18. private:
  19.  
  20.     // status
  21.     QString statusMessages;
  22.  
  23.     QString br;
  24.     QString rl;
  25.     QString nl;
  26.     QString rn;
  27.  
  28.     QString openp;
  29.     QString closep;
  30.     QString doublebr;
  31.  
  32. };
  33.  
  34. #endif // WORKER_H

The biggest thing to note about this code is that we’re not using the Qt Designer program to create the UI. It’s all hand coded, done for the sake of learning the core UI model. If you’re learning Qt I suggest you try this as well. Yes the Qt Designer tool is fantastic and yes I’ll use it for most tasks moving forward, but for this project we’ll keep it low-level.

Core Implementation

On the implementation level it’s important to note that we’re using a totally object oriented approach to the UI and logic. Speaking of UI and Logic, note how we’ve split the app in two logical components: cleaner.enc__cppqt which holds the presentation logic, worker.enc__cppqt for the ‘model’.

On a releated note, as the XML logic will almost certainly get parallelized we’ll take special note of how we add and handle additional classes and data structures. From what I can see Qt may want all parallel code in separate classes, so we’ll see. We may end up editing the core functionality of worker.enc__cppqt, or possibly add a workerXML.ccp to the mix.

Also note how our call to: QFileDialog::getExistingDirectory() via: void Cleaner::loadAction() in cleaner.enc__cppqt is how we get the file path to process. In short, we’ve already replaced the command line apps argument with a GUI based equivalent!

To that end notice that as of right now we still have implementation bugs. So for example we create pointer to an instance of Worker on the heap in processAction() but do not call delete() on it. Of course this is wrong, and we’ll fix that in time–for now though the main idea is this code creates the UI which reacts to member functions of the worker class.

Next Steps

That’s it for the core UI code, in part 2 we’ll start porting our base application.

Go To Part 3 –>
Link

Leave a Comment

* are Required fields