]> Nutra Git (v1) - gamesguru/feather.git/commitdiff
MainWindow: rework locking
authortobtoht <tob@featherwallet.org>
Thu, 19 Jan 2023 14:12:16 +0000 (15:12 +0100)
committertobtoht <tob@featherwallet.org>
Thu, 19 Jan 2023 14:25:45 +0000 (15:25 +0100)
src/MainWindow.cpp
src/MainWindow.h
src/MainWindow.ui
src/widgets/WalletUnlockWidget.cpp [new file with mode: 0644]
src/widgets/WalletUnlockWidget.h [new file with mode: 0644]
src/widgets/WalletUnlockWidget.ui [new file with mode: 0644]

index ad3f6e9cff0f1a8fa4ff0ef0702cae5c068641dc..c8cae11138821a1979dab5d542feb0632fc4905e 100644 (file)
@@ -224,6 +224,15 @@ void MainWindow::initWidgets() {
     connect(ui->btn_resetCoinControl, &QPushButton::clicked, [this]{
        m_ctx->setSelectedInputs({});
     });
+
+    m_walletUnlockWidget = new WalletUnlockWidget(this);
+    m_walletUnlockWidget->setWalletName(this->walletName());
+    ui->walletUnlockLayout->addWidget(m_walletUnlockWidget);
+
+    connect(m_walletUnlockWidget, &WalletUnlockWidget::closeWallet, this, &MainWindow::close);
+    connect(m_walletUnlockWidget, &WalletUnlockWidget::unlockWallet, this, &MainWindow::unlockWallet);
+
+    ui->stackedWidget->setCurrentIndex(0);
 }
 
 void MainWindow::initMenu() {
@@ -231,6 +240,7 @@ void MainWindow::initMenu() {
     // [File]
     connect(ui->actionOpen,        &QAction::triggered, this, &MainWindow::menuOpenClicked);
     connect(ui->actionNew_Restore, &QAction::triggered, this, &MainWindow::menuNewRestoreClicked);
+    connect(ui->actionLock,        &QAction::triggered, this, &MainWindow::lockWallet);
     connect(ui->actionClose,       &QAction::triggered, this, &MainWindow::menuWalletCloseClicked); // Close current wallet
     connect(ui->actionQuit,        &QAction::triggered, this, &MainWindow::menuQuitClicked);        // Quit application
     connect(ui->actionSettings,    &QAction::triggered, this, &MainWindow::menuSettingsClicked);
@@ -352,6 +362,7 @@ void MainWindow::initMenu() {
     ui->actionRefresh_tabs->setShortcut(QKeySequence("Ctrl+R"));
     ui->actionOpen->setShortcut(QKeySequence("Ctrl+O"));
     ui->actionNew_Restore->setShortcut(QKeySequence("Ctrl+N"));
+    ui->actionLock->setShortcut(QKeySequence("Ctrl+L"));
     ui->actionClose->setShortcut(QKeySequence("Ctrl+W"));
     ui->actionShow_debug_info->setShortcut(QKeySequence("Ctrl+D"));
     ui->actionSettings->setShortcut(QKeySequence("Ctrl+Alt+S"));
@@ -1655,6 +1666,16 @@ void MainWindow::userActivity() {
     m_userLastActive = QDateTime::currentSecsSinceEpoch();
 }
 
+void MainWindow::closeQDialogChildren(QObject *object) {
+    for (QObject *child : object->children()) {
+        if (auto *childDlg = dynamic_cast<QDialog*>(child)) {
+            qDebug() << "Closing dialog: " << childDlg->objectName();
+            childDlg->close();
+        }
+        this->closeQDialogChildren(child);
+    }
+}
+
 void MainWindow::checkUserActivity() {
     if (!config()->get(Config::inactivityLockEnabled).toBool()) {
         return;
@@ -1665,32 +1686,54 @@ void MainWindow::checkUserActivity() {
     }
 
     if ((m_userLastActive + (config()->get(Config::inactivityLockTimeout).toInt()*60)) < QDateTime::currentSecsSinceEpoch()) {
-        m_checkUserActivity.stop();
         qInfo() << "Locking wallet for inactivity";
-        ui->tabWidget->hide();
-        this->statusBar()->hide();
-        this->menuBar()->hide();
-        if (!this->verifyPassword(false)) {
-            this->setEnabled(false);
-            this->close();
-            // This doesn't close the wallet immediately.
-            // FIXME
-#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
-            do {
-#endif
-                QApplication::processEvents();
-#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
-            // Because running it a single time is apparently not enough.
-            // TODO: Qt bug? Need proper fix for this.
-            } while (QApplication::hasPendingEvents());
-#endif
-        } else {
-            ui->tabWidget->show();
-            this->statusBar()->show();
-            this->menuBar()->show();
-            m_checkUserActivity.start();
-        }
+        this->lockWallet();
+    }
+}
+
+void MainWindow::lockWallet() {
+    if (m_locked) {
+        return;
     }
+
+    if (m_constructingTransaction) {
+        QMessageBox::warning(this, "Lock wallet", "Unable to lock wallet during transaction construction");
+        return;
+    }
+    m_walletUnlockWidget->reset();
+
+    // Close all open QDialogs
+    this->closeQDialogChildren(this);
+
+    ui->tabWidget->hide();
+    this->statusBar()->hide();
+    this->menuBar()->hide();
+    ui->stackedWidget->setCurrentIndex(1);
+
+    m_checkUserActivity.stop();
+
+    m_locked = true;
+}
+
+void MainWindow::unlockWallet(const QString &password) {
+    if (!m_locked) {
+        return;
+    }
+
+    if (password != m_ctx->wallet->getPassword()) {
+        m_walletUnlockWidget->incorrectPassword();
+        return;
+    }
+    m_walletUnlockWidget->reset();
+
+    ui->tabWidget->show();
+    this->statusBar()->show();
+    this->menuBar()->show();
+    ui->stackedWidget->setCurrentIndex(0);
+
+    m_checkUserActivity.start();
+
+    m_locked = false;
 }
 
 void MainWindow::toggleSearchbar(bool visible) {
index 5d9fe57cbc22302d0c2a18b21a30b12fb1b7e311..5525f1361e091e1b592521f89e5db1bb42100423 100644 (file)
@@ -34,6 +34,7 @@
 #include "widgets/CCSWidget.h"
 #include "widgets/RedditWidget.h"
 #include "widgets/TickerWidget.h"
+#include "widgets/WalletUnlockWidget.h"
 #include "wizard/WalletWizard.h"
 
 #include "ContactsWidget.h"
@@ -221,6 +222,9 @@ private:
     void fillSendTab(const QString &address, const QString &description);
     void userActivity();
     void checkUserActivity();
+    void lockWallet();
+    void unlockWallet(const QString &password);
+    void closeQDialogChildren(QObject *object);
 
     QIcon hardwareDevicePairedIcon();
     QIcon hardwareDeviceUnpairedIcon();
@@ -233,6 +237,7 @@ private:
     SplashDialog *m_splashDialog = nullptr;
     AccountSwitcherDialog *m_accountSwitcherDialog = nullptr;
 
+    WalletUnlockWidget *m_walletUnlockWidget = nullptr;
 #ifdef HAS_XMRIG
     XMRigWidget *m_xmrig = nullptr;
 #endif
@@ -277,6 +282,7 @@ private:
     QTimer m_txTimer;
 
     bool cleanedUp = false;
+    bool m_locked = false;
     bool m_criticalWarningShown = false;
 
     EventFilter *m_eventFilter = nullptr;
index 513a251f7551f22bc8cef008b8d8732a52af977c..fa9799d1dc41af9c21483b4ec58844aea6d1fa77 100644 (file)
     <property name="horizontalSpacing">
      <number>12</number>
     </property>
-    <item row="1" column="0">
-     <widget class="QTabWidget" name="tabWidget">
+    <item row="0" column="0">
+     <widget class="QStackedWidget" name="stackedWidget">
       <property name="currentIndex">
-       <number>0</number>
+       <number>1</number>
       </property>
-      <property name="iconSize">
-       <size>
-        <width>16</width>
-        <height>16</height>
-       </size>
-      </property>
-      <widget class="QWidget" name="tabHome">
-       <attribute name="icon">
-        <iconset resource="assets.qrc">
-         <normaloff>:/assets/images/tab_home.png</normaloff>:/assets/images/tab_home.png</iconset>
-       </attribute>
-       <attribute name="title">
-        <string>Home</string>
-       </attribute>
-       <layout class="QVBoxLayout" name="verticalLayout_3">
+      <widget class="QWidget" name="page_wallet">
+       <layout class="QVBoxLayout" name="verticalLayout_11">
+        <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>5</number>
+         <number>0</number>
         </property>
         <item>
-         <layout class="QHBoxLayout" name="horizontalLayout">
-          <item>
-           <layout class="QHBoxLayout" name="tickerLayout"/>
-          </item>
-          <item>
-           <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>
-           <layout class="QHBoxLayout" name="fiatTickerLayout"/>
-          </item>
-         </layout>
-        </item>
-        <item>
-         <widget class="Line" name="line">
-          <property name="orientation">
-           <enum>Qt::Horizontal</enum>
-          </property>
-         </widget>
-        </item>
-        <item>
-         <widget class="QTabWidget" name="tabHomeWidget">
+         <widget class="QTabWidget" name="tabWidget">
           <property name="currentIndex">
            <number>0</number>
           </property>
-          <property name="documentMode">
-           <bool>true</bool>
+          <property name="iconSize">
+           <size>
+            <width>16</width>
+            <height>16</height>
+           </size>
           </property>
-          <widget class="QWidget" name="tab">
+          <widget class="QWidget" name="tabHome">
+           <attribute name="icon">
+            <iconset resource="assets.qrc">
+             <normaloff>:/assets/images/tab_home.png</normaloff>:/assets/images/tab_home.png</iconset>
+           </attribute>
            <attribute name="title">
-            <string>CCS</string>
+            <string>Home</string>
            </attribute>
-           <layout class="QVBoxLayout" name="verticalLayout_6">
-            <property name="leftMargin">
-             <number>0</number>
-            </property>
-            <property name="topMargin">
-             <number>0</number>
-            </property>
-            <property name="rightMargin">
-             <number>0</number>
-            </property>
+           <layout class="QVBoxLayout" name="verticalLayout_3">
             <property name="bottomMargin">
-             <number>0</number>
+             <number>5</number>
             </property>
             <item>
-             <widget class="CCSWidget" name="ccsWidget" native="true"/>
+             <layout class="QHBoxLayout" name="horizontalLayout">
+              <item>
+               <layout class="QHBoxLayout" name="tickerLayout"/>
+              </item>
+              <item>
+               <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>
+               <layout class="QHBoxLayout" name="fiatTickerLayout"/>
+              </item>
+             </layout>
+            </item>
+            <item>
+             <widget class="Line" name="line">
+              <property name="orientation">
+               <enum>Qt::Horizontal</enum>
+              </property>
+             </widget>
+            </item>
+            <item>
+             <widget class="QTabWidget" name="tabHomeWidget">
+              <property name="currentIndex">
+               <number>0</number>
+              </property>
+              <property name="documentMode">
+               <bool>true</bool>
+              </property>
+              <widget class="QWidget" name="tab">
+               <attribute name="title">
+                <string>CCS</string>
+               </attribute>
+               <layout class="QVBoxLayout" name="verticalLayout_6">
+                <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="CCSWidget" name="ccsWidget" native="true"/>
+                </item>
+               </layout>
+              </widget>
+              <widget class="QWidget" name="tab_4">
+               <attribute name="title">
+                <string>Bounties</string>
+               </attribute>
+               <layout class="QVBoxLayout" name="verticalLayout_10">
+                <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="BountiesWidget" name="bountiesWidget" native="true"/>
+                </item>
+               </layout>
+              </widget>
+              <widget class="QWidget" name="tab_2">
+               <attribute name="title">
+                <string>/r/Monero</string>
+               </attribute>
+               <layout class="QVBoxLayout" name="verticalLayout_7">
+                <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="RedditWidget" name="redditWidget" native="true"/>
+                </item>
+               </layout>
+              </widget>
+              <widget class="QWidget" name="tab_3">
+               <attribute name="title">
+                <string>Revuo</string>
+               </attribute>
+               <layout class="QVBoxLayout" name="verticalLayout_9">
+                <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="RevuoWidget" name="revuoWidget" native="true"/>
+                </item>
+               </layout>
+              </widget>
+             </widget>
             </item>
            </layout>
           </widget>
-          <widget class="QWidget" name="tab_4">
+          <widget class="QWidget" name="tabHistory">
+           <attribute name="icon">
+            <iconset resource="assets.qrc">
+             <normaloff>:/assets/images/history.png</normaloff>:/assets/images/history.png</iconset>
+           </attribute>
            <attribute name="title">
-            <string>Bounties</string>
+            <string>History</string>
            </attribute>
-           <layout class="QVBoxLayout" name="verticalLayout_10">
-            <property name="leftMargin">
-             <number>0</number>
+           <layout class="QGridLayout" name="gridLayout_3">
+            <property name="verticalSpacing">
+             <number>9</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="BountiesWidget" name="bountiesWidget" native="true"/>
+            <item row="0" column="0">
+             <layout class="QVBoxLayout" name="historyWidgetLayout"/>
             </item>
            </layout>
           </widget>
-          <widget class="QWidget" name="tab_2">
+          <widget class="QWidget" name="tabSend">
+           <property name="sizePolicy">
+            <sizepolicy hsizetype="Preferred" vsizetype="Preferred">
+             <horstretch>0</horstretch>
+             <verstretch>0</verstretch>
+            </sizepolicy>
+           </property>
+           <attribute name="icon">
+            <iconset resource="assets.qrc">
+             <normaloff>:/assets/images/tab_send.png</normaloff>:/assets/images/tab_send.png</iconset>
+           </attribute>
            <attribute name="title">
-            <string>/r/Monero</string>
+            <string>Send</string>
            </attribute>
-           <layout class="QVBoxLayout" name="verticalLayout_7">
-            <property name="leftMargin">
-             <number>0</number>
+           <layout class="QVBoxLayout" name="verticalLayout">
+            <property name="spacing">
+             <number>11</number>
             </property>
             <property name="topMargin">
-             <number>0</number>
-            </property>
-            <property name="rightMargin">
-             <number>0</number>
-            </property>
-            <property name="bottomMargin">
-             <number>0</number>
+             <number>11</number>
             </property>
             <item>
-             <widget class="RedditWidget" name="redditWidget" native="true"/>
+             <layout class="QVBoxLayout" name="sendWidgetLayout">
+              <property name="spacing">
+               <number>0</number>
+              </property>
+             </layout>
+            </item>
+            <item>
+             <widget class="Line" name="line_3">
+              <property name="minimumSize">
+               <size>
+                <width>0</width>
+                <height>0</height>
+               </size>
+              </property>
+              <property name="orientation">
+               <enum>Qt::Horizontal</enum>
+              </property>
+             </widget>
+            </item>
+            <item>
+             <layout class="QVBoxLayout" name="contactsWidgetLayout"/>
+            </item>
+           </layout>
+          </widget>
+          <widget class="QWidget" name="tabReceive">
+           <attribute name="icon">
+            <iconset resource="assets.qrc">
+             <normaloff>:/assets/images/coins.png</normaloff>:/assets/images/coins.png</iconset>
+           </attribute>
+           <attribute name="title">
+            <string>Receive</string>
+           </attribute>
+           <layout class="QGridLayout" name="gridLayout_5">
+            <item row="0" column="0">
+             <layout class="QVBoxLayout" name="receiveWidgetLayout"/>
+            </item>
+           </layout>
+          </widget>
+          <widget class="QWidget" name="tabCoins">
+           <attribute name="icon">
+            <iconset resource="assets.qrc">
+             <normaloff>:/assets/images/tab_coins.png</normaloff>:/assets/images/tab_coins.png</iconset>
+           </attribute>
+           <attribute name="title">
+            <string>Coins</string>
+           </attribute>
+           <layout class="QVBoxLayout" name="verticalLayout_2">
+            <item>
+             <layout class="QVBoxLayout" name="coinsWidgetLayout"/>
             </item>
            </layout>
           </widget>
-          <widget class="QWidget" name="tab_3">
+          <widget class="QWidget" name="tabCalc">
+           <attribute name="icon">
+            <iconset resource="assets.qrc">
+             <normaloff>:/assets/images/gnome-calc.png</normaloff>:/assets/images/gnome-calc.png</iconset>
+           </attribute>
            <attribute name="title">
-            <string>Revuo</string>
+            <string>Calc</string>
            </attribute>
-           <layout class="QVBoxLayout" name="verticalLayout_9">
+           <layout class="QVBoxLayout" name="verticalLayout_5">
+            <item>
+             <layout class="QHBoxLayout" name="horizontalLayout_2">
+              <item>
+               <widget class="CalcWidget" name="conversionWidget" native="true"/>
+              </item>
+             </layout>
+            </item>
+            <item>
+             <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>
+           </layout>
+          </widget>
+          <widget class="QWidget" name="tabExchange">
+           <attribute name="icon">
+            <iconset resource="assets.qrc">
+             <normaloff>:/assets/images/update.png</normaloff>:/assets/images/update.png</iconset>
+           </attribute>
+           <attribute name="title">
+            <string>Exchange</string>
+           </attribute>
+           <layout class="QVBoxLayout" name="verticalLayout_8">
             <property name="leftMargin">
              <number>0</number>
             </property>
              <number>0</number>
             </property>
             <item>
-             <widget class="RevuoWidget" name="revuoWidget" native="true"/>
+             <widget class="QTabWidget" name="tabWidgetExchanges">
+              <property name="currentIndex">
+               <number>0</number>
+              </property>
+              <widget class="QWidget" name="tabLocalMonero">
+               <attribute name="icon">
+                <iconset resource="assets.qrc">
+                 <normaloff>:/assets/images/localMonero_logo.png</normaloff>:/assets/images/localMonero_logo.png</iconset>
+               </attribute>
+               <attribute name="title">
+                <string>LocalMonero</string>
+               </attribute>
+               <layout class="QVBoxLayout" name="verticalLayout_4">
+                <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>
+                 <layout class="QVBoxLayout" name="localMoneroLayout"/>
+                </item>
+               </layout>
+              </widget>
+             </widget>
+            </item>
+           </layout>
+          </widget>
+          <widget class="QWidget" name="tabXmrRig">
+           <attribute name="icon">
+            <iconset resource="assets.qrc">
+             <normaloff>:/assets/images/mining.png</normaloff>:/assets/images/mining.png</iconset>
+           </attribute>
+           <attribute name="title">
+            <string>Mining</string>
+           </attribute>
+           <layout class="QGridLayout" name="gridLayout_2">
+            <item row="0" column="0">
+             <layout class="QGridLayout" name="xmrRigLayout"/>
             </item>
            </layout>
           </widget>
          </widget>
         </item>
-       </layout>
-      </widget>
-      <widget class="QWidget" name="tabHistory">
-       <attribute name="icon">
-        <iconset resource="assets.qrc">
-         <normaloff>:/assets/images/history.png</normaloff>:/assets/images/history.png</iconset>
-       </attribute>
-       <attribute name="title">
-        <string>History</string>
-       </attribute>
-       <layout class="QGridLayout" name="gridLayout_3">
-        <property name="verticalSpacing">
-         <number>9</number>
-        </property>
-        <item row="0" column="0">
-         <layout class="QVBoxLayout" name="historyWidgetLayout"/>
-        </item>
-       </layout>
-      </widget>
-      <widget class="QWidget" name="tabSend">
-       <property name="sizePolicy">
-        <sizepolicy hsizetype="Preferred" vsizetype="Preferred">
-         <horstretch>0</horstretch>
-         <verstretch>0</verstretch>
-        </sizepolicy>
-       </property>
-       <attribute name="icon">
-        <iconset resource="assets.qrc">
-         <normaloff>:/assets/images/tab_send.png</normaloff>:/assets/images/tab_send.png</iconset>
-       </attribute>
-       <attribute name="title">
-        <string>Send</string>
-       </attribute>
-       <layout class="QVBoxLayout" name="verticalLayout">
-        <property name="spacing">
-         <number>11</number>
-        </property>
-        <property name="topMargin">
-         <number>11</number>
-        </property>
         <item>
-         <layout class="QVBoxLayout" name="sendWidgetLayout">
-          <property name="spacing">
-           <number>0</number>
-          </property>
-         </layout>
-        </item>
-        <item>
-         <widget class="Line" name="line_3">
-          <property name="minimumSize">
-           <size>
-            <width>0</width>
-            <height>0</height>
-           </size>
+         <widget class="QFrame" name="frame_coinControl">
+          <property name="frameShape">
+           <enum>QFrame::StyledPanel</enum>
           </property>
-          <property name="orientation">
-           <enum>Qt::Horizontal</enum>
+          <property name="frameShadow">
+           <enum>QFrame::Raised</enum>
           </property>
+          <layout class="QHBoxLayout" name="horizontalLayout_3">
+           <property name="topMargin">
+            <number>0</number>
+           </property>
+           <property name="bottomMargin">
+            <number>0</number>
+           </property>
+           <item>
+            <widget class="QLabel" name="label_coinControl">
+             <property name="text">
+              <string>Coin control active: </string>
+             </property>
+             <property name="textInteractionFlags">
+              <set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse</set>
+             </property>
+            </widget>
+           </item>
+           <item>
+            <widget class="QPushButton" name="btn_resetCoinControl">
+             <property name="sizePolicy">
+              <sizepolicy hsizetype="Maximum" vsizetype="Fixed">
+               <horstretch>0</horstretch>
+               <verstretch>0</verstretch>
+              </sizepolicy>
+             </property>
+             <property name="text">
+              <string>Reset</string>
+             </property>
+            </widget>
+           </item>
+          </layout>
          </widget>
         </item>
-        <item>
-         <layout class="QVBoxLayout" name="contactsWidgetLayout"/>
-        </item>
-       </layout>
-      </widget>
-      <widget class="QWidget" name="tabReceive">
-       <attribute name="icon">
-        <iconset resource="assets.qrc">
-         <normaloff>:/assets/images/coins.png</normaloff>:/assets/images/coins.png</iconset>
-       </attribute>
-       <attribute name="title">
-        <string>Receive</string>
-       </attribute>
-       <layout class="QGridLayout" name="gridLayout_5">
-        <item row="0" column="0">
-         <layout class="QVBoxLayout" name="receiveWidgetLayout"/>
-        </item>
-       </layout>
-      </widget>
-      <widget class="QWidget" name="tabCoins">
-       <attribute name="icon">
-        <iconset resource="assets.qrc">
-         <normaloff>:/assets/images/tab_coins.png</normaloff>:/assets/images/tab_coins.png</iconset>
-       </attribute>
-       <attribute name="title">
-        <string>Coins</string>
-       </attribute>
-       <layout class="QVBoxLayout" name="verticalLayout_2">
-        <item>
-         <layout class="QVBoxLayout" name="coinsWidgetLayout"/>
-        </item>
-       </layout>
-      </widget>
-      <widget class="QWidget" name="tabCalc">
-       <attribute name="icon">
-        <iconset resource="assets.qrc">
-         <normaloff>:/assets/images/gnome-calc.png</normaloff>:/assets/images/gnome-calc.png</iconset>
-       </attribute>
-       <attribute name="title">
-        <string>Calc</string>
-       </attribute>
-       <layout class="QVBoxLayout" name="verticalLayout_5">
-        <item>
-         <layout class="QHBoxLayout" name="horizontalLayout_2">
-          <item>
-           <widget class="CalcWidget" name="conversionWidget" native="true"/>
-          </item>
-         </layout>
-        </item>
-        <item>
-         <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>
        </layout>
       </widget>
-      <widget class="QWidget" name="tabExchange">
-       <attribute name="icon">
-        <iconset resource="assets.qrc">
-         <normaloff>:/assets/images/update.png</normaloff>:/assets/images/update.png</iconset>
-       </attribute>
-       <attribute name="title">
-        <string>Exchange</string>
-       </attribute>
-       <layout class="QVBoxLayout" name="verticalLayout_8">
+      <widget class="QWidget" name="page_lock">
+       <layout class="QVBoxLayout" name="verticalLayout_12">
         <property name="leftMargin">
          <number>0</number>
         </property>
          <number>0</number>
         </property>
         <item>
-         <widget class="QTabWidget" name="tabWidgetExchanges">
-          <property name="currentIndex">
-           <number>0</number>
-          </property>
-          <widget class="QWidget" name="tabLocalMonero">
-           <attribute name="icon">
-            <iconset resource="assets.qrc">
-             <normaloff>:/assets/images/localMonero_logo.png</normaloff>:/assets/images/localMonero_logo.png</iconset>
-           </attribute>
-           <attribute name="title">
-            <string>LocalMonero</string>
-           </attribute>
-           <layout class="QVBoxLayout" name="verticalLayout_4">
-            <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>
-             <layout class="QVBoxLayout" name="localMoneroLayout"/>
-            </item>
-           </layout>
-          </widget>
-         </widget>
-        </item>
-       </layout>
-      </widget>
-      <widget class="QWidget" name="tabXmrRig">
-       <attribute name="icon">
-        <iconset resource="assets.qrc">
-         <normaloff>:/assets/images/mining.png</normaloff>:/assets/images/mining.png</iconset>
-       </attribute>
-       <attribute name="title">
-        <string>Mining</string>
-       </attribute>
-       <layout class="QGridLayout" name="gridLayout_2">
-        <item row="0" column="0">
-         <layout class="QGridLayout" name="xmrRigLayout"/>
+         <layout class="QVBoxLayout" name="walletUnlockLayout"/>
         </item>
        </layout>
       </widget>
      </widget>
     </item>
-    <item row="2" column="0">
-     <widget class="QFrame" name="frame_coinControl">
-      <property name="frameShape">
-       <enum>QFrame::StyledPanel</enum>
-      </property>
-      <property name="frameShadow">
-       <enum>QFrame::Raised</enum>
-      </property>
-      <layout class="QHBoxLayout" name="horizontalLayout_3">
-       <property name="topMargin">
-        <number>0</number>
-       </property>
-       <property name="bottomMargin">
-        <number>0</number>
-       </property>
-       <item>
-        <widget class="QLabel" name="label_coinControl">
-         <property name="text">
-          <string>Coin control active: </string>
-         </property>
-         <property name="textInteractionFlags">
-          <set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse</set>
-         </property>
-        </widget>
-       </item>
-       <item>
-        <widget class="QPushButton" name="btn_resetCoinControl">
-         <property name="sizePolicy">
-          <sizepolicy hsizetype="Maximum" vsizetype="Fixed">
-           <horstretch>0</horstretch>
-           <verstretch>0</verstretch>
-          </sizepolicy>
-         </property>
-         <property name="text">
-          <string>Reset</string>
-         </property>
-        </widget>
-       </item>
-      </layout>
-     </widget>
-    </item>
    </layout>
   </widget>
   <widget class="QStatusBar" name="statusBar"/>
     <addaction name="menuRecently_open"/>
     <addaction name="actionOpen"/>
     <addaction name="actionNew_Restore"/>
+    <addaction name="actionLock"/>
     <addaction name="actionClose"/>
     <addaction name="actionQuit"/>
     <addaction name="separator"/>
     <string>Documentation</string>
    </property>
   </action>
+  <action name="actionLock">
+   <property name="text">
+    <string>Lock wallet</string>
+   </property>
+  </action>
  </widget>
  <layoutdefault spacing="6" margin="11"/>
  <customwidgets>
diff --git a/src/widgets/WalletUnlockWidget.cpp b/src/widgets/WalletUnlockWidget.cpp
new file mode 100644 (file)
index 0000000..9fa0a7d
--- /dev/null
@@ -0,0 +1,58 @@
+// SPDX-License-Identifier: BSD-3-Clause
+// SPDX-FileCopyrightText: 2020-2023 The Monero Project
+
+#include "WalletUnlockWidget.h"
+#include "ui_WalletUnlockWidget.h"
+
+#include <QKeyEvent>
+#include <QPushButton>
+
+WalletUnlockWidget::WalletUnlockWidget(QWidget *parent)
+        : QWidget(parent)
+        , ui(new Ui::WalletUnlockWidget)
+{
+    ui->setupUi(this);
+    this->reset();
+
+    ui->buttonBox->button(QDialogButtonBox::Ok)->setAutoDefault(true);
+
+    connect(ui->buttonBox, &QDialogButtonBox::accepted, this, &WalletUnlockWidget::tryUnlock);
+    connect(ui->buttonBox, &QDialogButtonBox::rejected, this, &WalletUnlockWidget::closeWallet);
+}
+
+void WalletUnlockWidget::setWalletName(const QString &walletName) {
+    ui->label_fileName->setText(walletName);
+}
+
+void WalletUnlockWidget::reset() {
+    ui->label_incorrectPassword->hide();
+    ui->line_password->setText("");
+    ui->line_password->setFocus();
+}
+
+void WalletUnlockWidget::incorrectPassword() {
+    ui->label_incorrectPassword->show();
+    ui->line_password->clear();
+}
+
+void WalletUnlockWidget::tryUnlock() {
+    emit unlockWallet(ui->line_password->text());
+}
+
+void WalletUnlockWidget::keyPressEvent(QKeyEvent *e) {
+    switch (e->key()) {
+        case Qt::Key_Enter:
+        case Qt::Key_Return:
+            ui->buttonBox->accepted();
+            e->ignore();
+            break;
+        case Qt::Key_Escape:
+            ui->buttonBox->rejected();
+            e->ignore();
+            break;
+        default:
+            e->ignore();
+    }
+}
+
+WalletUnlockWidget::~WalletUnlockWidget() = default;
\ No newline at end of file
diff --git a/src/widgets/WalletUnlockWidget.h b/src/widgets/WalletUnlockWidget.h
new file mode 100644 (file)
index 0000000..99bd551
--- /dev/null
@@ -0,0 +1,40 @@
+// SPDX-License-Identifier: BSD-3-Clause
+// SPDX-FileCopyrightText: 2020-2023 The Monero Project
+
+#ifndef FEATHER_WALLETUNLOCKWIDGET_H
+#define FEATHER_WALLETUNLOCKWIDGET_H
+
+#include <QWidget>
+#include <QMenu>
+
+namespace Ui {
+    class WalletUnlockWidget;
+}
+
+class WalletUnlockWidget : public QWidget
+{
+Q_OBJECT
+
+public:
+    explicit WalletUnlockWidget(QWidget *parent = nullptr);
+    ~WalletUnlockWidget();
+
+    void setWalletName(const QString &walletName);
+    void reset();
+    void incorrectPassword();
+
+signals:
+    void unlockWallet(const QString &password);
+    void closeWallet();
+
+private slots:
+    void tryUnlock();
+
+protected:
+    void keyPressEvent(QKeyEvent* e) override;
+
+private:
+    QScopedPointer<Ui::WalletUnlockWidget> ui;
+};
+
+#endif //FEATHER_WALLETUNLOCKWIDGET_H
diff --git a/src/widgets/WalletUnlockWidget.ui b/src/widgets/WalletUnlockWidget.ui
new file mode 100644 (file)
index 0000000..fe445ff
--- /dev/null
@@ -0,0 +1,175 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>WalletUnlockWidget</class>
+ <widget class="QWidget" name="WalletUnlockWidget">
+  <property name="geometry">
+   <rect>
+    <x>0</x>
+    <y>0</y>
+    <width>918</width>
+    <height>255</height>
+   </rect>
+  </property>
+  <property name="windowTitle">
+   <string>Form</string>
+  </property>
+  <layout class="QVBoxLayout" name="verticalLayout">
+   <item>
+    <layout class="QHBoxLayout" name="horizontalLayout">
+     <item>
+      <spacer name="horizontalSpacer">
+       <property name="orientation">
+        <enum>Qt::Horizontal</enum>
+       </property>
+       <property name="sizeType">
+        <enum>QSizePolicy::MinimumExpanding</enum>
+       </property>
+       <property name="sizeHint" stdset="0">
+        <size>
+         <width>0</width>
+         <height>0</height>
+        </size>
+       </property>
+      </spacer>
+     </item>
+     <item>
+      <widget class="QWidget" name="widget" native="true">
+       <property name="minimumSize">
+        <size>
+         <width>500</width>
+         <height>0</height>
+        </size>
+       </property>
+       <property name="maximumSize">
+        <size>
+         <width>700</width>
+         <height>16777215</height>
+        </size>
+       </property>
+       <layout class="QVBoxLayout" name="verticalLayout_2">
+        <item>
+         <spacer name="verticalSpacer_2">
+          <property name="orientation">
+           <enum>Qt::Vertical</enum>
+          </property>
+          <property name="sizeType">
+           <enum>QSizePolicy::Expanding</enum>
+          </property>
+          <property name="sizeHint" stdset="0">
+           <size>
+            <width>20</width>
+            <height>0</height>
+           </size>
+          </property>
+         </spacer>
+        </item>
+        <item>
+         <widget class="QLabel" name="label">
+          <property name="font">
+           <font>
+            <pointsize>12</pointsize>
+            <weight>75</weight>
+            <bold>true</bold>
+           </font>
+          </property>
+          <property name="text">
+           <string>Unlock Wallet</string>
+          </property>
+         </widget>
+        </item>
+        <item>
+         <widget class="QLabel" name="label_fileName">
+          <property name="text">
+           <string>filename.keys</string>
+          </property>
+         </widget>
+        </item>
+        <item>
+         <widget class="QFrame" name="frame">
+          <property name="frameShape">
+           <enum>QFrame::StyledPanel</enum>
+          </property>
+          <property name="frameShadow">
+           <enum>QFrame::Raised</enum>
+          </property>
+          <layout class="QVBoxLayout" name="verticalLayout_3">
+           <item>
+            <widget class="QLabel" name="label_3">
+             <property name="text">
+              <string>Enter Password:</string>
+             </property>
+            </widget>
+           </item>
+           <item>
+            <widget class="QLabel" name="label_incorrectPassword">
+             <property name="text">
+              <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;span style=&quot; font-weight:600; color:#a40000;&quot;&gt;Incorrect password, try again.&lt;/span&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
+             </property>
+            </widget>
+           </item>
+           <item>
+            <widget class="QLineEdit" name="line_password">
+             <property name="echoMode">
+              <enum>QLineEdit::Password</enum>
+             </property>
+            </widget>
+           </item>
+           <item>
+            <layout class="QHBoxLayout" name="horizontalLayout_2">
+             <item>
+              <widget class="QDialogButtonBox" name="buttonBox">
+               <property name="focusPolicy">
+                <enum>Qt::StrongFocus</enum>
+               </property>
+               <property name="standardButtons">
+                <set>QDialogButtonBox::Close|QDialogButtonBox::Ok</set>
+               </property>
+              </widget>
+             </item>
+            </layout>
+           </item>
+          </layout>
+         </widget>
+        </item>
+        <item>
+         <spacer name="verticalSpacer">
+          <property name="orientation">
+           <enum>Qt::Vertical</enum>
+          </property>
+          <property name="sizeType">
+           <enum>QSizePolicy::Expanding</enum>
+          </property>
+          <property name="sizeHint" stdset="0">
+           <size>
+            <width>20</width>
+            <height>0</height>
+           </size>
+          </property>
+         </spacer>
+        </item>
+       </layout>
+      </widget>
+     </item>
+     <item>
+      <spacer name="horizontalSpacer_2">
+       <property name="orientation">
+        <enum>Qt::Horizontal</enum>
+       </property>
+       <property name="sizeType">
+        <enum>QSizePolicy::MinimumExpanding</enum>
+       </property>
+       <property name="sizeHint" stdset="0">
+        <size>
+         <width>0</width>
+         <height>0</height>
+        </size>
+       </property>
+      </spacer>
+     </item>
+    </layout>
+   </item>
+  </layout>
+ </widget>
+ <resources/>
+ <connections/>
+</ui>