text: // Copyright (c) 2011-2018 The Bitcoin Core developers
  // Distributed under the MIT software license, see the accompanying
  // file COPYING or http://www.opensource.org/licenses/mit-license.php.
  
  #include <wallet/wallet.h>
  
  #include <qt/receivecoinsdialog.h>
  #include <qt/forms/ui_receivecoinsdialog.h>
  
  #include <qt/addressbookpage.h>
  #include <qt/addresstablemodel.h>
  #include <qt/bitcoinunits.h>
  #include <qt/optionsmodel.h>
  #include <qt/platformstyle.h>
  #include <qt/receiverequestdialog.h>
  #include <qt/recentrequeststablemodel.h>
  #include <qt/walletmodel.h>
  
  #include <QAction>
  #include <QCursor>
  #include <QMessageBox>
  #include <QScrollBar>
  #include <QTextDocument>
  
  ReceiveCoinsDialog::ReceiveCoinsDialog(const PlatformStyle *_platformStyle, QWidget *parent) :
      QDialog(parent),
      ui(new Ui::ReceiveCoinsDialog),
      columnResizingFixer(nullptr),
      model(nullptr),
      platformStyle(_platformStyle)
  {
      ui->setupUi(this);
  
      // Hide URI-specific fields, since we don't support URIs
      ui->label_5->hide();
      ui->label->hide(); ui->reqAmount->hide();
      ui->label_3->hide(); ui->reqMessage->hide();
  
      if (!_platformStyle->getImagesOnButtons()) {
          ui->clearButton->setIcon(QIcon());
          ui->receiveButton->setIcon(QIcon());
          ui->showRequestButton->setIcon(QIcon());
          ui->removeRequestButton->setIcon(QIcon());
      } else {
          ui->clearButton->setIcon(_platformStyle->SingleColorIcon(":/icons/remove"));
          ui->receiveButton->setIcon(_platformStyle->SingleColorIcon(":/icons/receiving_addresses"));
          ui->showRequestButton->setIcon(_platformStyle->SingleColorIcon(":/icons/edit"));
          ui->removeRequestButton->setIcon(_platformStyle->SingleColorIcon(":/icons/remove"));
      }
  
      // context menu actions
      QAction *copyURIAction = new QAction(tr("Copy address"), this);
      QAction *copyLabelAction = new QAction(tr("Copy label"), this);
      QAction *copyMessageAction = new QAction(tr("Copy message"), this);
      QAction *copyAmountAction = new QAction(tr("Copy amount"), this);
  
      // context menu
      contextMenu = new QMenu(this);
      contextMenu->addAction(copyURIAction);
      contextMenu->addAction(copyLabelAction);
      contextMenu->addAction(copyMessageAction);
      contextMenu->addAction(copyAmountAction);
  
      // context menu signals
      connect(ui->recentRequestsView, &QWidget::customContextMenuRequested, this, &ReceiveCoinsDialog::showMenu);
      connect(copyURIAction, &QAction::triggered, this, &ReceiveCoinsDialog::copyURI);
      connect(copyLabelAction, &QAction::triggered, this, &ReceiveCoinsDialog::copyLabel);
      connect(copyMessageAction, &QAction::triggered, this, &ReceiveCoinsDialog::copyMessage);
      connect(copyAmountAction, &QAction::triggered, this, &ReceiveCoinsDialog::copyAmount);
  
      connect(ui->clearButton, &QPushButton::clicked, this, &ReceiveCoinsDialog::clear);
  }
  
  void ReceiveCoinsDialog::setModel(WalletModel *_model)
  {
      this->model = _model;
  
      if(_model && _model->getOptionsModel())
      {
          _model->getRecentRequestsTableModel()->sort(RecentRequestsTableModel::Date, Qt::DescendingOrder);
          connect(_model->getOptionsModel(), &OptionsModel::displayUnitChanged, this, &ReceiveCoinsDialog::updateDisplayUnit);
          updateDisplayUnit();
  
          QTableView* tableView = ui->recentRequestsView;
  
          tableView->verticalHeader()->hide();
          tableView->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
          tableView->setModel(_model->getRecentRequestsTableModel());
          tableView->setAlternatingRowColors(true);
          tableView->setSelectionBehavior(QAbstractItemView::SelectRows);
          tableView->setSelectionMode(QAbstractItemView::ContiguousSelection);
          tableView->setColumnWidth(RecentRequestsTableModel::Date, DATE_COLUMN_WIDTH);
          tableView->horizontalHeader()->setStretchLastSection(true);
  #if 0
          tableView->setColumnWidth(RecentRequestsTableModel::Label, LABEL_COLUMN_WIDTH);
          tableView->setColumnWidth(RecentRequestsTableModel::Amount, AMOUNT_MINIMUM_COLUMN_WIDTH);
  #endif
  
          connect(tableView->selectionModel(),
              &QItemSelectionModel::selectionChanged, this,
              &ReceiveCoinsDialog::recentRequestsView_selectionChanged);
  #if 0
          // Last 2 columns are set by the columnResizingFixer, when the table geometry is ready.
          columnResizingFixer = new GUIUtil::TableViewLastColumnResizingFixer(tableView, AMOUNT_MINIMUM_COLUMN_WIDTH, DATE_COLUMN_WIDTH, this);
  #endif
          if (model->wallet().getDefaultAddressType() == OutputType::BECH32) {
              ui->useBech32->setCheckState(Qt::Checked);
          } else {
              ui->useBech32->setCheckState(Qt::Unchecked);
          }
  
          // Set the button to be enabled or disabled based on whether the wallet can give out new addresses.
          ui->receiveButton->setEnabled(model->canGetAddresses());
  
          // Enable/disable the receive button if the wallet is now able/unable to give out new addresses.
          connect(model, &WalletModel::canGetAddressesChanged, [this] {
              ui->receiveButton->setEnabled(model->canGetAddresses());
          });
      }
  }
  
  ReceiveCoinsDialog::~ReceiveCoinsDialog()
  {
      delete ui;
  }
  
  void ReceiveCoinsDialog::clear()
  {
      ui->reqAmount->clear();
      ui->reqLabel->setText("");
      ui->reqMessage->setText("");
      updateDisplayUnit();
  }
  
  void ReceiveCoinsDialog::reject()
  {
      clear();
  }
  
  void ReceiveCoinsDialog::accept()
  {
      clear();
  }
  
  void ReceiveCoinsDialog::updateDisplayUnit()
  {
      if(model && model->getOptionsModel())
      {
          ui->reqAmount->setDisplayUnit(model->getOptionsModel()->getDisplayUnit());
      }
  }
  
  void ReceiveCoinsDialog::on_receiveButton_clicked()
  {
      if(!model || !model->getOptionsModel() || !model->getAddressTableModel() || !model->getRecentRequestsTableModel())
          return;
  
      QString address;
      QString label = ui->reqLabel->text();
      /* Generate new receiving address */
      OutputType address_type;
      if (ui->useBech32->isChecked()) {
          address_type = OutputType::BECH32;
      } else {
          address_type = model->wallet().getDefaultAddressType();
          if (address_type == OutputType::BECH32) {
              address_type = OutputType::P2SH_SEGWIT;
          }
      }
      address = model->getAddressTableModel()->addRow(AddressTableModel::Receive, label, "", address_type);
      SendCoinsRecipient info(address, label,
          ui->reqAmount->value(), ui->reqMessage->text());
      ReceiveRequestDialog *dialog = new ReceiveRequestDialog(this);
      dialog->setAttribute(Qt::WA_DeleteOnClose);
      dialog->setModel(model);
      dialog->setInfo(info);
      dialog->show();
      clear();
  
      /* Store request for later reference */
      model->getRecentRequestsTableModel()->addNewRequest(info);
  }
  
  void ReceiveCoinsDialog::on_recentRequestsView_doubleClicked(const QModelIndex &index)
  {
      const RecentRequestsTableModel *submodel = model->getRecentRequestsTableModel();
      ReceiveRequestDialog *dialog = new ReceiveRequestDialog(this);
      dialog->setModel(model);
      dialog->setInfo(submodel->entry(index.row()).recipient);
      dialog->setAttribute(Qt::WA_DeleteOnClose);
      dialog->show();
  }
  
  void ReceiveCoinsDialog::recentRequestsView_selectionChanged(const QItemSelection &selected, const QItemSelection &deselected)
  {
      // Enable Show/Remove buttons only if anything is selected.
      bool enable = !ui->recentRequestsView->selectionModel()->selectedRows().isEmpty();
      ui->showRequestButton->setEnabled(enable);
      ui->removeRequestButton->setEnabled(enable);
  }
  
  void ReceiveCoinsDialog::on_showRequestButton_clicked()
  {
      if(!model || !model->getRecentRequestsTableModel() || !ui->recentRequestsView->selectionModel())
          return;
      QModelIndexList selection = ui->recentRequestsView->selectionModel()->selectedRows();
  
      for (const QModelIndex& index : selection) {
          on_recentRequestsView_doubleClicked(index);
      }
  }
  
  void ReceiveCoinsDialog::on_removeRequestButton_clicked()
  {
      if(!model || !model->getRecentRequestsTableModel() || !ui->recentRequestsView->selectionModel())
          return;
      QModelIndexList selection = ui->recentRequestsView->selectionModel()->selectedRows();
      if(selection.empty())
          return;
      // correct for selection mode ContiguousSelection
      QModelIndex firstIndex = selection.at(0);
      model->getRecentRequestsTableModel()->removeRows(firstIndex.row(), selection.length(), firstIndex.parent());
  }
  
  // We override the virtual resizeEvent of the QWidget to adjust tables column
  // sizes as the tables width is proportional to the dialogs width.
  void ReceiveCoinsDialog::resizeEvent(QResizeEvent *event)
  {
      QWidget::resizeEvent(event);
  }
  
  void ReceiveCoinsDialog::keyPressEvent(QKeyEvent *event)
  {
      if (event->key() == Qt::Key_Return)
      {
          // press return -> submit form
          if (ui->reqLabel->hasFocus() || ui->reqAmount->hasFocus() || ui->reqMessage->hasFocus())
          {
              event->ignore();
              on_receiveButton_clicked();
              return;
          }
      }
  
      this->QDialog::keyPressEvent(event);
  }
  
  QModelIndex ReceiveCoinsDialog::selectedRow()
  {
      if(!model || !model->getRecentRequestsTableModel() || !ui->recentRequestsView->selectionModel())
          return QModelIndex();
      QModelIndexList selection = ui->recentRequestsView->selectionModel()->selectedRows();
      if(selection.empty())
          return QModelIndex();
      // correct for selection mode ContiguousSelection
      QModelIndex firstIndex = selection.at(0);
      return firstIndex;
  }
  
  // copy column of selected row to clipboard
  void ReceiveCoinsDialog::copyColumnToClipboard(int column)
  {
      QModelIndex firstIndex = selectedRow();
      if (!firstIndex.isValid()) {
          return;
      }
      GUIUtil::setClipboard(model->getRecentRequestsTableModel()->data(firstIndex.child(firstIndex.row(), column), Qt::EditRole).toString());
  }
  
  // context menu
  void ReceiveCoinsDialog::showMenu(const QPoint &point)
  {
      if (!selectedRow().isValid()) {
          return;
      }
      contextMenu->exec(QCursor::pos());
  }
  
  // context menu action: copy URI
  void ReceiveCoinsDialog::copyURI()
  {
      QModelIndex sel = selectedRow();
      if (!sel.isValid()) {
          return;
      }
  
      const RecentRequestsTableModel * const submodel = model->getRecentRequestsTableModel();
      const QString uri = submodel->entry(sel.row()).recipient.address;
      GUIUtil::setClipboard(uri);
  }
  
  // context menu action: copy label
  void ReceiveCoinsDialog::copyLabel()
  {
      copyColumnToClipboard(RecentRequestsTableModel::Label);
  }
  
  // context menu action: copy message
  void ReceiveCoinsDialog::copyMessage()
  {
      copyColumnToClipboard(RecentRequestsTableModel::Message);
  }
  
  // context menu action: copy amount
  void ReceiveCoinsDialog::copyAmount()
  {
      copyColumnToClipboard(RecentRequestsTableModel::Amount);
  }
  