From 4143675b2df288534e6e1a3f06a87d88dbaba257 Mon Sep 17 00:00:00 2001
From: Morph <39850852+Morph1984@users.noreply.github.com>
Date: Sat, 20 Mar 2021 07:57:31 -0400
Subject: [PATCH] overlay_dialog: Add an overlay text dialog that accepts
 controller input

An OverlayDialog is an interactive dialog that accepts controller input (while a game is running)
This dialog attempts to replicate the look and feel of the Nintendo Switch's overlay dialogs and
provide some extra features such as embedding HTML/Rich Text content in a QTextBrowser.
The OverlayDialog provides 2 modes: one to embed regular text into a QLabel and another to embed
HTML/Rich Text content into a QTextBrowser.

Co-authored-by: Its-Rei <kupfel@gmail.com>
---
 src/yuzu/CMakeLists.txt          |   3 +
 src/yuzu/main.cpp                |   6 +-
 src/yuzu/util/overlay_dialog.cpp | 249 +++++++++++++++++++
 src/yuzu/util/overlay_dialog.h   | 107 ++++++++
 src/yuzu/util/overlay_dialog.ui  | 404 +++++++++++++++++++++++++++++++
 5 files changed, 768 insertions(+), 1 deletion(-)
 create mode 100644 src/yuzu/util/overlay_dialog.cpp
 create mode 100644 src/yuzu/util/overlay_dialog.h
 create mode 100644 src/yuzu/util/overlay_dialog.ui

diff --git a/src/yuzu/CMakeLists.txt b/src/yuzu/CMakeLists.txt
index b025ced1c8..3e00ff39ff 100644
--- a/src/yuzu/CMakeLists.txt
+++ b/src/yuzu/CMakeLists.txt
@@ -143,6 +143,9 @@ add_executable(yuzu
     uisettings.h
     util/limitable_input_dialog.cpp
     util/limitable_input_dialog.h
+    util/overlay_dialog.cpp
+    util/overlay_dialog.h
+    util/overlay_dialog.ui
     util/sequence_dialog/sequence_dialog.cpp
     util/sequence_dialog/sequence_dialog.h
     util/url_request_interceptor.cpp
diff --git a/src/yuzu/main.cpp b/src/yuzu/main.cpp
index 422b3cff66..3d4558739e 100644
--- a/src/yuzu/main.cpp
+++ b/src/yuzu/main.cpp
@@ -101,6 +101,7 @@ static FileSys::VirtualFile VfsDirectoryCreateFileWrapper(const FileSys::Virtual
 #include "core/perf_stats.h"
 #include "core/telemetry_session.h"
 #include "input_common/main.h"
+#include "util/overlay_dialog.h"
 #include "video_core/gpu.h"
 #include "video_core/shader_notify.h"
 #include "yuzu/about_dialog.h"
@@ -2266,7 +2267,10 @@ void GMainWindow::OnExecuteProgram(std::size_t program_index) {
 }
 
 void GMainWindow::ErrorDisplayDisplayError(QString body) {
-    QMessageBox::critical(this, tr("Error Display"), body);
+    OverlayDialog dialog(render_window, Core::System::GetInstance(), body, QString{}, tr("OK"),
+                         Qt::AlignLeft | Qt::AlignVCenter);
+    dialog.exec();
+
     emit ErrorDisplayFinished();
 }
 
diff --git a/src/yuzu/util/overlay_dialog.cpp b/src/yuzu/util/overlay_dialog.cpp
new file mode 100644
index 0000000000..95b1485450
--- /dev/null
+++ b/src/yuzu/util/overlay_dialog.cpp
@@ -0,0 +1,249 @@
+// Copyright 2021 yuzu Emulator Project
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#include <QKeyEvent>
+#include <QScreen>
+
+#include "core/core.h"
+#include "core/frontend/input_interpreter.h"
+#include "ui_overlay_dialog.h"
+#include "yuzu/util/overlay_dialog.h"
+
+namespace {
+
+constexpr float BASE_TITLE_FONT_SIZE = 14.0f;
+constexpr float BASE_FONT_SIZE = 18.0f;
+constexpr float BASE_WIDTH = 1280.0f;
+constexpr float BASE_HEIGHT = 720.0f;
+
+} // Anonymous namespace
+
+OverlayDialog::OverlayDialog(QWidget* parent, Core::System& system, const QString& title_text,
+                             const QString& body_text, const QString& left_button_text,
+                             const QString& right_button_text, Qt::Alignment alignment,
+                             bool use_rich_text_)
+    : QDialog(parent), ui{std::make_unique<Ui::OverlayDialog>()}, use_rich_text{use_rich_text_} {
+    ui->setupUi(this);
+
+    setWindowFlags(Qt::Dialog | Qt::FramelessWindowHint | Qt::WindowTitleHint |
+                   Qt::WindowSystemMenuHint | Qt::CustomizeWindowHint);
+    setWindowModality(Qt::WindowModal);
+    setAttribute(Qt::WA_TranslucentBackground);
+
+    if (use_rich_text) {
+        InitializeRichTextDialog(title_text, body_text, left_button_text, right_button_text,
+                                 alignment);
+    } else {
+        InitializeRegularTextDialog(title_text, body_text, left_button_text, right_button_text,
+                                    alignment);
+    }
+
+    MoveAndResizeWindow();
+
+    // TODO (Morph): Remove this when InputInterpreter no longer relies on the HID backend
+    if (system.IsPoweredOn()) {
+        input_interpreter = std::make_unique<InputInterpreter>(system);
+
+        StartInputThread();
+    }
+}
+
+OverlayDialog::~OverlayDialog() {
+    StopInputThread();
+}
+
+void OverlayDialog::InitializeRegularTextDialog(const QString& title_text, const QString& body_text,
+                                                const QString& left_button_text,
+                                                const QString& right_button_text,
+                                                Qt::Alignment alignment) {
+    ui->stackedDialog->setCurrentIndex(0);
+
+    ui->label_title->setText(title_text);
+    ui->label_dialog->setText(body_text);
+    ui->button_cancel->setText(left_button_text);
+    ui->button_ok_label->setText(right_button_text);
+
+    ui->label_dialog->setAlignment(alignment);
+
+    if (title_text.isEmpty()) {
+        ui->label_title->hide();
+        ui->verticalLayout_2->setStretch(0, 0);
+        ui->verticalLayout_2->setStretch(1, 219);
+        ui->verticalLayout_2->setStretch(2, 82);
+    }
+
+    if (left_button_text.isEmpty()) {
+        ui->button_cancel->hide();
+        ui->button_cancel->setEnabled(false);
+    }
+
+    if (right_button_text.isEmpty()) {
+        ui->button_ok_label->hide();
+        ui->button_ok_label->setEnabled(false);
+    }
+
+    connect(
+        ui->button_cancel, &QPushButton::clicked, this,
+        [this](bool) {
+            StopInputThread();
+            QDialog::reject();
+        },
+        Qt::QueuedConnection);
+    connect(
+        ui->button_ok_label, &QPushButton::clicked, this,
+        [this](bool) {
+            StopInputThread();
+            QDialog::accept();
+        },
+        Qt::QueuedConnection);
+}
+
+void OverlayDialog::InitializeRichTextDialog(const QString& title_text, const QString& body_text,
+                                             const QString& left_button_text,
+                                             const QString& right_button_text,
+                                             Qt::Alignment alignment) {
+    ui->stackedDialog->setCurrentIndex(1);
+
+    ui->label_title_rich->setText(title_text);
+    ui->text_browser_dialog->setText(body_text);
+    ui->button_cancel_rich->setText(left_button_text);
+    ui->button_ok_rich->setText(right_button_text);
+
+    // TODO (Morph/Rei): Replace this with something that works better
+    ui->text_browser_dialog->setAlignment(alignment);
+
+    if (title_text.isEmpty()) {
+        ui->label_title_rich->hide();
+        ui->verticalLayout_3->setStretch(0, 0);
+        ui->verticalLayout_3->setStretch(1, 438);
+        ui->verticalLayout_3->setStretch(2, 82);
+    }
+
+    if (left_button_text.isEmpty()) {
+        ui->button_cancel_rich->hide();
+        ui->button_cancel_rich->setEnabled(false);
+    }
+
+    if (right_button_text.isEmpty()) {
+        ui->button_ok_rich->hide();
+        ui->button_ok_rich->setEnabled(false);
+    }
+
+    connect(
+        ui->button_cancel_rich, &QPushButton::clicked, this,
+        [this](bool) {
+            StopInputThread();
+            QDialog::reject();
+        },
+        Qt::QueuedConnection);
+    connect(
+        ui->button_ok_rich, &QPushButton::clicked, this,
+        [this](bool) {
+            StopInputThread();
+            QDialog::accept();
+        },
+        Qt::QueuedConnection);
+}
+
+void OverlayDialog::MoveAndResizeWindow() {
+    const auto pos = parentWidget()->mapToGlobal(parentWidget()->rect().topLeft());
+    const auto width = static_cast<float>(parentWidget()->width());
+    const auto height = static_cast<float>(parentWidget()->height());
+
+    // High DPI
+    const float dpi_scale = qApp->screenAt(pos)->logicalDotsPerInch() / 96.0f;
+
+    const auto title_text_font_size = BASE_TITLE_FONT_SIZE * (height / BASE_HEIGHT) / dpi_scale;
+    const auto body_text_font_size =
+        BASE_FONT_SIZE * (((width / BASE_WIDTH) + (height / BASE_HEIGHT)) / 2.0f) / dpi_scale;
+    const auto button_text_font_size = BASE_FONT_SIZE * (height / BASE_HEIGHT) / dpi_scale;
+
+    QFont title_text_font(QStringLiteral("MS Shell Dlg 2"), title_text_font_size, QFont::Normal);
+    QFont body_text_font(QStringLiteral("MS Shell Dlg 2"), body_text_font_size, QFont::Normal);
+    QFont button_text_font(QStringLiteral("MS Shell Dlg 2"), button_text_font_size, QFont::Normal);
+
+    if (use_rich_text) {
+        ui->label_title_rich->setFont(title_text_font);
+        ui->text_browser_dialog->setFont(body_text_font);
+        ui->button_cancel_rich->setFont(button_text_font);
+        ui->button_ok_rich->setFont(button_text_font);
+    } else {
+        ui->label_title->setFont(title_text_font);
+        ui->label_dialog->setFont(body_text_font);
+        ui->button_cancel->setFont(button_text_font);
+        ui->button_ok_label->setFont(button_text_font);
+    }
+
+    QDialog::move(pos);
+    QDialog::resize(width, height);
+}
+
+template <HIDButton... T>
+void OverlayDialog::HandleButtonPressedOnce() {
+    const auto f = [this](HIDButton button) {
+        if (input_interpreter->IsButtonPressedOnce(button)) {
+            TranslateButtonPress(button);
+        }
+    };
+
+    (f(T), ...);
+}
+
+void OverlayDialog::TranslateButtonPress(HIDButton button) {
+    QPushButton* left_button = use_rich_text ? ui->button_cancel_rich : ui->button_cancel;
+    QPushButton* right_button = use_rich_text ? ui->button_ok_rich : ui->button_ok_label;
+
+    // TODO (Morph): Handle QTextBrowser text scrolling
+    // TODO (Morph): focusPrevious/NextChild() doesn't work well with the rich text dialog, fix it
+
+    switch (button) {
+    case HIDButton::A:
+    case HIDButton::B:
+        if (left_button->hasFocus()) {
+            left_button->click();
+        } else if (right_button->hasFocus()) {
+            right_button->click();
+        }
+        break;
+    case HIDButton::DLeft:
+    case HIDButton::LStickLeft:
+        focusPreviousChild();
+        break;
+    case HIDButton::DRight:
+    case HIDButton::LStickRight:
+        focusNextChild();
+        break;
+    default:
+        break;
+    }
+}
+
+void OverlayDialog::StartInputThread() {
+    if (input_thread_running) {
+        return;
+    }
+
+    input_thread_running = true;
+
+    input_thread = std::thread(&OverlayDialog::InputThread, this);
+}
+
+void OverlayDialog::StopInputThread() {
+    input_thread_running = false;
+
+    if (input_thread.joinable()) {
+        input_thread.join();
+    }
+}
+
+void OverlayDialog::InputThread() {
+    while (input_thread_running) {
+        input_interpreter->PollInput();
+
+        HandleButtonPressedOnce<HIDButton::A, HIDButton::B, HIDButton::DLeft, HIDButton::DRight,
+                                HIDButton::LStickLeft, HIDButton::LStickRight>();
+
+        std::this_thread::sleep_for(std::chrono::milliseconds(50));
+    }
+}
diff --git a/src/yuzu/util/overlay_dialog.h b/src/yuzu/util/overlay_dialog.h
new file mode 100644
index 0000000000..e8c388bd01
--- /dev/null
+++ b/src/yuzu/util/overlay_dialog.h
@@ -0,0 +1,107 @@
+// Copyright 2021 yuzu Emulator Project
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#pragma once
+
+#include <array>
+#include <atomic>
+#include <memory>
+#include <thread>
+
+#include <QDialog>
+
+#include "common/common_types.h"
+
+enum class HIDButton : u8;
+
+class InputInterpreter;
+
+namespace Core {
+class System;
+}
+
+namespace Ui {
+class OverlayDialog;
+}
+
+/**
+ * An OverlayDialog is an interactive dialog that accepts controller input (while a game is running)
+ * This dialog attempts to replicate the look and feel of the Nintendo Switch's overlay dialogs and
+ * provide some extra features such as embedding HTML/Rich Text content in a QTextBrowser.
+ * The OverlayDialog provides 2 modes: one to embed regular text into a QLabel and another to embed
+ * HTML/Rich Text content into a QTextBrowser.
+ */
+class OverlayDialog final : public QDialog {
+    Q_OBJECT
+
+public:
+    explicit OverlayDialog(QWidget* parent, Core::System& system, const QString& title_text,
+                           const QString& body_text, const QString& left_button_text,
+                           const QString& right_button_text,
+                           Qt::Alignment alignment = Qt::AlignCenter, bool use_rich_text_ = false);
+    ~OverlayDialog() override;
+
+private:
+    /**
+     * Initializes a text dialog with a QLabel storing text.
+     * Only use this for short text as the dialog buttons would be squashed with longer text.
+     *
+     * @param title_text Title text to be displayed
+     * @param body_text Main text to be displayed
+     * @param left_button_text Left button text. If empty, the button is hidden and disabled
+     * @param right_button_text Right button text. If empty, the button is hidden and disabled
+     * @param alignment Main text alignment
+     */
+    void InitializeRegularTextDialog(const QString& title_text, const QString& body_text,
+                                     const QString& left_button_text,
+                                     const QString& right_button_text, Qt::Alignment alignment);
+
+    /**
+     * Initializes a text dialog with a QTextBrowser storing text.
+     * This is ideal for longer text or rich text content. A scrollbar is shown for longer text.
+     *
+     * @param title_text Title text to be displayed
+     * @param body_text Main text to be displayed
+     * @param left_button_text Left button text. If empty, the button is hidden and disabled
+     * @param right_button_text Right button text. If empty, the button is hidden and disabled
+     * @param alignment Main text alignment
+     */
+    void InitializeRichTextDialog(const QString& title_text, const QString& body_text,
+                                  const QString& left_button_text, const QString& right_button_text,
+                                  Qt::Alignment alignment);
+
+    /// Moves and resizes the dialog to be fully overlayed on top of the parent window.
+    void MoveAndResizeWindow();
+
+    /**
+     * Handles button presses and converts them into keyboard input.
+     *
+     * @tparam HIDButton The list of buttons that can be converted into keyboard input.
+     */
+    template <HIDButton... T>
+    void HandleButtonPressedOnce();
+
+    /**
+     * Translates a button press to focus or click either the left or right buttons.
+     *
+     * @param button The button press to process.
+     */
+    void TranslateButtonPress(HIDButton button);
+
+    void StartInputThread();
+    void StopInputThread();
+
+    /// The thread where input is being polled and processed.
+    void InputThread();
+
+    std::unique_ptr<Ui::OverlayDialog> ui;
+
+    bool use_rich_text;
+
+    std::unique_ptr<InputInterpreter> input_interpreter;
+
+    std::thread input_thread;
+
+    std::atomic<bool> input_thread_running{};
+};
diff --git a/src/yuzu/util/overlay_dialog.ui b/src/yuzu/util/overlay_dialog.ui
new file mode 100644
index 0000000000..278e2f219e
--- /dev/null
+++ b/src/yuzu/util/overlay_dialog.ui
@@ -0,0 +1,404 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>OverlayDialog</class>
+ <widget class="QDialog" name="OverlayDialog">
+  <property name="geometry">
+   <rect>
+    <x>0</x>
+    <y>0</y>
+    <width>1280</width>
+    <height>720</height>
+   </rect>
+  </property>
+  <property name="windowTitle">
+   <string>Dialog</string>
+  </property>
+  <property name="styleSheet">
+   <string notr="true"/>
+  </property>
+  <layout class="QVBoxLayout" name="verticalLayout">
+   <property name="spacing">
+    <number>0</number>
+   </property>
+   <property name="leftMargin">
+    <number>0</number>
+   </property>
+   <property name="topMargin">
+    <number>0</number>
+   </property>
+   <property name="rightMargin">
+    <number>0</number>
+   </property>
+   <property name="bottomMargin">
+    <number>0</number>
+   </property>
+   <item>
+    <widget class="QStackedWidget" name="stackedDialog">
+     <property name="currentIndex">
+      <number>0</number>
+     </property>
+     <widget class="QWidget" name="lineDialog">
+      <layout class="QGridLayout" name="lineDialogGridLayout" rowstretch="210,300,210" columnstretch="250,780,250">
+       <property name="leftMargin">
+        <number>0</number>
+       </property>
+       <property name="topMargin">
+        <number>0</number>
+       </property>
+       <property name="rightMargin">
+        <number>0</number>
+       </property>
+       <property name="bottomMargin">
+        <number>0</number>
+       </property>
+       <property name="spacing">
+        <number>0</number>
+       </property>
+       <item row="1" column="1">
+        <widget class="QWidget" name="contentDialog" native="true">
+         <layout class="QVBoxLayout" name="verticalLayout_2" stretch="70,149,82">
+          <property name="spacing">
+           <number>0</number>
+          </property>
+          <property name="leftMargin">
+           <number>0</number>
+          </property>
+          <property name="topMargin">
+           <number>0</number>
+          </property>
+          <property name="rightMargin">
+           <number>0</number>
+          </property>
+          <property name="bottomMargin">
+           <number>0</number>
+          </property>
+          <item>
+           <widget class="QLabel" name="label_title">
+            <property name="font">
+             <font>
+              <pointsize>14</pointsize>
+             </font>
+            </property>
+            <property name="alignment">
+             <set>Qt::AlignBottom|Qt::AlignLeading|Qt::AlignLeft</set>
+            </property>
+           </widget>
+          </item>
+          <item>
+           <widget class="QLabel" name="label_dialog">
+            <property name="font">
+             <font>
+              <pointsize>18</pointsize>
+             </font>
+            </property>
+            <property name="alignment">
+             <set>Qt::AlignCenter</set>
+            </property>
+            <property name="wordWrap">
+             <bool>true</bool>
+            </property>
+           </widget>
+          </item>
+          <item>
+           <widget class="QWidget" name="buttonsDialog" native="true">
+            <layout class="QHBoxLayout" name="horizontalLayout">
+             <property name="spacing">
+              <number>0</number>
+             </property>
+             <property name="leftMargin">
+              <number>0</number>
+             </property>
+             <property name="topMargin">
+              <number>0</number>
+             </property>
+             <property name="rightMargin">
+              <number>0</number>
+             </property>
+             <property name="bottomMargin">
+              <number>0</number>
+             </property>
+             <item>
+              <widget class="QPushButton" name="button_cancel">
+               <property name="sizePolicy">
+                <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
+                 <horstretch>0</horstretch>
+                 <verstretch>0</verstretch>
+                </sizepolicy>
+               </property>
+               <property name="font">
+                <font>
+                 <pointsize>18</pointsize>
+                </font>
+               </property>
+               <property name="text">
+                <string>Cancel</string>
+               </property>
+              </widget>
+             </item>
+             <item>
+              <widget class="QPushButton" name="button_ok_label">
+               <property name="sizePolicy">
+                <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
+                 <horstretch>0</horstretch>
+                 <verstretch>0</verstretch>
+                </sizepolicy>
+               </property>
+               <property name="font">
+                <font>
+                 <pointsize>18</pointsize>
+                </font>
+               </property>
+               <property name="text">
+                <string>OK</string>
+               </property>
+              </widget>
+             </item>
+            </layout>
+           </widget>
+          </item>
+         </layout>
+        </widget>
+       </item>
+       <item row="0" column="1">
+        <spacer name="verticalSpacer">
+         <property name="orientation">
+          <enum>Qt::Vertical</enum>
+         </property>
+         <property name="sizeHint" stdset="0">
+          <size>
+           <width>20</width>
+           <height>40</height>
+          </size>
+         </property>
+        </spacer>
+       </item>
+       <item row="1" column="0">
+        <spacer name="horizontalSpacer">
+         <property name="orientation">
+          <enum>Qt::Horizontal</enum>
+         </property>
+         <property name="sizeHint" stdset="0">
+          <size>
+           <width>40</width>
+           <height>20</height>
+          </size>
+         </property>
+        </spacer>
+       </item>
+       <item row="2" column="1">
+        <spacer name="verticalSpacer_2">
+         <property name="orientation">
+          <enum>Qt::Vertical</enum>
+         </property>
+         <property name="sizeHint" stdset="0">
+          <size>
+           <width>20</width>
+           <height>40</height>
+          </size>
+         </property>
+        </spacer>
+       </item>
+       <item row="1" column="2">
+        <spacer name="horizontalSpacer_2">
+         <property name="orientation">
+          <enum>Qt::Horizontal</enum>
+         </property>
+         <property name="sizeHint" stdset="0">
+          <size>
+           <width>40</width>
+           <height>20</height>
+          </size>
+         </property>
+        </spacer>
+       </item>
+      </layout>
+     </widget>
+     <widget class="QWidget" name="richDialog">
+      <layout class="QGridLayout" name="richDialogGridLayout" rowstretch="100,520,100" columnstretch="165,950,165">
+       <property name="leftMargin">
+        <number>0</number>
+       </property>
+       <property name="topMargin">
+        <number>0</number>
+       </property>
+       <property name="rightMargin">
+        <number>0</number>
+       </property>
+       <property name="bottomMargin">
+        <number>0</number>
+       </property>
+       <property name="spacing">
+        <number>0</number>
+       </property>
+       <item row="1" column="0">
+        <spacer name="horizontalSpacer_3">
+         <property name="orientation">
+          <enum>Qt::Horizontal</enum>
+         </property>
+         <property name="sizeHint" stdset="0">
+          <size>
+           <width>40</width>
+           <height>20</height>
+          </size>
+         </property>
+        </spacer>
+       </item>
+       <item row="2" column="1">
+        <spacer name="verticalSpacer_4">
+         <property name="orientation">
+          <enum>Qt::Vertical</enum>
+         </property>
+         <property name="sizeHint" stdset="0">
+          <size>
+           <width>20</width>
+           <height>40</height>
+          </size>
+         </property>
+        </spacer>
+       </item>
+       <item row="0" column="1">
+        <spacer name="verticalSpacer_3">
+         <property name="orientation">
+          <enum>Qt::Vertical</enum>
+         </property>
+         <property name="sizeHint" stdset="0">
+          <size>
+           <width>20</width>
+           <height>40</height>
+          </size>
+         </property>
+        </spacer>
+       </item>
+       <item row="1" column="1">
+        <widget class="QWidget" name="contentRichDialog" native="true">
+         <layout class="QVBoxLayout" name="verticalLayout_3" stretch="70,368,82">
+          <property name="spacing">
+           <number>0</number>
+          </property>
+          <property name="leftMargin">
+           <number>0</number>
+          </property>
+          <property name="topMargin">
+           <number>0</number>
+          </property>
+          <property name="rightMargin">
+           <number>0</number>
+          </property>
+          <property name="bottomMargin">
+           <number>0</number>
+          </property>
+          <item>
+           <widget class="QLabel" name="label_title_rich">
+            <property name="font">
+             <font>
+              <pointsize>14</pointsize>
+             </font>
+            </property>
+            <property name="text">
+             <string/>
+            </property>
+            <property name="alignment">
+             <set>Qt::AlignBottom|Qt::AlignLeading|Qt::AlignLeft</set>
+            </property>
+           </widget>
+          </item>
+          <item>
+           <widget class="QTextBrowser" name="text_browser_dialog">
+            <property name="font">
+             <font>
+              <pointsize>18</pointsize>
+             </font>
+            </property>
+            <property name="html">
+             <string>&lt;!DOCTYPE HTML PUBLIC &quot;-//W3C//DTD HTML 4.0//EN&quot; &quot;http://www.w3.org/TR/REC-html40/strict.dtd&quot;&gt;
+&lt;html&gt;&lt;head&gt;&lt;meta name=&quot;qrichtext&quot; content=&quot;1&quot; /&gt;&lt;style type=&quot;text/css&quot;&gt;
+p, li { white-space: pre-wrap; }
+&lt;/style&gt;&lt;/head&gt;&lt;body style=&quot; font-family:'MS Shell Dlg 2'; font-size:18pt; font-weight:400; font-style:normal;&quot;&gt;
+&lt;p style=&quot;-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;br /&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
+            </property>
+           </widget>
+          </item>
+          <item>
+           <widget class="QWidget" name="buttonsRichDialog" native="true">
+            <layout class="QHBoxLayout" name="horizontalLayout_2">
+             <property name="spacing">
+              <number>0</number>
+             </property>
+             <property name="leftMargin">
+              <number>0</number>
+             </property>
+             <property name="topMargin">
+              <number>0</number>
+             </property>
+             <property name="rightMargin">
+              <number>0</number>
+             </property>
+             <property name="bottomMargin">
+              <number>0</number>
+             </property>
+             <item>
+              <widget class="QPushButton" name="button_cancel_rich">
+               <property name="sizePolicy">
+                <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
+                 <horstretch>0</horstretch>
+                 <verstretch>0</verstretch>
+                </sizepolicy>
+               </property>
+               <property name="font">
+                <font>
+                 <pointsize>18</pointsize>
+                </font>
+               </property>
+               <property name="text">
+                <string>Cancel</string>
+               </property>
+              </widget>
+             </item>
+             <item>
+              <widget class="QPushButton" name="button_ok_rich">
+               <property name="sizePolicy">
+                <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
+                 <horstretch>0</horstretch>
+                 <verstretch>0</verstretch>
+                </sizepolicy>
+               </property>
+               <property name="font">
+                <font>
+                 <pointsize>18</pointsize>
+                </font>
+               </property>
+               <property name="text">
+                <string>OK</string>
+               </property>
+              </widget>
+             </item>
+            </layout>
+           </widget>
+          </item>
+         </layout>
+        </widget>
+       </item>
+       <item row="1" column="2">
+        <spacer name="horizontalSpacer_4">
+         <property name="orientation">
+          <enum>Qt::Horizontal</enum>
+         </property>
+         <property name="sizeHint" stdset="0">
+          <size>
+           <width>40</width>
+           <height>20</height>
+          </size>
+         </property>
+        </spacer>
+       </item>
+      </layout>
+     </widget>
+    </widget>
+   </item>
+  </layout>
+ </widget>
+ <resources>
+  <include location="../../../dist/icons/overlay/overlay.qrc"/>
+ </resources>
+ <connections/>
+</ui>