О лицензиях qt (и немного о компании)
Содержание:
Установка Qt Creator в Linux
На этих уроках используется операционная система Linux (Debian 9.x 64-bit), поэтому мы скачиваем , но вы также можете использовать соответствующие файлы Qt для Windows или macOS:
После окончания загрузки переходим в папку с необходимым нам файлом, нажимаем на него правой кнопкой мыши и выбираем . На вкладке видим , , , а также наименование родительской папки:
Переходим на вкладку и ставим галочку возле пункта :
Закрываем и запускаем программу.
Шаг №2: На следующем этапе установщик сообщает, что нам предоставлена версия с открытым исходным кодом Qt 5.13.0. Дальнейшая установка Qt предполагает регистрацию в Qt и создание Qt Account, который предоставляет доступ ко всем возможностям Qt. Кроме того, данное действие необходимо для проверки лицензии (коммерческая/некоммерческая). Если у вас уже есть учетная запись в Qt Account, то используйте кнопку .
Если учетной записи в Qt Account у вас еще нет, то её можно создать сейчас: для этого перейдите по соответствующей ссылке в установщике, и вы будете перенаправлены на сайт qt.io в соответствующий раздел, или просто используйте кнопку — вы сможете это сделать на следующем шаге:
Шаг №3: Здесь необходимо ввести логин и пароль от Qt Account или создать Qt Account, если его у вас еще нет. Кнопка переводит нас на следующий этап:
Добро пожаловать в настройки Qt 5.13.0! Для перехода к следующему шагу нажимаем :
Шаг №4: Выбираем каталог для установки Qt 5.13.0
Обратите внимание, адрес каталога указывается латинскими буквами (без кириллицы) и без пробелов! После того, как выбрали каталог, нажимаем :
Шаг №5: Выбираем компоненты, которые хотим установить. Если на данном этапе у вас нет уверенности в выборе конкретных компонентов, то добавление и удаление можно будет сделать позже, после установки программы:
Шаг №6: Принимаем лицензионное соглашение:
И нажимаем на кнопку :
Для завершения установки нажимаем . После завершения установки Qt Creator запустится самостоятельно (для этого необходимо поставить галочку возле пункта ):
Вот примерно следующее вы должны увидеть при запуске Qt Creator:
Поздравляем! Qt Creator установлен.
Вакансии
В этом году вакансий не так много, как в прошлом, но поиск новых сотрудников продолжается. Так что если что-то заинтересовало, можете написать мне, и я расскажу подробнее.
Вот например уже больше полутора лет (серьёзно) в берлинский офис разыскивается sales engineer — это такой человек, который разбирается в Qt и при этом может разговаривать с людьми (клиентами) и отвечать на их технические вопросы. Уже настолько отчаялись найти, что возьмём кого угодно будем рады любым кандидатам. Кстати, не самый плохой способ завести трактор, хотя наверное мне не стоит такое говорить. Осложняется вакансия тем, что так как позиция в Берлине, то очень желательно знание ещё и немецкого.
Всего в 2017 наняли около 130 человек. Люди приходят из всех (включая русскоязычные) частей планеты, никаких рассовых/религиозных/половых предпочтений/предрассудков нет (кроме того что на позиции эффективных менеджеров берут только чаще финнов (шутка)).
Разница в доступных компонентах по лицензиям
Различия в доступных компонентах есть не только между коммерческой и Open Source версией Qt, но также и между GPL и LGPL (какие-то компоненты доступны только в GPL).
Вот тут надо сказать о KDE Free Qt Foundation. В 1998 году между сообществом KDE и тогда ещё Trolltech было заключено соглашение, что Qt всегда будет доступен как свободное ПО, и это соглашение соблюдалось и соответствующе обновлялось при смене владельцев Qt. Но относительно недавно условия соглашения были, скажем так, нарушены — в составе Qt появился ряд библиотек, которые были доступны только под коммерческой лицензией — это как раз-таки Qt Charts, Qt Data Visualization, Qt Virtual Keyboard и другие. В общем, отношения начали слегка портиться. К счастью, руководство всё-таки приняло решение сделать эти библиотеки доступными и в Open Source, что и произошло в релизе Qt 5.7 — они стали доступны под GPL.
Но кстати говоря, разрыв между GPL и LGPL в этом плане в дальнейшем будет только увеличиваться — новые фичи будут лицензироваться преимущественно под GPL (и коммерческой лицензией, конечно).
Кроме разницы в доступных компонентах отдельного внимания заслуживает техническая поддержка, которая, как уже говорилось, доступна только с коммерческой лицензией, а также необходимость (или её отсутствие) соблюдать требования и ограничения соответствующей Open Source лицензии.
И всё же, если ставить вопрос ребром, что доступно в какой лицензий, и в какой чего наоборот не хватает, то для начала можно ознакомиться с таблицей сравнения на сайте, но её актуальность оставляет желать: там содержится не полный перечень отличий, а некоторые пункты и вовсе просто повторяются, предлагая одно и то же разными словами. В общем, я попытался создать более подробную таблицу. Хотя не исключено, что и моя тоже окажется неполной — в фреймворк входит слишком много компонентов (положительный такой минус).
Возможности разметки таблиц небогаты, потому пришлось картинкой. Ссылки на компоненты, понятное дело, теперь в виде пикселей.
И несколько комментариев по таблице.
Стоимость 0
За Open Source лицензии не нужно платить в явном виде, однако следует понимать, что некоторые расходы всё-таки последуют, пусть они и неочевидны на первый взгляд:
Charts, Visualization и Virtual Keyboard
Те самые компоненты, которые раньше были доступны только в коммерческой лицензии. Начиная с Qt 5.7 они доступны и под GPL (но по-прежнему недоступны под LGPL).
Qt Quick Compiler
Qt Quick Compiler был (и остаётся) доступным только в коммерческой версии Qt. Его обещали отдать в Open Source с релизом 5.7, потом 5.8, потом 5.9, а сейчас вроде как больше не обещают, только предложили “взамен” механизм кэширования (который всё же не то же самое).
Qt Quick 2D Renderer
Этот модуль был раньше только коммерческий, потом стал доступен и в GPL, а после релиза 5.8 перестал быть отдельным модулем, и теперь интегрирован в Qt Quick и доступен также под LGPL.
Готовые наборы инструментов сборки
Готовые «из коробки» наборы инструментов сборки для кросс-компиляции, отладки, деплоя и профилирования с хост-машины на присоединённом устройстве.
На скриншоте ниже показано меню выбора “таргета” для проекта в Qt Creator — под какую платформу компилировать (кросс-компилировать) и где запустить приложение. Конкретно тут я собираю проект под Raspberry Pi 3 и хочу запустить своё приложение на подключённом по сети устройстве:
А на этом скриншоте показан полный список устройств, для которых «из коробки» имеются готовые образы и инструменты сборки:
Разумеется, это не означает, что больше ни на каких устройствах разработку с Qt вести не получится. Свой образ Boot to Qt можно собрать для любой платформы, которая соответствует требованиям.
Why Qt?
Today’s consumers require and expect ever faster and more intuitive user experience along with a more modern, reliable, and responsive user interface. Expectations are high as people across the world have gotten used to the high benchmark set by their smartphones.
We at Qt have helped our customers in over 70 industries to develop world-class products for desktop, embedded, and mobile operating systems. The foremost global companies create medical, in-vehicle systems, and industrial automation devices with Qt. Why?
Reduced time-to-market: Key factors that affect the go-to-market time are actual product development time and regulatory and compliance time-frames. Qt’s various libraries and toolsets allow your software team to develop faster. Developers can focus on creating the best user experiences instead of coding what is already been coded for you. The cycle of Prototyping –Development – Testing – Deployment is faster and more efficient with Qt. Qt also supports your regulatory and compliance efforts through our internal resources or our industry-leading partner network.
Scalable Solution: Qt is a cross-platform framework, compatible with a multitude of operating systems and hardware. All you need is to write your source code once and have the capability to deploy it anywhere you need it. You do not need teams of developers coding specifically for different hardware architectures or operating systems.
Lower total cost of ownership (TCO): Fewer resources needed and quicker time to market means a lower total cost of ownership and faster revenue recognition.
Qt 2
KDE 2/Qt Programming Bible
|
Linux Rapid Application Development
|
Qt Programming for Linux and Windows 2000
|
Qt Programming in 24 hours
|
Редакторы
Qt Creator поставляется с редактором кода и Qt Designer для проектирования и сборки графических интерфейсов пользователя (GUI) из виджетов Qt.
Редактор кода
Так как он является IDE, Qt Creator отличается от текстового редактора тем, что знает как собирать и запускать приложения. Он понимает языки C++ и QML как код, а не как простой текст. Это позволяет ему:
- Дать вам возможность писать хорошо форматированный код
- Угадывать что вы хотите написать и дополнять код
- Отображать сообщения об ошибках и предупреждения
- Дать вам возможность перемещаться между классами, функциями и символами
- Предоставлять вам контекстно-зависимую справку по классам, функциям и символам
- Осмысленно переименовывать символы так, что другие символы с таким же именем но принадлежащие другим областям действия не будут переименованы
- Показывать вам место в коде где функция была описана или вызвана
Дизайнер интерфейса
Вы можете использовать Qt Designer чтобы располагать и настраивать ваши виджеты или диалоги и тестировать их используя разные стили и разрешения экрана. Созданные с помощью Qt Designer виджеты и формы легко интегрируются в программный код с использованием механизма сигналов и слотов Qt, которые позволят вам легко определить поведение графических элементов. Все свойства, установленные в Qt Designer, могут быть динамически изменены в коде. Более того, такие особенности как продвижение виджетов и собственные модули позволят вам использовать собственные виджеты с Qt Designer.
Архитектура сервера
Диаграмма классов сервера приведена на рисунке.
Толстыми стрелочками показана иерархия наследования классов, а тонкими — принадлежность членов и методов классам. В общем случае, для службы генерируется класс QServerService, где servicename — имя службы, объявленное в .proto файле. RPCCallData — это управляющие структуры, сгенерированные для каждой RPC в службе. В конструкторе класса QpingServerService происходит инициализация базового класса QGrpcServerService асинхронной службой gRPC pingpong::ping::AsyncService. Для запуска службы нужно вызвать метод Start() с адресом и портом, на которых будет работать служба. В функции Start() реализована стандартная процедура запуска службы.
В конце функции Start() вызывается вызывается чисто виртуальная функция makeRequests(), которая реализована в сгенерированном классе QpingServerService:
Второй шаблонный параметр функции needAnotherCallData — это сгенерированные структуры RPCCallData. Эти же структуры являются параметрами сигналов в сгенерированном классе Qt службы.
Сгенерированные структуры RPCCallData наследуются от класса ServerCallData. В свою очередь, класс ServerCallData наследуется от респондера ServerResponder. Таким образом, создание объекта сгеренированных структур приводит к созданию объекта респондера.
Конструктор класса ServerCallData принимает два параметра: signal_func и request_func. signal_func — это сгенерированный сигнал, который вызывается после получения тэга из очереди. request_func — это функция, которая должна быть вызвана при создании нового респондера. Например, в данном случае это может быть функция RequestSayHello(). Вызов request_func происходит именно в функции needAnotherCallData(). Это сделано для того, чтобы управление респондерами (создание и удаление) происходило в службе.
Код функции needAnotherCallData() состоит из создания объекта респондера и вызова функции, связывающей респондер с вызовом RPC:
Функции RequestRPC() — это шаблонные функции для четырех видов взаимодействия. В итоге, вызов RequestRPC() сводится к вызову:
где service_ — это служба gRPC. В данном случае, это pingpong::ping::AsyncService.
Для синхронной или асинхронной проверки очереди событий необходимо вызвать функции CheckCQ() или AsyncCheckCQ() соответственно. Код функции CheckCQ() сводится к вызовам функции синхронного получения тэга из очереди и обработки этого тэга:
После получения тэга из очереди идут проверки валидности тэга и старта сервера. Если сервер выключен, то тэг уже не нужен — его можно удалить. После этого вызывается функция cqReaction(), определенная в класса ServerCallData:
Флаг first_time_reaction_ говорит о том, что нужно создать новый респондер для вызванной RPC. Функции CouldBeDeleted() и ProcessEvent() унаследованы от класса респондера ServerResponder соответствующего вида. Функция CouldBeDeleted() возвращает признак того, что объект респондера может быть удален. Функция processEvent() обрабатывает тэг и флаг ok. Так, например, для респондера вида Client Streaming функция выглядит следующим образом:
Функция ProcessEvent() вне зависимости от вида респондера всегда возвращает true. Возвращаемое значение этой функции оставлено для возможного расширения функциональности и, теоретически, для устранения ошибок.
После обработки события следует вызов:
Переменная service_ — это экземпляр сгенерированной службы, в нашем случае QpingServerService. Переменная signal_func_ — это сигнал службы, соответствующий конкретной RPC. Например, SayHelloRequest(). Переменная genRpcCallData — это объект респондера соответствующего вида. С точки зрения вызывающего кода, переменная genRpcCallData — это объект одной из сгенерированных структур RPCCallData.
Архитектура клиента
По возможности, имена классов и функций клиента совпадают с именами классов и функций сервера. Диаграмма классов клиента приведена на рисунке.
Толстыми стрелочками показана иерархия наследования классов, а тонкими — принадлежность членов и методов классам. В общем случае, для службы генерируется класс QСlientService, где servicename — имя службы, объявленное в .proto файле. RPCCallData — это управляющие структуры, сгенерированные для каждой RPC в службе. Для вызова RPC, сгенерированный класс предоставляет функций, имена которых в точности соответствуют RPC, объявленным в .proto файле. В нашем примере, в .proto файле RPC SayHello() объявлена как:
В сгенерированном классе QpingClientService соответствующая RPC функция выглядит так:
Сгенерированные структуры RPCCallData, как и в случае сервера, наследуются в конечном счете от класса ClientResponder. Поэтому создание объекта сгенерированной структуры приводит к созданию респондера. После создания респондера происходит вызов RPC и связывание респондера с событием получения ответа от сервера. С точки зрения клиентского кода, вызов RPC выглядит следующим образом:
В отличии от сгенерированного класса сервера QpingServerService, класс QpingClientService наследуется от двух шаблонных классов: ConnectivityFeatures и MonitorFeatures.
Класс ConnectivityFeatures отвечает за состояние подключения клиента с сервером и предоставляет в использование три функции: grpc_connect(), grpc_disconnect(), grpc_reconnect(). Функция grpc_disconnect() просто удаляет все структуры данных, отвечающие за взаимодействие с сервером. Вызов функции grpc_connect сводится к вызовы функции grpc_connect_(), которая создает управляющие структуры данных:
Класс ChannelFeatures отслеживает состояние канала связи channel_ с сервером. Класс ConnectivityFeatures инкапсулирует объект класса ChannelFeatures и с помощью этого объекта реализует абстрактные функции channelState(), checkChannelState() и connected(). Функция channelState() выдает последнее наблюдаемое (last observed) состояние канала связи с сервером. Функция checkChannelState(), фактически, выдает текущее состояние канала. Функция connected() возвращает признак подключения клиента к серверу.
Класс MonitorFeatures отвечает за получение и обработку событий с сервера и предоставляет в использование функцию CheckCQ():
Структура кода такая же, как в случае сервера. В отличии от сервера, в клиенте добавляется блок кода, отвечающий за обработку текущего состояния. Если состояние канала связи изменилось, вызывается сигнал channelStateChangedSignal_(). Во всех сгенерированных службах это сигнал:
После получения события из очереди, как и в случае с сервером, вызывается функция cqReaction(), определенная в классе ClientCallData:
Как и в случае сервера, функция processEvent() обрабатывает тэг и флаг ok и всегда возвращает true. Как и в случае сервера, после обработки события следует вызов сигнала сгенерированной службы. Однако, здесь есть два существенных отличия от одноименной серверной функции. Первое отличие состоит в том, что в этой функции не происходит создание респондеров. Cоздание респондеров, как было показано выше, происходит при вызове RPC. Второе отличие состоит в том, что в этой функции не происходит удаление респондеров. Отсутствие удаления респондеров сделано по двум причинам. Во-первых, клиентский код может использовать указатели на сгенерированные структуры RPCCallData для своих целей. Удаление содержимого по этому указателю, скрытое от клиентского кода, может привести к неприятным последствиям. Во-вторых, удаление респондера приведет к тому, что сигнал с данными сгенерирован не будет. Следовательно, клиентский код не будет получать последнее сообщение сервера. Среди нескольких альтернатив решения обозначенных проблем, было выбрано решение переложить удаление респондера (сгенерированных структур) на клиентский код. Таким образом, функции-обработчики сигналов (слоты) должны содержать следующий код:
Отсутствие удаления респондера в клиентском коде приведет не только к утечке памяти, но и возможным проблемам с каналом связи. Обработчики сигналов всех видов взаимодействия RPC реализованы в коде примеров.
Создание проекта
Вначале нам необходимо создать проект. Сразу скажу, что наша программа будет консольным приложением. Для этого выберите или можно воспользоваться сочетанием клавиш :
Перед вами появится «Мастер настройки проектов». В левой колонке отметьте пункт , а затем в правой — :
На следующем шаге нужно будет указать имя для нашей будущей программы и папку, где будут располагаться файлы проекта. У меня это и соответственно:
На следующем шаге без изменений, поэтому просто нажимаем кнопку :
Теперь нам нужно выбрать набор компиляторов, который мы будем использовать для сборки нашего проекта. Я настоятельно рекомендую выбрать (сняв при этом отметки с остальных, если они у вас есть):
На последнем шаге нажимаем :
Теперь вы можете увидеть автоматически сгенерированный Qt-проект консольного приложения. Давайте рассмотрим его детально:
В корневой папке у нас лежит файл My_QtApplication.pro — это основной файл настроек проекта
Мы разберем его позже, а пока обратите внимание на папку «Исходники», в которой расположен файл main.cpp. Данный файл содержит минимальный исходный код нашей программы
Он был автоматически сгенерирован средствами Qt. Я не буду вдаваться в детальное описание класса QCoreApplication, скажу лишь, что он предоставляет обработку сообщений для консольного приложения Qt и является особенностью архитектуры построения Qt-приложений.
Detailed Description
An instance of a QLibrary object operates on a single shared object file (which we call a «library», but is also known as a «DLL»). A QLibrary provides access to the functionality in the library in a platform independent way. You can either pass a file name in the constructor, or set it explicitly with (). When loading the library, QLibrary searches in all the system-specific library locations (e.g. on Unix), unless the file name has an absolute path.
If the file name is an absolute path then an attempt is made to load this path first. If the file cannot be found, QLibrary tries the name with different platform-specific file prefixes, like «lib» on Unix and Mac, and suffixes, like «.so» on Unix, «.dylib» on the Mac, or «.dll» on Windows.
If the file path is not absolute then QLibrary modifies the search order to try the system-specific prefixes and suffixes first, followed by the file path specified.
This makes it possible to specify shared libraries that are only identified by their basename (i.e. without their suffix), so the same code will work on different operating systems yet still minimise the number of attempts to find the library.
The most important functions are () to dynamically load the library file, () to check whether loading was successful, and () to resolve a symbol in the library. The () function implicitly tries to load the library if it has not been loaded yet. Multiple instances of QLibrary can be used to access the same physical library. Once loaded, libraries remain in memory until the application terminates. You can attempt to unload a library using (), but if other instances of QLibrary are using the same library, the call will fail, and unloading will only happen when every instance has called ().
A typical use of QLibrary is to resolve an exported symbol in a library, and to call the C function that this symbol represents. This is called «explicit linking» in contrast to «implicit linking», which is done by the link step in the build process when linking an executable against a library.
The following code snippet loads a library, resolves the symbol «mysymbol», and calls the function if everything succeeded. If something goes wrong, e.g. the library file does not exist or the symbol is not defined, the function pointer will be and won’t be called.
myLib("mylib"); typedef void (*MyPrototype)(); MyPrototype myFunction = (MyPrototype) myLib.resolve("mysymbol"); if (myFunction) myFunction();
The symbol must be exported as a C function from the library for () to work. This means that the function must be wrapped in an block if the library is compiled with a C++ compiler. On Windows, this also requires the use of a macro; see () for the details of how this is done. For convenience, there is a static () function which you can use if you just want to call a function in a library without explicitly loading the library first:
Изменения в существующих модулях
-
В Qt Network и Qt WebSockets добавлена поддержка шифрования TLS PSK. Также в Qt Network была добавлена поддержка настраиваемых параметров Diffie-Hellman и поддержка HTTP/2 в QNetworkAccessManager.
-
Движок Chromium в Qt WebEngine обновлен до версии 53 и получил поддержку печати веб-страниц. Было добавлено новое QML API для создания кастомных диалогов, всплывающих подсказок и контекстных меню. Добавлена поддержка проверки правописания при помощи Hunspell. Также была добавлена поддержка схем view-source: и некотрых chrome:. Версия для Windows теперь требует MSVC 2015 Update 2 или новее.
-
В Qt Charts добавлена возможность создавать диаграммы типа «японские свечи» (candlestick).
-
В Qt Bluetooth добавлена тестовая поддержка периферийной роли BLE для macOS и iOS и центральной роли для WinRT.
- Для модуля Qt Multimedia появилась возможность преобразования громкости между логарифмической и линейной шкалой при помощи QAudio::convertVolume() (и соответствующего API в QML). Компонент VideoOutput в QML теперь поддерживает рендеринг кадров в формате YUV 4:2:2 (YUYV, UYVY). В бэкенд GStreamer для Linux добавлена возможность мониторинга видео с QCamera при помощи QVideoProbe.