2015-07-03 101 views
0

在我們使用Qt 4並支持觸摸輸入的應用程序中,我們使用帶有選項QFileDialog :: DontUseNativeDialog和QFileDialog :: ExistingFiles的QFileDialog。 第一個是需要的,因爲我們設置了自己的樣式表,並且不適用於本機對話框。第二個是需要選擇多個文件,這是我們想要做的。QFileDialog:如何用觸摸屏輸入選擇多個文件?

問題在於,由於我們沒有「shift」或「ctrl」鍵可用,因此無法在QFileDialog中選擇多個帶觸摸輸入的文件。在Windows中,問題通過向項目添加複選框來解決。 QFileDialog沒有複選框。

我試圖操縱Q​​FileDialog使它顯示項目的複選框,但我失敗了。

我試圖交換底層QTreeView和QListView使用的QFileSystemModel,但是這打破了模型和對話框之間的信號插槽連接。我無法找到恢復它們的方法,因爲它們深深陷入了對話的私密性。

在這一刻,我可以想象的唯一解決方案是編寫一個全新的對話框,但我想避免這種努力。

  • 那麼有沒有辦法將複選框添加到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

也許一個好的黑客會在你的QFileDialog中找到QListView/QTreeView(提示:'findChild ')並將其設置爲擴展選擇模式。 – peppe

+0

CheckableProxyModel的鏈接看起來很有前途,因爲它似乎不需要與另一個模型交換模型。另一個鏈接需要實現派生的QFileSystemModel,它將取代視圖中的正常QFileSystemModel。但我試過了,它打破了模型與QFileDialog的QFileDialogPrivate對象之間的信號槽連接,我無法從外部恢復。 – Knitschi

回答

0

由於我未能在項目視圖中添加複選框,我實現了一個「哈克」解決方案。它在充當「ctrl」鍵的對話框中添加了一個額外的可檢查按鈕。當按鈕被選中時,可以選擇多個文件。這個解決方案有點難以理解,因爲它依賴於瞭解對話框的內部,但它完成了這項工作。

所以這裏是頭的代碼...

// 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當對話框中的相應按鈕被選中時,將鼠標指向視圖的鼠標事件。

隨意發佈其他解決方案,因爲這有點簡單。