Logo    
Деловая газета CitCity.ru CITKIT.ru - все об Open Source Форумы Все публикации Учебный центр Курилка
CitForum    CITForum на CD    Подписка на новости портала Море(!) аналитической информации! :: CITFORUM.RU
IT-консалтинг Software Engineering Программирование СУБД Безопасность Internet Сети Операционные системы Hardware

18.06.2017

Google
WWW CITForum.ru
С Новым годом!
2003 г

Быстрый, гибкий и забавный Qt Script

Fun, Fast and Flexible Qt Script


Авторы: Reginald Stadlbauer & Monica Vittring
Перевод: Andi Peredri

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.

Что предоставляют сценарии?

Разработчики больших и сложных приложений сталкиваются с двумя проблемами:

  1. Независимо от функциональных возможностей и количества настроек приложения всегда бывают случаи, когда выбор пользователя оказывается в чем-то ограничен.
  2. Расширение функциональности и гибкости приложений, а также быстрое исправление ошибок могут обходиться очень дорого.

Использование сценариев в приложениях позволяет облегчить решение указанных проблем и предоставляет четыре дополнительных преимущества:

  1. Сценарии позволяют пользователям создавать собственные решения на базе функциональности, предоставляемой приложением.
  2. Сценарии позволяют отделам поддержки быстро и легко решать проблемы клиентов и исправлять ошибки без вмешательства в код приложений.
  3. Приложения с поддержкой сценариев более привлекательны для реселлеров. Они могут продавать готовые решения, основанные на приложениях и собственных сценариях.
  4. Приложения с поддержкой сценариев позволяют разработчикам сосредоточиться на создании базовых возможностей программы, а многочисленные функциональные вариации предоставить для реализации пользователям.

Поддержка сценариев - проверенное и широко используемое решение: от Microsoft Office VBA до Emacs Lisp. Некоторые клиенты Qt уже предлагают поддержку сценариев в своих приложениях на базе продуктов третьих фирм, поэтому потребность в поддержке сценариев для приложений Qt может быть удовлетворена Qt Script.

Добавление поддержки сценариев в приложение

Процесс добавления поддержки сценариев в приложение состоит из пяти шагов.

  1. Собрать с библиотекой QSA.
    Для этого достаточно в файл .pro приложения добавить пару строк:
        unix:LIBS  += -lqsa
        win32:LIBS += $(QTDIR)\lib\qsa100.lib
    
  2. Добавить объекты приложения в механизм поддержки сценариев.
    Обеспечить доступ к объектам приложения из сценариев можно с помощью вызова QtApplicationScript::addObject(). Например, если будет добавлен объект fadeEffects, то из Qt Script он будет доступен как Application.fadeEffects. После того, как объект добавлен, автор сценария может вызывать слоты объекта и изменять любые его свойства. Сигналы, которые посылает объект, могут быть связаны с функциями Qt Script. Удалить объекты из области видимости механизма поддержки сценариев можно с помощью removeObject().
    Любой подкласс QObject может быть сделан доступным для программистов Qt Script. На практике разработчики должны создать несколько подклассов QObject, которые будут использоваться для изменения состояния приложения. Чтобы подкласс QObject сделать доступным для использования в Qt Script, необходимо использовать макросс Q_OBJECT (который обычно используют все подклассы QObject), и макросс Q_PROPERTY для его свойств. Любые свойства, сигналы и слоты объекта можно сделать доступными для механизма поддержки сценариев.
  3. Открыть проект сценария.
    Проект сценария (scripting project) является контейнером для набора функций и классов. Некоторые приложения могут использовать один проект сценария; другие могут использовать несколько. QSA может открыть и сохранить проект сценария в файл или поместить его в поток (datastream). Например, при инициализации приложение создает указатель на объект QtApplicationScript, потом для тех объектов, доступ к которым нужно предоставить, вызывает addObject(), и затем с помощью QtApplicationScript::open() открывает проект сценария.
  4. Разрешить пользователю создавать и редактировать сценарии.
    Если пользователям разрешено создавать свои собственные диалоги (например, для установки параметров в пользовательских функциях), им может быть предоставлен доступ к программе QSA Designer, которая может использоваться для создания, редактирования, выполнения и отладки сценариев. Это достигается с помощью лишь одного вызова: QtApplicationScript::self()->openDeveloper().
    Если пользователям разрешено создавать лишь не-GUI функции, они могут использовать либо QSA Designer с отключенными возможностями по созданию интерфейса, например QtApplicationScript::self()->openDeveloper(FALSE), либо текстовый редактор (например, QTextEdit) для написания собственного кода.
  5. Разрешить пользователю выполнять сценарии.
    Сценарии могут выполняться программой 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.

 

Подписка на новости IT-портала CITForum.ru
(библиотека, CITKIT.ru, CitCity)

Новые публикации:

24 декабря

CITKIT.ru:

  • Новогодние поздравления
  • Сергей Кузнецов. Цикл Операционные системы: Ностальгия по будущему:

  • Алексей Федорчук. OpenSolaris 2008.11 Release

  • Сергей Голубев:

  • Евгений Чайкин aka StraNNik (Блогометки):

    17 декабря

  • С.Д.Кузнецов. Базы данных. Вводный курс

    10 декабря

    CITKIT.ru:

  • OpenSolaris 2008.11 Release

  • Альтернативные ОС: две грустные истории (С.Кузнецов)
  • Nokia N810 — доведение до ума
  • CitCity:

  • Платформа 2009: заоблачные перспективы Microsoft

    4 декабря

  • Лекция С.Д.Кузнецова Понятие модели данных. Обзор разновидностей моделей данных

    CITKIT.ru:

  • OpenSolaris 2008.11 Release. Первые впечатления

  • Linux vs FreeBSD: продолжим "Священные войны"?

  • Nokia N810 as is

  • Индульгенция для FOSS

  • Друзья СПО'2008

    26 ноября

  • Нечеткое сравнение коллекций: семантический и алгоритмический аспекты

    CitCity:

    CITKIT.ru:

  • Глава из книги А.Федорчука
    Сага о FreeBSD:
  • 19 ноября

  • Проблемы экономики производства крупных программных продуктов

  • Язык модификации данных формата XML функциональными методами

    CITKIT.ru:

  • Главы из книги А.Федорчука
    Сага о FreeBSD:

    Заметки к книге:

  • FreeBSD: монтирование сменных устройств и механизм HAL
  • Текстовый редактор ee

    12 ноября

  • Правило пяти минут двадцать лет спустя, и как флэш-память изменяет правила (Гоц Грейф, перевод: Сергей Кузнецов)

    CITKIT.ru:

  • Главы из книги А.Федорчука
    Сага о FreeBSD:
  • OSS в России: взгляд правоведа (В.Житомирский)

  • Новая статья из цикла С.Голубева "Железный марш":

    29 октября

  • О некоторых задачах обратной инженерии

  • Веб-сервисы и Ruby

  • Тестирование web-приложений с помощью Ruby

    CITKIT.ru:

  • Главы из книги А.Федорчука
    Сага о FreeBSD:

  • PuppyRus Linux - беседа с разработчиком (С.Голубев)

  • Сергей Кузнецов. Заметка не про Linux

    22 октября

  • Обзор методов описания встраиваемой аппаратуры и построения инструментария кросс-разработки

    CITKIT.ru:

  • Сергей Кузнецов. Почему я равнодушен к Linux

  • Глава из книги А.Федорчука
    Сага о FreeBSD:
  • Что надо иметь
    3. Базовые познания

    CitCity:

  • Управление IT-инфраструктурой на основе продуктов Microsoft

    15 октября

  • Методы бикластеризации для анализа интернет-данных

    CitCity:

  • Разъемы на ноутбуках: что они дают и зачем их так много?
  • AMD Puma и Intel Centrino 2: кто лучше?

    CITKIT.ru:

  • Новый цикл статей С.Голубева
    Железный марш:

  • Главы из книги А.Федорчука
    Сага о FreeBSD:

    8 октября

  • Автоматизация тестирования web-приложений, основанных на скриптовых языках
  • Опыт применения технологии Azov для тестирования библиотеки Qt3

    Обзоры журнала Computer:

  • SOA с гарантией качества
  • Пикоджоуль ватт бережет
  • ICT и всемирное развитие

    CitCity:

  • Пиррова победа корпорации Microsoft

    CITKIT.ru:

  • Главы из книги А.Федорчука
    Сага о FreeBSD:

    Статья из архива:

  • Я живу в FreeBSD (Вадим Колонцов)

    Новые Блогометки:

  • Перекройка шаблона Blogger или N шагов к настоящему
  • Blogger. Comment style
  • Screenie или глянцевый снимок экрана

    2 октября

    CITKIT.ru:

  • Сага о FreeBSD (А. Федорчук)

    Zenwalk: пакет недели

  • Банинг — интеллектуальное развлечение (С.Голубев)

    CitCity:

    25 сентября

  • Клермонтский отчет об исследованиях в области баз данных

    CITKIT.ru:

  • Пользователям просьба не беспокоиться... (В.Попов)

  • Снова про ZFS: диск хорошо, а два лучше
  • Командная оболочка tcsh (А.Федорчук)

    Zenwalk: пакет недели

    17 сентября

  • T2C: технология автоматизированной разработки тестов базовой функциональности программных интерфейсов
  • Технология Azov автоматизации массового создания тестов работоспособности

    CITKIT.ru:

  • FreeBSD: ZFS vs UFS, и обе-две — против всех (А.Федорчук)

    Zenwalk: пакет недели

  • Дачнет — практика без теории (С.Голубев)

    10 сентября

  • За чем следить и чем управлять при работе приложений с Oracle
  • Планировщик заданий в Oracle
    (В.Пржиялковский)

    CITKIT.ru:

  • Microsoft: ответный "боян" (С.Голубев)

  • Причуды симбиоза, или снова "сделай сам" (В.Попов)

  • Файловые системы современного Linux'а: последнее тестирование
  • Zsh. Введение и обзор возможностей
    (А.Федорчук)

    Описания пакетов Zenwalk: Zsh, Thunar, Thunar-bulk-rename, Xfce4-places-plugin, Xfce4-fsguard-plugin

    Блогометки:

  • Google Chrome
  • Лончер для ASUS Eee PC 701

    3 сентября

    CITKIT.ru:

  • Заметки о ядре (А.Федорчук):

    Добавлены описания пакетов Zenwalk: Galculator, Screenshot, Gnumeric, Pidgin

    В дискуссинном клубе:

  • И еще о Википедии и Google Knol

  • Лекция для начинающего линуксоида (С.Голубев)

    26 августа

  • Транзакционная память (Пересказ: С. Кузнецов)

    CITKIT.ru:

  • Открыт новый проект Zenwalk: пакет недели

  • Статья Текстовые процессоры и их быстродействие: конец еще одной легенды?

    21 августа

    CITKIT.ru:

  • Почему школам следует использовать только свободные программы (Ричард Столлман)
  • Беседа Сергея Голубева с учителем В.В.Михайловым

  • Википедия или Гуглезнание? Приглашение к обсуждению (Алексей Федорчук)
  • Народная энциклопедия от Google (StraNNik)

  • Обзор Mandriva 2009.0 Beta 1 Thornicrofti
  • Новичок в Линукс: Оптимизируем Mandriva 2008.1

  • Книга Zenwalk. Приобщение к Linux:

    13 августа

    CitCity:

  • Мирный Atom на службе человеку. Обзор платы Intel D945GCLF с интегрированным процессором
  • Обзор процессоров Intel Atom 230 на ядре Diamondville

  • iPhone - год спустя. Скоро и в России?

    CITKIT.ru:

  • Интермедия 3.4. GRUB: установка и настройка (из книги Zenwalk. Приобщение к Linux)

    6 августа

  • СУБД с хранением данных по столбцами и по строкам: насколько они отличаются в действительности? (Пересказ: С. Кузнецов)

    CITKIT.ru:

  • Интермедия 2.2. Что неплохо знать для начала (из книги Zenwalk. Приобщение к Linux)

  • И снова про шрифты в Иксах (А.Федорчук)

  • 20 самых быстрых и простых оконных менеджеров для Linux

  • Дело о трех миллиардах (С.Голубев)

    30 июля

  • OLTP в Зазеркалье (Пересказ: С. Кузнецов)

    CitCity:

  • Будущее BI в облаках?
  • Тиражные приложения и заказная разработка. Преимущества для заказчика
  • Дискуссия со сторонниками заказной разработки

    CITKIT.ru:

  • Новые главы книги Zenwalk. Приобщение к Linux:
  • Глава 8. Пакеты: средства установки, системы управления, системы построения
  • Глава 9. Zenwalk: репозитории, пакеты, методы установки

    23 июля

    CITKIT.ru:

  • Все против всех. 64 vs 32, Intel vs AMD, tmpfs vs ext3
  • Две головы от Intel

  • Zenwalk: обзор штатных приложений (глава из книги "Zenwalk. Приобщение к Linux")

  • Нормально, Григорий...

    16 июля

    Обзоры журнала Computer:

  • Перспективы и проблемы программной инженерии в XXI веке
  • Большие хлопоты с большими объемами данных
  • Перспективы наноэлектроники

    CITKIT.ru:

  • Интермедия о лицензиях (А.Федорчук. "Zenwalk. Приобщение к Linux")

  • Есть ли будущее у KDE?

  • Linux в школе: альтернативный вариант в задачах

  • Шифр (приключения агента Никодима)

    10 июля

    CITKIT.ru:

  • Новые разделы книги А. Федорчука Zenwalk. Приобщение к Linux:
  • Интермедия вступительная. Linux или GNU/Linux? Как вас теперь называть?
  • Глава 5. Среда Xfce
  • Глава 6. Xfce: приложения и плагины

  • ZUR (Zenwalk User Repository) FAQ

    2 июля

  • Персистентность данных в объектно-ориентированных приложениях (С. Кузнецов)

    CITKIT.ru:

  • Новые разделы книги А. Федорчука Zenwalk. Приобщение к Linux:
  • Интермедия 1.2. Дорога к Zenwalk'у. Период бури и натиска
  • Интермедия 3.3. Немного о Linux'е и "железе"
  • Глава 4. Настройка: инструментами и руками
  • Интермедия 4.1. Zenpanel и конфиги: поиски корреляции

  • Интервью с Жан-Филиппом Гийоменом, создателем дистрибутива Zenwalk

  • Linux в школе: первые итоги (С. Голубев)

    25 июня

    CITKIT.ru:

  • Zenwalk. Приобщение к Linux (А. Федорчук)

  • Логика и риторика (С.Голубев)

  • Технология Tru64 AdvFS

  • Ханс Райзер предлагает отвести полицейских к телу Нины

    18 июня

  • Проекты по управлению данными в Google (Пересказ: С. Кузнецов)

    CITKIT.ru:

  • ОС и поддержка "железа": мифы и реальность (А. Федорчук)

  • Linux в школе: другие дистрибутивы

  • Пинок (С. Голубев)

    4 июня

  • Ландшафт области управления данными: аналитический обзор (С. Кузнецов)

    CITKIT.ru:

  • Linux в школе: слово заинтересованным лицам

  • SlackBuild: пакеты своими руками

  • Linux от компании Novell. Установка и обзор openSUSE Linux

    Все публикации >>>




  • IT-консалтинг Software Engineering Программирование СУБД Безопасность Internet Сети Операционные системы Hardware

    Информация для рекламодателей Пресс-релизы — pr@citcity.ru
    Послать комментарий
    Информация для авторов
    Rambler's Top100 This Web server launched on February 24, 1997
    Copyright © 1997-2017 CIT, © 2001-2017 CIT Forum
    Внимание! Любой из материалов, опубликованных на этом сервере, не может быть воспроизведен в какой бы то ни было форме и какими бы то ни было средствами без письменного разрешения владельцев авторских прав. Подробнее...