QFileDialog:如何通过触摸屏输入选择多个文件?

时间:2015-07-03 09:00:28

标签: c++ qt qfiledialog

在我们使用Qt 4并支持触摸输入的应用程序中,我们使用QFileDialog和QFileDialog :: DontUseNativeDialog和QFileDialog :: ExistingFiles选项。 第一个是需要的,因为我们设置了自己的样式表,但这不适用于本机对话框。第二个是选择多个文件所需的,这是我们想要做的。

问题是在QFileDialog中无法选择带触摸输入的多个文件,因为我们没有“shift”或“ctrl”-key可用。在Windows中,通过向项添加复选框来解决问题。 QFileDialog没有复选框。

我试图操纵Q​​FileDialog以显示项目的复选框,但我失败了。

我尝试交换底层QTreeView和QListView使用的QFileSystemModel,但这会破坏模型和对话框之间的信号槽连接。我无法找到恢复它们的方法,因为它们深埋在对话框的私人空间中。

此时我能想象的唯一解决方案是编写一个全新的对话框,但我想避免这种努力。

  • 那么有没有办法在QFileDialog模型视图中添加复选框?
  • 您是否知道如何选择多个文件?
  • 问题是否已在Qt 5中修复?无论如何我们想要更新。

感谢您的帮助。

1 个答案:

答案 0 :(得分:0)

由于我没有在项目视图中添加复选框,因此我实施了一个" hacky"变通。它为对话框添加了一个额外的可检查按钮,用作" 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添加到视图的鼠标事件中。

随意发布其他解决方案,因为这有点即兴。