2015-07-03 4 views
0

В нашем приложении, использующем Qt 4 и поддерживающем сенсорный ввод, мы используем QFileDialog с параметрами QFileDialog :: DontUseNativeDialog и QFileDialog :: ExistingFiles. Первое необходимо, потому что мы устанавливаем собственную таблицу стилей и не работаем с родным диалогом. Второй - для выбора нескольких файлов, что мы и хотим делать.QFileDialog: Как выбрать несколько файлов с сенсорным экраном?

Проблема заключается в том, что нельзя выбрать несколько файлов с сенсорным вводом в QFileDialog, потому что у нас нет доступных клавиш «shift» или «ctrl». В Windows проблема решена путем добавления флажков к элементам. QFileDialog не имеет флажков.

Я попытался манипулировать QFileDialog, чтобы он отображал флажки для элементов, но мне не удалось.

Я попытался обменять QFileSystemModel, который используется базовыми QTreeView и QListView, но это нарушает соединения сигнального слота между моделью и диалогом. Я не мог найти способ восстановить их, потому что они зашли глубоко в частные завещания диалога.

В настоящий момент единственное решение, которое я могу себе представить, это написать совершенно новый диалог, но я бы хотел избежать усилий.

  • Итак, есть ли способ добавить флажки в представления модели QFileDialog?
  • Есть ли у вас другая идея, как можно было бы выбрать несколько файлов?
  • Является ли проблема исправлена ​​в Qt 5? Мы все равно хотим обновить.

Благодарим за помощь.

+1

Вы посмотрели на них? https://wiki.qt.io/QSortFilterProxyModel_subclass_to_add_a_checkbox http://www.qtcentre.org/threads/27253-QFileSystemModel-with-checkboxes – Miki

+1

Возможно, хороший хак будет искать QListView/QTreeView внутри вашего QFileDialog (подсказка: 'findChild ') и установите его в режиме расширенного выбора. – peppe

+0

Ссылка на CheckableProxyModel выглядит многообещающей, потому что кажется, что она не требует обмена модели с другой. Другая ссылка требует реализации производного QFileSystemModel, который заменит нормальный QFileSystemModel в представлениях. Но я попробовал это, и он сломал соединения сигнального слота между моделью и объектом QFileDialogPrivate QFileDialog, который я не смог восстановить извне. – Knitschi

ответ

0

Поскольку я не смог добавить флажки в представления элементов, я реализовал «хакерскую» работу. Он добавляет дополнительную проверяемую кнопку в диалог, который действует как «ctrl» -key. Когда кнопка отмечена, можно выбрать несколько файлов. Решение немного уродливое, потому что оно зависит от знания внутренних компонентов диалогового окна, но оно выполняет эту работу.

Так вот код для заголовка ...

// file touchfiledialog.h 

/* 
Event filter that is used to add a shift modifier to left mouse button events. 
This is used as a helper class for the TouchFileDialog 
*/ 
class EventFilterCtrlModifier : public QObject 
{ 
    Q_OBJECT; 

    bool addCtrlModifier; 

public: 
    EventFilterCtrlModifier(QObject* parent); 

    void setAddCtrlModifier(bool b); 

protected: 
    virtual bool eventFilter(QObject* watched, QEvent* e); 
}; 


/* 
TouchDialog adds the possibility to select multiple files with touch input to the QFileDialog. 
This is done by adding an extra button which can be used as control key replacement. 
*/ 
class QTOOLS_API TouchFileDialog : public QFileDialog 
{ 
    Q_OBJECT 

    EventFilterCtrlModifier* listViewEventFilter; 
    EventFilterCtrlModifier* treeViewEventFilter; 

    bool initialized; 

public: 
    TouchFileDialog(QWidget* parent); 


protected: 
    virtual void showEvent(QShowEvent* e); 

private slots: 
    void activateCtrlModifier(bool b); 

private: 
    void initObjectsForMultipleFileSelection(); 
}; 

с реализацией ...

// file touchfiledialog.cpp 

#include "touchfiledialog.h" 


EventFilterCtrlModifier::EventFilterCtrlModifier(QObject* parent) 
    : QObject(parent) 
    , addCtrlModifier(false) 
{ 

} 

void EventFilterCtrlModifier::setAddCtrlModifier(bool b) 
{ 
    addCtrlModifier = b; 
} 

bool EventFilterCtrlModifier::eventFilter(QObject* watched, QEvent* e) 
{ 
    QEvent::Type type = e->type(); 
    if(type == QEvent::MouseButtonPress || type == QEvent::MouseButtonRelease) 
    { 
     if(addCtrlModifier) 
     { 
      QMouseEvent* mouseEvent = static_cast<QMouseEvent*>(e); 
      // Create and post a new event with ctrl modifier if the event does not already have one. 
      if(!mouseEvent->modifiers().testFlag(Qt::ControlModifier)) 
      { 
       QMouseEvent* newEventWithModifier = new QMouseEvent( 
        type, 
        mouseEvent->pos(), 
        mouseEvent->globalPos(), 
        mouseEvent->button(), 
        mouseEvent->buttons(), 
        mouseEvent->modifiers() | Qt::ControlModifier 
        ); 

       QCoreApplication::postEvent(watched, newEventWithModifier); 

       return true; // absorb the original event 
      } 
     } 
    } 

    return false; 
} 


//####################################################################################### 
TouchFileDialog::TouchFileDialog(QWidget* parent) 
    : QFileDialog(parent) 
    , listViewEventFilter(NULL) 
    , treeViewEventFilter(NULL) 
    , initialized(false) 
{ 

} 

void TouchFileDialog::showEvent(QShowEvent* e) 
{ 
    // install objects that are needed for multiple file selection if needed 
    if(!initialized) 
    { 
     if(fileMode() == QFileDialog::ExistingFiles) 
     { 
      initObjectsForMultipleFileSelection(); 
     } 

     initialized = true; 
    } 

    QFileDialog::showEvent(e); 
} 

void TouchFileDialog::initObjectsForMultipleFileSelection() 
{ 
    // install event filter to item views that are used to add ctrl modifiers to mouse events 
    listViewEventFilter = new EventFilterCtrlModifier(this); 
    QListView* listView = findChild<QListView*>(); 
    listView->viewport()->installEventFilter(listViewEventFilter); 

    treeViewEventFilter = new EventFilterCtrlModifier(this); 
    QTreeView* treeView = findChild<QTreeView*>(); 
    treeView->viewport()->installEventFilter(treeViewEventFilter); 

    QGridLayout* dialogLayout = static_cast<QGridLayout*>(layout()); // Ugly because it makes assumptions about the internals of the QFileDialog 

    QPushButton* pushButtonSelectMultiple = new QPushButton(this); 
    pushButtonSelectMultiple->setText(tr("Select multiple")); 
    pushButtonSelectMultiple->setCheckable(true); 
    connect(pushButtonSelectMultiple, SIGNAL(toggled(bool)), this, SLOT(activateCtrlModifier(bool))); 

    dialogLayout->addWidget(pushButtonSelectMultiple, 2, 0); 
} 

void ZFFileDialog::activateCtrlModifier(bool b) 
{ 
    listViewEventFilter->setAddCtrlModifier(b); 
    treeViewEventFilter->setAddCtrlModifier(b); 
} 

TouchFileDialog устанавливает фильтр событий для представлений элементов, которые добавят ControlModifier для событий мыши в представлениях, когда проверяется соответствующая кнопка в диалоговом окне.

Не стесняйтесь публиковать другие решения, потому что это несколько импровизировано.

Смежные вопросы