QWidget *VariantFactory::createEditor(QtVariantPropertyManager *manager,
            QtProperty *property, QWidget *parent)
    {
        if (manager->propertyType(property) == VariantManager::filePathTypeId())
        {
            FileEdit *editor = new FileEdit(parent);
            QString path = manager->value(property).value<QtEntityUtils::FilePath>();

            editor->setFilePath(path);
            editor->setFilter(manager->attributeValue(property, QLatin1String("filter")).toString());
            _createdFileEditors[property].append(editor);
            _fileEditorToProperty[editor] = property;

            connect(editor, &FileEdit::filePathChanged, this, &VariantFactory::slotSetFilePathValue);
            connect(editor, &FileEdit::destroyed, this, &VariantFactory::slotEditorDestroyed);
            return editor;
        }
        if (manager->propertyType(property) == VariantManager::listId())
        {
            ListEdit *editor = new ListEdit(parent);

            _createdListEditors[property].append(editor);
            _listEditorToProperty[editor] = property;

            connect(editor, &ListEdit::listChanged, this, &VariantFactory::slotSetListValue);
            connect(editor, &ListEdit::destroyed, this, &VariantFactory::slotEditorDestroyed);
            return editor;
        }
        return QtVariantEditorFactory::createEditor(manager, property, parent);
    }
QWidget *FileEditFactory::createEditor(FilePathManager *manager,
        QtProperty *property, QWidget *parent)
{
    FileEdit *editor = new FileEdit(parent);
    editor->setFilePath(manager->value(property));
    editor->setFilter(manager->filter(property));
    theCreatedEditors[property].append(editor);
    theEditorToProperty[editor] = property;

    connect(editor, SIGNAL(filePathChanged(const QString &)),
                this, SLOT(slotSetValue(const QString &)));
    connect(editor, SIGNAL(destroyed(QObject *)),
                this, SLOT(slotEditorDestroyed(QObject *)));
    return editor;
}
QWidget *SnVariantFactory::createEditor(QtVariantPropertyManager *manager,
        QtProperty *property, QWidget *parent)
{
    if (manager->propertyType(property) == SnVariantManager::filePathTypeId()) {
        FileEdit *editor = new FileEdit(parent);
        editor->setFilePath(manager->value(property).toString());
        editor->setFilter(manager->attributeValue(property, QLatin1String("filter")).toString());
        theCreatedEditors[property].append(editor);
        theEditorToProperty[editor] = property;

        connect(editor, SIGNAL(filePathChanged(const QString &)),
                this, SLOT(slotSetValue(const QString &)));
        connect(editor, SIGNAL(destroyed(QObject *)),
                this, SLOT(slotEditorDestroyed(QObject *)));
        return editor;
    }
QWidget *VariantEditorFactory::createEditor(QtVariantPropertyManager *manager,
                                            QtProperty *property,
                                            QWidget *parent)
{
    const int type = manager->propertyType(property);

    if (type == filePathTypeId()) {
        FileEdit *editor = new FileEdit(parent);
        FilePath filePath = manager->value(property).value<FilePath>();
        editor->setFilePath(filePath.absolutePath);
        editor->setFilter(manager->attributeValue(property, QLatin1String("filter")).toString());
        mCreatedFileEdits[property].append(editor);
        mFileEditToProperty[editor] = property;

        connect(editor, &FileEdit::filePathChanged,
                this, &VariantEditorFactory::fileEditFilePathChanged);
        connect(editor, SIGNAL(destroyed(QObject *)),
                this, SLOT(slotEditorDestroyed(QObject *)));

        return editor;
    }
QWidget *VariantEditorFactory::createEditor(QtVariantPropertyManager *manager,
                                            QtProperty *property,
                                            QWidget *parent)
{
    const int type = manager->propertyType(property);

    if (type == filePathTypeId()) {
        FileEdit *editor = new FileEdit(parent);
        FilePath filePath = manager->value(property).value<FilePath>();
        editor->setFileUrl(filePath.url);
        editor->setFilter(manager->attributeValue(property, QLatin1String("filter")).toString());
        mCreatedFileEdits[property].append(editor);
        mFileEditToProperty[editor] = property;

        connect(editor, &FileEdit::fileUrlChanged,
                this, &VariantEditorFactory::fileEditFileUrlChanged);
        connect(editor, &QObject::destroyed,
                this, &VariantEditorFactory::slotEditorDestroyed);

        return editor;
    }

    if (type == VariantPropertyManager::tilesetParametersTypeId()) {
        auto editor = new TilesetParametersEdit(parent);
        editor->setTilesetDocument(manager->value(property).value<TilesetDocument*>());
        mCreatedTilesetEdits[property].append(editor);
        mTilesetEditToProperty[editor] = property;

        connect(editor, &QObject::destroyed,
                this, &VariantEditorFactory::slotEditorDestroyed);

        return editor;
    }

    if (type == QVariant::String) {
        bool multiline = manager->attributeValue(property, QLatin1String("multiline")).toBool();
        if (multiline) {
            auto editor = new TextPropertyEdit(parent);
            editor->setText(manager->value(property).toString());
            mCreatedTextPropertyEdits[property].append(editor);
            mTextPropertyEditToProperty[editor] = property;

            connect(editor, &TextPropertyEdit::textChanged,
                    this, &VariantEditorFactory::textPropertyEditTextChanged);
            connect(editor, &QObject::destroyed,
                    this, &VariantEditorFactory::slotEditorDestroyed);

            return editor;
        }
    }

    QWidget *editor = QtVariantEditorFactory::createEditor(manager, property, parent);

    if (type == QVariant::String) {
        // Add support for "suggestions" attribute that adds a QCompleter to the QLineEdit
        QVariant suggestions = manager->attributeValue(property, QLatin1String("suggestions"));
        if (!suggestions.toStringList().isEmpty()) {
            if (QLineEdit *lineEdit = qobject_cast<QLineEdit*>(editor)) {
                QCompleter *completer = new QCompleter(suggestions.toStringList(), lineEdit);
                completer->setCaseSensitivity(Qt::CaseInsensitive);
                lineEdit->setCompleter(completer);
            }
        }
    }

    if (type == QVariant::Color) {
        // Allow resetting a color property to the invalid color
        ResetWidget *resetWidget = new ResetWidget(property, editor, parent);
        connect(resetWidget, &ResetWidget::resetProperty,
                this, &VariantEditorFactory::resetProperty);
        editor = resetWidget;
    }

    return editor;
}