1 // Copyright (C) 2014-2018 Manuel Schneider
2
3 #include <QDebug>
4 #include <QKeyEvent>
5 #include <QMimeDatabase>
6 #include <QSortFilterProxyModel>
7 #include <QStandardItemModel>
8 #include <QStringListModel>
9 #include <QtConcurrent>
10 #include <thread>
11 #include "mimetypedialog.h"
12 #include "ui_mimetypedialog.h"
13
14
15 /** ***************************************************************************/
MimeTypeDialog(const QStringList & filters,QWidget * parent)16 Files::MimeTypeDialog::MimeTypeDialog(const QStringList &filters, QWidget *parent) :
17 QDialog(parent), ui(new Ui::MimeTypeDialog) {
18 ui->setupUi(this);
19
20 // Populate a standard itemmodel with mime types
21 QStandardItemModel *standardItemModel = new QStandardItemModel(this);
22 QList<QStandardItem*> items;
23 for (QMimeType mimeType : QMimeDatabase().allMimeTypes()) {
24 QStandardItem *item = new QStandardItem(mimeType.name());
25 item->setToolTip(mimeType.filterString());
26 item->setData(mimeType.iconName());
27 items.append(item);
28 }
29 standardItemModel->appendColumn(items);
30 standardItemModel->sort(0);
31
32 // Get the images in background
33 auto bg_task = [this, standardItemModel](){
34 static QIcon fallback = QIcon::fromTheme("unknown"); // TODO: resource fallback
35 for (int i = 0; i < standardItemModel->rowCount(); ++i) {
36 QStandardItem *item = standardItemModel->item(i);
37 item->setIcon(QIcon::fromTheme(item->data().toString(), fallback));
38 if (exit_thread)
39 break;
40 }
41 qDebug() << "DONE";
42 };
43
44 future = QtConcurrent::run(bg_task);
45
46 // Add a proxy model for mimtype filtering
47 QSortFilterProxyModel *mimeFilterModel = new QSortFilterProxyModel(this);
48 mimeFilterModel->setSourceModel(standardItemModel);
49 ui->listView_mimeTypes->setModel(mimeFilterModel);
50
51 // Add a stinglist model to the filter model
52 filtersModel = new QStringListModel(filters, this);
53 ui->listView_filters->setModel(filtersModel);
54
55 // Set the filter for the proxymodel if the users typed something
56 connect(ui->lineEdit, &QLineEdit::textChanged,
57 mimeFilterModel, &QSortFilterProxyModel::setFilterFixedString);
58
59 // On mimetype list activation add the mimetype to the filter list
60 connect(ui->listView_mimeTypes, &QListView::activated, [this](const QModelIndex &index){
61 filtersModel->insertRow(filtersModel->rowCount());
62 filtersModel->setData(filtersModel->index(filtersModel->rowCount()-1,0), index.data());
63 });
64
65 // On ">" button click add the mimetype to the filter list
66 connect(ui->toolButton_copyMimetype, &QToolButton::clicked, [this](){
67 QModelIndex index = ui->listView_mimeTypes->currentIndex();
68 filtersModel->insertRow(filtersModel->rowCount());
69 filtersModel->setData(filtersModel->index(filtersModel->rowCount()-1,0), index.data());
70 });
71
72 // Add a new line on "+"
73 connect(ui->toolButton_add, &QToolButton::clicked, [this](){
74 int row = filtersModel->rowCount();
75 filtersModel->insertRow(row);
76 ui->listView_filters->setCurrentIndex(filtersModel->index(row, 0));
77 ui->listView_filters->edit(filtersModel->index(row, 0));
78 });
79
80 // Remove the selected line on "-"
81 connect(ui->toolButton_remove, &QToolButton::clicked, [this](){
82 QModelIndex index = ui->listView_filters->currentIndex();
83 if ( index.isValid() )
84 filtersModel->removeRow(index.row());
85 });
86
87 // Let the listview intercept the input of the filter line edit (for navigation and activation)
88 ui->lineEdit->installEventFilter(this);
89 }
90
91
92
93 /** ***************************************************************************/
~MimeTypeDialog()94 Files::MimeTypeDialog::~MimeTypeDialog() {
95 exit_thread = true;
96 future.waitForFinished();
97 delete ui;
98 }
99
100
101
102 /** ***************************************************************************/
filters() const103 QStringList Files::MimeTypeDialog::filters() const {
104 return filtersModel->stringList();
105 }
106
107
108
109 /** ***************************************************************************/
eventFilter(QObject *,QEvent * event)110 bool Files::MimeTypeDialog::eventFilter(QObject * /*theres only the linedit*/, QEvent *event) {
111
112 if (event->type() == QEvent::KeyPress) {
113 QKeyEvent *keyEvent = static_cast<QKeyEvent*>(event);
114 switch (keyEvent->key()) {
115 case Qt::Key_Up:
116 case Qt::Key_Down:
117 case Qt::Key_Enter:
118 case Qt::Key_Return:
119 QApplication::sendEvent(ui->listView_mimeTypes, keyEvent);
120 return true;
121 default:
122 return false;
123 }
124 }
125 return false;
126 }
127
128
129
130 /** ***************************************************************************/
keyPressEvent(QKeyEvent * evt)131 void Files::MimeTypeDialog::keyPressEvent(QKeyEvent *evt) {
132 // Eat keys for desired behaviour
133 switch ( evt->key() ) {
134 case Qt::Key_Enter:
135 case Qt::Key_Return:
136 case Qt::Key_Escape:
137 return;
138 }
139 QDialog::keyPressEvent(evt);
140 }
141