限制用户在 QFileDialog 中可以 select 的文件数量
Limit amount of files user can select in QFileDialog
这里是代码:
dialog = new QFileDialog(this);
dialog->setFileMode(QFileDialog::ExistingFiles);
connect(dialog, SIGNAL(currentChanged(const QString&)),
this, SLOT(dialogSelectionChanged(const QString&)));
void MainWindow::dialogSelectionChanged(const QString& file)
{
QStringList selected = dialog->selectedFiles();
}
问题是
fileSelected(const QString&)
和 filesSelected(const QStringList&)
只有在我按下 'Open' 按钮后才会发出。
currentChanged(const QString&)
只传递新选择的文件
- 和
selectedFiles()
returns 我在那种情况下是在上一步选择的文件。可能对话框在发出 currentChanged(const QString&)
. 后更新文件
这就是我不知道如何跟踪当前选定文件的原因。
另一个问题是,如果用户超过允许的选择限制,我目前还不知道如何取消选择最后选择的文件。
我见过几个示例,其中人们使用 QProxyModel
或 QFileDialog
的自定义实现来实现自定义功能,但我不确定哪种方式最适合我的需求。
没有方法可以做到这一点,但是一旦您的客户完成选择,您就可以通过调用方法 selectedFiles
来验证操作
QStringList 的大小是否大于您的约束,您可以中止操作并显示一些错误消息。
喜欢
void MainWindow::dialogSelectionChanged(const QString& file)
{
QStringList selected = dialog->selectedFiles();
if(selected.size()>LIMIT)
{
showErrorMsg("some helpful mesage");
}
}
如果你愿意接受无耻的黑客攻击,这是可以做到的:-)
假设以下代码...
QFileDialog fd;
使用 fd.findChildren<QListView *>()
检查 fd
显示它有两个 children 是或继承自 QListView
...
- 名为 listView 的 QListView
- QSidebar 名为侧边栏
(其中 QSidebar 是 Qt 私有的)。
假定名为 listView
的 QListView
是您感兴趣的小部件,您可以将回调连接到其选择模型...
QFileDialog fd;
for (const auto &i: fd.findChildren<QListView *>("listView")) {
auto *sm = i->selectionModel();
QObject::connect(sm, &QItemSelectionModel::selectionChanged,
[sm](const QItemSelection &selected, const QItemSelection &deselected)
{
/*
* Here we pass a hard-coded max selected items
* value of 5 to the real callback/slot.
*/
handle_selection_updated(5, sm, selected, deselected);
});
}
这里handle_selection_updated
有如下定义...
void handle_selection_updated (int selection_max, QItemSelectionModel *sm,
const QItemSelection &selected,
const QItemSelection &deselected)
{
/*
* We need to remember the last valid selection. The following
* is declared static in this simple case but would generally be
* a class member in `real' code.
*/
static QItemSelection last_selected;
/*
* Because we update the selection model `sm' from within this
* slot this function will recurse which will cause problems if
* we don't detect it and take appropriate action.
*/
static bool recursing = false;
if (recursing)
return;
/*
* If the number of rows selected is greater than the value
* specified by `selection_max' then revert to the last valid
* selection as specified by `last_selected'.
*/
if (sm->selectedRows().size() > selection_max) {
/*
* The following call to QItemSelectionModel::clearSelection
* will result in a recursive call to this function. Set
* `recursing' to true to catch this and avoid associated
* problems.
*/
recursing = true;
/*
* Now clear the selection and reset it to the items from
* `last_selected'.
*/
sm->clearSelection();
for (const auto &i: last_selected.indexes()) {
sm->select(i, QItemSelectionModel::Select);
}
recursing = false;
}
/*
* Update `last_selected'.
*/
last_selected = sm->selection();
}
我只简单地测试了上面的代码,但它的行为似乎符合要求。
这里是代码:
dialog = new QFileDialog(this);
dialog->setFileMode(QFileDialog::ExistingFiles);
connect(dialog, SIGNAL(currentChanged(const QString&)),
this, SLOT(dialogSelectionChanged(const QString&)));
void MainWindow::dialogSelectionChanged(const QString& file)
{
QStringList selected = dialog->selectedFiles();
}
问题是
fileSelected(const QString&)
和filesSelected(const QStringList&)
只有在我按下 'Open' 按钮后才会发出。currentChanged(const QString&)
只传递新选择的文件- 和
selectedFiles()
returns 我在那种情况下是在上一步选择的文件。可能对话框在发出currentChanged(const QString&)
. 后更新文件
这就是我不知道如何跟踪当前选定文件的原因。 另一个问题是,如果用户超过允许的选择限制,我目前还不知道如何取消选择最后选择的文件。
我见过几个示例,其中人们使用 QProxyModel
或 QFileDialog
的自定义实现来实现自定义功能,但我不确定哪种方式最适合我的需求。
没有方法可以做到这一点,但是一旦您的客户完成选择,您就可以通过调用方法 selectedFiles
来验证操作QStringList 的大小是否大于您的约束,您可以中止操作并显示一些错误消息。
喜欢
void MainWindow::dialogSelectionChanged(const QString& file)
{
QStringList selected = dialog->selectedFiles();
if(selected.size()>LIMIT)
{
showErrorMsg("some helpful mesage");
}
}
如果你愿意接受无耻的黑客攻击,这是可以做到的:-)
假设以下代码...
QFileDialog fd;
使用 fd.findChildren<QListView *>()
检查 fd
显示它有两个 children 是或继承自 QListView
...
- 名为 listView 的 QListView
- QSidebar 名为侧边栏
(其中 QSidebar 是 Qt 私有的)。
假定名为 listView
的 QListView
是您感兴趣的小部件,您可以将回调连接到其选择模型...
QFileDialog fd;
for (const auto &i: fd.findChildren<QListView *>("listView")) {
auto *sm = i->selectionModel();
QObject::connect(sm, &QItemSelectionModel::selectionChanged,
[sm](const QItemSelection &selected, const QItemSelection &deselected)
{
/*
* Here we pass a hard-coded max selected items
* value of 5 to the real callback/slot.
*/
handle_selection_updated(5, sm, selected, deselected);
});
}
这里handle_selection_updated
有如下定义...
void handle_selection_updated (int selection_max, QItemSelectionModel *sm,
const QItemSelection &selected,
const QItemSelection &deselected)
{
/*
* We need to remember the last valid selection. The following
* is declared static in this simple case but would generally be
* a class member in `real' code.
*/
static QItemSelection last_selected;
/*
* Because we update the selection model `sm' from within this
* slot this function will recurse which will cause problems if
* we don't detect it and take appropriate action.
*/
static bool recursing = false;
if (recursing)
return;
/*
* If the number of rows selected is greater than the value
* specified by `selection_max' then revert to the last valid
* selection as specified by `last_selected'.
*/
if (sm->selectedRows().size() > selection_max) {
/*
* The following call to QItemSelectionModel::clearSelection
* will result in a recursive call to this function. Set
* `recursing' to true to catch this and avoid associated
* problems.
*/
recursing = true;
/*
* Now clear the selection and reset it to the items from
* `last_selected'.
*/
sm->clearSelection();
for (const auto &i: last_selected.indexes()) {
sm->select(i, QItemSelectionModel::Select);
}
recursing = false;
}
/*
* Update `last_selected'.
*/
last_selected = sm->selection();
}
我只简单地测试了上面的代码,但它的行为似乎符合要求。