Andrei Yankovich
Andrei YankovichНаурыз 24, 2020, 9:50 Т.Ж.

C++/Qt және QML қолданбасын орналастыру утилитасының CQtDeployer v1.4.0 шығарылымы (екілік қорап)

Спустя почти полгода вышло крупное обновление утилиты развертывания CQtDeployer.
В этом обновлении много нововведений, но основной упор сделан на создание пакетов.


CQtDeployer 1.4.0

Исправления

  • Исправлен вывод справки в консоль, теперь перед выводом пересчитывается реальный размер консоли, что позволяет корректно передавать текст.
  • Исправлена работа с деплоем плагинов Qt. Теперь плагины извлекают не все системные зависимости, а только qt. Извлечение системных зависимостей приводило к сбою приложений из-за несовместимых библиотек плагинов.
  • Мелкие исправления ошибок и улучшения.

Новые особенности

  • Добавлена поддержка поиска qmake из системной среды.
  • Добавлена возможность инициализировать репозиторий для дальнейшей упаковки, аналогично git init.
  • Добавлена поддержка пакетов Qt Install Framework. Теперь можно запаковать дистрибутив в установщик.
  • Добавлена возможность разбивать конечный дистрибутив на несколько пакетов.
  • Добавлена возможность унифицировать создание пакетов для финальной раздачи.
  • Добавлена поддержка добавления пользовательских скриптов в скрипты запуска приложений.
  • Добавлена поддержка извлечения системных зависимостей для Windows.
  • Добавлена поддержка RPATH для Linux. Теперь cqtdeployer может самостоятельно определить необходимый qmake для развертывания приложения.
  • Добавлена поддержка поиска нужной зависимости по имени библиотеки.
  • Добавлена поддержка библиотек Qt из репозиториев дистрибутивов Linux.
  • Добавлен новый псевдоним для команды запуска (cqt и cqtdeployer.cqt) для быстрого развертывания приложений.
  • Добавлена поддержка нативного имени команды для windows. Теперь вы можете запустить cqtdeployer из команды cqtdeployer в cmd и powershell.

Новые опции

  • init - инициализирует файл cqtdeployer.json (файл конфигурации). Например: «cqtdeployer init» — для инициализации конфигурации базового пакета. «cqtdeployer -init multi» — для инициализации конфигурации нескольких пакетов.
  • noCheckRPATH - отключает автоматический поиск путей к qmake в исполняемых файлах (только для Linux).
  • noCheckPATH - отключает автоматический поиск путей к qmake в системном окружении.
  • ExtractPlugins - принудительно извлекает все зависимости плагинов.
    -qif - создает установщик в конце развертывания.
  • extraLibs - добавляет шаблон для дополнительной библиотеки, которая должна быть включена в дистрибутив.
  • customScript - добавляет пользовательский скрипт в скрипт запуска приложения.
    --targetPackage [пакет; tar1, пакет; tar2] — используется для формирования пакетов, обозначает списки целевых файлов для конкретных пакетов.
    — recOut — указывает, в какую папку будут добавлены ресурсы после развертывания.
  • name - задает имя пакета.
  • description - устанавливает описание пакета
  • deployVersion — устанавливает версию пакета
  • releaseDate — устанавливает дату выпуска пакета.
  • icon - задает значок пакета.
  • publisher - устанавливает издателя пакета.
  • qifStyle - Задает путь к файлу стилей CSS или задает стиль по умолчанию. Доступные стили: квазар
  • qifBanner - Устанавливает путь к png файлу баннера.
  • qifLogo - Устанавливает путь к png файлу логотипа.

Ссылки для скачивания

Установщик:

Установщик можно скачать на социальной странице github

Snap

Get it from the Snap Store

Внимание

В снап-версии обязательно дайте программе доступ на чтение других процессов. Так как это необходимо для создания установщика и корректного поиска qt.

Подробный разбор самых интересных изменений.

Первое, на что следует обратить внимание, это то, что CQtDeployer научился работать с RPATH (только для Linux) и PATH. Это означает, что если ваше приложение собрано с поддержкой RPATH (а RPATH в qt включен по умолчанию) или ваш qmake прописан в PATH, то вам не нужно указывать путь к qmake. CQtDeployer сам найдет qmake.

Проверим на практике.
Я создал простое консольное приложение с помощью Qt.

#include <QString>
#include <QDebug>
int main(int, char *[])
{
    QString str = "hello CQtDeployer 1.4";
    qInfo() << str;
    return 0;
}

Я буду использовать систему сборки cmake, так как она более актуальна, чем qmake.

andrei@HP:~/Hello$ tree 
.
├── CMakeLists.txt
├── CMakeLists.txt.user
└── main.cpp

0 directories, 3 files

Создайте папку для сборки.

andrei@HP:~/Hello$ mkdir build 

Запустите cmake в созданной папке.

andrei@HP:~/Hello/build$ cmake .. -DCMAKE_PREFIX_PATH=~/Qt/5.14.1/gcc_64
-- Configuring done
-- Generating done
-- Build files have been written to: /home/andrei/Hello/build

создание проекта

andrei@HP:~/Hello/build$ make 
Scanning dependencies of target Hello_autogen
[ 25%] Automatic MOC and UIC for target Hello
[ 25%] Built target Hello_autogen
Scanning dependencies of target Hello
[ 50%] Building CXX object CMakeFiles/Hello.dir/Hello_autogen/mocs_compilation.cpp.o
[ 75%] Building CXX object CMakeFiles/Hello.dir/main.cpp.o
[100%] Linking CXX executable Hello
[100%] Built target Hello

Проверяем нашу программу.

andrei@HP:~/Hello/build$ ls
CMakeCache.txt  CMakeFiles  cmake_install.cmake  Hello  Hello_autogen  Makefile

И запускаем cqtdeployer минуя его программу без qmake.

andrei@HP:~/Hello/build$ cqtdeployer -bin Hello 
Deploy ...
flag targetDir not  used. use default target dir : "/home/andrei/Hello/build/DistributionKit"
target deploy started!!
copy : "/home/andrei/Hello/build/Hello"
extract lib : "/home/andrei/Hello/build/DistributionKit//bin//Hello"
copy : "/home/andrei/Qt/5.14.1/gcc_64/lib/libQt5Core.so.5"
copy : "/home/andrei/Qt/5.14.1/gcc_64/lib/libicuuc.so.56"
copy : "/home/andrei/Qt/5.14.1/gcc_64/lib/libicui18n.so.56"
copy : "/home/andrei/Qt/5.14.1/gcc_64/lib/libicudata.so.56"
copy : "/home/andrei/Qt/5.14.1/gcc_64/translations/qtbase_ar.qm"
copy : "/home/andrei/Qt/5.14.1/gcc_64/translations/qtbase_bg.qm"
copy : "/home/andrei/Qt/5.14.1/gcc_64/translations/qtbase_ca.qm"
copy : "/home/andrei/Qt/5.14.1/gcc_64/translations/qtbase_cs.qm"
copy : "/home/andrei/Qt/5.14.1/gcc_64/translations/qtbase_da.qm"
copy : "/home/andrei/Qt/5.14.1/gcc_64/translations/qtbase_de.qm"
copy : "/home/andrei/Qt/5.14.1/gcc_64/translations/qtbase_en.qm"
copy : "/home/andrei/Qt/5.14.1/gcc_64/translations/qtbase_es.qm"
copy : "/home/andrei/Qt/5.14.1/gcc_64/translations/qtbase_fi.qm"
copy : "/home/andrei/Qt/5.14.1/gcc_64/translations/qtbase_fr.qm"
copy : "/home/andrei/Qt/5.14.1/gcc_64/translations/qtbase_gd.qm"
copy : "/home/andrei/Qt/5.14.1/gcc_64/translations/qtbase_he.qm"
copy : "/home/andrei/Qt/5.14.1/gcc_64/translations/qtbase_hu.qm"
copy : "/home/andrei/Qt/5.14.1/gcc_64/translations/qtbase_it.qm"
copy : "/home/andrei/Qt/5.14.1/gcc_64/translations/qtbase_ja.qm"
copy : "/home/andrei/Qt/5.14.1/gcc_64/translations/qtbase_ko.qm"
copy : "/home/andrei/Qt/5.14.1/gcc_64/translations/qtbase_lv.qm"
copy : "/home/andrei/Qt/5.14.1/gcc_64/translations/qtbase_pl.qm"
copy : "/home/andrei/Qt/5.14.1/gcc_64/translations/qtbase_ru.qm"
copy : "/home/andrei/Qt/5.14.1/gcc_64/translations/qtbase_sk.qm"
copy : "/home/andrei/Qt/5.14.1/gcc_64/translations/qtbase_uk.qm"
copy : "/home/andrei/Qt/5.14.1/gcc_64/translations/qtbase_zh_TW.qm"
try deploy msvc
deploy done!

О чудо, теперь наше приложение полностью автономно.
Проверьте это.

andrei@HP:~/Hello/build$ cd DistributionKit/
andrei@HP:~/Hello/build/DistributionKit$ tree 
.
├── bin
│   ├── Hello
│   └── qt.conf
├── Hello.sh
├── lib
│   ├── libicudata.so.56
│   ├── libicui18n.so.56
│   ├── libicuuc.so.56
│   └── libQt5Core.so.5
└── translations
    ├── qtbase_ar.qm
    ├── qtbase_bg.qm
    ├── qtbase_ca.qm
    ├── qtbase_cs.qm
    ├── qtbase_da.qm
    ├── qtbase_de.qm
    ├── qtbase_en.qm
    ├── qtbase_es.qm
    ├── qtbase_fi.qm
    ├── qtbase_fr.qm
    ├── qtbase_gd.qm
    ├── qtbase_he.qm
    ├── qtbase_hu.qm
    ├── qtbase_it.qm
    ├── qtbase_ja.qm
    ├── qtbase_ko.qm
    ├── qtbase_lv.qm
    ├── qtbase_pl.qm
    ├── qtbase_ru.qm
    ├── qtbase_sk.qm
    ├── qtbase_uk.qm
    └── qtbase_zh_TW.qm

3 directories, 29 files
andrei@HP:~/Hello/build/DistributionKit$ 

Корень программы:

image

Библиотеки необходимые для работы программы:

image

Как видно из примера, приложение полностью собрано.

Каркас установщика Qt

Второе новшество, о котором стоит знать, — это возможность формировать QIF-установщики из коробки. Все, что нужно для нашего примера, это добавить опцию qif в команду упаковки.

Пример использования.

andrei@HP:~/Hello/build$ cqtdeployer -bin Hello qif 

Всего одна простая команда и программа приобретает презентабельный вид.

image

Этот установщик поддерживает минимальную интеграцию дистрибутивов Linux и Windows. А именно: создание ярлыков, и регистрация приложения в ОС.
Если вас по какой-то причине не устраивает внешний вид этого установщика, вы можете изменить его с помощью флага qifStyle. На момент версии 1.4 cqtdeployer поддерживает только 2 стиля (native и quasar).

Пример стиля квазара:

image

Вы также можете использовать свою собственную таблицу стилей qss. Для этого передайте путь к вашему qss или css файлу вместо имени стиля.
Например, рассмотрим следующую таблицу стилей qss.

Style.qss:

QWidget
{
    color: white;
    background-color: rgb(65, 65, 65);
}

QPushButton
{
    background: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 rgba(150, 150, 150, 60%), stop:1 rgba(50, 50, 50, 60%));
    border-color: rgb(60, 60, 60);
    border-style: solid;
    border-width: 2px;
    border-radius: 9px;
    min-height: 20px;
    max-height: 20px;
    min-width: 60px;
    max-width: 60px;
    padding-left: 15px;
    padding-right: 15px;
}

QPushButton:pressed, QPushButton:checked
{
    background: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 rgba(50, 50, 50, 60%), stop:1 rgba(150, 150, 150, 60%));
}

Давайте проверим, что мы получаем в этом случае.

cqtdeployer -bin Hello qif -qifStyle ./../style.qss

image

Вот, собственно, и темная тема установщика.

Разбивка на пакеты

И, наверное, последнее важное обновление, о котором стоит знать, — это возможность разбивать большой мультибинарный проект на подпроекты.

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

Для начала усложним наш проект, добавив в него еще 2 исполняемых файла. Я не стал заморачиваться и просто сделал 2 копии своей утилиты Hello.

Для упрощения работы с пакетами необходимо инициализировать каталог.

cqtdeployer init

Это еще одна новая функция, которая создает файл CQtDeployer.json, в который мы будем писать наши конфигурации, вместо того, чтобы передавать параметры утилите.

{
    "binDir": ".",
    "clear": true,
    "libDir": "./",
    "recursiveDepth": 5
}

Теперь сделаем 2 пакета из 3-х наших программ. Для этого укажите:

{
    "binDir": ".",
    "clear": true,
    "libDir": "./",
    "recursiveDepth": 5,
    "targetPackage": [
        ["Dstro1", "Hello1"],
        ["Dstro2", "Hello2"],
        ["Dstro2", "Hello3"]
    ]
}

Обратите внимание, что мне пришлось явно указать привязку Dstro2 к Hello2 Hello3. К сожалению, во время версии 1.4 cqtdeployer не мог анализировать целевые перечисления. Обратите внимание, что если я напишу вместо Hello1 Hello, то отбор будет производиться по всем совпадениям и будут выбраны все 3 программы.
Итак, давайте посмотрим, что произошло.

cqtdeployer

.
├── Dstro1
│   ├── bin
│   │   ├── Hello1
│   │   └── qt.conf
│   ├── Hello1.sh
│   ├── lib
│   │   ├── libicudata.so.56
│   │   ├── libicui18n.so.56
│   │   ├── libicuuc.so.56
│   │   └── libQt5Core.so.5
│   └── translations
│       ├── qtbase_ar.qm
│       ├── qtbase_bg.qm
│       ├── qtbase_ca.qm
│       ├── qtbase_cs.qm
│       ├── qtbase_da.qm
│       ├── qtbase_de.qm
│       ├── qtbase_en.qm
│       ├── qtbase_es.qm
│       ├── qtbase_fi.qm
│       ├── qtbase_fr.qm
│       ├── qtbase_gd.qm
│       ├── qtbase_he.qm
│       ├── qtbase_hu.qm
│       ├── qtbase_it.qm
│       ├── qtbase_ja.qm
│       ├── qtbase_ko.qm
│       ├── qtbase_lv.qm
│       ├── qtbase_pl.qm
│       ├── qtbase_ru.qm
│       ├── qtbase_sk.qm
│       ├── qtbase_uk.qm
│       └── qtbase_zh_TW.qm
└── Dstro2
    ├── bin
    │   ├── Hello2
    │   ├── Hello3
    │   └── qt.conf
    ├── Hello2.sh
    ├── Hello3.sh
    ├── lib
    │   ├── libicudata.so.56
    │   ├── libicui18n.so.56
    │   ├── libicuuc.so.56
    │   └── libQt5Core.so.5
    └── translations
        ├── qtbase_ar.qm
        ├── qtbase_bg.qm
        ├── qtbase_ca.qm
        ├── qtbase_cs.qm
        ├── qtbase_da.qm
        ├── qtbase_de.qm
        ├── qtbase_en.qm
        ├── qtbase_es.qm
        ├── qtbase_fi.qm
        ├── qtbase_fr.qm
        ├── qtbase_gd.qm
        ├── qtbase_he.qm
        ├── qtbase_hu.qm
        ├── qtbase_it.qm
        ├── qtbase_ja.qm
        ├── qtbase_ko.qm
        ├── qtbase_lv.qm
        ├── qtbase_pl.qm
        ├── qtbase_ru.qm
        ├── qtbase_sk.qm
        ├── qtbase_uk.qm
        └── qtbase_zh_TW.qm

8 directories, 60 files

Как видно из дерева результатов, у нас получилось 2 дистрибутива.
1. Dstro1 - содержит приложение Hello1
2. Dstro2 - содержит оставшиеся 2.

Теперь проверим, что будет, если все это запаковать установщиком. Добавьте для параметра qif значение true в CQtDeployer.json: qif: true, .

{
    "binDir": ".",
    "clear": true,
    "qif": true,
    "libDir": "./",
    "recursiveDepth": 5,
    "targetPackage": [
        ["Dstro1", "Hello1"],
        ["Dstro2", "Hello2"],
        ["Dstro2", "Hello3"]
    ]

image

Как видно из скриншота, теперь у нас 2 пакета при установке.

Новые псевдонимы

И последнее небольшое, но приятное дополнение: теперь в cqtdeployer добавлены новые команды.

  • сqt — — это быстрый способ развернуть ваше приложение. Это упрощает вызов развертывания.

    • Пример:
      cqt myApp — это то же самое, что cqtdeployer -bin myApp .
  • cqtdeployer.cqt - то же, что и cqt, но для пакета snap.

  • В windows-версии теперь не нужно добавлять знак % для вызова утилиты.

  • В версии для windows теперь нет необходимости добавлять знак % для вызова утилиты.
    Теперь вызов выглядит как в Linux. (cqtdeployer)

Рекомендуем хостинг TIMEWEB
Рекомендуем хостинг TIMEWEB
Стабильный хостинг, на котором располагается социальная сеть EVILEG. Для проектов на Django рекомендуем VDS хостинг.

Ол саған ұнайды ма? Әлеуметтік желілерде бөлісіңіз!

o
  • Наурыз 24, 2020, 2:51 Т.Қ.

спасибо, за обзор!

Andrei Yankovich
  • Наурыз 24, 2020, 3:29 Т.Қ.

Если будут вопросы, пишите. Найдем решение)

Ruslan Polupan
  • Наурыз 26, 2020, 7:47 Т.Ж.

Супер. Спасибо!

D
  • Наурыз 26, 2020, 8:50 Т.Ж.

Добрый день. У меня есть приложение с библиотеками собранными отдельно. Как мне сделать так, чтобы эти библиотеки помещались в установщик и при установке приложение были вместе с исполняемым файлом? И почему утилита при использовании -bin или -bindir создает ярылки для каких-то библиотек, но не для исполняемого файла? Я использую Windows.

Andrei Yankovich
  • Наурыз 26, 2020, 9:27 Т.Ж.
  • (өңделген)
  1. Откройте cmd, перейдите в папку с вашими проектами, запустите cqtdeployer init.
  2. Должен появится файл CQtDeployer.json, откройте его.
{
    "bin": [
        "./path/to/my/file.exe",
    ],
    "qmake": "C:/path/to/my/qmake.exe",
    "clear": true,
    "libDir": "./",
    "recursiveDepth": 5,
    "qif": true
}

Если все ваши библиотеки требуются для работы ./path/to/my/file.exe т они автоматически попадут в инсталятор. если ваши библиотеки очень далеко запрятаны от расположения json файла то можете по больше выставить значение "recursiveDepth": 5,
путь "./path/to/my/file.exe", должен обязательно начинается с "." и быть относительным от json файла.

Обратите внимание на то что в Windows версии все еще нужно явно указывать путь к qmake которым был собран проект.
Исключение составляет тот факт что если qmake уже прописан у вас в окружении PATH, тогда cqtdeployer будет использовать значение из PATH.
затем сохраняете ваш файл и повторно запускаете cqtdeployer.

что касается ярлыков на библиотеки то звучит как ошибка. Собирите максимум информации о ваших дествиях и опишите ошибку на GitHub

Andrei Yankovich
  • Наурыз 26, 2020, 10:29 Т.Ж.

можно еще так:

cqtdeployer -bin "path/to/my/file.exe" -qmake "C:/path/to/my/qmake.exe" -libDir "./" -recursiveDepth 5 qif

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

D
  • Наурыз 26, 2020, 11:56 Т.Ж.

LibDir вообще не видит библиотеки. Пробовал разные попытки записи, исходя из вашего сообщения. Библиотеки лежат рядом с исполняемым файлом, json там же. Если использовать binDir вместо bin тогда библиотеки добавляются. А при установке создадутся ярлыки на все библиотеки, но не на исполняемый файл. Оно так и должно работать?

Andrei Yankovich
  • Наурыз 26, 2020, 12:39 Т.Қ.
  • (өңделген)

нет, так не должно быть, вы уверены что ваш исполняемый файл зависит от ваших библиотек ? или он подключает их как плагины?
а с ярлыками это точно ошибка, уже завел задачу на это .

Andrei Yankovich
  • Наурыз 26, 2020, 12:42 Т.Қ.

@Den125 можно взгялнуть на ваш проект ?

D
  • Наурыз 26, 2020, 12:51 Т.Қ.

Мой исполняемый файл не зависит от библиотек. Библиотеки подключаются при необходимости в процессе работы программы.

Andrei Yankovich
  • Наурыз 26, 2020, 1:13 Т.Қ.
  • (өңделген)

тогда это плагины )
для них есть отделный флаг extraPlugin

{
    "bin": [
        "./path/to/my/file.exe",
    ],
    "qmake": "C:/path/to/my/qmake.exe",
    "extraPlugin": [
        "./plugin1.dll",
        "./plugin2.dll",
    ],
    "clear": true,
    "libDir": "./",
    "recursiveDepth": 5,
    "qif": true
}
D
  • Наурыз 26, 2020, 1:34 Т.Қ.

Это сработало, но библиотеки при установке находятся в папке plugins. А можно их вынести к исполняемому файлу? Можно ли в установщик закинуть файл не библиотеку и не исполняемый, например *.jar?

Andrei Yankovich
  • Наурыз 26, 2020, 1:37 Т.Қ.

тогда переместите ваши библиотеки из extraPlugin в bin

{
    "bin": [
        "./path/to/my/file.exe",
        "./plugin1.dll",
        "./plugin2.dll",
    ],
    "qmake": "C:/path/to/my/qmake.exe",
    "clear": true,
    "libDir": "./",
    "recursiveDepth": 5,
    "qif": true
}
Andrei Yankovich
  • Наурыз 26, 2020, 1:37 Т.Қ.

но появятся ярлыки, сейчас поправим

Andrei Yankovich
  • Наурыз 27, 2020, 2:47 Т.Ж.

Ошибка с ярлыками в Windows исправлена в версиии 1.4.0.4

Пікірлер

Тек рұқсаты бар пайдаланушылар ғана пікір қалдыра алады.
Кіріңіз немесе Тіркеліңіз
AD

C++ - Тест 004. Указатели, Массивы и Циклы

  • Нәтиже:50ұпай,
  • Бағалау ұпайлары-4
m
  • molni99
  • Қаз. 26, 2024, 1:37 Т.Ж.

C++ - Тест 004. Указатели, Массивы и Циклы

  • Нәтиже:80ұпай,
  • Бағалау ұпайлары4
m
  • molni99
  • Қаз. 26, 2024, 1:29 Т.Ж.

C++ - Тест 004. Указатели, Массивы и Циклы

  • Нәтиже:20ұпай,
  • Бағалау ұпайлары-10
Соңғы пікірлер
ИМ
Игорь МаксимовҚар. 22, 2024, 11:51 Т.Ж.
Django - Оқулық 017. Теңшелген Django кіру беті Добрый вечер Евгений! Я сделал себе авторизацию аналогичную вашей, все работает, кроме возврата к предидущей странице. Редеректит всегда на главную, хотя в логах сервера вижу запросы на правильн…
Evgenii Legotckoi
Evgenii LegotckoiҚаз. 31, 2024, 2:37 Т.Қ.
Django - Сабақ 064. Python Markdown кеңейтімін қалай жазуға болады Добрый день. Да, можно. Либо через такие же плагины, либо с постобработкой через python библиотеку Beautiful Soup
A
ALO1ZEҚаз. 19, 2024, 8:19 Т.Ж.
Qt Creator көмегімен fb3 файл оқу құралы Подскажите как это запустить? Я не шарю в программировании и кодинге. Скачал и установаил Qt, но куча ошибок выдается и не запустить. А очень надо fb3 переконвертировать в html
ИМ
Игорь МаксимовҚаз. 5, 2024, 7:51 Т.Ж.
Django - Сабақ 064. Python Markdown кеңейтімін қалай жазуға болады Приветствую Евгений! У меня вопрос. Можно ли вставлять свои классы в разметку редактора markdown? Допустим имея стандартную разметку: <ul> <li></li> <li></l…
d
dblas5Шілде 5, 2024, 11:02 Т.Ж.
QML - Сабақ 016. SQLite деректер қоры және онымен QML Qt-та жұмыс істеу Здравствуйте, возникает такая проблема (я новичок): ApplicationWindow неизвестный элемент. (М300) для TextField и Button аналогично. Могу предположить, что из-за более новой верси…
Енді форумда талқылаңыз
m
moogoҚар. 22, 2024, 7:17 Т.Ж.
Mosquito Spray System Effective Mosquito Systems for Backyard | Eco-Friendly Misting Control Device & Repellent Spray - Moogo ; Upgrade your backyard with our mosquito-repellent device! Our misters conce…
Evgenii Legotckoi
Evgenii LegotckoiМаусым 24, 2024, 3:11 Т.Қ.
добавить qlineseries в функции Я тут. Работы оень много. Отправил его в бан.
t
tonypeachey1Қар. 15, 2024, 6:04 Т.Ж.
google domain [url=https://google.com/]domain[/url] domain [http://www.example.com link title]
NSProject
NSProjectМаусым 4, 2022, 3:49 Т.Ж.
Всё ещё разбираюсь с кешем. В следствии прочтения данной статьи. Я принял для себя решение сделать кеширование свойств менеджера модели LikeDislike. И так как установка evileg_core для меня не была возможна, ибо он писался…

Бізді әлеуметтік желілерде бақылаңыз