Search code examples
qtc++11qlineeditqcompleter

QLineEdit: automatically append backslash to directory name


I'm trying to automatically add a backslash to valid file paths in a QLineEdit, which is used to show the current path of a QFileSystemModel.

The code looks as follows:

fileSystem  =   new QFileSystemModel;
fileSystem->setRootPath(QObject::tr("C:\\"));

QCompleter* fileSystemCompleter = new QCompleter(fileSystem);
fileSystemCompleter->setCaseSensitivity(Qt::CaseInsensitive);

fileTree    =   new QDeselectableTreeView();
fileTree->setModel(fileSystem);
fileTree->setRootIndex(fileSystem->index(fileSystem->rootPath()));
connect(fileTree, &QTreeView::clicked, [&] (QModelIndex index) 
{
    QString toAppend("");
    if (fileSystem->isDir(index))
    {
        toAppend = '/';
    }
    fileSystemPathEdit->setText(fileSystem->filePath(index)+toAppend);
});

// path line edit
fileSystemPathEdit = new QLineEdit(fileSystem->rootPath());
fileSystemPathEdit->setPlaceholderText("Path...");
fileSystemPathEdit->setCompleter(fileSystemCompleter);
connect(fileSystemPathEdit, &QLineEdit::editingFinished, [&]()
{
    // jump to that location
    qDebug() << fileSystemPathEdit->text();
    QModelIndex index = fileSystem->index(fileSystemPathEdit->text());
    qDebug() << index;
    fileTree->setExpanded(index,true); 
    fileTree->setCurrentIndex(index);
    // CLOSE IF EMPTY
    if (fileSystemPathEdit->text().isEmpty())
    {
        fileTree->collapseAll();
        fileSystemPathEdit->setText(fileSystem->rootPath());
    }
    // append slashes to dirs
    else if (fileSystem->isDir(index) && index.isValid())
    {
        qDebug() << "it's a dir";
        if (!fileSystemPathEdit->text().endsWith('/',Qt::CaseInsensitive))
        {
            qDebug() << "added slash";
            fileSystemPathEdit->setText(fileSystemPathEdit->text().append('/'));
            qDebug() << fileSystemPathEdit->text();
        }
    }
    this->update();
});

I get the following output when running the code:

"C:/export/home"
QModelIndex(0,0,0x3adb840,QFileSystemModel(0x1d9b7c0) ) 
it's a dir
added slash
"C:/export/home/"

It works ok when I push the Enter key from within the lineEdit, but if the text is set by the QCompleter, I still get the same debug output showing that the text has been changed, but the slash doesn't appear in the lineEdit. Does the QCompleter somehow unset the text?


Solution

  • This is a hack, but adding this connection to the QCompleter gives the desired behavior. I think there is a race condition when using editingFinished() at the same time that the QCompleter is activated, so adding delay allows the slash to be appended without being overridden. On the down side, that function know gets called several times to many per change. I'd still be interested in a better solution.

    connect(fileSystemCompleter, activatedOverloadPtr, [&](QModelIndex index)
    {
        QTimer* timer =  new QTimer;
        timer->setSingleShot(true);
        timer->setInterval(10);
        connect(timer, &QTimer::timeout, fileSystemPathEdit,  &QLineEdit::editingFinished);
        timer->start();
    });