2

I am using Qt 5.12 and trying to write test (using QTest) for opening of project stored in some xml format.

In test I use QTimer::singleShot to wait QFileDialog to appear as proposed in QT close window by QTest in locked thread.

The problem is that QFileDialog::selectFile doesn't select anything. This means that OK button is not active, so I can't click on it in my test.

I assume in the following example that full path to file is /tmp/project.xml. Notice that QFileDialog::setDirectory works great: when the following example starts, you are in /tmp dir instead of /.

#include <QApplication>

#include <QFileDialog>
#include <QTimer>

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);

    QTimer::singleShot(300, []() {
        QWidget* window = nullptr;
        while (!window) {
            window = qApp->activeModalWidget();
        }
        QFileDialog* fd = qobject_cast<QFileDialog*>(window);

        fd->setDirectory("/tmp");
        fd->selectFile("project.xml");
    });

    QString path = QFileDialog::getOpenFileName(nullptr, "Open Project",
                                                "/", QString(),
                                                nullptr, QFileDialog::DontUseNativeDialog);
}
  • IMO problem is that your code is badly written and as a result hard to test. In well written code tests are just invoking a signals and listen to slots. If you do that like this then you do not have to hack `QFileDialog::getOpenFileName` and test will be faster. – Marek R Dec 21 '18 at 13:18
  • @MarekR What exactly is bad? I would like to use only signals and slots, but it is impossible when we have modal widgets. With modal widgets I have to use `QTimer::singleShot` trick. –  Dec 21 '18 at 13:20
  • Probably your controller (in Qt a `QMainWindow` has this responsibility) does to much stuff and your function are to long, so you have a problem with testing it. – Marek R Dec 21 '18 at 13:28
  • Maybe first you should explain what are you testing? – Marek R Dec 21 '18 at 13:30

1 Answers1

1

The function selectFile didn't work because of the file name text box (lineEdit) is focused. This behavior comes from the implementation of QFileDialog::selectFile() :

void QFileDialog::selectFile(const QString &filename)
{
    // ... function body

    //Put the filename into the lineEdit when :
    //1. The dialog is not visible or
    //2. The lineEdit is not focused.

    if (!isVisible() || !d->lineEdit()->hasFocus())
        d->lineEdit()->setText(index.isValid() ? index.data().toString() : fileFromPath(d->rootPath(), filename));
}

To make the program works, there are two ways :

  1. Put the file name directly in the text box
  2. Give the focus away then call selectFile

       fd->setDirectory("/tmp");
    
       QLineEdit * lineEdit = qobject_cast<QLineEdit*>(fd->focusWidget());
    
        if( lineEdit ){
    
            //Method 1
            lineEdit->setText("project.xml");
    
            //Method 2
            lineEdit->nextInFocusChain()->setFocus();
            fd->selectFile("project.xml");
    
        }else { //no lineEdit focus found
    
            fd->selectFile("project.xml");
        }
    
tunglt
  • 1,022
  • 1
  • 9
  • 16