簡體   English   中英

在 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&)
  • currentChanged(const QString&)只傳遞新選擇的文件
  • 並且selectedFiles()在這種情況下返回我在上一步中選擇的文件。 對話框在發出currentChanged(const QString&)后可能會更新文件。

這就是為什么我不知道如何跟蹤當前選擇的文件。 另一個問題是,如果用戶超出允許選擇的限制,我目前不知道如何取消選擇最后選擇的文件。

我見過幾個例子,人們使用QProxyModelQFileDialog的自定義實現來實現自定義功能,但我不確定什么最適合我的需求。

沒有辦法,但是一旦您的客戶完成選擇,您就可以通過調用方法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表明它有兩個子代,它們要么是 QListView 要么繼承自QListView ...

  1. QListView 命名為 listView
  2. QSidebar 命名的側邊欄

(其中 Qsidebar 是 Qt 私有的)。

假設名為listViewQListView是感興趣的小部件,您可以將回調連接到其選擇 model ...

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();
}

我只是簡單地測試了上面的代碼,但它似乎以所需的方式運行。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM