PDA

View Full Version : How do I make my own QDialog working like for example QFileDialog



Randulf
30th May 2007, 09:00
Hi!!

I have an application where i can import raw videofiles and make some transformations on it.
When I am done I would want to open up a QDialog so that the user can specify some settings when exporting the sequence and when the user press the export button the sequence will be processed and exported. But I would want to keep it simple, i.e all this should be made in the same method with no connections like for example a QFileDialog.

I have made a new class that inherits from QDialog but I there must be some thing wrong.
When i call myDialog->exec() the dialog pops up but the code in the mainwindow contiues to execute.

I want the program to wait so that the user can make his choises in the dialog and when the ok button is pressed i can read out what settings was made and start export.
Kind of like this:


MyDialog myDialog = new MyDialog(this);
QStringList settings = myDialog->exec();

or


MyDialog myDialog = new MyDialog(this);
myDialog->exec();
QStringList settings = myDialog->getSettings();


When I use QFileDialog it possible to do like:

QString file = QFileDialog::getSaveFileName(.........

This is how I do it now:

void MainWindow::exportSequence()
{
// open a dialog for choosing export settings
MyDialog *md = new MyDialog(this);
md->exec();
qDebug() << esw->getSettings();
//start exporting video
.....

MyDialog:

class MyDialog: public QDialog
{
Q_OBJECT

public:
MyDialog(QWidget *parent=0);

QStringList getSettings() {return settings;}
public slots:
int exec();
void done(int val);
void accept();
void reject();
private:
QStringList settings;
QPushButton *exportButton;
QPushButton *cancelButton;
.....
Lots of buttons and other stuff
.....
};

MyDialog::MyDialog(QWidget *parent) : QDialog(parent)
{


setModal(true);
setFocusPolicy(Qt::StrongFocus);
setFocus();
......
exportButton = new QPushButton(tr("Export"));
connect(exportButton, SIGNAL(clicked()), this, SLOT(accept()));
cancelButton = new QPushButton(tr("Cancel"));
connect(cancelButton, SIGNAL(clicked()), this, SLOT(reject()));
.....
}
int MyDialog::exec()
{
activateWindow();
this->show();
return 1;
}
void MyDialog::done(int val)
{
printf("done()\n");
}

void MyDialog::accept()
{
settings << "setting1" << "setting2" << "ect";
printf("Accept.\n");
this->hide();
}
void ExportSequenceWidget::reject()
{
settings.clear();
printf("Reject.\n");
this->hide();
}


I have been looking at the examples but I can't really figure out how to do this.
Please help me solve this.
Many thanks.
//Nils

marcel
30th May 2007, 09:08
What do you mean when you say the code in main window continues? That is not possible...
Have you tested this in debug?
Do you have other threads running?

Anyway, exec() returns a code that specifies if the user pressed OK or cancel. So you should test for that ( provided that you have OK and cancel buttons ).

regards

Randulf
30th May 2007, 09:21
What do you mean when you say the code in main window continues? That is not possible...
Have you tested this in debug?
Do you have other threads running?


I know I thougt it sholdn't, I have no other threads.
But if do like this using the code above.


int r = esw->exec();
qDebug() << r;
qDebug() << esw->getSettings();

printout is:
1
()
Accept.


Anyway, exec() returns a code that specifies if the user pressed OK or cancel. So you should test for that ( provided that you have OK and cancel buttons ).


I have only impelemented two buttons and connected them to accept and reject slots. Is that enough?

But....Ah...hmmm..."show() returns control to the caller immediately". Maybe I shouldn't use show() but how do I tell it to be visible?

marcel
30th May 2007, 09:23
Oh, that's because in your exec() implementation you call show() :). I missed that.
You must call QDialog::exec().

Regards

jpn
30th May 2007, 09:26
MyDialog::exec() is incorrect. First of all, QDialog::exec() is not virtual so it might be a better idea to rename the method to avoid confusion if you even need a method like that at all. I'd suggest removing it and using QDialog::exec() which should be sufficient for you. QDialog::exec() starts an event loop which blocks while the dialog is open.

The static convenience methods of various QDialog subclasses work more or less like this:


class MyDialog : public QDialog
{
public:
static QString doSomething(QWidget* parent = 0);

private:
QString info;
};

QString MyDialog::doSomething(QWidget* parent)
{
MyDialog dialog(parent);
if (dialog.exec() == QDialog::Accepted)
return dialog.info;
return QString();
}

// usage:
QString blaa = MyDialog::doSomething();
if (!blaa.isNull())
{
// dialog was accepted, blaa contains the info
}

marcel
30th May 2007, 09:29
First of all, QDialog::exec() (http://doc.trolltech.com/latest/qdialog.html#exec) is not virtual
exec() is a slot in QDialog, therefore it is virtual.

But yes, you are right, it is better to use QDialog::exec directly and won't make any difference in this case.

Regards

wysota
30th May 2007, 09:35
exec() is a slot in QDialog, therefore it is virtual.
Only when called as a slot.

Randulf
30th May 2007, 09:37
Thanks a lot for the help and tips!!
Got it working now.
Removed exec(), accept(), reject() and done().

Now I can just


int r = myDialog->exec()
if(r==1)
QStringList settings = myDialog->readSettings()
delete myDialog


Thanks again!!!

marcel
30th May 2007, 09:38
Only when called as a slot.
Yes. Damn it!:)

wysota
30th May 2007, 09:57
Yes. Damn it!:)
It doesn't have to be virtual to reimplement and use it of course... Virtuality is only needed when something else calls the method.

jpn
30th May 2007, 10:03
It doesn't have to be virtual to reimplement and use it of course... Virtuality is only needed when something else calls the method.
True, but it's still a bad practice to shadow non-virtual methods. ;)

wysota
31st May 2007, 01:11
True, but it's still a bad practice to shadow non-virtual methods. ;)

"It depends" :) I don't see anything improper in reimplementing QDialog::exec() :) I know it's possible that someone will want to call it after casting to QDialog, but hey! let's try our luck :) Of course it's better to avoid such risks...