Sunday, May 8, 2011

Create Custom QDialogs With QLayout Classes

Qt Designer is used to design user interfaces for QT applications. In addition to using QT Designer to generate user interfaces, you can populate your dialogs with widgets on them dynamically at runtime by using layout classes. To achieve this, you need to extend qdialog class and add widgets to your derived qdialog instance dynamically at runtime.
Qt's layout classes are used to place widgets on parent dialogs or widgets. Instead of manually placing widgets on main containers and creating static user interfaces, layout classes help to place widgets easily. There are different QT layout classes but QHBoxLayout and QVBoxLayout are the most popular of them. By using the addWidget() method of layout class, you place items on the layout. After adding widgets to the layout properly, it is required to call setLayout() method of the main container to make layout visible on it.
Sample project started as a QT Gui Application and contains main.cpp, DynamicQDialog.h and DynamicQDialog.cpp files.
DynamicDialog.pro is the project configuration file contains:
TARGET = DynamicDialog
CONFIG   += qt gui
TEMPLATE = app
SOURCES += main.cpp \
    DynamicQDialog.cpp
HEADERS += \
    DynamicQDialog.h

main.cpp file contains the custom QDialog instance and shows it.
#include <QApplication>
#include "DynamicQDialog.h"
int main(int argc, char *argv[]) {
    QApplication app(argc, argv);
    DynamicQDialog dialog;
    dialog.show();
    return app.exec();
}

DynamicQDialog.h file is the derived QDialog class header file. Custom QDialog contains signals and slots to be associated with buttons on the dialog.
#ifndef DYNAMICQDIALOG_H
#define DYNAMICQDIALOG_H
#include <QDialog>
class DynamicQDialog : public QDialog
{
    Q_OBJECT
public:
    DynamicQDialog(QWidget * parent = 0, Qt::WindowFlags f = 0);
    ~DynamicQDialog();
public slots:
    void sl_accept();
    void sl_cancel();
signals:
};
#endif // DYNAMICQDIALOG_H

DynamicQDialog.cpp file contains implementation details for derived QDialog class. 2 QPushButtons added to the QHBoxLayout dynamically at runtime and displayed on the DynamicQDialog instance.
#include "DynamicQDialog.h"
#include <QHBoxLayout>
#include <QPushButton>
#include <QTextEdit>
#include <QMessageBox>

DynamicQDialog::DynamicQDialog(QWidget* parent, Qt::WindowFlags flags): QDialog( parent, flags )
{
    QGridLayout* mainGrid = new QGridLayout;
    QVBoxLayout* topLayout = new QVBoxLayout;
    topLayout->addWidget(new QTextEdit);
    mainGrid->addLayout(topLayout,0,0);

    QHBoxLayout* hLayout = new QHBoxLayout;
    QPushButton* btn;
    for( int i=0; i<2 br="" i="">        if( i == 0 ) {
            btn = new QPushButton("OK");
            connect(btn, SIGNAL(clicked()), this, SLOT(sl_accept()));
        }
        else if( i == 1 ) {
            btn = new QPushButton("Cancel");
            connect(btn, SIGNAL(clicked()), this, SLOT(sl_cancel()));
        }
        hLayout->addWidget(btn);
    }
    mainGrid->addLayout(hLayout,1,0);

    setLayout(mainGrid);
}

DynamicQDialog::~DynamicQDialog(){}

void DynamicQDialog::sl_accept(){
    QMessageBox msgBox;
    msgBox.setText("OK Clicked!");
    msgBox.exec();
}

void DynamicQDialog::sl_cancel(){
    QMessageBox msgBox;
    msgBox.setText("Cancel Clicked!");
    msgBox.exec();
}



Application created by QT Creator and uses Qt4.7 .

Tuesday, November 23, 2010

Using qmake from WinXP Command Line

qmake is used to create Makefiles from .pro files for QT projects.
qmake uses what you put in your project (.pro) files to decide what should go in the Makefiles it produces.

In order to test your installed qmake version type:
C:\>qmake -v
from command line but it produces an error message like:
'qmake' is not recognized as an internal or external command,
operable program or batch file.

In order to use qmake from winXP command line set following variables:
1-) Set the QMAKESPEC environment variable to point to a directory containing a description of your platform and compiler
2-) Add the 'qmake' executable to your PATH

I have installed QT4.6 at C:\Qt\4.6.0 , it can be at a different location on your disk. Execute following commands from command line respectively:

C:\>set QMAKESPEC=C:\Qt\4.6.0\mkspecs\win32-msvc
C:\>set PATH=%PATH%;C:\Qt\4.6.0\qmake

And then to check it type following.

C:\>qmake -v
QMake version 2.01a

Now you can use qmake to generate Makefiles from your .pro files.

Monday, October 25, 2010

Log Time, Date, FileName, FunctionName, LineNumber for QT Applications in C++

Logging provides developers with detailed information about program flow. Logging also makes tracing of exceptions occured easier at run-time. By including date, time, filename, functionname, linenumber into a text file; it becomes a helpful guide for program flow trace. C++ comes with macros that are usable for logging purposes.
"__FILE__" macro gives information about the curent fileName and returns a string. "__FUNCTION__" macro gives information about the name of the current function and returns a string. "__LINE__" macro gives information about the current line number and returns an integer value. These are ANSI-Compliant Predefined Macros.
Logger.h file contains declaration for Log class.
#include <fstream>
#include <QString>
using namespace std;

class Log {
public:
 Log();
 ~Log();
 void trace(QString fileName, QString functionName, int lineNumber);
private:
 ofstream myFile;
 char stime[9];
 char sdate[9];
};


Logger.cpp file contains implementation for Log class. trace() method takes fileName, functionName and lineNumber as parameters.
#include <fstream>
#include "Logger.h"
#include <time.h>
using namespace std;

Log::Log() {
}

void Log::trace(QString fileName, QString functionName, int lineNumber) {
 _strtime(stime);
 _strdate(sdate);
 myFile.open("C:\\example.txt", fstream::in | fstream::out | fstream::app);
 myFile<<"Date:"<<sdate<<";"<<" Time:"<<stime<<";"<<" FileName:"<<qPrintable(fileName)<<";"<<" FunctionName:"<<qPrintable(functionName)<<";"<<" LineNo:"<<lineNumber<<endl;
 myFile.close(); 
}

Log::~Log(){
 myFile.close();
}


main.cpp file uses Log class trace method for logging purposes.
#include "logger.h"
int main(int argc, char *argv[])
{
   Log* logger = new Log();
   logger->trace(__FILE__, __FUNCTION__, __LINE__);
   return 0;
}


trace method produces the output to the example.txt file that is located under the c:\ root directory. Sample output is generated as follows:
Date:10/25/10; Time:21:07:25; FileName:.\main.cpp; FunctionName:main; LineNo:5