PDA

View Full Version : Absurd behaviour with QstatusBar's showMessage



yagabey
27th May 2012, 12:06
Hello,

I am wirting a fingerprint reader app, and i am using api of Secugen. Actually i have no problem with the api. I can read fingerprint images succesfully. But when i want to show some messages on status bar , some of the text is being truncated. I mean; if i want to write " CreateTemplate() failed. Error = 12" on status bar, it is written something like " ) failed. Er ". The truncation is random; sometimes from the beginning and sometimes from the end. The problem doesnt look like related to QStatusBar only. The same problem occurs when i try to setText on a Qlabel or on a QLineEdit.

That is really annoying. I have no clue about the solution. May the secugen api cause some inconsistency in QT. Here is my code, thanks in advance... : (by the way; i am using msvc compiler with qt 4.8.1)


#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QDebug>
#include <windows.h>

#define REG_IMG_QUALITY 70
#define VRF_IMG_QUALITY 50


bool g_CapturedR1, g_CapturedR2, g_CapturedV1;
int SecurityLevel[9]= {SL_LOWEST, SL_LOWER, SL_LOW, SL_BELOW_NORMAL, SL_NORMAL, SL_ABOVE_NORMAL, SL_HIGH, SL_HIGHER, SL_HIGHEST};


MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);

m_DibCtl = NULL;
m_ImgBuf = NULL;
m_FetBuf1 = NULL;
m_FetBuf2 = NULL;
m_FetBufM = NULL;
m_ImageWidth = 0;
m_ImageHeight = 0;
m_MaxTemplateSize = 0;

g_CapturedR1 = g_CapturedR2 = g_CapturedV1 = false;

ui->m_CBDevName->addItem("USB FDU03");
ui->m_CBDevName->addItem("USB FDU02");
ui->m_CBDevName->addItem("Parallel FDP02");

ui->m_TemplateFormat->addItem("SG400");
ui->m_TemplateFormat->addItem("ANSI378");

ui->m_SecureLevel->addItems(QStringList()<<"1 Lowest"<<"2 Lower"<<"3 Low"<<"4 Below Normal"<<"5 Normal"<< "6 Above Normal"<<"7 High"<<"8 Higher"<< "9 Highest");

ui->cR2lbl->setScaledContents(true);
ui->cR1lbl->setScaledContents(true);

ui->m_TemplateFormat->setCurrentIndex(0);
ui->m_SecureLevel->setCurrentIndex(4);
DWORD err = SGFPM_Create(&m_hFPM);

}

MainWindow::~MainWindow()
{
delete ui;
}

void MainWindow::on_Initbutton_clicked()
{

DWORD err;
DWORD devname = SG_DEV_FDU03;
DWORD devid = 255; // Auto detect

QString devstr;
devstr = ui->m_CBDevName->currentText();

if (devstr == "USB FDU03") // USB: FDU03
devname = SG_DEV_FDU03;
else if (devstr == "USB FDU02") // USB: FDU02
devname = SG_DEV_FDU02;
else if (devstr == "Parallel FDP02") // USB: FDP02
devname = SG_DEV_FDP02;

err = SGFPM_Init(m_hFPM, devname);

if (err != SGFDX_ERROR_NONE)
{
this->statusBar()->showMessage( "Initialization Failed. Error = "+QString::number( err));
return;
}

err = SGFPM_OpenDevice(m_hFPM, devid);

if (err != SGFDX_ERROR_NONE)
{
this->statusBar()->showMessage( "OpenDevice() failed. Error = "+QString::number( err));
return;
}

SGDeviceInfoParam device_info;
err = SGFPM_GetDeviceInfo(m_hFPM, &device_info);

if (err != SGFDX_ERROR_NONE)
{
this->statusBar()->showMessage( "GetDeviceInfo() failed. Error = "+QString::number( err));
return;
}

m_ImageWidth = device_info.ImageWidth;
m_ImageHeight = device_info.ImageHeight;


if (m_ImgBuf == NULL)
m_ImgBuf = new BYTE[m_ImageWidth*m_ImageHeight];

// Initialize minutiae buffer
err = SGFPM_GetMaxTemplateSize(m_hFPM, &m_MaxTemplateSize);

if (err != SGFDX_ERROR_NONE)
{
this->statusBar()->showMessage( "GetMaxTemplateSize() failed. Error = "+QString::number( err));
}

if (m_FetBuf1)
delete [] m_FetBuf1;
m_FetBuf1 = new BYTE[m_MaxTemplateSize];

if (m_FetBuf2)
delete [] m_FetBuf2;
m_FetBuf2 = new BYTE[m_MaxTemplateSize];

if (m_FetBufM)
delete [] m_FetBufM;
m_FetBufM = new BYTE[m_MaxTemplateSize];

this->statusBar()->showMessage( "Initialization SuccessÄŸ");

ui->m_CapBtnV1->setEnabled(true);
ui->m_ConfigBtn->setEnabled(true);
ui->BtnCaptureR1->setEnabled(true);
ui->BtnCaptureR2->setEnabled(true);
ui->m_FormatBtn->setEnabled(true);

}

void MainWindow::on_BtnCaptureR1_clicked()
{

// Capture fingerprint
qDebug()<<"Capturing";

QImage cImage;

DWORD err = SGFPM_GetImageEx(m_hFPM, m_ImgBuf, 5000, NULL, REG_IMG_QUALITY);

if (err == SGFDX_ERROR_NONE)
{
cImage = QImage((const unsigned char*)(m_ImgBuf), m_ImageWidth, m_ImageHeight, QImage::Format_Indexed8);
QPixmap cPixmap;
cPixmap.convertFromImage(cImage);
ui->cR1lbl->setPixmap(cPixmap);
DWORD img_qlty;
err = SGFPM_GetImageQuality(m_hFPM, m_ImageWidth, m_ImageHeight, m_ImgBuf, &img_qlty);

// // Extract Fingerprint
err = SGFPM_CreateTemplate(m_hFPM, 0, m_ImgBuf, m_FetBuf1);
if (err == SGFDX_ERROR_NONE)
{
g_CapturedR1 = true;
this->statusBar()->showMessage("The first template is created. Image Quality= "+ img_qlty);
}
else{
this->statusBar()->showMessage(QString::fromUtf8(" CreateTemplate() failed. Error = ")+ QString::number(err));

}
}
else{
this->statusBar()->showMessage(QString("The captured image is not good. Try again...Err:")+QString::number(err));
}

if (g_CapturedR1 && g_CapturedR2)
{
ui->m_RegisterBtn->setDisabled(false);
}

// UpdateData(false);
}


void MainWindow::on_BtnCaptureR2_clicked()
{
// Capture fingerprint
DWORD img_qlty;
DWORD err = SGFPM_GetImageEx(m_hFPM, m_ImgBuf, 5000, NULL, REG_IMG_QUALITY);

if (err == SGFDX_ERROR_NONE)
{
QImage cImage;
cImage = QImage((const unsigned char*)(m_ImgBuf), m_ImageWidth, m_ImageHeight, QImage::Format_Indexed8);
QPixmap cPixmap;
cPixmap.convertFromImage(cImage);
ui->cR2lbl->setPixmap(cPixmap);
err = SGFPM_GetImageQuality(m_hFPM, m_ImageWidth, m_ImageHeight, m_ImgBuf, &img_qlty);

// Extract Fingerprint.
err = SGFPM_CreateTemplate(m_hFPM, 0, m_ImgBuf, m_FetBuf2);

if (err == SGFDX_ERROR_NONE)
{
this->statusBar()->showMessage("The second template is created. Image Quality= "+ img_qlty);
g_CapturedR2 = true;
}
else
{
this->statusBar()->showMessage("CreateTemplate() failed. Error = "+ QString::number(err));
}
}
else
{
this->statusBar()->showMessage("The captured image is not good. Try again...");
}

if (g_CapturedR1 && g_CapturedR2)
{
ui->m_RegisterBtn->setDisabled(false);
}

}

void MainWindow::on_m_CapBtnV1_clicked()
{
// Capture fingerprint
DWORD img_qlty;
DWORD err = SGFPM_GetImageEx(m_hFPM, m_ImgBuf, 5000, ui->cv1lbl->winId(), VRF_IMG_QUALITY);
if (err == SGFDX_ERROR_NONE)
{
err = SGFPM_GetImageQuality(m_hFPM,m_ImageWidth, m_ImageHeight, m_ImgBuf, &img_qlty);

// Extract Fingerprint.
err = SGFPM_CreateTemplate(m_hFPM, 0, m_ImgBuf, m_FetBufM);
if (err == SGFDX_ERROR_NONE)
{
g_CapturedV1 = true;
this->statusBar()->showMessage("The template for verification and identification. Image Quality="+QString::number( img_qlty));
}
else
{
this->statusBar()->showMessage("CreateTemplate() failed. Error = "+QString::number(err));
}

}
else
{
this->statusBar()->showMessage("The captured image is not good. Try again...");
}


if (g_CapturedR1 && g_CapturedR2 && g_CapturedV1)
{
ui->m_VerifyBtn->setDisabled(false);
ui->m_IdentifyBtn->setDisabled(false);
}
}

void MainWindow::on_m_FormatBtn_clicked()
{
WORD template_format;
if (ui->m_TemplateFormat->currentIndex() == 0)
template_format = TEMPLATE_FORMAT_SG400;
else
template_format = TEMPLATE_FORMAT_ANSI378;

DWORD err = SGFPM_SetTemplateFormat(m_hFPM, template_format);
if (err == SGFDX_ERROR_NONE){
//this->statusBar()->showMessage("SetTemplateFormat() Success");
}
else
{
//this->statusBar()->showMessage("SetTemplateFormat() failed. Error = "+ QString::number(err));
}
}

void MainWindow::on_m_RegisterBtn_clicked()
{
if ((m_FetBuf1 == NULL) || (m_FetBuf2 == NULL))
return;

BOOL matched;
DWORD err = SGFPM_MatchTemplate(m_hFPM, m_FetBuf1, m_FetBuf2, SecurityLevel[ui->m_SecureLevel->currentIndex()], &matched);

if ((err == SGFDX_ERROR_NONE) && matched)
{
QFile dFile(ui->uName->text()+".min");
if(dFile.open(QIODevice::ReadWrite))
{
dFile.write((const char *)m_FetBuf1,400);
dFile.write((const char *)m_FetBuf2,400);
dFile.close();
}
DWORD match_score;
err = SGFPM_GetMatchingScore(m_hFPM, m_FetBuf1, m_FetBuf2, &match_score);
this->statusBar()->showMessage("Registration Success : Matching Score ="+ match_score);
}
else{
this->statusBar()->showMessage("Registration Fail");
}

}

ChrisW67
28th May 2012, 05:21
When you reduce the claimed problem to a minimal example you'll quickly find the problem is not Qt:

#include <QtGui>

class MainWindow: public QMainWindow {
Q_OBJECT
public:
MainWindow(QWidget *p = 0): QMainWindow(p) {
QWidget *central = new QWidget(this);
QVBoxLayout *layout = new QVBoxLayout(this);
m_label = new QLabel(this);
m_lineEdit = new QLineEdit(this);
layout->addWidget(m_label);
layout->addWidget(m_lineEdit);
central->setLayout(layout);
setCentralWidget(central);
resize(640, 480);
m_count = 0;
QTimer *t = new QTimer(this);
t->start(1000);
connect(t, SIGNAL(timeout()), SLOT(doit()));
}
public slots:
void doit() {
statusBar()->showMessage("I am a status bar " + QString::number(++m_count));
m_lineEdit->setText("I am a line edit " + QString::number(++m_count));
m_label->setText("I am a label " + QString::number(++m_count));
}
private:
QLabel *m_label;
QLineEdit *m_lineEdit;
int m_count;
};

int main(int argc, char *argv[])
{
QApplication app(argc, argv);
MainWindow m;
m.show();
return app.exec();
}
#include "main.moc"

Did SGFPM_Create() succeed?

yagabey
29th May 2012, 11:01
Thanks Chris, actually i also think that the problem is not Qt. I have written lots of apps like this without any problems before . But i am worrying if some external libraries like this one cause some problems with Qt in rare cases ? If yes, is there any solution. For example i've heard that boost library has some problems when working with Qt. By the way, SGFPM_Create() succeds, no problem with it.

ChrisW67
30th May 2012, 01:20
If the external library is trashing memory there's nothing much can be done other than fix the library.

The reason I asked if SGFPM_Create() succeeds is that if you continue after it failed you may well find the library assuming the handle is correctly initialised and doing odd things to memory outside itself as a result. You don't check the return code in the code you posted but the docs I see are light on that too. Try initialising m_hFPM to zero in the constructor before you call SGFPM_Create().

Also I don't see your MainWindow destructor cleaning up with SGFPM_Terminate(). Perhaps after several unterminated runs the library loses the plot? Does it happen the first time you run it on a freshly booted machine?

yagabey
30th May 2012, 20:23
SGFPM_Create() returns SGFDX_ERROR_NONE , no problem with it. Initialising m_hFPM to 0 didn't make ant difference. The problem occurs any time including fresh boot.

The visual c++ mfc version of the application using the api works without any problem.. Stuck..

d_stranz
31st May 2012, 20:41
For example i've heard that boost library has some problems when working with Qt.

I use the boost templates extensively in my Qt apps (particularly smart pointers and including some difficult ones like boost::graph) and have also used parts of loki. I have never seen any problem or error related to either of these except those due to my own programming mistakes (which I must say occur only very rarely... ;) )

If I were to guess, the problems you might have heard about are probably due to misuse of QObject instances with smart pointer wrappers or containers which do not respect the parent - child ownership and lifetimes used in Qt.

yagabey
2nd June 2012, 08:59
When i change


this->statusBar()->showMessage("The first template is created. Image Quality= "+ img_qlty);

to:


this->statusBar()->showMessage("The first template is created. Image Quality= "+ QString::number(img_qlty));

the problem looks solved. But i dont know why any error or warning isnt given when appending dword to QString, there is no such operator i think. Thanks, anyway...

ChrisW67
2nd June 2012, 10:32
Interesting. I only looked at the specific error message you mentioned, and it has a QString::number() call. Clearly the compiler was doing something with it though: Taking the const char * address and adding img_qlty bytes to it then using that as a string address. So your example string "CreateTemplate() failed. Error = " + 12 was offset by 12 bytes to give "te() failed. Error = ". For large (or negative) values of img_qlty you may find ourself stepping completely out of the intended string and into the next in data section or crashing the program.

I'd be inclined to do this:


QString("The first template is created. Image Quality %1").arg(img_qlty);
//or
tr("The first template is created. Image Quality %1").arg(img_qlty);

as a precaution against the similar errors.