PDA

View Full Version : closing a dialog



chrisb123
24th October 2009, 11:36
I made a plasma app that opens a settings dialog
I'm trying to close a dialog with a close button
If I open it like this


void test::settings() {
myQtApp *dialog = new myQtApp;
dialog->show();
}


How can i close it like this


myQtApp::myQtApp(QWidget *parent)
{
setupUi(this);
connect( pushButton_close, SIGNAL( clicked() ), this, SLOT( close() ) );
}
void myQtApp::close() {
QMessageBox::about(this,"close",
"this shold close the dialog");
}

axeljaeger
24th October 2009, 13:12
First, you are leaking memory because you create a QDialog on the heap without a proper parent. Don't do this, read something about object trees in Qt:

http://doc.trolltech.com/4.5/objecttrees.html

Then remove your own implementation of close because there is already one in QDialog. I am pretty sure that you showing your message box, you overwrite the already provided close-slot.

chrisb123
24th October 2009, 13:37
i found out if use
this->hide();it will close, however I should delete the close function
Sorry my programming skills are limited, I still dont quite understand
I do a lot of copy, paste, modify with-out understanding whats really going on
If I remove the "QWidget *parent" is that better?
The application still works as expected

squidge
24th October 2009, 13:51
If you don't use parent you should use a model dialog so you can delete the dialog when the model returns

chrisb123
24th October 2009, 14:16
Don't you just hate crappy programmers like me...
I have a
target::target(QObject *parent, const QVariantList &args)
: Plasma::Applet(parent, args),
it contains parent, again, which I don't understand.

axeljaeger
24th October 2009, 14:29
The point is:

You usually create a tree of objects. If you delete an object, all its childs are deleted as well. So usually you do not have to care about deleting most of the objects because they will be deleted by their parent object.

Also if you create an object on the stack (without new and not as a pointer) it will be deleted when going "out of scope", e.g. when the program goes out of the "block" in which the object was created.

Your dialog was not created on the stack but on the heap, it did not got a parent pointer and you do not delete it yourself. So it will not be deleted at all.

I'm a bit picky about this because at some other forum, a lot of people completely ignoring this fundamental feature of Qt. So everytime I see someone now who does not use proper parent child, some red lights turn on here.

chrisb123
24th October 2009, 14:38
I understand I should be correctly creating child objects of the parent
I dont understand how do write code so the object is a child of the parent
Like I said I barely understand what I'm doing
is there another tutorial I can read relating to this?

axeljaeger
24th October 2009, 15:04
Pass some other QWidget as the first argument to the constructor of myQtApp.
e.g not myQtApp but myQtApp(this).

chrisb123
24th October 2009, 15:43
doing this

myQtApp::myQtApp(this)
i get the error
expected unqualified-id before 'this'

axeljaeger
24th October 2009, 16:06
No no, like this:



void test::settings() {
myQtApp *dialog = new myQtApp(this);
dialog->show();
}


But you see that everytime you call the settings slot, a new instance is created and only released when you delete "this". Do it rather like this:



void test::settings() {
myQtApp dialog(this);
dialog.show();
} // dialog is deleted now.

chrisb123
24th October 2009, 18:00
neither work
i need to change the header, to what i have no idea

axeljaeger
24th October 2009, 18:12
Well, without knowing the error message we cannot help.

chrisb123
24th October 2009, 18:45
the error i get

test.cpp:112: error: no matching function for call to 'myQtApp::myQtApp(test* const)'
test.cpp:65: note: candidates are: myQtApp::myQtApp()
test.h:79: note: myQtApp::myQtApp(const myQtApp&)

axeljaeger
24th October 2009, 18:47
You need your constructor to accept a QObject parent as argument. See the signature of QDialog's constructor.

chrisb123
24th October 2009, 19:16
I dont get it ??? I'm lost

So I should not open a new dialog like this


void test::web() {
QWidget *web = new webapp();
web->show();


and adding a webkit widget to this new dialg like this is incorrect


webapp::webapp(){
QWebView *view = new QWebView(this);
view->show();
}

axeljaeger
24th October 2009, 19:36
I dont get it ??? I'm lost
So I should not open a new dialog like this


void test::web() {
QWidget *web = new webapp();
web->show();


Right, because web will never be freed again and you lose memory. Also the dialog does not have a parent that is used for other purposes, for example, center the dialog above the mainwindow. Even if you would have passed a proper parent, the dialog would be created again and again and you would have a lot of instances of it in memory. So either create it on the stack or save the pointer to that dialog so that the next time you do not have to create a new one.




and adding a webkit widget to this new dialg like this is incorrect


webapp::webapp(){
QWebView *view = new QWebView(this);
view->show();
}
No, this is correct, because you pass a proper parent to the webview. But make the webview's constructor have a single argument, a QWidget so you can also pass a proper parent to that:



webapp::webapp(QWidget* parent) : QWidget(parent) { // I assume here that webapp directly inherits QWidget
QWebView *view = new QWebView(this);
view->show();
}

You will also have to adjust your header file to have that argument to the constructor.

chrisb123
24th October 2009, 20:11
ok, how should the function create the new dialog
and what should the header for it look like?
and I also assume that webapp directly inherits QWidget

class webapp : public QWidget

{
Q_OBJECT
public:
webapp(QWidget* parent);
~webapp();
private:
QWebView *view;

protected:
void resizeEvent(QResizeEvent *event);

};

axeljaeger
24th October 2009, 20:52
Header looks OK. The only thing I do not like is a lowercase class name because usually the first letter in the classname is uppercase.

Regarding the dialog: Create the constructor in the constructor, save the pointer in a member variable and then only call show on it in your method.

chrisb123
24th October 2009, 22:08
Regarding the dialog: Create the constructor in the constructor, save the pointer in a member variable and then only call show on it in your method.
how do i save the pointer in a member variable?
i assume you mean "web"
and how do i only call show in the method?
I want the widget to display immediately after selecting the menu item

so it should like this
the slot function gets called from a menu item

void test::web() {
webapp::webapp(*parent);

which calls this

webapp::webapp(QWidget* parent) {
QWidget *web = new webapp(this);
web->resize(1000, 350);
web->show();
view = new QWebView(this);
view->show();
}
It doesnt work, the program runs but the new widget doesnt display

axeljaeger
24th October 2009, 22:18
Yes, because both widget gets "this" as parent. If you want your webview to be shown inside "web", pass web as the parent to the webview.

Then do not use QWidget as baseclass for web but QDialog so it will be shown in a new window on the screen.

chrisb123
24th October 2009, 22:39
Still does not bring up a new dialog


class webapp : public QDialog {
Q_OBJECT
public:
webapp(QDialog* parent);
.............
void test::web() {
webapp::webapp(*parent);
}
webapp::webapp(QDialog* parent) {
QDialog *web = new webapp(this);
web->show();
view = new QWebView(web);

axeljaeger
24th October 2009, 23:02
Please find the attached example.

chrisb123
24th October 2009, 23:38
thanks, i'll have to study this tonight at work

chrisb123
25th October 2009, 10:29
I dont have main because it is a plasma widget
It's setup like the example you gave me


mum::mum(QObject *parent, const QVariantList &args)
: Plasma::Applet(parent, args),
m_svg(this),
m_icon("document"),
m_webapp(NULL),
m_setapp(NULL)
{
m_webapp = new webapp(this);
m_setapp = new setapp();
}
void mum::settings() {
m_setapp->show();

}
void mum::web() {
m_webapp->show();
}


setapp works as expected
webapp gives the following error


mum.cpp: In constructor 'mum::mum(QObject*, const QVariantList&)':
mum.cpp:30: error: no matching function for call to 'webapp::webapp(mum* const)'
webapp.h:33: note: candidates are: webapp::webapp(QWidget*)

axeljaeger
25th October 2009, 10:39
Looks like Plasma::Applet does not inherit QWidget. OK, then you can't have that as parent, just pass NULL as parent and delete webapp in your destructor.

chrisb123
25th October 2009, 11:18
how would i make it show the exisitng m_webapp from m_setapp?

axeljaeger
25th October 2009, 11:32
Either create m_webapp inside m_setapp or have m_setapp emit a signal and connect that to the show-slot of m_webapp.

chrisb123
25th October 2009, 12:11
Either create m_webapp inside m_setapp or have m_setapp emit a signal and connect that to the show-slot of m_webapp.
I'll have to read up on that

I want the widget to not create the web app utill its called for e.g.

void mum::web() {
if ( ! m_webapp ) {
m_webapp = new webapp(NULL);
}
m_webapp->show();
}
How do I destroy m_webapp after closing it?

axeljaeger
25th October 2009, 12:36
Just delete it in the destructor. (once in the lifetime of your application).

chrisb123
25th October 2009, 13:36
delete it like this?

webapp::~webapp(){
delete this;
}
doesnt seem to delete m_webapp

also emitting the signal and connecting to it
what am I doing wrong?


m_setapp = new SetApp(NULL);
connect(m_setapp, SIGNAL(showeb()), this SLOT(web()));
}
void mum::web() {
m_webapp->show();
}
..................
connect( pushButton_node, SIGNAL( clicked() ), this, SLOT( node() ) );
}
void SetApp::node() {
emit showeb(); //this pushbutton code work

or can I do I connect to a slot in a different class?

axeljaeger
25th October 2009, 13:42
delete this in a destructor is an infinite recursion.

delete calls the destructor. It is basically calling a method within itself. This will not work.


Regarding your signal & slots connection: What does not work? Do you get any warnings in the console? Do all connect-statements return true?

chrisb123
25th October 2009, 13:58
delete this in a destructor is an infinite recursion.

delete calls the destructor. It is basically calling a method within itself. This will not work.

closing it does not destroy it, it just hides it



Regarding your signal & slots connection: What does not work? Do you get any warnings in the console? Do all connect-statements return true?
syntax error, i missed the , after this
it works as expected

axeljaeger
25th October 2009, 14:09
closing it does not destroy it, it just hides it
What do you want to tell me?

chrisb123
25th October 2009, 16:24
Think I've worked it out
I want the plasmoid to display a seperate dialog and QWebView when requested.
I dont want the QWebView to be always loaded but hidden

So currently it does the following, From my understadning

1. when the plasmoid starts it creates the constructor which just creates the dialog
2. when i select the item to show the dialog I use showEvent to create a QWebView and display the page.
3. When I close the dialog I use closeEvent to delete the QWebView

What can I use as profiling software?

axeljaeger
25th October 2009, 16:30
Why on earth do you want to create the webView in the showEvent and destroy it when it gets closed? Just do it like anyone else: Create it in the constructor let it Qt destroy when necessary. Dont try to be too clever, keep it simple stupid, trust Qt.

You can use either valgrind or oprofile for profiling. But if there is already need for profiling, then your computer has a problem.

RSX
25th October 2009, 18:08
I made a plasma app that opens a settings dialog
I'm trying to close a dialog with a close button
If I open it like this


void test::settings() {
myQtApp *dialog = new myQtApp;
dialog->show();
}


How can i close it like this


myQtApp::myQtApp(QWidget *parent)
{
setupUi(this);
connect( pushButton_close, SIGNAL( clicked() ), this, SLOT( close() ) );
}
void myQtApp::close() {
QMessageBox::about(this,"close",
"this shold close the dialog");
}


Didn't read up all if you actually fixed your problem already but:

myQtApp *dialog = new myQtApp(this);
dialog->setAttribute(Qt::WA_DeleteOnClose);
dialog->show();

this would solve your problem with deleting dialog.

chrisb123
26th October 2009, 13:07
Didn't read up all if you actually fixed your problem already but:

myQtApp *dialog = new myQtApp(this);
dialog->setAttribute(Qt::WA_DeleteOnClose);
dialog->show();

this would solve your problem with deleting dialog.

That works but how do I test if dialog has been deleted or not, I only want to have one created at any one time

jano_alex_es
26th October 2009, 14:15
I think it's deleted when you close the dialog. Qt uses to do a lot of hard work for you ;)

Well, if so, you can delete it manually.

myQtApp *dialog = new myQtApp(this);
dialog->setAttribute(Qt::WA_DeleteOnClose);
dialog->show();
delete dialog;
dialog = 0;

What I do is to create the dialog on the stack. So it will be deleted for sure when it's out of scope. But I do it with small and temporary dialogs.


myQtApp dialog(this);
dialog.setAttribute(Qt::WA_DeleteOnClose);
dialog.show();

chrisb123
26th October 2009, 17:06
My application is a plasma widget so 99.99% of the time its just the one widget, there is no reason to have anything else just waiting, hidden, invisible or not shown.

When I use this code

m_setapp = new SetApp(this);
I get this error while compiling

mum.cpp: In member function 'void mum::settings()':
mum.cpp:75: error: no matching function for call to 'SetApp::SetApp(mum* const)'
myqtapp.h:34: note: candidates are: SetApp::SetApp(QWidget*)
myqtapp.h:29: note: SetApp::SetApp(const SetApp&)
But this works ok

m_setapp = new SetApp(NULL);

From what I can tell it's not deleted when it's closed, I have to manually delete it when its closed, then create it again when required

axeljaeger
27th October 2009, 06:29
Right, you have to delete it yourself when you close the application.

But again: Dont try to be to clever. Get your application up and running and dont bother too much in saving memory when you are not know what you are actually doing. Keeping the dialog in memory will not hurt very much. I'd keep it there so it gets shown faster the second time I open it.

chrisb123
27th October 2009, 12:37
thanks for your help, its been useful
I still need to learn c++ as object oriented programming is new to me
As for my application, it does what is needed thats why Ive moved onto improving it