statuswidget.cpp 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336
  1. #include "ui_statuswidget.h"
  2. #include "statuswidget.h"
  3. #include "models/patchdownloader.h"
  4. #include "widgets/mainwindow.h"
  5. #include "constants.h"
  6. #include <QDesktopServices>
  7. #include <QUrl>
  8. #include <QDebug>
  9. #include <QMessageBox>
  10. #include <QRandomGenerator>
  11. StatusWidget::StatusWidget(QWidget *parent)
  12. : QWidget(parent)
  13. , ui(new Ui::StatusWidget)
  14. {
  15. ui->setupUi(this);
  16. last_statusbar_update_time_.start();
  17. ui->galadriel_tooltip_example->hide();
  18. connect(ui->weekly_code_widget, &WeeklyCodeWidget::showCompletedTooltip, this, [this](){setToolTipMessage("ЕЖЕНЕДЕЛЬНЫЙ КОД СКОПИРОВАН В БУФЕР ОБМЕНА", E_INFO);});
  19. connect(ui->weekly_code_widget, &WeeklyCodeWidget::showHelpTooltip, this, [this](){setToolTipMessage("КЛИКНИТЕ ПО ЕЖЕНЕДЕЛЬНОМУ КОДУ, ЧТОБЫ СКОПИРОВАТЬ ЕГО", E_INFO);});
  20. connect(ui->weekly_code_widget, &WeeklyCodeWidget::showNoTooltip, this, [this](){unsetToolTipMessage(E_INFO);});
  21. connect(ui->news_list, &NewsListWidget::showHelpToolTip, this, [this](){setToolTipMessage("НАЖМИТЕ НА ЗАГОЛОВОК НОВОСТИ, ЧТОБЫ ОТКРЫТЬ ЕЕ В БРАУЗЕРЕ", E_INFO);});
  22. connect(ui->news_list, &NewsListWidget::showNoToolTip, this, [this](){unsetToolTipMessage(E_INFO);});
  23. connect(ui->server_status_widget, &ServerStatusWidget::showServersTooltip, this, [this](QString message){setToolTipMessage(message, E_INFO);});
  24. connect(ui->server_status_widget, &ServerStatusWidget::showNoTooltip, this, [this](){unsetToolTipMessage(E_INFO);});
  25. connect(&PatchDownloader::instance(), &PatchDownloader::started, this, &StatusWidget::onPatchDownloaderStarted);
  26. connect(&PatchDownloader::instance(), &PatchDownloader::progressChanged, this, &StatusWidget::onPatchDownloaderProgressChanged);
  27. connect(&PatchDownloader::instance(), &PatchDownloader::finished, this, &StatusWidget::onPatchDownloaderFinished);
  28. connect(&PatchInstaller::instance(), &PatchInstaller::started, this, &StatusWidget::onPatchInstallerStarted);
  29. connect(&PatchInstaller::instance(), &PatchInstaller::progressChanged, this, &StatusWidget::onPatchInstallerProgressChanged);
  30. connect(&PatchInstaller::instance(), &PatchInstaller::finished, this, &StatusWidget::onPatchInstallerFinished);
  31. generateRandomTooltipMessage();
  32. random_tooltip_generator_timer_.setInterval(5 * 1000);
  33. connect(&random_tooltip_generator_timer_, &QTimer::timeout, this, &StatusWidget::generateRandomTooltipMessage);
  34. random_tooltip_generator_timer_.start();
  35. process_completed_tooltip_hide_timer_.setInterval(10 * 1000); // 10 seconds message "Installation completed" will be shown
  36. process_completed_tooltip_hide_timer_.stop();
  37. connect(&process_completed_tooltip_hide_timer_, &QTimer::timeout, this, [this](){unsetToolTipMessage(E_PROCESS); process_completed_tooltip_hide_timer_.stop();});
  38. }
  39. StatusWidget::~StatusWidget()
  40. {
  41. delete ui;
  42. }
  43. void StatusWidget::updateFontsSizes()
  44. {
  45. ui->game_button->setFont(trajan_11pt);
  46. ui->news_label->setFont(trajan_10pt);
  47. }
  48. void StatusWidget::setToolTipMessage(QString message, StatusWidget::ToolTipState state)
  49. {
  50. tooltip_messages_[state] = message;
  51. tooltip_state_ = ToolTipState(int(tooltip_state_) | int(state));
  52. QString message_id = message;
  53. if (state == E_PROCESS) {
  54. message_id = "E_PROCESS";
  55. }
  56. if (!tooltip_widgets_.contains(message_id)) {
  57. createTooltipMessageWidget(message_id);
  58. }
  59. tooltip_widgets_[message_id]->setText(message);
  60. if (tooltip_state_ < state * 2) {
  61. fadeBetweenToolTips(message_id);
  62. }
  63. }
  64. void StatusWidget::unsetToolTipMessage(StatusWidget::ToolTipState state)
  65. {
  66. tooltip_state_ = ToolTipState(int(tooltip_state_) & (~int(state)));
  67. ToolTipState showing_state = E_RANDOM;
  68. if (tooltip_state_ & E_INFO) {
  69. showing_state = E_INFO;
  70. } else if (tooltip_state_ & E_ERROR) {
  71. showing_state = E_ERROR;
  72. } else if (tooltip_state_ & E_PROCESS) {
  73. showing_state = E_PROCESS;
  74. }
  75. QString message_id = tooltip_messages_[showing_state];
  76. if (showing_state == E_PROCESS) {
  77. message_id = "E_PROCESS";
  78. }
  79. if (!tooltip_widgets_.contains(message_id)) {
  80. createTooltipMessageWidget(message_id);
  81. }
  82. tooltip_widgets_[message_id]->setText(tooltip_messages_[showing_state]);
  83. fadeBetweenToolTips(message_id);
  84. }
  85. void StatusWidget::onErrorStatusChanged(AppErrorStatus status)
  86. {
  87. if (status == E_NO_ERRORS) {
  88. init_error_type_message_ = "";
  89. unsetToolTipMessage(E_ERROR);
  90. ui->news_list->updateNewsWidget();
  91. ui->server_status_widget->updateServerStatus();
  92. ui->weekly_code_widget->updateWeeklyCodeWidget();
  93. return;
  94. }
  95. error_timeout_message_ = "Повторная попытка инициализации через 10 секунд";
  96. if (status & E_WRONG_GAME_FOLDER) {
  97. init_error_type_message_ = "Ошибка инициализации: некорректная папка с игрой!\n";
  98. setToolTipMessage(init_error_type_message_ + error_timeout_message_, E_ERROR);
  99. return;
  100. }
  101. if (status & E_DAT_FILES_MISSING) {
  102. init_error_type_message_ = "Ошибка инициализации: отсутствуют файлы данных игры!\n";
  103. setToolTipMessage(init_error_type_message_ + error_timeout_message_, E_ERROR);
  104. return;
  105. }
  106. if (status & E_WRONG_FILE_PERMISSIONS) {
  107. init_error_type_message_ = "Ошибка инициализации: недостаточно прав для изменения файлов данных!\n";
  108. setToolTipMessage(init_error_type_message_ + error_timeout_message_, E_ERROR);
  109. return;
  110. }
  111. if (status & E_CANNOT_ACCESS_DAT_FILES) {
  112. init_error_type_message_ = "Ошибка инициализации: нет доступа к файлам данных!\n";
  113. setToolTipMessage(init_error_type_message_ + error_timeout_message_, E_ERROR);
  114. return;
  115. }
  116. if (status & E_DAT_FILE_INCORRECT) {
  117. init_error_type_message_ = "Ошибка инициализации: формат файла данных устарел или некорректен!\n";
  118. setToolTipMessage(init_error_type_message_ + error_timeout_message_, E_ERROR);
  119. return;
  120. }
  121. if (status & E_NO_SERVER_CONNECTION) {
  122. init_error_type_message_ = "Ошибка инициализации: нет связи с сервером Наследия!\n";
  123. setToolTipMessage(init_error_type_message_ + error_timeout_message_, E_ERROR);
  124. return;
  125. }
  126. }
  127. void StatusWidget::onSecondsToNextTryToInitChanged(size_t seconds_elapsed)
  128. {
  129. if (!init_error_type_message_.isEmpty()) {
  130. error_timeout_message_ = "Повторная попытка инициализации через " + QString::number(seconds_elapsed) + " секунд";
  131. setToolTipMessage(init_error_type_message_ + error_timeout_message_, E_ERROR);
  132. }
  133. }
  134. void StatusWidget::resizeEvent(QResizeEvent *)
  135. {
  136. double coefficient = window_width / default_window_width;
  137. // ui->game_button->move(QPoint(820, 460) * coefficient);
  138. // ui->game_button->resize(QSize(150, 60) * coefficient);
  139. // ui->progressBar->move(QPoint(320, 480) * coefficient);
  140. // ui->progressBar->resize(QSize(470, 40) * coefficient);
  141. // ui->progress_label->move(QPoint(330, 390) * coefficient);
  142. // ui->progress_label->resize(QSize(380, 90) * coefficient);
  143. // ui->news_label->move(QPoint(45, 33)* coefficient);
  144. // ui->news_label->resize(QSize(180, 21) * coefficient);
  145. // ui->news_scroll_area->move(QPoint(40, 75) * coefficient);
  146. // ui->news_scroll_area->resize(QSize(240, 440) * coefficient);
  147. // ui->server_status_widget->move(QPoint(820, 90) * coefficient);
  148. // ui->server_status_widget->resize(QSize(155, 320) * coefficient);
  149. // ui->weekly_code_widget->move(QPoint(810, 13) * coefficient);
  150. // ui->weekly_code_widget->resize(QSize(173, 57) * coefficient);
  151. // ui->galadriel_widget->move(QPoint(320, 20) * coefficient);
  152. // ui->galadriel_widget->resize(QSize(531, 461) * coefficient);
  153. // ui->news_tooltip->move(QPoint(38, 13) * coefficient);
  154. // ui->news_tooltip->resize(QSize(365, 114) * coefficient);
  155. // ui->weekly_code_tooltip_1->move(QPoint(38, 13) * coefficient);
  156. // ui->weekly_code_tooltip_1->resize(QSize(365, 114) * coefficient);
  157. // ui->weekly_code_tooltip_2->move(QPoint(38, 13) * coefficient);
  158. // ui->weekly_code_tooltip_2->resize(QSize(365, 114) * coefficient);
  159. // ui->server_status_tooltip->move(QPoint(38, 13) * coefficient);
  160. // ui->server_status_tooltip->resize(QSize(365, 114) * coefficient);
  161. // ui->patches_status->move(QPoint(38, 13) * coefficient);
  162. // ui->patches_status->resize(QSize(385, 114) * coefficient);
  163. updateFontsSizes();
  164. }
  165. void StatusWidget::generateRandomTooltipMessage()
  166. {
  167. quint32 number = QRandomGenerator::system()->generate();
  168. setToolTipMessage("СЛУЧАЙНОЕ СООБЩЕНИЕ №" + QString::number(number), E_RANDOM);
  169. }
  170. void StatusWidget::fadeBetweenToolTips(QString tooltip_id)
  171. {
  172. if (tooltip_id == current_tooltip_message_) {
  173. return;
  174. }
  175. QPropertyAnimation* showing_anim = tooltip_animations_[tooltip_id];
  176. showing_anim->setDirection(QAbstractAnimation::Forward);
  177. if (showing_anim->state() == QAbstractAnimation::Stopped) {
  178. showing_anim->start();
  179. }
  180. if (tooltip_widgets_.contains(current_tooltip_message_)) {
  181. QString msg = current_tooltip_message_;
  182. connect(tooltip_animations_[current_tooltip_message_], &QPropertyAnimation::finished, this, [&, msg](){
  183. if (tooltip_effects_.contains(msg) && tooltip_effects_[msg]->opacity() == 0) {
  184. tooltip_widgets_.take(msg)->deleteLater();
  185. tooltip_effects_.take(msg)->deleteLater();
  186. tooltip_animations_.take(msg)->deleteLater();
  187. }
  188. });
  189. QPropertyAnimation* hiding_anim = tooltip_animations_[current_tooltip_message_];
  190. hiding_anim->setDirection(QAbstractAnimation::Backward);
  191. if (hiding_anim->state() == QAbstractAnimation::Stopped) {
  192. hiding_anim->start();
  193. }
  194. }
  195. current_tooltip_message_ = tooltip_id;
  196. }
  197. void StatusWidget::onPatchDownloaderStarted() {
  198. all_patch_operations_finished_ = false;
  199. ui->game_button->setEnabled(false);
  200. ui->check_for_updates_button->setEnabled(false);
  201. setToolTipMessage("Проверка обновлений русификации...", E_PROCESS);
  202. }
  203. void StatusWidget::onPatchDownloaderFinished() {
  204. all_patch_operations_finished_ = true;
  205. ui->game_button->setEnabled(true);
  206. ui->check_for_updates_button->setEnabled(true);
  207. setToolTipMessage("Скачивание данных русификации завершено!", E_PROCESS);
  208. process_completed_tooltip_hide_timer_.start();
  209. }
  210. void StatusWidget::onPatchDownloaderProgressChanged(Downloader::Status status) {
  211. if (last_statusbar_update_time_.elapsed() > 650) {
  212. double download_percent = double(status.downloaded_bytes) * 100.0 / double(status.total_bytes);
  213. QString text = "Загрузка данных: " + QString::number(download_percent, 'f', 1) + "% ("
  214. + Downloader::getSizeFormatted(status.downloaded_bytes) + "/"
  215. + Downloader::getSizeFormatted(status.total_bytes) + ")\n"
  216. + "До конца загрузки: " + Downloader::getElapsedTimeFormatted(status.elapsed_time);
  217. setToolTipMessage(text, E_PROCESS);
  218. last_statusbar_update_time_.restart();
  219. }
  220. }
  221. void StatusWidget::onPatchInstallerStarted() {
  222. all_patch_operations_finished_ = false;
  223. ui->game_button->setEnabled(false);
  224. ui->check_for_updates_button->setEnabled(false);
  225. setToolTipMessage("Подготовка русификатора...", E_PROCESS);
  226. }
  227. void StatusWidget::onPatchInstallerFinished() {
  228. all_patch_operations_finished_ = true;
  229. ui->game_button->setEnabled(true);
  230. ui->check_for_updates_button->setEnabled(true);
  231. setToolTipMessage("Все операции выполнены!", E_PROCESS);
  232. process_completed_tooltip_hide_timer_.start();
  233. }
  234. void StatusWidget::onPatchInstallerProgressChanged(PatchInstaller::Status status) {
  235. if (last_statusbar_update_time_.elapsed() > 650 || status.finished_parts == 0) {
  236. QString text = "Установка русификации: "
  237. + QString::number(double(status.finished_parts) * 100.0 / double(status.total_parts), 'f', 1)
  238. + "% (" + QString::number(status.finished_parts)
  239. + " фрагментов из " + QString::number(status.total_parts) + ")";
  240. setToolTipMessage(text, E_PROCESS);
  241. last_statusbar_update_time_.restart();
  242. }
  243. }
  244. void StatusWidget::onPatchInstallerVideoProgressChanged(Downloader::Status status) {
  245. if (last_statusbar_update_time_.elapsed() > 650) {
  246. double download_percent = double(status.downloaded_bytes) * 100.0 / double(status.total_bytes);
  247. QString text = "Загрузка видеороликов: " + QString::number(download_percent, 'f', 1) + "% ("
  248. + Downloader::getSizeFormatted(status.downloaded_bytes) + "/"
  249. + Downloader::getSizeFormatted(status.total_bytes) + ")\n"
  250. + "До конца загрузки: " + Downloader::getElapsedTimeFormatted(status.elapsed_time);
  251. setToolTipMessage(text, E_PROCESS);
  252. last_statusbar_update_time_.restart();
  253. }
  254. }
  255. void StatusWidget::on_game_button_clicked()
  256. {
  257. MainWindow* window = qobject_cast<MainWindow*>(parentWidget()->parentWidget()->parentWidget());
  258. window->showChooseVersionDialog();
  259. }
  260. void StatusWidget::createTooltipMessageWidget(QString tooltip_id)
  261. {
  262. tooltip_widgets_[tooltip_id] = new QLabel(ui->galadriel_widget);
  263. tooltip_widgets_[tooltip_id]->setGeometry(ui->galadriel_tooltip_example->geometry());
  264. tooltip_widgets_[tooltip_id]->setStyleSheet(ui->galadriel_tooltip_example->styleSheet());
  265. tooltip_widgets_[tooltip_id]->setFont(ui->galadriel_tooltip_example->font());
  266. tooltip_widgets_[tooltip_id]->setWordWrap(true);
  267. tooltip_widgets_[tooltip_id]->setAlignment(Qt::AlignCenter);
  268. tooltip_widgets_[tooltip_id]->show();
  269. tooltip_effects_[tooltip_id] = new QGraphicsOpacityEffect(tooltip_widgets_[tooltip_id]);
  270. tooltip_effects_[tooltip_id]->setOpacity(0);
  271. tooltip_animations_[tooltip_id] = new QPropertyAnimation(tooltip_effects_[tooltip_id], "opacity");
  272. tooltip_animations_[tooltip_id]->setDuration(300);
  273. tooltip_animations_[tooltip_id]->setStartValue(0);
  274. tooltip_animations_[tooltip_id]->setEndValue(1);
  275. tooltip_animations_[tooltip_id]->setDirection(QAbstractAnimation::Forward);
  276. tooltip_widgets_[tooltip_id]->setGraphicsEffect(tooltip_effects_[tooltip_id]);
  277. }
  278. void StatusWidget::on_check_for_updates_button_clicked()
  279. {
  280. QMetaObject::invokeMethod(&PatchDownloader::instance(), &PatchDownloader::startPatchDownloaderChain, Qt::QueuedConnection);
  281. }