/ src / qt / utilitydialog.cpp
utilitydialog.cpp
  1  // Copyright (c) 2011-present The Bitcoin Core developers
  2  // Distributed under the MIT software license, see the accompanying
  3  // file COPYING or http://www.opensource.org/licenses/mit-license.php.
  4  
  5  #include <bitcoin-build-config.h> // IWYU pragma: keep
  6  
  7  #include <qt/utilitydialog.h>
  8  
  9  #include <qt/forms/ui_helpmessagedialog.h>
 10  
 11  #include <qt/guiutil.h>
 12  
 13  #include <clientversion.h>
 14  #include <common/args.h>
 15  #include <common/license_info.h>
 16  #include <init.h>
 17  #include <util/strencodings.h>
 18  
 19  #include <cstdio>
 20  
 21  #include <QCloseEvent>
 22  #include <QLabel>
 23  #include <QMainWindow>
 24  #include <QRegularExpression>
 25  #include <QString>
 26  #include <QTextCursor>
 27  #include <QTextTable>
 28  #include <QVBoxLayout>
 29  
 30  /** "Help message" or "About" dialog box */
 31  HelpMessageDialog::HelpMessageDialog(QWidget *parent, bool about) :
 32      QDialog(parent, GUIUtil::dialog_flags),
 33      ui(new Ui::HelpMessageDialog)
 34  {
 35      ui->setupUi(this);
 36  
 37      QString version = QString{CLIENT_NAME} + " " + tr("version") + " " + QString::fromStdString(FormatFullVersion());
 38  
 39      if (about)
 40      {
 41          setWindowTitle(tr("About %1").arg(CLIENT_NAME));
 42  
 43          std::string licenseInfo = LicenseInfo();
 44          /// HTML-format the license message from the core
 45          QString licenseInfoHTML = QString::fromStdString(LicenseInfo());
 46          // Make URLs clickable
 47          QRegularExpression uri(QStringLiteral("<(.*)>"), QRegularExpression::InvertedGreedinessOption);
 48          licenseInfoHTML.replace(uri, QStringLiteral("<a href=\"\\1\">\\1</a>"));
 49          // Replace newlines with HTML breaks
 50          licenseInfoHTML.replace("\n", "<br>");
 51  
 52          ui->aboutMessage->setTextFormat(Qt::RichText);
 53          ui->scrollArea->setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded);
 54          text = version + "\n" + QString::fromStdString(FormatParagraph(licenseInfo));
 55          ui->aboutMessage->setText(version + "<br><br>" + licenseInfoHTML);
 56          ui->aboutMessage->setWordWrap(true);
 57          ui->helpMessage->setVisible(false);
 58      } else {
 59          setWindowTitle(tr("Command-line options"));
 60          QString header = "The bitcoin-qt application provides a graphical interface for interacting with " CLIENT_NAME ".\n\n"
 61                           "It combines the core functionalities of bitcoind with a user-friendly interface for wallet management, transaction history, and network statistics.\n\n"
 62                           "It is suitable for users who prefer a graphical over a command-line interface.\n\n"
 63                           "You can optionally specify a payment [URI], in e.g. the BIP21 URI format.\n\n"
 64                           "Usage: bitcoin-qt [options] [URI]\n\n";
 65          QTextCursor cursor(ui->helpMessage->document());
 66          cursor.insertText(version);
 67          cursor.insertBlock();
 68          cursor.insertText(header);
 69          cursor.insertBlock();
 70  
 71          std::string strUsage = gArgs.GetHelpMessage();
 72          QString coreOptions = QString::fromStdString(strUsage);
 73          text = version + "\n\n" + header + "\n" + coreOptions;
 74  
 75          QTextTableFormat tf;
 76          tf.setBorderStyle(QTextFrameFormat::BorderStyle_None);
 77          tf.setCellPadding(2);
 78          QVector<QTextLength> widths;
 79          widths << QTextLength(QTextLength::PercentageLength, 35);
 80          widths << QTextLength(QTextLength::PercentageLength, 65);
 81          tf.setColumnWidthConstraints(widths);
 82  
 83          QTextCharFormat bold;
 84          bold.setFontWeight(QFont::Bold);
 85  
 86          for (const QString &line : coreOptions.split("\n")) {
 87              if (line.startsWith("  -"))
 88              {
 89                  cursor.currentTable()->appendRows(1);
 90                  cursor.movePosition(QTextCursor::PreviousCell);
 91                  cursor.movePosition(QTextCursor::NextRow);
 92                  cursor.insertText(line.trimmed());
 93                  cursor.movePosition(QTextCursor::NextCell);
 94              } else if (line.startsWith("   ")) {
 95                  cursor.insertText(line.trimmed()+' ');
 96              } else if (line.size() > 0) {
 97                  //Title of a group
 98                  if (cursor.currentTable())
 99                      cursor.currentTable()->appendRows(1);
100                  cursor.movePosition(QTextCursor::Down);
101                  cursor.insertText(line.trimmed(), bold);
102                  cursor.insertTable(1, 2, tf);
103              }
104          }
105  
106          ui->helpMessage->moveCursor(QTextCursor::Start);
107          ui->scrollArea->setVisible(false);
108          ui->aboutLogo->setVisible(false);
109      }
110  
111      GUIUtil::handleCloseWindowShortcut(this);
112  }
113  
114  HelpMessageDialog::~HelpMessageDialog()
115  {
116      delete ui;
117  }
118  
119  void HelpMessageDialog::printToConsole()
120  {
121      // On other operating systems, the expected action is to print the message to the console.
122      tfm::format(std::cout, "%s", qPrintable(text));
123  }
124  
125  void HelpMessageDialog::showOrPrint()
126  {
127  #if defined(WIN32)
128      // On Windows, show a message box, as there is no stderr/stdout in windowed applications
129      exec();
130  #else
131      // On other operating systems, print help text to console
132      printToConsole();
133  #endif
134  }
135  
136  void HelpMessageDialog::on_okButton_accepted()
137  {
138      close();
139  }
140  
141  
142  /** "Shutdown" window */
143  ShutdownWindow::ShutdownWindow(QWidget *parent, Qt::WindowFlags f):
144      QWidget(parent, f)
145  {
146      QVBoxLayout *layout = new QVBoxLayout();
147      layout->addWidget(new QLabel(
148          tr("%1 is shutting down…").arg(CLIENT_NAME) + "<br /><br />" +
149          tr("Do not shut down the computer until this window disappears.")));
150      setLayout(layout);
151  
152      GUIUtil::handleCloseWindowShortcut(this);
153  }
154  
155  QWidget* ShutdownWindow::showShutdownWindow(QMainWindow* window)
156  {
157      assert(window != nullptr);
158  
159      // Show a simple window indicating shutdown status
160      QWidget *shutdownWindow = new ShutdownWindow();
161      shutdownWindow->setWindowTitle(window->windowTitle());
162  
163      // Center shutdown window at where main window was
164      const QPoint global = window->mapToGlobal(window->rect().center());
165      shutdownWindow->move(global.x() - shutdownWindow->width() / 2, global.y() - shutdownWindow->height() / 2);
166      shutdownWindow->show();
167      return shutdownWindow;
168  }
169  
170  void ShutdownWindow::closeEvent(QCloseEvent *event)
171  {
172      event->ignore();
173  }