PDA

View Full Version : How do i close a buttonless dialog.



geekshlby
12th January 2010, 01:22
Good day.

I am opening a dialog that contains no buttons while the OS performs the task I have requested it to do.

I am using a QMessageBox to confirm the action is to be performed with an OK and Cancel button.

If OK is clicked a new form is opened up to serve as visual notification that the requested action is being completed i.e Hey, I'm doing this... be patient.

I would like for this second form to be closed once the OS has finished its task.

I can not figure out out to simply close the second form.

I am opening the second form with:


void MainWindow::on_actionPurge_Cache_triggered()
{
QMessageBox purgeMsgBox;
purgeMsgBox.setWindowTitle("Purge Cache Request");
purgeMsgBox.setText("Are you sure you would like to purge the local cache?");
purgeMsgBox.setStandardButtons(QMessageBox::Ok | QMessageBox::Cancel);
purgeMsgBox.setDefaultButton(QMessageBox::Cancel);
int purgeReply = purgeMsgBox.exec();
switch (purgeReply)
{
case QMessageBox::Cancel:
qDebug() << "We Clicked cancel";
break;
case QMessageBox::Ok:
qDebug() << "We clicked ok";
purge dialog(this);
if (dialog.exec() != QDialog::Accepted)
return;
break;
}
}

Am I opening the second form "purge" incorrectly?
The second form simply removes some local files, and should close once completed. Yet I can not figure out how to close the form.

Once the second form is instantiated I am calling the following function to remove some local files:

void purge::purgeCache()
{
qDebug() << "We are in function to purge cache";
QString cacheLocation = "/var/cache/lxc";
QString removeProgram = "/bin/rm";
QStringList arguements;
arguements << "-rf" << cacheLocation;
QProcess *removeProcess = new QProcess(this);
removeProcess->start(removeProgram, arguements);
removeProcess->waitForFinished(-1);
}

Do I create a signal to indicate the purge action is complete, and connect it to the close slot?

Your help is appreciated :)

bood
12th January 2010, 01:57
You can just call the "accept()" slot after purgeCache is finished.
But as a reminder, calling it from the constructor could possibly leads to a failure coz the dialog is not created yet at that time.

geekshlby
12th January 2010, 02:38
As you suggested, I called the accept() slot after the purgeCache function is completed.

However, the form does not close.

bood
12th January 2010, 02:59
Need more code to see...

geekshlby
12th January 2010, 04:12
Thank you for your assistance.
This is my first c++ program so please be patient with me :)

Please forgive the long post. The following is a small app that I am using for testing before I add it into the real app.

First up is mainwindow.cpp


#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "purge.h"
#include <QtGui>
#include <QProcess>
#include <QTimer>
#include <QtDebug> // don't forget to remove when we are done
//#include <QDialog>

MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
QTimer *timer = new QTimer(this);
connect( timer, SIGNAL(timeout()), SLOT(listContainers()) );
timer->start(5000);
listContainers(); // implicitly call the function to display the containers
// instead of waiting for the timer
}

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

void MainWindow::changeEvent(QEvent *e)
{
QMainWindow::changeEvent(e);
switch (e->type()) {
case QEvent::LanguageChange:
ui->retranslateUi(this);
break;
default:
break;
}
}

// List containers registered with LXC. We use stdout from lxc-ls to grab the container name
// and then we use stdout from lxc-info to determine the status of the container.
void MainWindow::listContainers()
{
ui->treeWidget->header()->setResizeMode(0, QHeaderView::Stretch);
ui->treeWidget->header()->setResizeMode(1, QHeaderView::Stretch);
ui->treeWidget->clear();
QString listProgram = "/usr/bin/lxc-ls";
QProcess *listProcess = new QProcess( this );
listProcess->start(listProgram);
listProcess->waitForFinished(-1);
QString listOutput;
do
{
item = new QTreeWidgetItem;
listOutput = listProcess->readLine();
listOutput.chop(1);
if (listOutput.isEmpty())
break;
QString infoProgram = "/usr/bin/lxc-info";
QStringList arguements;
arguements << "-n" << listOutput;
QProcess *infoProcess = new QProcess( this );
infoProcess->start(infoProgram, arguements);
infoProcess->waitForFinished(-1);
QString infoOutput = infoProcess->readLine();
// The output of lxc-info includes the container name as well as the status,
// but the status is in all caps.
// Grab just the status and then beautify it.
infoOutput.chop(1);
if (infoOutput.contains("RUNNING", Qt::CaseInsensitive))
infoOutput = "Running";
if (infoOutput.contains("STOPPED", Qt::CaseInsensitive))
infoOutput = "Shutoff";
if (infoOutput.contains("FROZEN", Qt::CaseInsensitive))
infoOutput = "Paused";
item->setText(0, listOutput);
item->setText(1, infoOutput);
ui->treeWidget->addTopLevelItem(item);
}
while (listOutput != NULL);
};

// Use a messagebox to confirm we want the cache removed and then
// display a new form until the cache removal process is complete.
void MainWindow::on_actionPurge_Cache_triggered()
{
qDebug() << "Displaying confirmation message";
QMessageBox purgeMsgBox;
purgeMsgBox.setWindowTitle("Purge Cache Request");
purgeMsgBox.setText("Are you sure you would like to purge the local cache?");
purgeMsgBox.setStandardButtons(QMessageBox::Ok | QMessageBox::Cancel);
purgeMsgBox.setDefaultButton(QMessageBox::Cancel);
int purgeReply = purgeMsgBox.exec();
switch (purgeReply)
{
case QMessageBox::Cancel:
qDebug() << "We Clicked cancel";
break;
case QMessageBox::Ok:
qDebug() << "We clicked ok";
purge dialog(this);
dialog.exec();
if (dialog.exec() != QDialog::Accepted)
return;
break;
}
}

Next up is mainwindow.h:

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include <QTreeWidget>

namespace Ui {
class MainWindow;
}

class MainWindow : public QMainWindow {
Q_OBJECT
public:
MainWindow(QWidget *parent = 0);
~MainWindow();

protected:
void changeEvent(QEvent *e);

private:
Ui::MainWindow *ui;
QTreeWidgetItem *item;

private slots:
void on_actionPurge_Cache_triggered();
void listContainers();

};

#endif // MAINWINDOW_H

Next we have the window that I can't seem to close.
purge.cpp

#include "purge.h"
#include "ui_purge.h"
#include <QtDebug>
#include <QProcess>

purge::purge(QWidget *parent) :
QDialog(parent),
ui(new Ui::purge)
{
ui->setupUi(this);
purgeCache();
qDebug() << "we are no longer in the purgeCache function";

}

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

void purge::changeEvent(QEvent *e)
{
QDialog::changeEvent(e);
switch (e->type()) {
case QEvent::LanguageChange:
ui->retranslateUi(this);
break;
default:
break;
}
}

// Use QProcess to monitor the removal of the local cache and wait until the cache is removed
// until we exit the function
void purge::purgeCache()
{
qDebug() << "We are in function to purge cache";
QString cacheLocation = "/var/cache/lxc";
QString removeProgram = "/bin/rm";
QStringList arguements;
arguements << "-rf" << cacheLocation;
QProcess *removeProcess = new QProcess(this);
removeProcess->start(removeProgram, arguements);
removeProcess->waitForFinished(-1);
qDebug() << "purge process has completed";
close();
}

And the header for purge:

#ifndef PURGE_H
#define PURGE_H

#include <QDialog>

namespace Ui {
class purge;
}

class purge : public QDialog {
Q_OBJECT
public:
purge(QWidget *parent = 0);
~purge();

protected:
void changeEvent(QEvent *e);

private:
Ui::purge *ui;
void purgeCache();

};

#endif // PURGE_H

And lastly, main.cpp:

#include <QtGui/QApplication>
#include "mainwindow.h"

int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
w.show();
return a.exec();
}

bood
12th January 2010, 04:58
Well, I think I've told you not to call the accept slot in the constructor in my last reply...
try calling the purgeCache function in qwidget.html#showEvent

geekshlby
12th January 2010, 06:01
Updated mainwindow.cpp to show the form with:

purge dialog(this);
dialog.exec()

Updated purge.h to:


protected:
void changeEvent(QEvent *e);
void showEvent(QShowEvent *);
void closeEvent(QCloseEvent *e);


Updated purge.cpp to make a call to purgeCache function in the showEvent:


void purge::showEvent(QShowEvent *)
{
qDebug() << "in the show event";
purge::purgeCache();
}


Updated purge.cpp to output when the closeEvent occurs:

void purge::closeEvent(QCloseEvent *e)
{
qDebug() << " in the close event";
}

I can clearly see the call to close the window, yet it does not close.
Also, now that I am calling the purgeCache function from the showEvent, and the purgeCache function includes "close()" the form will not close whatsoever. Every time I click the close button on the window manager, it outputs "in the close event", so I show to be in the close handler, yet it doesn't happen, and I have to kill the app.

Once again, I apprecaite your input :)

geekshlby
12th January 2010, 06:29
I had to cheat to make it work the way I wanted.

I added a check in the changeEvent:

if (strPurged == "True")
close();

At the end of the purgeCache function I assign True to strPurged.

I noticed that even though I enter the closeEvent and the window wouldn't close, that a call was made to the changeEvent since closing is a changeEvent.

Although this is a bit hackish it works. If there is a better way please let me know.

bood
12th January 2010, 07:11
After you override those virtual function, you should call the original version to make it do original things. e.g.


void purge::closeEvent(QCloseEvent *e)
{
qDebug() << " in the close event";
QDialog::closeEvent(e);
}

geekshlby
12th January 2010, 07:37
Will try thanks for the help.

MarkoSan
12th January 2010, 07:39
Create a timer with some timeout constants and then connect its timeout() signal to window close slot.

geekshlby
12th January 2010, 08:19
Thanks for the reply MarkoSan.

I thought about the timer idea, but since I will be removing local files, it would be difficult to determine how long to wait for the timeout. I could run some test with a stopwatch, but the cache size on disk will change depending on what is cached.

I do however, greatly appreciate the idea :)

For the moment, I have it working even if it is a bit on the hackish side.

MarkoSan
12th January 2010, 08:26
Hmm, then create a list of files to be deleted, from every entry create a qfile object and then call QFile::remove() method. This method returns bool (true if delete was sucessfull, false if faled, I think). The described result is added to another QList (resultList) and if every entry in result is true, close window, otherwise ...