PDA

View Full Version : QDialog, editingFinished, and Cancel Button.



jeffpogo
2nd June 2009, 00:24
I have a form with a lineedit widget that calls a function to validate the data on the signal editingFinished.

... but I do not want the lineedit to be validated if the cancel button is pressed. (I just want cancel to mean "Cancel -- Abort" no data validation.)



connect(this->pushButton_Cancel, SIGNAL(clicked()), this, SLOT(myReject()));
connect(this->lineEdit_DriverCode, SIGNAL(editingFinished()), this, SLOT(checkDriverCode()));




current processing:
Enter invalid data in the lineedit widget.
Press the cancel button. (I think this actually happens after line 3.)
The lineedit widget loses focus and causes the editingFinished signal to be emitted. (checkDriverCode called)
I can not tell the cancel button was pressed from checkDriverCode because the editingFinished is called before the cancel button pressed registers.
Any ideas to help.

Thank you, Jeff.

nish
2nd June 2009, 02:50
i think eventFilter() can help you.


MyDialog::MyDialog(QWidget* p):QDialog(p)
{
....
....
//do not connect the editingFinished() signal
connect(this->pushButton_Cancel, SIGNAL(clicked()), this, SLOT(myReject()));
//connect(this->lineEdit_DriverCode, SIGNAL(editingFinished()), this, SLOT(checkDriverCode()));

//this->pushButton_Cancel->installEventFilter(this);
//this->lineEdit_DriverCode->installEventFilter(this);
qApp->installEventFilter(this);//i think this is better than calling installEventFilter() on every widget
}

bool MyDialog::eventFilter(QObject* o,QEvent* e)
{
static bool focusLostFromLineEdit=false;

//check if we lost focus from lineedit
if(e->type()==QEvent::FocusOut)
{
if(o==this->lineEdit_DriverCode)
focusLostFromLineEdit=true;
else
focusLostFromLineEdit=false;
}

//we got a focusIn in some widget... if the previous widget is lineEdit and the new widget is
// cancel button than do not validate.
if(e->type()==QEvent::FocusIn)
{
if(focusLostFromLineEdit)
{
if(o!=this->pushButton_Cancel)//the focus was lost from lineedit and some other widget got it
checkDriverCode();
focusLostFromLineEdit=false;//just over cautious
}
}

return QDialog::eventFilter(o,e);

}

This is just a quick idea.. please check for errors

Edit: Few problems:-
One problem with this code is that it does not handle the case when you pressed() the cancel button but do not clicked() it. In other words, just press the mouse button on the cancel button but do not release it(moved the mouse in pressed state out of cancel button). :confused:

Second problem is that if you get to cancel button using the Tab key. (this can be handled easily though, just by not placing the lineedit and button next to each other)

Third problem: I have not tested this code:p

jeffpogo
2nd June 2009, 18:22
Thank you for the idea!

Your suggestion was a good idea, but I can not get it to work correcly for the problems you already mentioned.

This problem seems like a common issue and saw others asking similar questions, but no good solutions are posted.

I will try a new design unless someone has other ideas.

Jeff.

shentian
2nd June 2009, 19:29
It depends what you need the validation for:


Don't allow the user to enter invalid values -> Use QValidator
Don't allow the user to click on OK with an invalid value entered. -> Validate on signal QLineEdit::textEdited(QString) and enabled/disable OK button.
Just do the validation after the user clicked on OK. -> Validate on signal QDialog::accepted()


Or did I miss a point?

jeffpogo
2nd June 2009, 19:54
Problem:

The user enters some invalid data in a lineedit and presses the cancel button.

The cancel button should allow the user to abort the dialog entry without complaining about the invalid data in the lineedit.

but ... the lineitem editingFinished signal is triggered before the program knows the cancel button was pressed.

I need a way to tell the slot function called using the editingFinished signal to ignore the validation checks because the cancel button was pressed.

shentian
2nd June 2009, 20:17
I woudn't use the editingFinished signal to validate.

If you want to validate only when the OK button is clicked, do it like this:


MyDialog::MyDialog(QWidget *parent) :
QDialog(parent),
{
// ...
connect(pushButton_OK, SIGNAL(clicked()), this, SLOT(validate()));
connect(pushButton_Cancel, SIGNAL(clicked()), this, SLOT(reject()));
}

void MyDialog::validate()
{
if (lineEdit->text() != "Valid data")
{
QMessageBox::critical(this, tr("Invalid Data"), tr("You entered invalid data"));
return;
}
accept();
}

nish
3rd June 2009, 01:57
Thank you for the idea!

Your suggestion was a good idea, but I can not get it to work correcly for the problems you already mentioned.

This problem seems like a common issue and saw others asking similar questions, but no good solutions are posted.

I will try a new design unless someone has other ideas.

Jeff.

All the problems can be solved by just some hacking here and there... previously you were stuck with the editfinish() signal emiting before the cancel button.. that was solved by eventfilter... now as far as pressed() goes...

i think your problem can be solved by just extending the code a bit more... i can give you some hints..

1. button has a pressed() signal
2. a button subclass can monitor mouseEnter, mousePress, mouseRelease
3. events can be sent back to parent widget
4. you can generate any event (QEvent*) and sent it to any widget.

using subclasses, eventfilter, and lil bit here an there u can overcome the problem... its may take less than a day. but something tells me it is possible.

but i like to tell u that the behaviour you want to achieve is very uncommon and i as a user also do not like it... do it the standard way as suggested by someone before.

jeffpogo
3rd June 2009, 03:02
For now...

I am going with the web page style solution...check all the lineedit fields in the form after the ok button is pressed.

I wanted to only enable the ok button after all the fields had valid data but I will change the logic to enable when all the required fields "are filled-in" and do the database look ups at accept().

Thank you for the help!

nish
3rd June 2009, 03:22
For now...

I am going with the web page style solution...check all the lineedit fields in the form after the ok button is pressed.

I wanted to only enable the ok button after all the fields had valid data but I will change the logic to enable when all the required fields "are filled-in" and do the database look ups at accept().

Thank you for the help!

thats the standard way... !! good luck