Qt Script for Applications (QSA) - это инструментарий, обеспечивающий поддержку сценариев в приложениях, написанных на С++. QSA включает интерпретатор для языка Qt Script, который основан на ECMAScript (JavaScript). Программы, написанные с использованием Qt Script, имеют полный доступ к интерфейсу прикладного программирования (API) Qt и к любому API, который разработчики приложения захотят предоставить пользователям.
Введение
Инструментарий включает интегрированное средство разработки (IDE) Qt Script for Applications Designer (QSA Designer). QSA Designer похож на Qt Designer, но обладает дополнительной функциональностью, включая более развитый редактор кода и интегрированный отладчик.
QSA находится в состоянии бета-тестирования и, как ожидается, выйдет позже в этом (2002) году для платформ Windows, Unix/Linux и Mac OS X.
Что предоставляют сценарии?
Разработчики больших и сложных приложений сталкиваются с двумя проблемами:
- Независимо от функциональных возможностей и количества настроек приложения всегда бывают случаи, когда выбор пользователя оказывается в чем-то ограничен.
- Расширение функциональности и гибкости приложений, а также быстрое исправление ошибок могут обходиться очень дорого.
Использование сценариев в приложениях позволяет облегчить решение указанных проблем и предоставляет четыре дополнительных преимущества:
- Сценарии позволяют пользователям создавать собственные решения на базе функциональности, предоставляемой приложением.
- Сценарии позволяют отделам поддержки быстро и легко решать проблемы клиентов и исправлять ошибки без вмешательства в код приложений.
- Приложения с поддержкой сценариев более привлекательны для реселлеров. Они могут продавать готовые решения, основанные на приложениях и собственных сценариях.
- Приложения с поддержкой сценариев позволяют разработчикам сосредоточиться на создании базовых возможностей программы, а многочисленные функциональные вариации предоставить для реализации пользователям.
Поддержка сценариев - проверенное и широко используемое решение: от Microsoft Office VBA до Emacs Lisp. Некоторые клиенты Qt уже предлагают поддержку сценариев в своих приложениях на базе продуктов третьих фирм, поэтому потребность в поддержке сценариев для приложений Qt может быть удовлетворена Qt Script.
Добавление поддержки сценариев в приложение
Процесс добавления поддержки сценариев в приложение состоит из пяти шагов.
- Собрать с библиотекой QSA.
Для этого достаточно в файл .pro приложения добавить пару строк:
unix:LIBS += -lqsa
win32:LIBS += $(QTDIR)\lib\qsa100.lib
- Добавить объекты приложения в механизм поддержки сценариев.
Обеспечить доступ к объектам приложения из сценариев можно с помощью вызова QtApplicationScript::addObject(). Например, если будет добавлен объект fadeEffects, то из Qt Script он будет доступен как Application.fadeEffects. После того, как объект добавлен, автор сценария может вызывать слоты объекта и изменять любые его свойства. Сигналы, которые посылает объект, могут быть связаны с функциями Qt Script. Удалить объекты из области видимости механизма поддержки сценариев можно с помощью removeObject().
Любой подкласс QObject может быть сделан доступным для программистов Qt Script. На практике разработчики должны создать несколько подклассов QObject, которые будут использоваться для изменения состояния приложения. Чтобы подкласс QObject сделать доступным для использования в Qt Script, необходимо использовать макросс Q_OBJECT (который обычно используют все подклассы QObject), и макросс Q_PROPERTY для его свойств. Любые свойства, сигналы и слоты объекта можно сделать доступными для механизма поддержки сценариев.
- Открыть проект сценария.
Проект сценария (scripting project) является контейнером для набора функций и классов. Некоторые приложения могут использовать один проект сценария; другие могут использовать несколько. QSA может открыть и сохранить проект сценария в файл или поместить его в поток (datastream). Например, при инициализации приложение создает указатель на объект QtApplicationScript, потом для тех объектов, доступ к которым нужно предоставить, вызывает addObject(), и затем с помощью QtApplicationScript::open() открывает проект сценария.
- Разрешить пользователю создавать и редактировать сценарии.
Если пользователям разрешено создавать свои собственные диалоги (например, для установки параметров в пользовательских функциях), им может быть предоставлен доступ к программе QSA Designer, которая может использоваться для создания, редактирования, выполнения и отладки сценариев. Это достигается с помощью лишь одного вызова: QtApplicationScript::self()->openDeveloper().
Если пользователям разрешено создавать лишь не-GUI функции, они могут использовать либо QSA Designer с отключенными возможностями по созданию интерфейса, например QtApplicationScript::self()->openDeveloper(FALSE), либо текстовый редактор (например, QTextEdit) для написания собственного кода.
- Разрешить пользователю выполнять сценарии.
Сценарии могут выполняться программой QSA Designer. Сценарии, созданные в текстовом редакторе, могут быть выполнены передачей строки, содержащей сценарий, в функцию QtApplicationScript::evaluate(). На практике мы хотим предоставить пользователям доступ к своим сценариям непосредственно из приложения. Вот пример, показывающий, как автоматически создать QAction для любой пользовательской глобальной функции:
void MyApp::addScript(const QString &funcName,
const QPixmap &pixmap )
{
QAction *a = new QAction( funcName, pixmap,
funcName, 0, this,
funcName.latin1() );
a->addTo( scriptsToolbar );
a->addTo( scriptsMenu );
connect( a, SIGNAL( activated() ), this,
SLOT( runScript() ) );
}
В этом примере мы создаем объект QAction, добавляем его в меню и панель инструментов Qt Script, и связываем сигнал activated() с нашим слотом runScript().
Когда пользователь произведет выбор из меню или панели инструментов, сценарий будет выполнен с помощью функции call():
void MyApp::runScript()
{
QAction *action = (QAction*)sender();
QtApplicationScript::self()->call(
action->text(), QValueList < QVariant >() );
}
Сначала мы получаем указатель на объект QAction, затем с помощью функции call() по имени объекта action вызываем сценарий. Так как в вызываемую функцию мы не передаем никаких параметров, указываем пустой объект QValueList. В случае необходимости передачи параметров пользователь должен будет создать диалог и установить параметры с помощью элементов управления.
Функция QtApplicationScript::globalFunctions() возвращает список всех глобальных функций в текущем проекте сценария.
Как мы увидели, добавление поддержки сценариев в приложение является простым делом. Чтобы получить доступ к механизму поддержки сценариев и программе QSA Designer, приложение должно быть собрано с библиотекой QSA. Как только библиотека QSA становится доступной, добавление объектов приложения в механизм поддержки сценариев, открытие проектов сценариев и предоставление пользователям возможности создания, редактирования, выполнения и отладки сценариев может быть достигнуто всего лишь с помощью нескольких строк кода.
QSA Designer
QSA Designer - это инструмент, который пользователи и разработчики используют для создания, редактирования, выполнения и отладки сценариев. QSA Designer включен в QSA-библиотеку и доступен всем приложениям. Кроме длинного названия QSA Designer включает средство создания GUI-интерфейса, аналогичное имеющемуся в Qt Designer, редактор кода Qt Script и интегрированный отладчик.
Интегрированная среда разработки использует те же самые подходы в создании GUI-интерфейса, что и Qt Designer. Пользователи могут приближенно размещать элементы интерфейса и выбором одного из типов компоновок в панели инструментов создавать масштабируемые диалоги. Также среда разработки позволяет легко связывать сигналы со слотами.
Если у пользователей не должно быть возможности создавать собственные диалоги, разработчики могут отключить возможности создания GUI в среде QSA Designer. В этом режиме пользователи могут создавать, редактировать, выполнять и отлаживать лишь не-GUI функции.
QSA Designer включает полностью интегрированный отладчик, который предлагает точки останова, пошаговое выполнение, отслеживание переменных и окно стека. Если в процессе отладки курсор мыши остановить над переменной, в окне всплывающей подсказки отобразится тип переменной и ее значение. Редактор кода имеет подсветку синтаксиса, авто-завершение, подсказку аргументов и сворачивание.
Внутри
Использование сценариев делает возможным интеграцию объектной модели приложения C++ с интерпретатором сценариев. Для QSA это означает, что большая часть Qt и, в особенности, объектная модель Qt должны быть доступны для Qt Script.
Предоставление доступа к откомпилированным функциям из сценариев называется 'привязыванием' (binding). Для осуществления привязывания применяются различные подходы, но наиболее распространенным является использование генератора кода, который производит синтаксический разбор объявлений классов C++, и на основе собранной информации для каждого класса создает обертку (wrapper), которая обычно является подклассом. В дальнейшем интерпретатор сценариев вызывает код обертки. Этот подход имеет два существенных недостатка: он сильно раздувает код, потому что подкласс обертки должен быть создан для каждого класса, и очень утомителен, потому что обертка должна быть создана для каждого класса, который разработчик захочет использовать в сценариях.
Подход, использованный в QSA, совершенно отличен, и основан на мета-объектной системе Qt. Мета-объектная система использует механизм сигналов и слотов, с которым знакомы все программисты Qt. Она также использует систему свойств Qt. Мета-объектная система может использоваться во время выполнения для создания и удаления связей сигнал-слот, для запросов, получения и изменения свойств, и для доступа к информации RTTI (Run Time Type Identification). Ни для одной из этих динамических возможностей не нужны подклассы оберток и не потребуется писать какой-либо другой код.
Небольшое количество кода, который предоставляет эти возможности, уже создано компилятором moc (Meta Object Compiler). В результате каждый класс и подкласс QObject, а также все их свойства, сигналы и слоты автоматически доступны для использования в сценариях. Не-QObject классы могут легко быть сделаны доступными для сценариев, если их обернуть в QObject. Этот подход работает даже для плагинов (plugins), поэтому классы или подклассы QObject, используемые в плагинах, будут доступны в сценариях.
Приведенная диаграмма показывает взаимосвязи между механизмом поддержки сценариев (QSA Library), приложением и сценариями приложения. Разработчики сценариев могут получить доступ непосредственно к объектам QObject, для которых был вызван метод addObject(), как будто эти объекты встроены в сам язык Qt Script. Объекты QObject могут быть объектами приложения или объектами, специально созданными разработчиками для программистов сценариев с целью предоставления им простого управления приложением. QSA Designer интегрирован с механизмом поддержки сценариев для обеспечения удобства создания, редактирования, выполнения и отладки сценариев.
Язык Qt Script
Qt Script основан на ECMAScript 4.0 (также известном, как JavaScript 2.0 или JScript.NET). Qt Script полностью объектно-ориентирован и использует объектную модель, подобную имеющейся в Qt. Он обладает возможностями современных языков, такими как использование высокоуровневых типов данных и управление исключениями, а также предлагает полный Qt API. Синтаксис Qt Script подобен C++ и Java, но менее сложен. Qt Script обеспечивает более богатые возможности, чем того требует ECMAScript; например, класс String обладает всей функциональностью QString. Такие расширения языка разрешены стандартом ECMAScript.
Ниже представленный код является примером реализации слота в Qt Script.
function buttonCalculate_clicked()
{
var divisor;
switch ( comboCurrency.currentText ) {
case "EUR":
divisor = 1.13091;
break;
case "GBP":
divisor = 0.700417;
break;
case "JPY":
divisor = 131.446;
break;
}
const spinOutCol = spinOutputColumn.value - 1;
const spinCol = spinColumn.value - 1;
for ( var i = spinStartRow.value - 1;
i <= spinEndRow.value - 1; ++i )
with ( Application.sheet1 )
setText( i, spinOutCol,
text( i, spinCol ) / divisor );
accept();
}
Переменные объявляются с помощью var, а не конкретным именем типа, потому что, как и большинство языков сценариев, Qt Script не является строго типизированным языком. Объекты comboCurrency, spinStartRow и другие 'spin'-объекты являются элементами того же самого диалога, в котором размещена кнопка этого слота. Оператор with позволяет пользователям опускать подробные описания. Например, Application.sheet1.setText() и Application.sheet1.text() в представленном выше коде записаны как setText() и text(). Для доступа к глобальным объектам в слоте используется объект Application.
Основу языка Qt Script составляют арифметические и логические операторы, циклы for и while, операторы if, switch, и др., которые уже знакомы многочисленным пользователям языков JavaScript и JScript. Это обстоятельство наряду с гибкой функциональностью и простотой в использовании делает Qt Script идеальным языком сценариев для пользователей конечных приложений. Тем не менее, в некоторых отраслях промышленности и сегментах рынка пользователи уже столкнулись с другими языками сценариев, такими, как Python и Tcl. QSA-технология привязывания является нейтральной по отношению к языку, и поэтому в будущих версиях QSA другие языки будут получать поддержку по мере востребованности.
Подведение итогов
Приложения с поддержкой сценариев обеспечивают гибкость и выгоду для отделов поддержки и конечных пользователей, а также освобождают разработчиков от многочисленных функциональных вариаций. QSA предоставляет в распоряжение программистов сценариев все возможности Qt.
Библиотека QSA представляет собой готовое решение для включения его разработчиками в свои приложения. Она содержит интерпретатор языка сценариев и QSA Designer, мощную интегрированную среду разработки, предназначенную для создания, редактирования, выполнения и отладки сценариев конечными пользователями. QSA позволяет легко добавить в приложения поддержку сценариев. Если вы хотите узнать больше о QSA, пишите qsa@trolltech.com.