#include "ui_statuswidget.h" #include "statuswidget.h" #include "models/patchdownloader.h" #include "widgets/mainwindow.h" #include "constants.h" #include #include #include #include #include StatusWidget::StatusWidget(QWidget *parent) : QWidget(parent) , ui(new Ui::StatusWidget) { ui->setupUi(this); last_statusbar_update_time_.start(); ui->galadriel_tooltip_example->hide(); ui->c_progress_bar->setProgress(100); connect(ui->weekly_code_widget, &WeeklyCodeWidget::showCompletedTooltip, this, [this](){setToolTipMessage("Еженедельный код скопирован в буфер обмена.", E_INFO);}); connect(ui->weekly_code_widget, &WeeklyCodeWidget::showHelpTooltip, this, [this](){setToolTipMessage("Нажмите по еженедельному коду, чтобы скопировать его.", E_INFO);}); connect(ui->weekly_code_widget, &WeeklyCodeWidget::showNoTooltip, this, [this](){unsetToolTipMessage(E_INFO);}); connect(ui->news_list, &NewsListWidget::showHelpToolTip, this, [this](){setToolTipMessage("Нажмите на заголовок новости, чтобы открыть её в браузере.", E_INFO);}); connect(ui->news_list, &NewsListWidget::showNoToolTip, this, [this](){unsetToolTipMessage(E_INFO);}); connect(ui->server_status_widget, &ServerStatusWidget::showServersTooltip, this, [this](QString message){setToolTipMessage(message, E_INFO);}); connect(ui->server_status_widget, &ServerStatusWidget::showNoTooltip, this, [this](){unsetToolTipMessage(E_INFO);}); connect(&PatchDownloader::instance(), &PatchDownloader::started, this, &StatusWidget::onPatchDownloaderStarted); connect(&PatchDownloader::instance(), &PatchDownloader::progressChanged, this, &StatusWidget::onPatchDownloaderProgressChanged); connect(&PatchDownloader::instance(), &PatchDownloader::finished, this, &StatusWidget::onPatchDownloaderFinished); connect(&PatchInstaller::instance(), &PatchInstaller::started, this, &StatusWidget::onPatchInstallerStarted); connect(&PatchInstaller::instance(), &PatchInstaller::progressChanged, this, &StatusWidget::onPatchInstallerProgressChanged); connect(&PatchInstaller::instance(), &PatchInstaller::finished, this, &StatusWidget::onPatchInstallerFinished); connect(&PatchInstaller::instance(), &PatchInstaller::videosDownloadProgressChanged, this, &StatusWidget::onPatchInstallerVideoProgressChanged); connect(&PatchInstaller::instance(), &PatchInstaller::successfullyInitialized, this, &StatusWidget::showComponentsStatus); connect(&PatchInstaller::instance(), &PatchInstaller::deinitialized, this, &StatusWidget::hideComponentsStatus); connect(ui->b_components_status, &TranslationComponents::needToPatch, this, &StatusWidget::onTranslationComponentsNeedToPatch); connect(ui->b_components_status, &TranslationComponents::noNeedToPatch, this, &StatusWidget::onTranslationComponentsNoNeedToPatch); ui->b_components_status->hide(); _components_status_opacity_effect = new QGraphicsOpacityEffect(); _components_status_opacity_animation = new QPropertyAnimation(_components_status_opacity_effect, "opacity"); _components_status_opacity_animation->setStartValue(0); _components_status_opacity_animation->setDuration(1000); ui->b_components_status->setGraphicsEffect(_components_status_opacity_effect); } StatusWidget::~StatusWidget() { _components_status_opacity_animation->stop(); _components_status_opacity_animation->deleteLater(); _components_status_opacity_effect->deleteLater(); random_tooltip_generator_timer_.stop(); process_completed_tooltip_hide_timer_.stop(); delete ui; } void StatusWidget::updateFontsSizes() { ui->game_button->setFont(trajan_11pt); ui->news_label->setFont(trajan_10pt); } void StatusWidget::setToolTipMessage(QString message, StatusWidget::ToolTipState state) { if (state == E_RANDOM) { random_tooltip_generator_timer_.start(); } else { random_tooltip_generator_timer_.stop(); } tooltip_messages_[state] = message; tooltip_state_ = ToolTipState(int(tooltip_state_) | int(state)); QString message_id = message; if (state == E_PROCESS) { message_id = "E_PROCESS"; } if (tooltip_state_ < state * 2) { if (!tooltip_widgets_.contains(message_id)) { createTooltipMessageWidget(message_id); } tooltip_widgets_[message_id]->setText(message); fadeBetweenToolTips(message_id); } } void StatusWidget::unsetToolTipMessage(StatusWidget::ToolTipState state) { tooltip_state_ = ToolTipState(int(tooltip_state_) & (~int(state))); ToolTipState showing_state = E_RANDOM; if (tooltip_state_ & E_INFO) { showing_state = E_INFO; } else if (tooltip_state_ & E_ERROR) { showing_state = E_ERROR; } else if (tooltip_state_ & E_PROCESS) { showing_state = E_PROCESS; } QString message_id = tooltip_messages_[showing_state]; if (showing_state == E_PROCESS) { message_id = "E_PROCESS"; } if (showing_state == E_RANDOM) { random_tooltip_generator_timer_.start(); } else { random_tooltip_generator_timer_.stop(); } if (!tooltip_widgets_.contains(message_id)) { createTooltipMessageWidget(message_id); } tooltip_widgets_[message_id]->setText(tooltip_messages_[showing_state]); fadeBetweenToolTips(message_id); } void StatusWidget::onErrorStatusChanged(AppErrorStatus status) { if (status == E_NO_ERRORS) { init_error_type_message_ = ""; unsetToolTipMessage(E_ERROR); ui->news_list->updateNewsWidget(); ui->server_status_widget->updateServerStatus(); ui->weekly_code_widget->updateWeeklyCodeWidget(); return; } error_timeout_message_ = "Повторная попытка инициализации через 10 секунд"; if (status & E_WRONG_GAME_FOLDER) { init_error_type_message_ = "Ошибка инициализации: некорректная папка с игрой!\n"; setToolTipMessage(init_error_type_message_ + error_timeout_message_, E_ERROR); return; } if (status & E_DAT_FILES_MISSING) { init_error_type_message_ = "Ошибка инициализации: отсутствуют файлы данных игры!\n"; setToolTipMessage(init_error_type_message_ + error_timeout_message_, E_ERROR); return; } if (status & E_WRONG_FILE_PERMISSIONS) { init_error_type_message_ = "Ошибка инициализации: недостаточно прав для изменения файлов данных!\n"; setToolTipMessage(init_error_type_message_ + error_timeout_message_, E_ERROR); return; } if (status & E_CANNOT_ACCESS_DAT_FILES) { init_error_type_message_ = "Ошибка инициализации: нет доступа к файлам данных!\n"; setToolTipMessage(init_error_type_message_ + error_timeout_message_, E_ERROR); return; } if (status & E_DAT_FILE_INCORRECT) { init_error_type_message_ = "Ошибка инициализации: формат файла данных устарел или некорректен!\n"; setToolTipMessage(init_error_type_message_ + error_timeout_message_, E_ERROR); return; } if (status & E_NO_SERVER_CONNECTION) { init_error_type_message_ = "Ошибка инициализации: нет связи с сервером Наследия!\n"; setToolTipMessage(init_error_type_message_ + error_timeout_message_, E_ERROR); return; } } void StatusWidget::onSecondsToNextTryToInitChanged(size_t seconds_elapsed) { if (!init_error_type_message_.isEmpty()) { error_timeout_message_ = "Повторная попытка инициализации через " + QString::number(seconds_elapsed) + " секунд"; setToolTipMessage(init_error_type_message_ + error_timeout_message_, E_ERROR); } } void StatusWidget::resizeEvent(QResizeEvent *) { double coefficient = window_width / default_window_width; // ui->game_button->move(QPoint(820, 460) * coefficient); // ui->game_button->resize(QSize(150, 60) * coefficient); // ui->progressBar->move(QPoint(320, 480) * coefficient); // ui->progressBar->resize(QSize(470, 40) * coefficient); // ui->progress_label->move(QPoint(330, 390) * coefficient); // ui->progress_label->resize(QSize(380, 90) * coefficient); // ui->news_label->move(QPoint(45, 33)* coefficient); // ui->news_label->resize(QSize(180, 21) * coefficient); // ui->news_scroll_area->move(QPoint(40, 75) * coefficient); // ui->news_scroll_area->resize(QSize(240, 440) * coefficient); // ui->server_status_widget->move(QPoint(820, 90) * coefficient); // ui->server_status_widget->resize(QSize(155, 320) * coefficient); // ui->weekly_code_widget->move(QPoint(810, 13) * coefficient); // ui->weekly_code_widget->resize(QSize(173, 57) * coefficient); // ui->galadriel_widget->move(QPoint(320, 20) * coefficient); // ui->galadriel_widget->resize(QSize(531, 461) * coefficient); // ui->news_tooltip->move(QPoint(38, 13) * coefficient); // ui->news_tooltip->resize(QSize(365, 114) * coefficient); // ui->weekly_code_tooltip_1->move(QPoint(38, 13) * coefficient); // ui->weekly_code_tooltip_1->resize(QSize(365, 114) * coefficient); // ui->weekly_code_tooltip_2->move(QPoint(38, 13) * coefficient); // ui->weekly_code_tooltip_2->resize(QSize(365, 114) * coefficient); // ui->server_status_tooltip->move(QPoint(38, 13) * coefficient); // ui->server_status_tooltip->resize(QSize(365, 114) * coefficient); // ui->patches_status->move(QPoint(38, 13) * coefficient); // ui->patches_status->resize(QSize(385, 114) * coefficient); updateFontsSizes(); } void StatusWidget::generateRandomTooltipMessage() { quint32 number = QRandomGenerator::system()->generate(); QVector messages = { "

Atra du evarínya ono varda! Я видела тебя в своём зеркале...

", "

Опасно ходить в рейды в одиночку! Зачищать инсты лучше в хорошей компании :)

", "

Какое-то ещё мудрое высказывание в стиле эльфов...

", "

Мудрые сидят в дискорде Наследия, присоединяйся!

", }; setToolTipMessage(messages[number % messages.size()], E_RANDOM); } void StatusWidget::fadeBetweenToolTips(QString tooltip_id) { if (tooltip_id == current_tooltip_message_) { return; } QPropertyAnimation* showing_anim = tooltip_animations_[tooltip_id]; showing_anim->setDirection(QAbstractAnimation::Forward); if (showing_anim->state() == QAbstractAnimation::Stopped) { showing_anim->start(); } if (tooltip_widgets_.contains(current_tooltip_message_)) { QString msg = current_tooltip_message_; connect(tooltip_animations_[current_tooltip_message_], &QPropertyAnimation::finished, this, [&, msg](){ if (tooltip_effects_.contains(msg) && tooltip_effects_[msg]->opacity() == 0) { tooltip_widgets_.take(msg)->deleteLater(); tooltip_effects_.take(msg)->deleteLater(); tooltip_animations_.take(msg)->deleteLater(); } }); QPropertyAnimation* hiding_anim = tooltip_animations_[current_tooltip_message_]; hiding_anim->setDirection(QAbstractAnimation::Backward); if (hiding_anim->state() == QAbstractAnimation::Stopped) { hiding_anim->start(); } } current_tooltip_message_ = tooltip_id; } void StatusWidget::onPatchDownloaderStarted() { process_completed_tooltip_hide_timer_.stop(); all_patch_operations_finished_ = false; ui->game_button->setEnabled(false); setToolTipMessage("Проверка обновлений русификации...", E_PROCESS); } void StatusWidget::onPatchDownloaderFinished() { all_patch_operations_finished_ = true; ui->game_button->setEnabled(true); setToolTipMessage("Скачивание данных русификации завершено!", E_PROCESS); process_completed_tooltip_hide_timer_.start(); } void StatusWidget::onPatchDownloaderProgressChanged(Downloader::Status status) { double download_percent = status.total_bytes > 0 ? double(status.downloaded_bytes) * 100.0 / double(status.total_bytes) : 100; ui->c_progress_bar->setProgress(download_percent); if (last_statusbar_update_time_.elapsed() > 450) { QString text = "Загрузка данных: " + QString::number(download_percent, 'f', 1) + "% (" + Downloader::getSizeFormatted(status.downloaded_bytes) + "/" + Downloader::getSizeFormatted(status.total_bytes) + ")\n" + "До конца загрузки: " + Downloader::getElapsedTimeFormatted(status.elapsed_time); setToolTipMessage(text, E_PROCESS); last_statusbar_update_time_.restart(); } } void StatusWidget::onPatchInstallerStarted() { process_completed_tooltip_hide_timer_.stop(); all_patch_operations_finished_ = false; ui->game_button->setEnabled(false); setToolTipMessage("

Подготовка русификатора...

", E_PROCESS); } void StatusWidget::onPatchInstallerFinished() { all_patch_operations_finished_ = true; ui->game_button->setEnabled(true); setToolTipMessage("

Все операции выполнены!

", E_PROCESS); process_completed_tooltip_hide_timer_.start(); } void StatusWidget::onPatchInstallerProgressChanged(PatchInstaller::Status status) { double install_percent = status.total_parts > 0 ? double(status.finished_parts) * 100.0 / double(status.total_parts) : 100; ui->c_progress_bar->setProgress(install_percent); if (last_statusbar_update_time_.elapsed() > 450 || status.finished_parts == 0) { QString text = "Установка русификации: " + QString::number(double(status.finished_parts) * 100.0 / double(status.total_parts), 'f', 1) + "%\n(" + QString::number(status.finished_parts) + " фрагментов из " + QString::number(status.total_parts) + ")"; setToolTipMessage(text, E_PROCESS); last_statusbar_update_time_.restart(); } } void StatusWidget::onPatchInstallerVideoProgressChanged(int finished_videos, int total_videos, Downloader::Status status) { if (last_statusbar_update_time_.elapsed() > 450) { double download_percent = double(status.downloaded_bytes) * 100.0 / double(status.total_bytes); QString text = "Загрузка и установка видеороликов (" + QString::number(finished_videos + 1) + " из " + QString::number(total_videos) + ")\n" + "Загружено: " + QString::number(download_percent, 'f', 1) + "% (" + Downloader::getSizeFormatted(status.downloaded_bytes) + "/" + Downloader::getSizeFormatted(status.total_bytes) + ")"; setToolTipMessage(text, E_PROCESS); last_statusbar_update_time_.restart(); } } void StatusWidget::on_game_button_clicked() { } void StatusWidget::createTooltipMessageWidget(QString tooltip_id) { tooltip_widgets_[tooltip_id] = new QLabel(this); tooltip_widgets_[tooltip_id]->setGeometry(ui->galadriel_tooltip_example->geometry()); tooltip_widgets_[tooltip_id]->setStyleSheet(ui->galadriel_tooltip_example->styleSheet()); tooltip_widgets_[tooltip_id]->setFont(ui->galadriel_tooltip_example->font()); tooltip_widgets_[tooltip_id]->setWordWrap(true); tooltip_widgets_[tooltip_id]->setOpenExternalLinks(true); tooltip_widgets_[tooltip_id]->setAlignment(Qt::AlignHCenter | Qt::AlignBottom); tooltip_effects_[tooltip_id] = new QGraphicsOpacityEffect(tooltip_widgets_[tooltip_id]); tooltip_effects_[tooltip_id]->setOpacity(0); tooltip_animations_[tooltip_id] = new QPropertyAnimation(tooltip_effects_[tooltip_id], "opacity"); tooltip_animations_[tooltip_id]->setDuration(300); tooltip_animations_[tooltip_id]->setStartValue(0); tooltip_animations_[tooltip_id]->setEndValue(1); tooltip_animations_[tooltip_id]->setDirection(QAbstractAnimation::Forward); tooltip_widgets_[tooltip_id]->setGraphicsEffect(tooltip_effects_[tooltip_id]); tooltip_widgets_[tooltip_id]->show(); } void StatusWidget::on_check_for_updates_button_clicked() { QMetaObject::invokeMethod(&PatchDownloader::instance(), &PatchDownloader::startPatchDownloaderChain, Qt::QueuedConnection); } void StatusWidget::showComponentsStatus() { _components_status_opacity_animation->disconnect(); ui->b_components_status->show(); _components_status_opacity_animation->stop(); _components_status_opacity_animation->setEndValue(1); _components_status_opacity_animation->start(); } void StatusWidget::hideComponentsStatus() { if (this->isVisible()) { _components_status_opacity_animation->stop(); _components_status_opacity_animation->setEndValue(0); _components_status_opacity_animation->start(); connect(_components_status_opacity_animation, &QPropertyAnimation::finished, ui->b_components_status, &QWidget::hide); } } void StatusWidget::onTranslationComponentsNeedToPatch() { _need_to_install_patches = true; updateButtonStatus(); } void StatusWidget::onTranslationComponentsNoNeedToPatch() { _need_to_install_patches = false; updateButtonStatus(); } void StatusWidget::updateButtonStatus() { if (_need_to_update) { setToolTipMessage("Доступна новая версия русификации. Нажмите \"Обновить\", чтобы начать загрузку.", ToolTipState::E_INFO); ui->game_button->setText("ОБНОВИТЬ"); } else { unsetToolTipMessage(ToolTipState::E_INFO); ui->game_button->setText("ИГРАТЬ"); } if (_need_to_install_patches) { setToolTipMessage("Нажмите \"Установить\", чтобы начать процесс русификации.", ToolTipState::E_INFO); ui->game_button->setText("установить"); } else { unsetToolTipMessage(ToolTipState::E_INFO); ui->game_button->setText("ИГРАТЬ"); } }