Updates refactoring
Install updates immediately after click Separate loader and installer logic
This commit is contained in:
parent
9706ab1c12
commit
413cae80c4
@ -616,74 +616,69 @@ Ctrl - продолжить выделять</translation>
|
||||
<translation>Любой язык</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../src/manager.cpp" line="42"/>
|
||||
<location filename="../../src/manager.cpp" line="41"/>
|
||||
<source>app</source>
|
||||
<translation>приложение</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../src/manager.cpp" line="43"/>
|
||||
<location filename="../../src/manager.cpp" line="42"/>
|
||||
<source>recognizers</source>
|
||||
<translation>распознавание</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../src/manager.cpp" line="44"/>
|
||||
<location filename="../../src/manager.cpp" line="43"/>
|
||||
<source>correction</source>
|
||||
<translation>коррекция</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../src/manager.cpp" line="45"/>
|
||||
<location filename="../../src/manager.cpp" line="44"/>
|
||||
<source>translators</source>
|
||||
<translation>перевод</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../src/manager.cpp" line="60"/>
|
||||
<location filename="../../src/manager.cpp" line="59"/>
|
||||
<source>Screen translator started</source>
|
||||
<translation>Экранный переводчик запущен</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../src/manager.cpp" line="68"/>
|
||||
<source>Update completed</source>
|
||||
<translation>Обновление завершено</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../src/manager.cpp" line="72"/>
|
||||
<location filename="../../src/manager.cpp" line="67"/>
|
||||
<source>Updates available</source>
|
||||
<translation>Доступны обновления</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../src/manager.cpp" line="98"/>
|
||||
<location filename="../../src/manager.cpp" line="95"/>
|
||||
<source>Current version might be outdated.
|
||||
Check for updates to silence this warning</source>
|
||||
<translation>Текущая версия может быть устаревшей.
|
||||
Проверьте обновления, чтобы отключить это сообщение</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../src/manager.cpp" line="127"/>
|
||||
<location filename="../../src/manager.cpp" line="124"/>
|
||||
<source>No recognition languages available. Install some via Settings->Updates</source>
|
||||
<translation>Нет доступных языков распознавания. Установите нужные через Настройки->Обновление</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../src/manager.cpp" line="132"/>
|
||||
<location filename="../../src/manager.cpp" line="129"/>
|
||||
<source>Recognition language not set. Go to Settings->Recognition and set it</source>
|
||||
<translation>Язык распознавания не задан. Задайте его в Настройки->Распознавание</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../src/manager.cpp" line="136"/>
|
||||
<location filename="../../src/manager.cpp" line="133"/>
|
||||
<source>No translators enabled. Go to Settings->Translation and select some</source>
|
||||
<translation>Не выбран ни один переводчик. Активируйте хотя бы один в Настройки->Перевод</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../src/manager.cpp" line="141"/>
|
||||
<location filename="../../src/manager.cpp" line="138"/>
|
||||
<source>Translation language not set. Go to Settings->Translation and set it</source>
|
||||
<translation>Язык перевода не задан. Задайте его в Настройки->Перевод</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../src/manager.cpp" line="209"/>
|
||||
<location filename="../../src/manager.cpp" line="205"/>
|
||||
<source>Failed to set log file: %1</source>
|
||||
<translation>Ошибка установки лог-файла: %1</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../src/manager.cpp" line="215"/>
|
||||
<location filename="../../src/manager.cpp" line="211"/>
|
||||
<source>Started logging to file: %1</source>
|
||||
<translation>Начата запись в лог-файл: %1</translation>
|
||||
</message>
|
||||
@ -732,32 +727,32 @@ in %1</source>
|
||||
<translation>Не восстанавливать интерфейс пользователя (размер и положения окна и т.д.)</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../src/settingseditor.cpp" line="117"/>
|
||||
<location filename="../../src/settingseditor.cpp" line="116"/>
|
||||
<source><p>Optical character recognition (OCR) and translation tool</p></source>
|
||||
<translation><p>Инструмент оптического распознавания текста (OCR) и перевода</p></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../src/settingseditor.cpp" line="119"/>
|
||||
<location filename="../../src/settingseditor.cpp" line="118"/>
|
||||
<source><p>Version: %1</p></source>
|
||||
<translation><p>Версия: %1</p></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../src/settingseditor.cpp" line="121"/>
|
||||
<location filename="../../src/settingseditor.cpp" line="120"/>
|
||||
<source><p>Changelog: <a href="%1">%2</a></p></source>
|
||||
<translation><p>Список изменений: <a href="%1">%2</a></p></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../src/settingseditor.cpp" line="123"/>
|
||||
<location filename="../../src/settingseditor.cpp" line="122"/>
|
||||
<source><p>License: <a href="%3">MIT</a></p></source>
|
||||
<translation><p>Лицензия: <a href="%3">MIT</a></p></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../src/settingseditor.cpp" line="124"/>
|
||||
<location filename="../../src/settingseditor.cpp" line="123"/>
|
||||
<source><p>Author: Gres (<a href="mailto:%1">%1</a>)</p></source>
|
||||
<translation><p>Автор: Gres (<a href="mailto:%1">%1</a>)</p></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../src/settingseditor.cpp" line="126"/>
|
||||
<location filename="../../src/settingseditor.cpp" line="125"/>
|
||||
<source><p>Issues: <a href="%1">%1</a></p></source>
|
||||
<translation><p>Поддержка: <a href="%1">%1</a></p></translation>
|
||||
</message>
|
||||
@ -1034,20 +1029,15 @@ in %1</source>
|
||||
<translation>Показывать распознанное</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../src/settingseditor.ui" line="648"/>
|
||||
<location filename="../../src/settingseditor.ui" line="629"/>
|
||||
<source>Update check interval (days):</source>
|
||||
<translation>Интервал проверки обновления (дней):</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../src/settingseditor.ui" line="655"/>
|
||||
<location filename="../../src/settingseditor.ui" line="636"/>
|
||||
<source>0 - disabled</source>
|
||||
<translation>- отключено</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../src/settingseditor.ui" line="688"/>
|
||||
<source>Apply updates</source>
|
||||
<translation>Применить изменения</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../src/settingseditor.ui" line="390"/>
|
||||
<source>Translate text</source>
|
||||
@ -1074,7 +1064,7 @@ in %1</source>
|
||||
<translation>Окно</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../src/settingseditor.ui" line="671"/>
|
||||
<location filename="../../src/settingseditor.ui" line="652"/>
|
||||
<source>Check now</source>
|
||||
<translation>Проверить сейчас</translation>
|
||||
</message>
|
||||
@ -1159,7 +1149,7 @@ in %1</source>
|
||||
<translation>Текст для проверки</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../src/settingseditor.cpp" line="134"/>
|
||||
<location filename="../../src/settingseditor.cpp" line="133"/>
|
||||
<source>The program workflow consists of the following steps:
|
||||
1. Selection on the screen area
|
||||
2. Recognition of the selected area
|
||||
@ -1182,7 +1172,7 @@ Then set default recognition and translation languages, enable some (or all) tra
|
||||
Далее установите языки распознавания и перевода по умолчанию, активируйте некоторые (или все) переводчики и настройку "переводить текст", если нужно.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../src/settingseditor.cpp" line="366"/>
|
||||
<location filename="../../src/settingseditor.cpp" line="363"/>
|
||||
<source>Portable changed. Apply settings first</source>
|
||||
<translation>Portable режиме изменени. Сначала применить настройки</translation>
|
||||
</message>
|
||||
@ -1310,73 +1300,94 @@ Most likely they are already in use by another program</source>
|
||||
<context>
|
||||
<name>Updates</name>
|
||||
<message>
|
||||
<location filename="../../src/service/updates.cpp" line="90"/>
|
||||
<location filename="../../src/service/updates.cpp" line="88"/>
|
||||
<source>Tb</source>
|
||||
<translation>Тб</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../src/service/updates.cpp" line="94"/>
|
||||
<location filename="../../src/service/updates.cpp" line="92"/>
|
||||
<source>Gb</source>
|
||||
<translation>Гб</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../src/service/updates.cpp" line="98"/>
|
||||
<location filename="../../src/service/updates.cpp" line="96"/>
|
||||
<source>Mb</source>
|
||||
<translation>Мб</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../src/service/updates.cpp" line="102"/>
|
||||
<location filename="../../src/service/updates.cpp" line="100"/>
|
||||
<source>Kb</source>
|
||||
<translation>Кб</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../src/service/updates.cpp" line="105"/>
|
||||
<location filename="../../src/service/updates.cpp" line="103"/>
|
||||
<source>bytes</source>
|
||||
<translation>байт</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../src/service/updates.cpp" line="113"/>
|
||||
<location filename="../../src/service/updates.cpp" line="111"/>
|
||||
<source>Not installed</source>
|
||||
<translation>Не установлено</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../src/service/updates.cpp" line="115"/>
|
||||
<location filename="../../src/service/updates.cpp" line="113"/>
|
||||
<source>Update available</source>
|
||||
<translation>Доступно обновление</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../src/service/updates.cpp" line="116"/>
|
||||
<location filename="../../src/service/updates.cpp" line="114"/>
|
||||
<source>Up to date</source>
|
||||
<translation>Последняя версия</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../src/service/updates.cpp" line="125"/>
|
||||
<location filename="../../src/service/updates.cpp" line="122"/>
|
||||
<source>Remove</source>
|
||||
<translation>Удалить</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../src/service/updates.cpp" line="126"/>
|
||||
<location filename="../../src/service/updates.cpp" line="123"/>
|
||||
<source>Install/Update</source>
|
||||
<translation>Установить/Обновить</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../src/service/updates.cpp" line="1032"/>
|
||||
<location filename="../../src/service/updates.cpp" line="1049"/>
|
||||
<location filename="../../src/service/updates.cpp" line="628"/>
|
||||
<source>Directory is not writable
|
||||
%1</source>
|
||||
<translation>Папка недоступна для записи
|
||||
%1</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../src/service/updates.cpp" line="1041"/>
|
||||
<source>Downloaded file not exists
|
||||
%1</source>
|
||||
<translation>Скачанный файл не существует
|
||||
%1</translation>
|
||||
<location filename="../../src/service/updates.cpp" line="657"/>
|
||||
<source>Failed to create temp file
|
||||
%1
|
||||
Error %2</source>
|
||||
<translation>Ошибка создания временного файла
|
||||
%1
|
||||
%2</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../src/service/updates.cpp" line="1061"/>
|
||||
<location filename="../../src/service/updates.cpp" line="1079"/>
|
||||
<location filename="../../src/service/updates.cpp" line="665"/>
|
||||
<source>Failed to write to temp file
|
||||
%1
|
||||
Error %2</source>
|
||||
<translation>Ошибка записи во временный файл
|
||||
%1
|
||||
%2</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../src/service/updates.cpp" line="682"/>
|
||||
<source>Failed to copy file
|
||||
%1
|
||||
to %2
|
||||
Error %3</source>
|
||||
<translation>Ошибка копирования файла
|
||||
%1
|
||||
в %2
|
||||
%3</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../src/service/updates.cpp" line="640"/>
|
||||
<location filename="../../src/service/updates.cpp" line="675"/>
|
||||
<source>Failed to remove file
|
||||
%1
|
||||
Error %2</source>
|
||||
@ -1385,23 +1396,12 @@ Error %2</source>
|
||||
Текст %2</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../src/service/updates.cpp" line="1072"/>
|
||||
<location filename="../../src/service/updates.cpp" line="650"/>
|
||||
<source>Failed to create path
|
||||
%1</source>
|
||||
<translation>Ошибка создания папки
|
||||
%1</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../src/service/updates.cpp" line="1087"/>
|
||||
<source>Failed to move file
|
||||
%1
|
||||
to %2
|
||||
Error %3</source>
|
||||
<translation>Ошибка переименования файла
|
||||
%1
|
||||
в %2
|
||||
Текст %3</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>WebPage</name>
|
||||
@ -1414,142 +1414,76 @@ Error %3</source>
|
||||
<context>
|
||||
<name>update::Loader</name>
|
||||
<message>
|
||||
<location filename="../../src/service/updates.cpp" line="220"/>
|
||||
<source>Empty updates info from
|
||||
%1</source>
|
||||
<translation>Пустой файл обновлений из
|
||||
%1</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../src/service/updates.cpp" line="229"/>
|
||||
<source>Empty updates info unpacked from
|
||||
%1</source>
|
||||
<translation>Пустой файл обновлений распакован из
|
||||
%1</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../src/service/updates.cpp" line="237"/>
|
||||
<source>Failed to parse updates from
|
||||
%1 (%2)</source>
|
||||
<translation>Ошибка разбора файла обновлений
|
||||
%1 (%2)</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../src/service/updates.cpp" line="251"/>
|
||||
<location filename="../../src/service/updates.cpp" line="576"/>
|
||||
<source>Failed to download file
|
||||
%1. Error %2</source>
|
||||
<translation>Ошибка скачивания файла
|
||||
%1. Текст %2</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../src/service/updates.cpp" line="259"/>
|
||||
<source>Already updating</source>
|
||||
<translation>Обновление в процессе</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../src/service/updates.cpp" line="265"/>
|
||||
<source>No actions selected</source>
|
||||
<translation>Нет выделенных действий</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../src/service/updates.cpp" line="330"/>
|
||||
<source>Failed to create temp path
|
||||
%1</source>
|
||||
<translation>Ошибка создания временной папки
|
||||
%1</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../src/service/updates.cpp" line="337"/>
|
||||
<location filename="../../src/service/updates.cpp" line="584"/>
|
||||
<source>Empty data downloaded from
|
||||
%1</source>
|
||||
<translation>Пустой файл из
|
||||
%1</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>update::Model</name>
|
||||
<message>
|
||||
<location filename="../../src/service/updates.cpp" line="350"/>
|
||||
<location filename="../../src/service/updates.cpp" line="158"/>
|
||||
<source>Failed to parse: %1 at %2</source>
|
||||
<translation>Ошибка разбора: %1 в %2</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../src/service/updates.cpp" line="166"/>
|
||||
<source>Wrong updates version: %1</source>
|
||||
<translation>Неверная версия файла обновлений: %1</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../src/service/updates.cpp" line="178"/>
|
||||
<source>No data parsed</source>
|
||||
<translation>Нет разобранных данных</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../src/service/updates.cpp" line="481"/>
|
||||
<source>Name</source>
|
||||
<translation>Название</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../src/service/updates.cpp" line="481"/>
|
||||
<source>State</source>
|
||||
<translation>Состояние</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../src/service/updates.cpp" line="482"/>
|
||||
<source>Size</source>
|
||||
<translation>Размер</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../src/service/updates.cpp" line="482"/>
|
||||
<source>Version</source>
|
||||
<translation>Версия</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../src/service/updates.cpp" line="483"/>
|
||||
<source>Progress</source>
|
||||
<translation>Прогресс</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>update::Updater</name>
|
||||
<message>
|
||||
<location filename="../../src/service/updates.cpp" line="850"/>
|
||||
<source>Empty data unpacked from
|
||||
%1</source>
|
||||
<translation>Пустой файл распакован из
|
||||
%1</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../src/service/updates.cpp" line="360"/>
|
||||
<source>Failed to save downloaded file
|
||||
%1
|
||||
to %2
|
||||
Error %3</source>
|
||||
<translation>Ошибка сохранения скачанного файла
|
||||
%1
|
||||
в %2
|
||||
Текст %3</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../src/service/updates.cpp" line="398"/>
|
||||
<source>Update failed: %1</source>
|
||||
<translation>Ошибка обновления: %1</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>update::Model</name>
|
||||
<message>
|
||||
<location filename="../../src/service/updates.cpp" line="460"/>
|
||||
<source>Select all updates</source>
|
||||
<translation>Выбрать все обновления</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../src/service/updates.cpp" line="461"/>
|
||||
<source>Reset actions</source>
|
||||
<translation>Сбросить действия</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../src/service/updates.cpp" line="499"/>
|
||||
<source>Failed to parse: %1 at %2</source>
|
||||
<translation>Ошибка разбора: %1 в %2</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../src/service/updates.cpp" line="507"/>
|
||||
<source>Wrong updates version: %1</source>
|
||||
<translation>Неверная версия файла обновлений: %1</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../src/service/updates.cpp" line="519"/>
|
||||
<source>No data parsed</source>
|
||||
<translation>Нет разобранных данных</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../src/service/updates.cpp" line="876"/>
|
||||
<source>Name</source>
|
||||
<translation>Название</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../src/service/updates.cpp" line="876"/>
|
||||
<source>State</source>
|
||||
<translation>Состояние</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../src/service/updates.cpp" line="877"/>
|
||||
<source>Action</source>
|
||||
<translation>Действие</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../src/service/updates.cpp" line="877"/>
|
||||
<source>Size</source>
|
||||
<translation>Размер</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../src/service/updates.cpp" line="878"/>
|
||||
<source>Version</source>
|
||||
<translation>Версия</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../src/service/updates.cpp" line="878"/>
|
||||
<source>Progress</source>
|
||||
<translation>Прогресс</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../src/service/updates.cpp" line="879"/>
|
||||
<source>Files</source>
|
||||
<translation>Файла</translation>
|
||||
<location filename="../../src/service/updates.cpp" line="921"/>
|
||||
<source>Update all</source>
|
||||
<translation>Обновить все</translation>
|
||||
</message>
|
||||
</context>
|
||||
</TS>
|
||||
|
@ -33,8 +33,7 @@ using Loader = update::Loader;
|
||||
Manager::Manager()
|
||||
: models_(std::make_unique<CommonModels>())
|
||||
, settings_(std::make_unique<Settings>())
|
||||
, updater_(std::make_unique<Loader>(Loader::Urls{{updatesUrl}}))
|
||||
, updateAutoChecker_(std::make_unique<update::AutoChecker>(*updater_))
|
||||
, updater_(std::make_unique<update::Updater>(QVector<QUrl>{{updatesUrl}}))
|
||||
{
|
||||
SOFT_ASSERT(settings_, return );
|
||||
|
||||
@ -61,13 +60,9 @@ Manager::Manager()
|
||||
|
||||
warnIfOutdated();
|
||||
|
||||
QObject::connect(updater_.get(), &update::Loader::error, //
|
||||
QObject::connect(updater_.get(), &update::Updater::error, //
|
||||
tray_.get(), &TrayIcon::showError);
|
||||
QObject::connect(updater_.get(), &update::Loader::updated, //
|
||||
tray_.get(), [this] {
|
||||
tray_->showInformation(QObject::tr("Update completed"));
|
||||
});
|
||||
QObject::connect(updater_.get(), &update::Loader::updatesAvailable, //
|
||||
QObject::connect(updater_.get(), &update::Updater::updatesAvailable, //
|
||||
tray_.get(), [this] {
|
||||
tray_->showInformation(QObject::tr("Updates available"));
|
||||
});
|
||||
@ -76,8 +71,10 @@ Manager::Manager()
|
||||
Manager::~Manager()
|
||||
{
|
||||
SOFT_ASSERT(settings_, return );
|
||||
if (updateAutoChecker_ && updateAutoChecker_->isLastCheckDateChanged()) {
|
||||
settings_->lastUpdateCheck = updateAutoChecker_->lastCheckDate();
|
||||
SOFT_ASSERT(updater_, return );
|
||||
if (updater_->lastUpdateCheck().isValid() &&
|
||||
settings_->lastUpdateCheck != updater_->lastUpdateCheck()) {
|
||||
settings_->lastUpdateCheck = updater_->lastUpdateCheck();
|
||||
settings_->saveLastUpdateCheck();
|
||||
LTRACE() << "saved last update time";
|
||||
}
|
||||
@ -170,16 +167,15 @@ void Manager::setupProxy(const Settings &settings)
|
||||
|
||||
void Manager::setupUpdates(const Settings &settings)
|
||||
{
|
||||
updater_->model()->setExpansions({
|
||||
updater_->setExpansions({
|
||||
{"$translators$", settings.translatorsDir},
|
||||
{"$tessdata$", settings.tessdataPath},
|
||||
{"$hunspell$", settings.hunspellDir},
|
||||
{"$appdir$", QApplication::applicationDirPath()},
|
||||
});
|
||||
|
||||
SOFT_ASSERT(updateAutoChecker_, return );
|
||||
updateAutoChecker_->setLastCheckDate(settings.lastUpdateCheck);
|
||||
updateAutoChecker_->setCheckIntervalDays(settings.autoUpdateIntervalDays);
|
||||
updater_->setAutoUpdate(settings.autoUpdateIntervalDays,
|
||||
settings.lastUpdateCheck);
|
||||
}
|
||||
|
||||
bool Manager::setupTrace(bool isOn)
|
||||
|
@ -43,7 +43,6 @@ private:
|
||||
std::unique_ptr<Corrector> corrector_;
|
||||
std::unique_ptr<Translator> translator_;
|
||||
std::unique_ptr<Representer> representer_;
|
||||
std::unique_ptr<update::Loader> updater_;
|
||||
std::unique_ptr<update::AutoChecker> updateAutoChecker_;
|
||||
std::unique_ptr<update::Updater> updater_;
|
||||
int activeTaskCount_{0};
|
||||
};
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -11,20 +11,19 @@ class QTreeView;
|
||||
namespace update
|
||||
{
|
||||
enum class State { NotAvailable, NotInstalled, UpdateAvailable, Actual };
|
||||
enum class Action { NoAction, Remove, Install };
|
||||
enum class Action { Install, Remove };
|
||||
|
||||
class Updater;
|
||||
|
||||
struct File {
|
||||
QVector<QUrl> urls;
|
||||
QString rawPath;
|
||||
QString expandedPath;
|
||||
QString downloadPath;
|
||||
QString md5;
|
||||
QDateTime versionDate;
|
||||
int progress{0};
|
||||
};
|
||||
|
||||
using UserActions = std::multimap<Action, File>;
|
||||
|
||||
class UpdateDelegate : public QStyledItemDelegate
|
||||
{
|
||||
Q_OBJECT
|
||||
@ -38,30 +37,17 @@ class Model : public QAbstractItemModel
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
enum class Column {
|
||||
Name,
|
||||
State,
|
||||
Action,
|
||||
Size,
|
||||
Version,
|
||||
Progress,
|
||||
Files,
|
||||
Count
|
||||
};
|
||||
enum class Column { Name, State, Size, Version, Progress, Count };
|
||||
|
||||
explicit Model(QObject* parent = nullptr);
|
||||
|
||||
void initView(QTreeView* view);
|
||||
explicit Model(Updater& updater);
|
||||
|
||||
QString parse(const QByteArray& data);
|
||||
void setExpansions(const std::map<QString, QString>& expansions);
|
||||
UserActions userActions() const;
|
||||
void setExpansions(const QHash<QString, QString>& expansions);
|
||||
void updateStates();
|
||||
bool hasUpdates() const;
|
||||
void updateProgress(const QUrl& url, int progress);
|
||||
void resetProgress();
|
||||
void selectAllUpdates();
|
||||
void resetActions();
|
||||
void tryAction(Action action, const QModelIndex& index);
|
||||
|
||||
QModelIndex index(int row, int column,
|
||||
const QModelIndex& parent) const override;
|
||||
@ -72,16 +58,13 @@ public:
|
||||
int role) const override;
|
||||
QVariant data(const QModelIndex& index, int role) const override;
|
||||
Qt::ItemFlags flags(const QModelIndex& index) const override;
|
||||
bool setData(const QModelIndex& index, const QVariant& value,
|
||||
int role) override;
|
||||
|
||||
private:
|
||||
struct Component {
|
||||
QString name;
|
||||
State state{State::NotAvailable};
|
||||
Action action{Action::NoAction};
|
||||
QString version;
|
||||
std::vector<File> files;
|
||||
QVector<File> files;
|
||||
bool checkOnly{false};
|
||||
std::vector<std::unique_ptr<Component>> children;
|
||||
Component* parent{nullptr};
|
||||
@ -91,33 +74,14 @@ private:
|
||||
};
|
||||
|
||||
std::unique_ptr<Component> parse(const QJsonObject& json) const;
|
||||
void updateProgress(Component& component, const QUrl& url, int progress);
|
||||
void updateState(Component& component);
|
||||
State currentState(const File& file) const;
|
||||
QString expanded(const QString& source) const;
|
||||
Component* toComponent(const QModelIndex& index) const;
|
||||
QModelIndex toIndex(const Component& component, int column) const;
|
||||
|
||||
Updater& updater_;
|
||||
std::unique_ptr<Component> root_;
|
||||
std::map<QString, QString> expansions_;
|
||||
};
|
||||
|
||||
class Installer
|
||||
{
|
||||
public:
|
||||
explicit Installer(const UserActions& actions);
|
||||
bool commit();
|
||||
QString errorString() const;
|
||||
|
||||
private:
|
||||
void remove(const File& file);
|
||||
void install(const File& file);
|
||||
void checkRemove(const File& file);
|
||||
void checkInstall(const File& file);
|
||||
bool checkIsPossible();
|
||||
|
||||
UserActions actions_;
|
||||
QStringList errors_;
|
||||
QHash<QString, QString> expansions_;
|
||||
};
|
||||
|
||||
class Loader : public QObject
|
||||
@ -125,60 +89,85 @@ class Loader : public QObject
|
||||
Q_OBJECT
|
||||
public:
|
||||
using Urls = QVector<QUrl>;
|
||||
explicit Loader(const Urls& updateUrls, QObject* parent = nullptr);
|
||||
explicit Loader(Updater& updater);
|
||||
|
||||
void checkForUpdates();
|
||||
void applyUserActions();
|
||||
Model* model() const;
|
||||
|
||||
signals:
|
||||
void updatesAvailable();
|
||||
void updated();
|
||||
void error(const QString& error);
|
||||
void download(const Urls& urls);
|
||||
|
||||
private:
|
||||
void addError(const QString& text);
|
||||
void dumpErrors();
|
||||
void start(const Urls& urls, const QUrl& previous, const QString& error);
|
||||
void handleReply(QNetworkReply* reply);
|
||||
bool handleComponentReply(QNetworkReply* reply);
|
||||
void handleUpdateReply(QNetworkReply* reply);
|
||||
QString toError(QNetworkReply& reply) const;
|
||||
void finishUpdate(const QString& error = {});
|
||||
void commitUpdate();
|
||||
void updateProgress(qint64 bytesSent, qint64 bytesTotal);
|
||||
bool startDownload(File& file);
|
||||
void startDownloadUpdates(const QUrl& previous);
|
||||
|
||||
Updater& updater_;
|
||||
QNetworkAccessManager* network_;
|
||||
Model* model_;
|
||||
Urls updateUrls_;
|
||||
QString downloadPath_;
|
||||
std::map<QNetworkReply*, File*> downloads_;
|
||||
QStringList errors_;
|
||||
UserActions currentActions_;
|
||||
QHash<QNetworkReply*, Urls> downloads_;
|
||||
};
|
||||
|
||||
class Installer
|
||||
{
|
||||
public:
|
||||
void remove(const File& file);
|
||||
void install(const File& file, const QByteArray& data);
|
||||
void checkInstall(const File& file);
|
||||
const QString& error() const;
|
||||
|
||||
private:
|
||||
QString error_;
|
||||
};
|
||||
|
||||
class AutoChecker : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit AutoChecker(Loader& loader, QObject* parent = nullptr);
|
||||
AutoChecker(Updater& updater, int intervalDays, const QDateTime& lastCheck);
|
||||
~AutoChecker();
|
||||
|
||||
bool isLastCheckDateChanged() const;
|
||||
QDateTime lastCheckDate() const;
|
||||
void setCheckIntervalDays(int days);
|
||||
void setLastCheckDate(const QDateTime& dt);
|
||||
const QDateTime& lastCheckDate() const;
|
||||
|
||||
private:
|
||||
void handleModelReset();
|
||||
void updateLastCheckDate();
|
||||
void scheduleNextCheck();
|
||||
|
||||
Loader& loader_;
|
||||
bool isLastCheckDateChanged_{false};
|
||||
Updater& updater_;
|
||||
int checkIntervalDays_{0};
|
||||
QDateTime lastCheckDate_;
|
||||
std::unique_ptr<QTimer> timer_;
|
||||
};
|
||||
|
||||
class Updater : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit Updater(const QVector<QUrl>& updateUrls);
|
||||
|
||||
void initView(QTreeView* view);
|
||||
void setExpansions(const QHash<QString, QString>& expansions);
|
||||
void checkForUpdates();
|
||||
|
||||
QDateTime lastUpdateCheck() const;
|
||||
void setAutoUpdate(int intervalDays, const QDateTime& lastCheck);
|
||||
|
||||
void applyAction(Action action, const QVector<File>& files);
|
||||
void downloaded(const QUrl& url, const QByteArray& data);
|
||||
void updateProgress(const QUrl& url, qint64 bytesSent, qint64 bytesTotal);
|
||||
void downloadFailed(const QUrl& url, const QString& error);
|
||||
|
||||
signals:
|
||||
void checkedForUpdates();
|
||||
void updatesAvailable();
|
||||
void updated();
|
||||
void error(const QString& error);
|
||||
|
||||
private:
|
||||
void handleModelDoubleClick(const QModelIndex& index);
|
||||
void showModelContextMenu();
|
||||
int findDownload(const QUrl& url) const;
|
||||
QModelIndex fromProxy(const QModelIndex& index) const;
|
||||
|
||||
std::unique_ptr<Model> model_;
|
||||
std::unique_ptr<Loader> loader_;
|
||||
std::unique_ptr<AutoChecker> autoChecker_;
|
||||
QVector<QUrl> updateUrls_;
|
||||
QVector<File> downloading_;
|
||||
};
|
||||
|
||||
} // namespace update
|
||||
|
@ -9,7 +9,7 @@
|
||||
|
||||
#include <QColorDialog>
|
||||
|
||||
SettingsEditor::SettingsEditor(Manager &manager, update::Loader &updater)
|
||||
SettingsEditor::SettingsEditor(Manager &manager, update::Updater &updater)
|
||||
: ui(new Ui::SettingsEditor)
|
||||
, manager_(manager)
|
||||
, updater_(updater)
|
||||
@ -92,16 +92,15 @@ SettingsEditor::SettingsEditor(Manager &manager, update::Loader &updater)
|
||||
this, [this] { pickColor(ColorContext::Bagkround); });
|
||||
|
||||
// updates
|
||||
updater.model()->initView(ui->updatesView);
|
||||
ui->updatesView->header()->setObjectName("updatesHeader");
|
||||
updater_.initView(ui->updatesView);
|
||||
adjustUpdatesView();
|
||||
connect(updater_.model(), &QAbstractItemModel::modelReset, //
|
||||
connect(&updater_, &update::Updater::checkedForUpdates, //
|
||||
this, &SettingsEditor::adjustUpdatesView);
|
||||
connect(&updater_, &update::Loader::updated, //
|
||||
connect(&updater_, &update::Updater::updated, //
|
||||
this, &SettingsEditor::adjustUpdatesView);
|
||||
connect(ui->checkUpdates, &QPushButton::clicked, //
|
||||
&updater_, &update::Loader::checkForUpdates);
|
||||
connect(ui->applyUpdates, &QPushButton::clicked, //
|
||||
&updater_, &update::Loader::applyUserActions);
|
||||
&updater_, &update::Updater::checkForUpdates);
|
||||
|
||||
// about
|
||||
{
|
||||
@ -317,8 +316,6 @@ void SettingsEditor::updateTranslators()
|
||||
|
||||
void SettingsEditor::adjustUpdatesView()
|
||||
{
|
||||
ui->updatesView->resizeColumnToContents(int(update::Model::Column::Name));
|
||||
|
||||
if (ui->tessdataPath->text().isEmpty()) // not inited yet
|
||||
return;
|
||||
|
||||
|
@ -16,7 +16,7 @@ class SettingsEditor : public QDialog
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
SettingsEditor(Manager &manager, update::Loader &updater);
|
||||
SettingsEditor(Manager &manager, update::Updater &updater);
|
||||
~SettingsEditor();
|
||||
|
||||
Settings settings() const;
|
||||
@ -35,7 +35,7 @@ private:
|
||||
|
||||
Ui::SettingsEditor *ui;
|
||||
Manager &manager_;
|
||||
update::Loader &updater_;
|
||||
update::Updater &updater_;
|
||||
CommonModels models_;
|
||||
QStringList enabledTranslators_;
|
||||
bool wasPortable_{false};
|
||||
|
@ -613,33 +613,14 @@
|
||||
</widget>
|
||||
<widget class="QWidget" name="pageUpdate">
|
||||
<layout class="QGridLayout" name="gridLayout_5">
|
||||
<item row="2" column="0">
|
||||
<spacer name="horizontalSpacer_2">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
<item row="1" column="0" colspan="2">
|
||||
<widget class="QTreeView" name="updatesView">
|
||||
<property name="sortingEnabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>204</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="2">
|
||||
<spacer name="horizontalSpacer_3">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>203</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item row="0" column="0" colspan="3">
|
||||
<item row="0" column="0" colspan="2">
|
||||
<widget class="QWidget" name="widget_3" native="true">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<item>
|
||||
@ -675,20 +656,6 @@
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0" colspan="3">
|
||||
<widget class="QTreeView" name="updatesView">
|
||||
<property name="sortingEnabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QPushButton" name="applyUpdates">
|
||||
<property name="text">
|
||||
<string>Apply updates</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QWidget" name="pageAbout">
|
||||
|
@ -22,8 +22,7 @@ class CommonModels;
|
||||
|
||||
namespace update
|
||||
{
|
||||
class Loader;
|
||||
class AutoChecker;
|
||||
class Updater;
|
||||
} // namespace update
|
||||
|
||||
using TaskPtr = std::shared_ptr<Task>;
|
||||
|
@ -14,10 +14,9 @@ const auto f1 = "from1.txt";
|
||||
const auto t1 = "test/to1.txt";
|
||||
const auto data = "sample";
|
||||
|
||||
File toFile(const QString& from, const QString& to)
|
||||
File toFile(const QString& to)
|
||||
{
|
||||
File result;
|
||||
result.downloadPath = from;
|
||||
result.expandedPath = to;
|
||||
return result;
|
||||
}
|
||||
@ -47,41 +46,24 @@ bool removeFile(const QString& name)
|
||||
}
|
||||
} // namespace
|
||||
|
||||
TEST(UpdateInstaller, Empty)
|
||||
{
|
||||
UserActions actions;
|
||||
Installer testee(actions);
|
||||
ASSERT_TRUE(testee.commit());
|
||||
}
|
||||
|
||||
TEST(UpdateInstaller, SuccessInstall)
|
||||
{
|
||||
ASSERT_TRUE(removeFile(t1));
|
||||
ASSERT_TRUE(writeFile(f1, data));
|
||||
|
||||
UserActions actions{{Action::Install, toFile(f1, t1)}};
|
||||
Installer testee(actions);
|
||||
ASSERT_TRUE(testee.commit());
|
||||
Installer testee;
|
||||
testee.install(toFile(t1), data);
|
||||
ASSERT_EQ(data, readFile(t1));
|
||||
ASSERT_TRUE(testee.error().isEmpty());
|
||||
}
|
||||
|
||||
TEST(UpdateInstaller, SuccessRemove)
|
||||
{
|
||||
ASSERT_TRUE(writeFile(f1, data));
|
||||
|
||||
UserActions actions{{Action::Remove, toFile(f1, f1)}};
|
||||
Installer testee(actions);
|
||||
ASSERT_TRUE(testee.commit());
|
||||
Installer testee;
|
||||
testee.remove(toFile(f1));
|
||||
ASSERT_FALSE(QFile::exists(f1));
|
||||
}
|
||||
|
||||
TEST(UpdateInstaller, FailInstallNoSource)
|
||||
{
|
||||
ASSERT_TRUE(removeFile(f1));
|
||||
|
||||
UserActions actions{{Action::Install, toFile(f1, t1)}};
|
||||
Installer testee(actions);
|
||||
ASSERT_FALSE(testee.commit());
|
||||
ASSERT_TRUE(testee.error().isEmpty());
|
||||
}
|
||||
|
||||
TEST(UpdateInstaller, FailInstallNoWritable)
|
||||
@ -90,9 +72,9 @@ TEST(UpdateInstaller, FailInstallNoWritable)
|
||||
QFile f(t1);
|
||||
ASSERT_FALSE(f.isWritable());
|
||||
|
||||
UserActions actions{{Action::Install, toFile(f1, t1)}};
|
||||
Installer testee(actions);
|
||||
ASSERT_FALSE(testee.commit());
|
||||
Installer testee;
|
||||
testee.install(toFile(t1), data);
|
||||
ASSERT_FALSE(testee.error().isEmpty());
|
||||
}
|
||||
|
||||
TEST(UpdateInstaller, FailRemove)
|
||||
@ -103,9 +85,9 @@ TEST(UpdateInstaller, FailRemove)
|
||||
return;
|
||||
ASSERT_FALSE(QFile::copy(f1, f1 + "1")); // non writable
|
||||
|
||||
UserActions actions{{Action::Remove, toFile(f1, f1)}};
|
||||
Installer testee(actions);
|
||||
ASSERT_FALSE(testee.commit());
|
||||
Installer testee;
|
||||
testee.remove(toFile(f1));
|
||||
ASSERT_FALSE(testee.error().isEmpty());
|
||||
}
|
||||
|
||||
TEST(UpdateModel, ParseFail)
|
||||
@ -113,7 +95,8 @@ TEST(UpdateModel, ParseFail)
|
||||
const auto updates = R"({
|
||||
})";
|
||||
|
||||
Model testee;
|
||||
Updater updater({});
|
||||
Model testee(updater);
|
||||
const auto error = testee.parse(updates);
|
||||
|
||||
ASSERT_FALSE(error.isEmpty());
|
||||
@ -134,7 +117,8 @@ TEST(UpdateModel, Parse)
|
||||
}
|
||||
})";
|
||||
|
||||
Model testee;
|
||||
Updater updater({});
|
||||
Model testee(updater);
|
||||
const auto error = testee.parse(updates);
|
||||
|
||||
ASSERT_TRUE(error.isEmpty());
|
||||
@ -146,40 +130,3 @@ TEST(UpdateModel, Parse)
|
||||
comp1.sibling(comp1.row(), int(Model::Column::Name)).data().toString();
|
||||
ASSERT_EQ("comp1", comp1Name);
|
||||
}
|
||||
|
||||
TEST(UpdateLoader, InstallFile)
|
||||
{
|
||||
const auto uf = "updates.json";
|
||||
const auto url = QUrl::fromLocalFile(QFileInfo(f1).absoluteFilePath());
|
||||
const auto updates = QString(R"({
|
||||
"version":1,
|
||||
"comp1":{"files":[{"url":"%1", "path":"./%2", "md5":"1"}]}
|
||||
})")
|
||||
.arg(url.toString(), t1);
|
||||
ASSERT_TRUE(writeFile(uf, updates.toUtf8()));
|
||||
ASSERT_TRUE(writeFile(f1, updates.toUtf8()));
|
||||
ASSERT_TRUE(removeFile(t1));
|
||||
|
||||
Loader testee({QUrl::fromLocalFile(QFileInfo(uf).absoluteFilePath())});
|
||||
testee.checkForUpdates();
|
||||
QCoreApplication::processEvents();
|
||||
|
||||
auto model = testee.model();
|
||||
ASSERT_NE(nullptr, model);
|
||||
ASSERT_EQ(1, model->rowCount({}));
|
||||
|
||||
const auto comp1 = model->index(0, int(Model::Column::Action), {});
|
||||
model->setData(comp1, int(Action::Install), Qt::EditRole);
|
||||
|
||||
QSignalSpy okSpy(&testee, &Loader::updated);
|
||||
QSignalSpy errorSpy(&testee, &Loader::error);
|
||||
|
||||
testee.applyUserActions();
|
||||
|
||||
QCoreApplication::processEvents();
|
||||
ASSERT_EQ(1, okSpy.count());
|
||||
ASSERT_EQ(0, errorSpy.count());
|
||||
|
||||
ASSERT_TRUE(QFile::exists(f1));
|
||||
ASSERT_EQ(updates, readFile(t1));
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user