I'm having an issue inheriting from QFileDialog and controlling the enabling/disabling of the Open button as needed. I've read a lot of posts online, but no one seems to be having my problem. I've tried a number of things on my own, but don't seem to be working this one out.
What I'm tasked with:
I need to be able to keep the inherited dialog's Open button disabled (unclickable) as long as the selection is not a file or not of a specified extension (which is partially handled by filtering, though All Files is an option), and also as long as the content of the selected file is not of the correct proprietary format (which is where my issue shows up). This means when the user selects a file from the list, I read a format specifier from the head of the file, and need to keep the Open button disabled as long as the format is not correct for the current run of the application.
I am very much trying to avoid a user having to get a separate "Are you sure?" dialog. I will show an error in the dialog itself, and want to only enable the Open button when a file with the correct type and format is selected.
What I've done:
I have created a class called MyFileDialog (code shown below - name changed to protect the innocent) which inherits QFileDialog and connects the QFileDialog::currentChanged() signal to a local slot function fileSelectionChanged(). The slot calls a helper function which opens and checks the file for valid format, and returns a bool for validity. The slot receives this return value and grabs the Open button (retrieved from the file dialog button box and stored at construction time) and sets the Open button's enabled state to that bool value.
When I run the program and open the file dialog and click on a file that does not have a valid format, the Open button remains enabled which is incorrect, but when I debug through the given code, I see that I do have the correct button (the text of the button shows as "&Open"), and that the button was set enabled = false (both tests shown in the code below).
I assume that there is a timing issue here, so that I'm responding to a signal, and then maybe sometime after I respond the button is reset to enabled = true by the QFileDialog itself. Not sure how to get passed this if that's the case.
I also tried overriding the mouseReleaseEvent() (code not shown). I get into this event handler when I click anywhere in the QFileDialog other than sub-widgets. If I click on any sub-widget (such as the list view, the folder drop-down, the file name text box, or any of the buttons) I don't get into the event handler at all. It seems that QFileDialog is accepting and not propagating the event. Does anybody see a way around this? I really need this to work as described.
The following code has been fully tested before submitting:
// Class declaration for MyFileDialog
#pragma once
#include <qfiledialog.h>
{
Q_OBJECT
public:
//! \brief CTOR
//! \brief DTOR
virtual ~MyFileDialog() {}
protected slots:
virtual void fileSelectionChanged(const QString& file);
protected:
bool formatCheck(const QString& file);
private:
};
// Class declaration for MyFileDialog
#pragma once
#include <qfiledialog.h>
class MyFileDialog : public QFileDialog
{
Q_OBJECT
public:
//! \brief CTOR
MyFileDialog(QWidget* parent, QString directory);
//! \brief DTOR
virtual ~MyFileDialog() {}
protected slots:
virtual void fileSelectionChanged(const QString& file);
protected:
bool formatCheck(const QString& file);
private:
QPushButton* myOpenButton;
};
To copy to clipboard, switch view to plain text mode
// Class definition for MyFileDialog
#include "MyFileDialog.h"
#include "qdialogbuttonbox.h"
#include "qpushbutton.h"
: QFileDialog(parent, tr
("Load Correct Format"), startdir
),
myOpenButton(0)
{
// for an Open File dialog, get the Open button for later use
{
if (button_box) {
// the following line shows that I've retrieved
// a button with the text: "&Open".
QString buttonText
= myOpenButton
->text
();
}
}
connect(this, SIGNAL(currentChanged(const QString&)), this, SLOT(fileSelectionChanged(const QString&)));
}
void MyFileDialog::fileSelectionChanged(const QString& file)
{
if (fileInfo.exists())
{
if (myOpenButton) {
bool isvalid = formatCheck(file);
myOpenButton->setEnabled(isvalid);
// the following two lines for testing. Shows the
// button's text is "&Open" and the enabled state is
// the same as the value of the "isvalid" variable.
QString buttonText
= myOpenButton
->text
();
bool enabled = myOpenButton->isEnabled();
}
}
}
bool MyFileDialog::formatCheck(const QString& file)
{
// opens the file and returns the boolean result
// of the format check.
// true leaves the button enabled; false also leaves the button enabled
//bool result = true;
bool result = false;
return result;
}
// Class definition for MyFileDialog
#include "MyFileDialog.h"
#include "qdialogbuttonbox.h"
#include "qpushbutton.h"
MyFileDialog::MyFileDialog(QWidget* parent, QString startdir)
: QFileDialog(parent, tr("Load Correct Format"), startdir),
myOpenButton(0)
{
// for an Open File dialog, get the Open button for later use
if (acceptMode() == QFileDialog::AcceptOpen)
{
QDialogButtonBox *button_box = findChild<QDialogButtonBox *>();
if (button_box) {
myOpenButton = (QPushButton *)button_box->button(QDialogButtonBox::Open);
// the following line shows that I've retrieved
// a button with the text: "&Open".
QString buttonText = myOpenButton->text();
}
}
connect(this, SIGNAL(currentChanged(const QString&)), this, SLOT(fileSelectionChanged(const QString&)));
}
void MyFileDialog::fileSelectionChanged(const QString& file)
{
QFileInfo fileInfo(file);
if (fileInfo.exists())
{
if (myOpenButton) {
bool isvalid = formatCheck(file);
myOpenButton->setEnabled(isvalid);
// the following two lines for testing. Shows the
// button's text is "&Open" and the enabled state is
// the same as the value of the "isvalid" variable.
QString buttonText = myOpenButton->text();
bool enabled = myOpenButton->isEnabled();
}
}
}
bool MyFileDialog::formatCheck(const QString& file)
{
// opens the file and returns the boolean result
// of the format check.
// true leaves the button enabled; false also leaves the button enabled
//bool result = true;
bool result = false;
return result;
}
To copy to clipboard, switch view to plain text mode
// main() function instantiating and exec'ing MyFileDialog
#include "MyFileDialog.h"
int main(int argc, char *argv[])
{
MyFileDialog d(parent, "@C:\tmp");
d.exec();
}
// main() function instantiating and exec'ing MyFileDialog
#include "MyFileDialog.h"
int main(int argc, char *argv[])
{
MyFileDialog d(parent, "@C:\tmp");
d.exec();
}
To copy to clipboard, switch view to plain text mode
Bookmarks