14 "com.software-inc.TextArt.TextArtInterface/1.0")

В классе интерфейса обычно объявляются виртуальный деструктор, виртуальная функция, возвращающая список QStringList, и одна или несколько других виртуальных функций. Деструктор объявляется прежде всего для того, чтобы компилятор не жаловался на отсутствие виртуального деструктора в классе, который имеет виртуальные функции. В данном примере функция effects() возвращает список текстовых эффектов, которые могут создаваться подключаемым модулем. Этот список можно рассматривать как список ключей. При каждом вызове одной из функций мы передаем эти ключи в качестве первого аргумента, позволяя реализовать в одном подключаемом модуле несколько эффектов.

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

Это приложение реализуется в виде класса TextArtDialog. Мы будем показывать только тот программный код, который связан с применением подключаемых модулей. Давайте начнем с конструктора:

01 TextArtDialog::TextArtDialog(const QString &text, QWidget *parent)

02 : QDialog(parent)

03 {

04 listWidget = new QListWidget;

05 listWidget->setViewMode(QListWidget::IconMode);

06 listWidget->setMovement(QListWidget::Static);

07 listWidget->setIconSize(QSize(260, 80));

08 …

09 loadPlugins();

10 populateListWidget(text);

11 …

12 }

Конструктор создает виджет QListWidget, содержащий список доступных эффектов. Он вызывает закрытую функцию loadPlugins() для поиска и загрузки всех подключаемых модулей, реализующих интерфейс TextArtInterface, и заполняет список виджетов с помощью вызова другой закрытой функции — populateListWidget().

01 void TextArtDialog::loadPlugins()

02 {

03 QDir pluginDir(QApplication::applicationDirPath());

04 #if defined(Q_OS_WIN)

05 if (pluginDir.dirName().toLower() == "debug"

06 || pluginDir.dirName().toLower() == "release")

07 pluginDir.cdUp();

08 #elif defined(Q_OS_MAC)

09 if (pluginDir.dirName() == "MacOS") {

10 pluginDir.cdUp();

11 pluginDir.cdUp();

12 pluginDir.cdUp();

13 }

14 #endif

15 if (!pluginDir.cd("plugins"))

16 return;

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

18 QPluginLoader loader(pluginDir.absoluteFilePath(fileName));

19 if (TextArtInterface *interface =

20 qobject_cast(loader.instance()))

21 interfaces.append(interface);

22 }

23 }

В функции loadPlugins() мы пытаемся загрузить все файлы, находящиеся в каталоге приложения plugins. (В Windows исполняемый модуль приложения обычно находится в подкаталоге debug или release, поэтому поднимаемся на один каталог выше. В Mac OS X учитываем структуру группового каталога (bundle directory).)

Перейти на страницу:

Похожие книги