PDA

View Full Version : Customizing QFileDialog



ScabrusMantra
20th October 2009, 18:38
I am trying to customize QFileDialog, so that custom information is dispayed in 'Type' column for certain files and directories. I've started by subclassing QFileSystemModel and redefining type() function. So, for certain file extensions it would return custom type. Now I want to use this class as model for QFileDialog and I see only one possibility. Namely, use proxy model. So, I have my custom file dialog class, which is derived from QFileDialog that has this in a constructor:



MyFileDialog::MyFileDialog
(
const QList<QUrl> &a_urls,
QWidget *parent,
const QString &caption,
const QString &directory,
const QString &filter
)
: QFileDialog(parent,caption,directory,filter)
{
setSidebarUrls(a_urls);
QListView *sidebar = this->findChild<QListView *>("sidebar");
m_proxy = new QSortFilterProxyModel();
QFileDialog::setProxyModel(m_proxy);
m_data = new MyFileSystemModel();
QString rootPath = this->directory().path();
m_data->setRootPath(rootPath);
m_proxy->setSourceModel(m_data);



Now I am getting memory access error when file dialog appears and I try to select anything there.

I also see another problem here. If I comment out last line (m_proxy->setSourceModel(m_data)) everything works except for sidebar. I suspect there may be a bug in Qt's qfiledialog.cpp setProxyModel() function. While proxyModel is set as model for list and tree views



if (proxyModel != 0) {
proxyModel->setParent(this);
d->proxyModel = proxyModel;
proxyModel->setSourceModel(d->model);
d->qFileDialogUi->listView->setModel(d->proxyModel);
d->qFileDialogUi->treeView->setModel(d->proxyModel);
connect(d->proxyModel, SIGNAL(rowsInserted(const QModelIndex &, int, int)),
this, SLOT(_q_rowsInserted(const QModelIndex &)));


it is not done for sidebar.

So, I have two questions here: 1) what am I doing wrong here or is this a bug in Qt? and 2) is there a better way to get custom file dialog working besides rewriting it from scratch?

Any advise would be greatly appreciated. Thanks.

wysota
20th October 2009, 19:37
It's not a bug. The file dialog is simply not meant to be subclassed that way.

ScabrusMantra
20th October 2009, 19:56
It's not a bug. The file dialog is simply not meant to be subclassed that way.

Ok... What would be a right way to customize file dialog then?

Yet even if I don't subclass QFileDialog using setProxyModel() will probably cause sidebar to fail.

Thanks.

wysota
20th October 2009, 20:45
I wouldn't say there is any right way to do it. Especially that in 90% of the cases native dialogs are used and not the dialog created by Qt.

UrfinJuice
21st July 2011, 17:32
Is it possible to customize QFileDialog in the way that there is no way to leave a particular (specified) subdirectory? The reason is, I wouldn't like the user to choose the files from ANY directory but from the given ones.

Thanks in advance

totem
21st July 2011, 17:41
I guess you could read this thread : http://www.qtcentre.org/threads/28170-Restrict-QFileDialog-to-one-specific-directory

UrfinJuice
21st July 2011, 17:48
Oh, thanks, I guess, this should work!!

UrfinJuice
22nd July 2011, 10:16
Well, this works only partially. Namely, e.g. I wanna stay in the directory /tmp. And click to Up-icon in the QFileDialog window. This generates the signal directoryEntered(const QString), which I can catch up and move back to /tmp. However, the path "/" remains in the history. And then backButton from the QFileDialogPrivate can be used and does not generate the signal. In this way, I can traverse the entire /-tree.

Would appreciate any comments

P.S. clearing histroy also didn't help.

P.P.S changeEvent also doesn't react to back- and forward-buttons. However, it does work on go-up-button

UrfinJuice
22nd July 2011, 13:03
Ok, just to tell how I solved the problem:

In the file qfiledialog.cpp in functions
void QFileDialogPrivate::_q_navigateForward()
and
void QFileDialogPrivate::_q_navigateBackward()
after
q->setDirectory(nextHistory);
and
q->setDirectory(previousHistory);

I added
emit q->directoryEntered(nextHistory);
and
emit q->directoryEntered(previousHistory);
respectively.

Recompile -> runs :)

However, I'm not sure, if it's a bug or a feature