|
| 1 | +#include "TutorialWidget.h" |
| 2 | + |
| 3 | +#include <QHBoxLayout> |
| 4 | +#include <QLabel> |
| 5 | +#include <QPushButton> |
| 6 | + |
| 7 | +#include "MainWindow.h" |
| 8 | +#include "ui_MainWindow.h" |
| 9 | + |
| 10 | +const QString TutorialWidget::TUTORIAL_HEADER_TEXT = tr("<b>Moolticute Tutorial - %1</b><br><br>"); |
| 11 | +const QString TutorialWidget::TUTORIAL_FINISHED_SETTING = "settings/tutorial_finished"; |
| 12 | + |
| 13 | +TutorialWidget::TutorialWidget(QWidget *parent) : |
| 14 | + QFrame(parent), |
| 15 | + m_messageLabel{new QLabel}, |
| 16 | + m_nextButton{new QPushButton}, |
| 17 | + m_exitButton{new QPushButton} |
| 18 | +{ |
| 19 | + QHBoxLayout *lay = new QHBoxLayout(this); |
| 20 | + setLayout(lay); |
| 21 | + |
| 22 | + m_messageLabel->setMinimumWidth(600); |
| 23 | + |
| 24 | + lay->addStretch(); |
| 25 | + lay->addWidget(m_messageLabel); |
| 26 | + lay->addItem(new QSpacerItem(40, 20, QSizePolicy::Expanding, QSizePolicy::Minimum)); |
| 27 | + lay->addWidget(m_nextButton); |
| 28 | + lay->addWidget(m_exitButton); |
| 29 | + lay->addStretch(); |
| 30 | + |
| 31 | + setStyleSheet("TutorialWidget {border: 15px solid #60B1C7;}"); |
| 32 | + |
| 33 | + m_messageLabel->setAlignment(Qt::AlignCenter); |
| 34 | + m_messageLabel->setTextFormat(Qt::RichText); |
| 35 | + m_messageLabel->setTextInteractionFlags(Qt::TextBrowserInteraction); |
| 36 | + m_messageLabel->setOpenExternalLinks(true); |
| 37 | + |
| 38 | + m_nextButton->setText(tr("Next")); |
| 39 | + m_nextButton->setStyleSheet(CSS_BLUE_BUTTON); |
| 40 | + |
| 41 | + m_exitButton->setText(tr("Exit")); |
| 42 | + m_exitButton->setStyleSheet(CSS_BLUE_BUTTON); |
| 43 | + connect(m_exitButton, &QPushButton::clicked, this, &TutorialWidget::onExitClicked); |
| 44 | + connect(m_nextButton, &QPushButton::clicked, this, &TutorialWidget::onNextClicked); |
| 45 | + |
| 46 | + QSettings s; |
| 47 | + m_tutorialFinished = s.value(TUTORIAL_FINISHED_SETTING, false).toBool(); |
| 48 | + m_mw = static_cast<MainWindow*>(parent->parent()); |
| 49 | + if (m_tutorialFinished) |
| 50 | + { |
| 51 | + hide(); |
| 52 | + } |
| 53 | + else |
| 54 | + { |
| 55 | + initTutorial(); |
| 56 | + startTutorial(); |
| 57 | + show(); |
| 58 | + } |
| 59 | + |
| 60 | + if (!m_tutorialFinished) |
| 61 | + { |
| 62 | + connect(m_mw->wsClient, &WSClient::deviceConnected, this, &TutorialWidget::onDeviceConnected); |
| 63 | + connect(m_mw->wsClient, &WSClient::deviceDisconnected, this, &TutorialWidget::onDeviceDisconnected); |
| 64 | + connect(m_mw->wsClient, &WSClient::statusChanged, this, &TutorialWidget::onStatusChanged); |
| 65 | + } |
| 66 | +} |
| 67 | + |
| 68 | +TutorialWidget::~TutorialWidget() |
| 69 | +{ |
| 70 | + |
| 71 | +} |
| 72 | + |
| 73 | +void TutorialWidget::setText(const QString &text) |
| 74 | +{ |
| 75 | + m_messageLabel->setText(text); |
| 76 | +} |
| 77 | + |
| 78 | +void TutorialWidget::displayCurrentTab() |
| 79 | +{ |
| 80 | + if (m_current_index != -1) |
| 81 | + { |
| 82 | + m_mw->ui->widgetHeader->setEnabled(true); |
| 83 | + m_tabs[m_current_index].button()->setEnabled(true); |
| 84 | + } |
| 85 | +} |
| 86 | + |
| 87 | +void TutorialWidget::changeTutorialFinished(bool enabled) |
| 88 | +{ |
| 89 | + QSettings s; |
| 90 | + s.setValue(TUTORIAL_FINISHED_SETTING, !enabled); |
| 91 | +} |
| 92 | + |
| 93 | +void TutorialWidget::onExitClicked() |
| 94 | +{ |
| 95 | + QSettings s; |
| 96 | + s.setValue(TUTORIAL_FINISHED_SETTING, true); |
| 97 | + m_tutorialFinished = true; |
| 98 | + hide(); |
| 99 | + disconnect(m_mw->wsClient, &WSClient::deviceConnected, this, &TutorialWidget::onDeviceConnected); |
| 100 | + disconnect(m_mw->wsClient, &WSClient::deviceDisconnected, this, &TutorialWidget::onDeviceDisconnected); |
| 101 | + disconnect(m_mw->wsClient, &WSClient::statusChanged, this, &TutorialWidget::onStatusChanged); |
| 102 | + m_mw->updateTabButtons(); |
| 103 | +} |
| 104 | + |
| 105 | +void TutorialWidget::onNextClicked() |
| 106 | +{ |
| 107 | + if (m_current_index != -1) |
| 108 | + { |
| 109 | + m_tabs[m_current_index].button()->setEnabled(false); |
| 110 | + } |
| 111 | + m_mw->ui->widgetHeader->setEnabled(true); |
| 112 | + m_current_index++; |
| 113 | + if (m_current_index >= m_tabs.size()) |
| 114 | + { |
| 115 | + qCritical() << "No more tutorial page"; |
| 116 | + QMessageBox::information(this, tr("Tutorial finished"), tr("Congratulation, you have completed the tutorial.")); |
| 117 | + onExitClicked(); |
| 118 | + return; |
| 119 | + } |
| 120 | + QPushButton *button = m_tabs[m_current_index].button(); |
| 121 | + button->setEnabled(true); |
| 122 | + QWidget* page = nullptr; |
| 123 | + for (auto* tabButton : m_mw->m_tabMap) |
| 124 | + { |
| 125 | + if (tabButton == button) |
| 126 | + { |
| 127 | + page = m_mw->m_tabMap.key(button); |
| 128 | + } |
| 129 | + } |
| 130 | + if (page) |
| 131 | + { |
| 132 | + m_mw->ui->stackedWidget->setCurrentWidget(page); |
| 133 | + } |
| 134 | + else |
| 135 | + { |
| 136 | + qCritical() << "Cannot find page!"; |
| 137 | + } |
| 138 | + m_messageLabel->setText(TUTORIAL_HEADER_TEXT.arg(button->text()) + m_tabs[m_current_index].text()); |
| 139 | +} |
| 140 | + |
| 141 | +void TutorialWidget::onDeviceConnected() |
| 142 | +{ |
| 143 | + if (!m_tutorialFinished) |
| 144 | + { |
| 145 | + bool connected = m_mw->wsClient->isMPBLE(); |
| 146 | + if (connected) |
| 147 | + { |
| 148 | + m_nextButton->setEnabled(Common::MPStatus::Unlocked == m_mw->wsClient->get_status()); |
| 149 | + } |
| 150 | + else |
| 151 | + { |
| 152 | + m_nextButton->setEnabled(false); |
| 153 | + QMessageBox::warning(this, tr("Tutorial warning"), tr("Tutorial is only available for BLE device, please attach one or Exit tutorial.")); |
| 154 | + } |
| 155 | + } |
| 156 | +} |
| 157 | + |
| 158 | +void TutorialWidget::onDeviceDisconnected() |
| 159 | +{ |
| 160 | + if (!m_tutorialFinished) |
| 161 | + { |
| 162 | + m_nextButton->setEnabled(false); |
| 163 | + // Display connect device again |
| 164 | + startTutorial(); |
| 165 | + } |
| 166 | +} |
| 167 | + |
| 168 | +void TutorialWidget::onStatusChanged(Common::MPStatus status) |
| 169 | +{ |
| 170 | + if (!m_tutorialFinished) |
| 171 | + { |
| 172 | + m_nextButton->setEnabled(Common::MPStatus::Unlocked == status); |
| 173 | + } |
| 174 | +} |
| 175 | + |
| 176 | +void TutorialWidget::initTutorial() |
| 177 | +{ |
| 178 | + Ui::MainWindow* ui = m_mw->ui; |
| 179 | + m_tabs = { |
| 180 | + {ui->pushButtonDevSettings, tr("You can use the ‘Device Settings’ tab to change parameters on your Mooltipass device.<br>Hovering the mouse pointer over an option will gives a short description of what that option does.")}, |
| 181 | + {ui->pushButtonCred, tr("In case you aren't using our browser extensions, this tab allows you to manually add credentials to your database.<br>By clicking the \"Enter Credentials Management Mode\" button, you will be able to visualize and<br>modify the credentials stored on your database.")}, |
| 182 | + {ui->pushButtonNotes, tr("This tab allows you to securely store text on your device. Simply add a new note, set a title and type its contents.")}, |
| 183 | + {ui->pushButtonFiles, tr("The Mooltipass device can operate as a flash drive.<br>The ‘Files’ tab allows you to add, store and access small files on your Mooltipass.")}, |
| 184 | + {ui->pushButtonFido, tr("Similarly to the credentials tab, the FIDO2 tab allows you to visualize and delete FIDO2 credentials stored on your device.")}, |
| 185 | + {ui->pushButtonSync, tr("The different buttons in the synchronization tab will allow you to backup and<br>restore the credentials you have stored inside the memory of your Mooltipass.<br>You can also select a backup monitoring file to make sure your Mooltipass database is always in sync with it.")}, |
| 186 | + {ui->pushButtonAppSettings, tr("The ‘Settings’ tab lets you change parameters on the Moolticute app.")}, |
| 187 | + {ui->pushButtonAbout, tr("Finally, the ‘About’ tab provides you with general information about your device and app.<br>It allows you to check that you are running the latest version of Moolticute.")} |
| 188 | + }; |
| 189 | +} |
| 190 | + |
| 191 | +void TutorialWidget::startTutorial() |
| 192 | +{ |
| 193 | + m_current_index = -1; |
| 194 | + auto connected = m_mw->wsClient->isConnected(); |
| 195 | + if (!connected) |
| 196 | + { |
| 197 | + m_nextButton->setEnabled(false); |
| 198 | + } |
| 199 | + m_messageLabel->setText(TUTORIAL_HEADER_TEXT.arg("Welcome") + tr("Welcome to Mooltice tutorial! Please connect your device and unlock it to continue the tutorial.")); |
| 200 | +} |
0 commit comments