Qt PluginFramework. Объявите плагины с плагинами - PullRequest
2 голосов
/ 05 февраля 2012

Я хочу создать приложение с плагинами, которые также могут иметь плагины (о которых основное приложение не должно знать).Причина в том, что я хочу сделать общую среду разработки для некоторых проектов кода, а затем я делаю плагин для обработки изображений.Затем я хотел бы, чтобы плагин обработчика изображений имел некоторые собственные плагины фильтров, о которых основное приложение не должно знать.Это возможно?

Вот что я получил сам:

Я хотел бы создать основную IDE с некоторыми интерфейсами.

class IDocumentFactory
{
public:
    virtual ~IDocumentFactory() {}

     //virtual QStringList documents() const = 0;
     virtual QVector<FileOpenEntries>   name_filters() const = 0;
     virtual QWidget* open_document( QWidget* parent,
                                     const QStringList &filepaths,
                                     const QString &name_filter_key) const = 0;

};
Q_DECLARE_INTERFACE(IDocumentFactory,       "S-DAIDE.IDocumentFactory/1.0")
class IDeclarePlugins
{
public:
    virtual ~IDeclarePlugins() {}

    virtual QStringList plugins() const = 0;
    virtual void load_plugings(QObject * plugins) = 0;
};
Q_DECLARE_INTERFACE(IDeclarePlugins,        "S-DAIDE.IDeclarePlugins/1.0")

Теперь я хотел бы определить интерфейсв моем плагине, который могут реализовать другие плагины.

class MyPlugin : public QObject, IDeclarePlugins
{
    Q_OBJECT
    Q_INTERFACES(IDeclarePlugins)

    ...
    QStringList ImagePlugin::plugins() const
    {
    return QStringList() << "S-DAIDE.ImagePlugin.IOverlay/1.0";
    }
}

В моих плагинах загрузки основного приложения.

foreach (QString fileName, m_plugins_dir.entryList(QDir::Files)) {

         QPluginLoader loader(m_plugins_dir.absoluteFilePath(fileName));
         QObject *plugin = loader.instance();

}

Существует ли способ проверить, реализует ли плагин интерфейс, основанный настрока используется с Q_DECLARE_INTERFACE.Таким образом я могу заставить плагин загружать все другие плагины, которые он объявляет virtual QStringList plugins() const = 0;

1 Ответ

1 голос
/ 05 февраля 2012

По умолчанию вы должны qobject_cast использовать интерфейсные классы, но не использовать их ids.

Вы все еще можете создать функцию QString id(), которая будет возвращать ваш id для каждого плагина, вы можете проверить результат этой функции в своем коде загрузчика.

Вы можете проверить, дал ли ваш плагин id, как вы хотите, в принципе, вы можете найти способ сделать это в Q_DECLARE_INTERFACE макроопределении.

bool isIdMatch = const_cast<QObject *>(object)->qt_metacast(IId) != 0;

Но qt_metacast не задокументировано, поэтому я не рекомендую вам использовать этот метод.

Если вы хотите избавиться от многократной записи идентификаторов 2 раза, вы можете использовать макросы, которые так любят в Qt:

#define DECLARE_ID(__iid) \
    virtual QString id() const {return iid_private();}\
    static const char* const iid_private() {return __iid;}

#define GET_ID(IFace) IFace::iid_private()

class IFace
{
public:
    DECLARE_ID("Iface")
};
Q_DECLARE_INTERFACE(IFace, GET_ID(IFace))

class IFace2: public IFace
{
public:
    DECLARE_ID("Iface2")
};
Q_DECLARE_INTERFACE(IFace2,GET_ID(IFace2))


int main(int c, char**v)
{
    IFace* f = new IFace2();
    qDebug() << f->id() << f->iid_private();
    qDebug() << GET_ID(IFace) <<GET_ID(IFace2);
    return 0;//a.exec();
}

Изучите вывод и обратите внимание, что вы должны использовать функцию id() вместо iid_private

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...