Results 1 to 5 of 5

Thread: QFileDialog: Enable/Disable "Open" button in inherited class not working

  1. #1
    Join Date
    Oct 2009
    Posts
    38
    Qt products
    Qt4
    Platforms
    MacOS X Unix/X11 Windows Symbian S60

    Unhappy QFileDialog: Enable/Disable "Open" button in inherited class not working

    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:

    Qt Code:
    1. // Class declaration for MyFileDialog
    2.  
    3. #pragma once
    4.  
    5. #include <qfiledialog.h>
    6.  
    7. class MyFileDialog : public QFileDialog
    8. {
    9. Q_OBJECT
    10.  
    11. public:
    12. //! \brief CTOR
    13. MyFileDialog(QWidget* parent, QString directory);
    14.  
    15. //! \brief DTOR
    16. virtual ~MyFileDialog() {}
    17.  
    18. protected slots:
    19. virtual void fileSelectionChanged(const QString& file);
    20.  
    21. protected:
    22. bool formatCheck(const QString& file);
    23.  
    24. private:
    25. QPushButton* myOpenButton;
    26. };
    To copy to clipboard, switch view to plain text mode 

    Qt Code:
    1. // Class definition for MyFileDialog
    2.  
    3. #include "MyFileDialog.h"
    4. #include "qdialogbuttonbox.h"
    5. #include "qpushbutton.h"
    6.  
    7. MyFileDialog::MyFileDialog(QWidget* parent, QString startdir)
    8. : QFileDialog(parent, tr("Load Correct Format"), startdir),
    9. myOpenButton(0)
    10. {
    11. // for an Open File dialog, get the Open button for later use
    12. if (acceptMode() == QFileDialog::AcceptOpen)
    13. {
    14. QDialogButtonBox *button_box = findChild<QDialogButtonBox *>();
    15. if (button_box) {
    16. myOpenButton = (QPushButton *)button_box->button(QDialogButtonBox::Open);
    17.  
    18. // the following line shows that I've retrieved
    19. // a button with the text: "&Open".
    20. QString buttonText = myOpenButton->text();
    21. }
    22. }
    23.  
    24. connect(this, SIGNAL(currentChanged(const QString&)), this, SLOT(fileSelectionChanged(const QString&)));
    25. }
    26.  
    27. void MyFileDialog::fileSelectionChanged(const QString& file)
    28. {
    29. QFileInfo fileInfo(file);
    30. if (fileInfo.exists())
    31. {
    32. if (myOpenButton) {
    33. bool isvalid = formatCheck(file);
    34. myOpenButton->setEnabled(isvalid);
    35.  
    36. // the following two lines for testing. Shows the
    37. // button's text is "&Open" and the enabled state is
    38. // the same as the value of the "isvalid" variable.
    39. QString buttonText = myOpenButton->text();
    40. bool enabled = myOpenButton->isEnabled();
    41. }
    42. }
    43. }
    44.  
    45. bool MyFileDialog::formatCheck(const QString& file)
    46. {
    47. // opens the file and returns the boolean result
    48. // of the format check.
    49.  
    50. // true leaves the button enabled; false also leaves the button enabled
    51. //bool result = true;
    52. bool result = false;
    53.  
    54. return result;
    55. }
    To copy to clipboard, switch view to plain text mode 

    Qt Code:
    1. // main() function instantiating and exec'ing MyFileDialog
    2.  
    3. #include "MyFileDialog.h"
    4.  
    5. int main(int argc, char *argv[])
    6. {
    7. MyFileDialog d(parent, "@C:\tmp");
    8. d.exec();
    9. }
    To copy to clipboard, switch view to plain text mode 

  2. #2
    Join Date
    Jan 2006
    Location
    Graz, Austria
    Posts
    8,416
    Thanks
    37
    Thanked 1,544 Times in 1,494 Posts
    Qt products
    Qt3 Qt4 Qt5
    Platforms
    Unix/X11 Windows

    Default Re: QFileDialog: Enable/Disable "Open" button in inherited class not working

    It could be that something else is changing the enabling state as well, e.g. the file dialog starting with button disabled and enabling it when a file is selected.

    What you could try is to intercept the change of the enabling state using an event filter and revert the unwanted change when the event happens.

    If you look at the documentation of the enabled property http://qt-project.org/doc/qt-4.8/qwi...l#enabled-prop you see that any change to it is signalled via QEvent::EnabledChanged.

    Your event filter would need to know, e.g. through a flag or similar, that it is you that triggered the change and just keep resetting the state to false if the flag is not set.

    Cheers,
    _

  3. #3
    Join Date
    Oct 2009
    Posts
    38
    Qt products
    Qt4
    Platforms
    MacOS X Unix/X11 Windows Symbian S60

    Thumbs up Re: QFileDialog: Enable/Disable "Open" button in inherited class not working

    Yes, that was it. I made the following changes to my code. When I grab the Open button in the constructor, I install the event filter on that button. I overrode the eventFilter() function as shown. Fixed my problem. Thanks for the help. Now I know...

    Qt Code:
    1. MyFileDialog::MyFileDialog(QWidget* parent, QString startdir)
    2. : QFileDialog(parent, tr("Load Correct Format"), startdir),
    3. myOpenButton(0)
    4. {
    5. // constructor - on setting the myOpenButton pointer, I register
    6. // the event filter on that button.
    7. myOpenButton->installEventFilter(this);
    8. }
    9.  
    10. bool MyFileDialog::eventFilter(QObject* obj, QEvent* event)
    11. {
    12. if (obj == myOpenButton)
    13. {
    14. QEvent::Type type = event->type();
    15. bool valid = validSelection();
    16. bool enabled = myOpenButton->isEnabled();
    17. if (type == QEvent::EnabledChange && enabled && !valid)
    18. {
    19. // don't allow QFileDialog to alter the state of the
    20. // Open button. This is to be handled locally in the
    21. // MyFileDialog::fileSelectionChanged() function.
    22. myOpenButton->setEnabled(false);
    23. return true;
    24. }
    25. else
    26. return false;
    27. }
    28.  
    29. // pass unfiltered events on to the parent class
    30. return QFileDialog::eventFilter(obj, event);
    31. }
    To copy to clipboard, switch view to plain text mode 

  4. #4
    Join Date
    Jan 2006
    Location
    Graz, Austria
    Posts
    8,416
    Thanks
    37
    Thanked 1,544 Times in 1,494 Posts
    Qt products
    Qt3 Qt4 Qt5
    Platforms
    Unix/X11 Windows

    Default Re: QFileDialog: Enable/Disable "Open" button in inherited class not working

    I would suggest to check the event type right in the first if, otherwise you are calling validSelection() for every event that the button gets.
    As long as validSelection() is basically just returning a boolean that is fine either way, but if you ever change it to do something more, it becomes just unnecessary overhead.

    Cheers,
    _

  5. #5
    Join Date
    Oct 2009
    Posts
    38
    Qt products
    Qt4
    Platforms
    MacOS X Unix/X11 Windows Symbian S60

    Default Re: QFileDialog: Enable/Disable "Open" button in inherited class not working

    Yeah, I had updated that myself after submitting, but thanks for catching it. The actual version of the if statement is shown in the following code block. validSelection() only returns a bool that was already figured out before this point, but it's better this way, because validSelection() never gets called if the type isn't EnabledChange, and if the button isn't currently enabled:

    Qt Code:
    1. if (obj == myOpenButton)
    2. {
    3. if (event->type() == QEvent::EnabledChange &&
    4. myOpenButton->isEnabled() &&
    5. !validSelection())
    6. {
    7. // don't allow QFileDialog to alter the state of the
    8. // Open button. This is to be handled locally in the
    9. // MyFileDialog::fileSelectionChanged() function.
    10. myOpenButton->setEnabled(false);
    11. return true;
    12. }
    13. else
    14. return false;
    15. }
    To copy to clipboard, switch view to plain text mode 

Similar Threads

  1. "Change widget class on button click" problem
    By utkozanenje in forum Newbie
    Replies: 3
    Last Post: 23rd May 2011, 00:40
  2. Replies: 3
    Last Post: 26th April 2009, 17:54
  3. Replies: 4
    Last Post: 19th March 2008, 17:47
  4. Translation QFileDialog standart buttons ("Open"/"Save"/"Cancel")
    By victor.yacovlev in forum Qt Programming
    Replies: 4
    Last Post: 24th January 2008, 19:05
  5. QFile Problem~ "Unknow error" in "open(QIODevice::ReadWrite)"
    By fengtian.we in forum Qt Programming
    Replies: 3
    Last Post: 23rd May 2007, 15:58

Tags for this Thread

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  
Digia, Qt and their respective logos are trademarks of Digia Plc in Finland and/or other countries worldwide.