What is New in Qt 5: QMimeDatabase and QMimeType

What's New in Qt 5: QMimeDatabase and QMimeType

By Jeff Tranter

QMimeDatabase and QMimeType are new classes introduced in Qt 5. MIME, which stands for Multipurpose Internet Mail Extensions, is an Internet standard for identifying file formats. The MIME standard was originally created to support attachment of files in e-mail messages. A good reference for MIME can be found here.

The QMimeDatabase class returns information about the database of MIME types on a system. Instances of the QMimeType class describe the type of a file or data.

I wrote a small graphical Qt demo application that illustrates these classes. It allows the user to enter or browse for a file name. When the Lookup button is pressed it looks up the MIME type for the file using the mimeTypeForFile() method from the QMimeDatabase class. This returns a QMimeType object. The program displays the information that QMimeType provides for the file.

The application lets you select from the three available ways of looking up the MIME type for a file, looking at the file's content, looking at the file's name, or both (the default).

For example, for a C++ source file like the file main.cpp for the demo application, on my system the MIME information is displayed as follows:

Snapshot51
 

These classes are quite straightforward to use. They can be useful if your application needs to identify the types of files it works with or use appropriate file name extensions, for example.

A related Qt class is QMimeData which was also available in Qt 4. It stores a MIME type and is typically used when implementing clipboard or drag and drop functionality in an application.

Let's walk through the source files for the application.

The file main.cpp was generated by Qt Creator's new project wizard and needed no other changes. It follows the usual Qt convention of creating a QApplication, then creating and showing the main widget, here called "MainWindow".

#include "mainwindow.h"
#include <QApplication>

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    MainWindow w;
    w.show();
    
    return a.exec();
}

File mainwindow.h declares the MainWindow class. It is derived from QMainWindow. The code was initially generated by Qt Creator's new project wizard. I added two slots, browse() and lookup(), that get connected to the pushbutton's clicked() signals.

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>

namespace Ui {
class MainWindow;
}

class MainWindow : public QMainWindow
{
    Q_OBJECT
    
public:
    explicit MainWindow(QWidget *parent = 0);
    ~MainWindow();

public slots:
    void browse();
    void lookup();

private:
    Ui::MainWindow *ui;
};

#endif // MAINWINDOW_H

File mainwindow.cpp implements the main application logic. It was also initially created by Qt Creator. In the constructor we connect the clicked() signals for the two buttons to our slots to handle the Browser and Lookup functionality. Note the new connect syntax for signals and slots. This new format does checking of the arguments at compile-time. This catches the common error of getting the signal or slot arguments wrong that is only detected at run-time with the older connect syntax. The older connect syntax is still supported in Qt 5.

The browse() method is a slot that simply invokes QFileDialog to get a filename and writes the path into the line edit widget. The lookup() method is a slot that gets the MIME type information for the path in the line edit by creating a QMimeDatabase object and calling its mimeTypeForFile() method. It uses the match mode corresponding to the value of the combo box. It then calls a number of the QMimeType methods and displays the results in the text edit widget.

During testing with Qt 5.0.1 a colleague found that the QMimeDatabase::mimeTypeForFile method that accepts a QString fileName and MatchMode does not work properly when the MatchMode is QMimeDatabase::MatchContent. It uses MatchDefault instead. The cause was found and a Qt bug reported. A workaround is to use the alternate QMimeDatabase::mimeTypeForFile method that accepts a QFileInfo and MatchMode. Here is the source code for mainwindow.cpp:

#include <QFileDialog>
#include <QMimeType>
#include <QMimeDatabase>
#include <QFile>
#include "mainwindow.h"
#include "ui_mainwindow.h"

/*

 Demo of Qt 5 QMimeType and QMimeDatabase classes. Displays MIME information for a file.

*/

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);

    // Connect signals and slots.
    connect(ui->browseButton, &QPushButton::clicked, this, &MainWindow::browse);
    connect(ui->lookupButton, &QPushButton::clicked, this, &MainWindow::lookup);
}

MainWindow::~MainWindow()
{
    delete ui;
}

void MainWindow::browse()
{
    QString filename = QFileDialog::getOpenFileName(this, tr("Select File"));

    if (!filename.isEmpty()) {
        ui->filenameLineEdit->setText(filename);
        ui->textEdit->clear();
    }
}

void MainWindow::lookup()
{
    QString text;
    QMimeDatabase mimeDatabase;
    QMimeType mimeType;

    if (ui->filenameLineEdit->text().isEmpty()) {
        text = tr("No file specified. Enter a file name or browse for a file.");
    } else if (!QFile::exists(ui->filenameLineEdit->text())) {
        text = tr("File '%1' was not found.").arg(ui->filenameLineEdit->text());
    } else {
        enum QMimeDatabase::MatchMode mode = (enum QMimeDatabase::MatchMode) ui->modeComboBox->currentIndex();
        // Note: Due to a Qt 5.0.1 bug, mimeTypeForFile(QString, MatchMode) doesn't
        // function properly for mode == MatchContent. 
        // mimeTypeForFile(QFileInfo, MatchMode) does work correctly.
        mimeType = mimeDatabase.mimeTypeForFile(QFileInfo(ui->filenameLineEdit->text()), mode);

        text = "<b>MIME Type:</b>  " + mimeType.name() + "<br>"
            + "<b>Comment:</b>  " + mimeType.comment() + "<br>"
            + "<b>Filter string:</b>  " + mimeType.filterString() + "<br>"
            + "<b>Icon Name:</b> " + mimeType.iconName() + "<br>"
            + "<b>Generic Icon Name:</b>" + mimeType.genericIconName() + "<br>"
            + "<b>Preferred Suffix:</b> " + mimeType.preferredSuffix() + "<br>"
            + "<b>Is Valid:</b> " + (mimeType.isValid() == true ? "Yes" : "No" ) + "<br>"
            + "<b>Is Default:</b> " + (mimeType.isDefault() == true ? "Yes" : "No" ) + "<br>"
            + "<b>Suffixes:</b> " + mimeType.suffixes().join(" ") + "<br>"
            + "<b>Glob Patterns:</b> " + mimeType.globPatterns().join(" ") + "<br>"
            + "<b>Aliases:</b> " + mimeType.aliases().join(" ") + "<br>"
            + "<b>Parent MIME Types:</b> " + mimeType.parentMimeTypes().join(" ") + "<br>"
            + "<b>All Ancestors:</b> " + mimeType.allAncestors().join(" ") + "<br>";
    }

    ui->textEdit->setText(text);
}

The file mainwindow.ui is the user interface created using Qt Designer that consists of a QMainWindow, line edit and combo box (with associated labels), and a text edit.

Another screen shot of the running application is shown below.

Snapshot52
 

In summary, the new QMimeDatabase and QMimeType classes in Qt 5 are useful for dealing with MIME type information for files, allowing your application to better integrate with the platform it is running on in a portable way.

You can download a zip archive of the source files for the application from here.