<commit_before>/*
 * ============================================================================
 *
 *       Filename:  test-io.cc
 *    Description:  Tests of the IO module.
 *        License:  LGPL-3+
 *         Author:  Kevin Murray, spam@kdmurray.id.au
 *
 * ============================================================================
 */

#include "catch.hpp"
#include "helpers.hh"

#include "qc-io.hh"

#include <iostream>

TEST_CASE("Read structure behaves correctly", "[Read]") {
    qcpp::Read read;
    read.name = "Name";
    read.sequence = "ACGT";
    read.quality = "IIII";

    SECTION("Filling read members works") {
        REQUIRE(read.name.size() == 4);
        REQUIRE(read.sequence.size() == 4);
        REQUIRE(read.quality.size() == 4);
    }

    SECTION("Clearing a read empties members") {
        read.clear();

        REQUIRE(read.name.size() == 0);
        REQUIRE(read.sequence.size() == 0);
        REQUIRE(read.quality.size() == 0);
    }

    SECTION("size() gives correct results w/ quality") {
        REQUIRE(read.sequence.size() == read.size());
        REQUIRE(read.quality.size() == read.size());
    }

    SECTION("size() gives correct results w/o quality") {
        read.quality.clear();
        REQUIRE(read.sequence.size() == read.size());
        REQUIRE(read.quality.size() == 0);
    }

    SECTION("str() works w/ quality") {
        REQUIRE(read.str() == "@Name\nACGT\n+\nIIII\n");
    }
    SECTION("str() works w/o quality") {
        read.quality.clear();
        REQUIRE(read.str() == ">Name\nACGT\n");
    }
}

TEST_CASE("ReadParser opening works", "[ReadParser]") {
    qcpp::ReadParser parser;
    TestConfig *config = TestConfig::get_config();
    std::string infile = config->get_data_file("valid_il.fastq");

    SECTION("opening valid FASTQ as std::string works") {
        REQUIRE_NOTHROW(parser.open(infile));
    }

    SECTION("opening valid FASTQ as char * works") {
        REQUIRE_NOTHROW(parser.open(infile.c_str()));
    }
}

TEST_CASE("Valid file parsing, including get_num_reads", "[ReadParser]") {
    qcpp::Read read;
    qcpp::ReadParser parser;
    TestConfig *config = TestConfig::get_config();
    std::string infile;
    size_t n_reads = 0;

    SECTION("valid_il.fastq") {
        infile = config->get_data_file("valid_il.fastq");

        REQUIRE_NOTHROW(parser.open(infile));

        // Count all reads, parse_read returns false on EOF
        while (parser.parse_read(read)) {
            n_reads++;
        }

        REQUIRE(n_reads == 10);
        REQUIRE(parser.get_num_reads() == n_reads);
    }

    SECTION("valid.fasta") {
        infile = config->get_data_file("valid.fasta");

        REQUIRE_NOTHROW(parser.open(infile));

        // Count all reads, parse_read returns false on EOF
        while (parser.parse_read(read)) {
            n_reads++;
        }

        REQUIRE(n_reads == 10);
        REQUIRE(parser.get_num_reads() == n_reads);
    }
}

TEST_CASE("Parsing of invalid or weird files", "[ReadParser]") {
    qcpp::Read              read;
    qcpp::ReadParser        parser;
    TestConfig             *config = TestConfig::get_config();
    std::string             infile;
    size_t                  n_reads = 0;

    SECTION("Empty fastq") {
        infile = config->get_data_file("empty.fastq");
        REQUIRE_THROWS_AS(parser.open(infile), qcpp::IOError);

        while (parser.parse_read(read)) {
            n_reads++;
        }

        REQUIRE(n_reads == 0);
        REQUIRE(parser.get_num_reads() == n_reads);
    }

    SECTION("Truncated fastq") {
        infile = config->get_data_file("truncated.fastq");
        REQUIRE_NOTHROW(parser.open(infile));

        REQUIRE_NOTHROW(parser.parse_read(read)); // First read is OK
        REQUIRE_THROWS_AS(parser.parse_read(read), qcpp::IOError); // 2nd bad
    }
}

TEST_CASE("Read Interleaving", "[ReadInterleaver]") {
    qcpp::ReadPair          read_parser_pair;
    qcpp::ReadPair          read_interleaver_pair;
    qcpp::ReadParser        parser;
    qcpp::ReadInterleaver   interleaver;
    TestConfig             *config = TestConfig::get_config();
    std::string             il_file = config->get_data_file("valid_il.fastq");
    std::string             r1_file = config->get_data_file("valid_R1.fastq");
    std::string             r2_file = config->get_data_file("valid_R2.fastq");

    REQUIRE_NOTHROW(parser.open(il_file));
    REQUIRE_NOTHROW(interleaver.open(r1_file, r2_file));

    SECTION("Interleaving yields a correctly paired read stream") {
        size_t n_pairs = 0;
        bool parse_ret = true, il_ret = true;

        // Count all reads, parse_read returns false on EOF
        while (parse_ret && il_ret) {
            parse_ret = parser.parse_read_pair(read_parser_pair);
            il_ret = interleaver.parse_read_pair(read_interleaver_pair);
            REQUIRE(read_parser_pair == read_interleaver_pair);
            if (parse_ret && il_ret) {
                n_pairs++;
            }
        }
        REQUIRE(parse_ret == il_ret);

        size_t n_reads = n_pairs * 2;
        REQUIRE(n_reads == 10);
        REQUIRE(parser.get_num_reads() == n_reads);
        REQUIRE(interleaver.get_num_reads() == n_reads);
        REQUIRE(interleaver.get_num_pairs() == n_pairs);
    }
}

TEST_CASE("Fastq writing", "[ReadParser]") {
    qcpp::Read read;
    qcpp::ReadParser parser;
    TestConfig *config = TestConfig::get_config();
    std::string infile = config->get_data_file("valid_il.fastq");
    REQUIRE_NOTHROW(parser.open(infile));

    SECTION("Parsing a valid fastq works, including get_num_reads") {
        size_t n_reads = 0;

        // Count all reads, parse_read returns false on EOF
        while (parser.parse_read(read)) {
            n_reads++;
        }

        REQUIRE(n_reads == 10);
        REQUIRE(parser.get_num_reads() == n_reads);
    }
}
<commit_msg>Add tests of writing and round-trip parsing<commit_after>/*
 * ============================================================================
 *
 *       Filename:  test-io.cc
 *    Description:  Tests of the IO module.
 *        License:  LGPL-3+
 *         Author:  Kevin Murray, spam@kdmurray.id.au
 *
 * ============================================================================
 */

#include "catch.hpp"
#include "helpers.hh"

#include "qc-io.hh"

#include <iostream>

TEST_CASE("Read structure behaves correctly", "[Read]") {
    qcpp::Read read("Name", "ACGT", "IIII");

    SECTION("Filling read members works") {
        REQUIRE(read.name.size() == 4);
        REQUIRE(read.sequence.size() == 4);
        REQUIRE(read.quality.size() == 4);
    }

    SECTION("Clearing a read empties members") {
        read.clear();

        REQUIRE(read.name.size() == 0);
        REQUIRE(read.sequence.size() == 0);
        REQUIRE(read.quality.size() == 0);
    }

    SECTION("size() gives correct results w/ quality") {
        REQUIRE(read.sequence.size() == read.size());
        REQUIRE(read.quality.size() == read.size());
    }

    SECTION("size() gives correct results w/o quality") {
        read.quality.clear();
        REQUIRE(read.sequence.size() == read.size());
        REQUIRE(read.quality.size() == 0);
    }

    SECTION("str() works w/ quality") {
        REQUIRE(read.str() == "@Name\nACGT\n+\nIIII\n");
    }
    SECTION("str() works w/o quality") {
        read.quality.clear();
        REQUIRE(read.str() == ">Name\nACGT\n");
    }
}

TEST_CASE("ReadParser opening works", "[ReadParser]") {
    qcpp::ReadParser parser;
    TestConfig *config = TestConfig::get_config();
    std::string infile = config->get_data_file("valid_il.fastq");

    SECTION("opening valid FASTQ as std::string works") {
        REQUIRE_NOTHROW(parser.open(infile));
    }

    SECTION("opening valid FASTQ as char * works") {
        REQUIRE_NOTHROW(parser.open(infile.c_str()));
    }
}

TEST_CASE("Valid file parsing, including get_num_reads", "[ReadParser]") {
    qcpp::Read read;
    qcpp::ReadParser parser;
    TestConfig *config = TestConfig::get_config();
    std::string infile;
    size_t n_reads = 0;

    SECTION("valid_il.fastq") {
        infile = config->get_data_file("valid_il.fastq");

        REQUIRE_NOTHROW(parser.open(infile));

        // Count all reads, parse_read returns false on EOF
        while (parser.parse_read(read)) {
            n_reads++;
        }

        REQUIRE(n_reads == 10);
        REQUIRE(parser.get_num_reads() == n_reads);
    }

    SECTION("valid.fasta") {
        infile = config->get_data_file("valid.fasta");

        REQUIRE_NOTHROW(parser.open(infile));

        // Count all reads, parse_read returns false on EOF
        while (parser.parse_read(read)) {
            n_reads++;
        }

        REQUIRE(n_reads == 10);
        REQUIRE(parser.get_num_reads() == n_reads);
    }
}

TEST_CASE("Parsing of invalid or weird files", "[ReadParser]") {
    qcpp::Read              read;
    qcpp::ReadParser        parser;
    TestConfig             *config = TestConfig::get_config();
    std::string             infile;
    size_t                  n_reads = 0;

    SECTION("Empty fastq") {
        infile = config->get_data_file("empty.fastq");
        REQUIRE_THROWS_AS(parser.open(infile), qcpp::IOError);

        while (parser.parse_read(read)) {
            n_reads++;
        }

        REQUIRE(n_reads == 0);
        REQUIRE(parser.get_num_reads() == n_reads);
    }

    SECTION("Truncated fastq") {
        infile = config->get_data_file("truncated.fastq");
        REQUIRE_NOTHROW(parser.open(infile));

        REQUIRE_NOTHROW(parser.parse_read(read)); // First read is OK
        REQUIRE_THROWS_AS(parser.parse_read(read), qcpp::IOError); // 2nd bad
    }
}

TEST_CASE("Read Interleaving", "[ReadInterleaver]") {
    qcpp::ReadPair          read_parser_pair;
    qcpp::ReadPair          read_interleaver_pair;
    qcpp::ReadParser        parser;
    qcpp::ReadInterleaver   interleaver;
    TestConfig             *config = TestConfig::get_config();
    std::string             il_file = config->get_data_file("valid_il.fastq");
    std::string             r1_file = config->get_data_file("valid_R1.fastq");
    std::string             r2_file = config->get_data_file("valid_R2.fastq");

    REQUIRE_NOTHROW(parser.open(il_file));
    REQUIRE_NOTHROW(interleaver.open(r1_file, r2_file));

    SECTION("Interleaving yields a correctly paired read stream") {
        size_t n_pairs = 0;
        bool parse_ret = true, il_ret = true;

        // Count all reads, parse_read returns false on EOF
        while (parse_ret && il_ret) {
            parse_ret = parser.parse_read_pair(read_parser_pair);
            il_ret = interleaver.parse_read_pair(read_interleaver_pair);
            REQUIRE(read_parser_pair == read_interleaver_pair);
            if (parse_ret && il_ret) {
                n_pairs++;
            }
        }
        REQUIRE(parse_ret == il_ret);

        size_t n_reads = n_pairs * 2;
        REQUIRE(n_reads == 10);
        REQUIRE(parser.get_num_reads() == n_reads);
        REQUIRE(interleaver.get_num_reads() == n_reads);
        REQUIRE(interleaver.get_num_pairs() == n_pairs);
    }
}

TEST_CASE("Fastq writing", "[ReadParser]") {
    qcpp::ReadWriter writer;
    TestConfig *config = TestConfig::get_config();
    std::string outfile = config->get_writable_file("fastq");

    CAPTURE(outfile);
    REQUIRE_NOTHROW(writer.open(outfile));

    SECTION("Writing a single read works") {
        qcpp::Read read("Name", "ACGT", "IIII");

        REQUIRE(writer.get_num_reads() == 0);

        REQUIRE_NOTHROW(writer.write_read(read));

        REQUIRE(writer.get_num_reads() == 1);

        REQUIRE_NOTHROW(writer.close());
        REQUIRE(filecmp(outfile, "data/truths/se.fastq"));
    }
    SECTION("Writing a single read works") {
        qcpp::ReadPair rp("seq1", "ACGT", "IIII",
                          "seq2", "ACGT", "IIII");

        REQUIRE(writer.get_num_reads() == 0);

        REQUIRE_NOTHROW(writer.write_read_pair(rp));

        REQUIRE(writer.get_num_reads() == 2);

        REQUIRE_NOTHROW(writer.close());
        REQUIRE(filecmp(outfile, "data/truths/pe.fastq"));
    }
}

TEST_CASE("Round-trip parse-write", "[ReadParser]") {
    qcpp::ReadParser    parser;
    qcpp::ReadWriter    writer;
    TestConfig         *config = TestConfig::get_config();
    std::string         infile = config->get_data_file("valid_il.fastq");
    std::string         outfile = config->get_writable_file("fastq", true);
    size_t              n_reads = 0;

    CAPTURE(infile);
    CAPTURE(outfile);
    REQUIRE_NOTHROW(parser.open(infile));
    REQUIRE_NOTHROW(writer.open(outfile));

    SECTION("Single-ended round trip") {
        qcpp::Read read;

        while (parser.parse_read(read)) {
            REQUIRE_NOTHROW(writer.write_read(read));
            n_reads++;
        }

        REQUIRE(n_reads == 10);
        REQUIRE(parser.get_num_reads() == n_reads);
        REQUIRE(writer.get_num_reads() == n_reads);

        REQUIRE_NOTHROW(writer.close());
        REQUIRE(filecmp(infile, outfile));
    }

    SECTION("Paired-ended round trip") {
        qcpp::ReadPair pair;

        while (parser.parse_read_pair(pair)) {
            REQUIRE_NOTHROW(writer.write_read_pair(pair));
            n_reads++;
        }

        REQUIRE(n_reads == 5); // Pairs, not reads
        REQUIRE(parser.get_num_reads() == 10);
        REQUIRE(writer.get_num_reads() == 10);

        REQUIRE_NOTHROW(writer.close());
        REQUIRE(filecmp(infile, outfile));
    }
}
<|endoftext|>


<commit_before><commit_msg>Remove unnecessary hardcode framework api path<commit_after><|endoftext|>


<commit_before>#include <grl/ros/KukaLBRiiwaROSPlugin.hpp>

using namespace grl::ros;

int main(int argc, char **argv) {

  ros::init(argc,argv,"kuka_lbr_ros_bridge");

  if(!ros::master::check())
  {
    std::cerr << "WARNING: roscore does not appear to be running\n";
  }

  std::shared_ptr<KukaLBRiiwaROSPlugin> plugin(std::make_shared<KukaLBRiiwaROSPlugin>());
  plugin->construct();

  ::ros::Rate rate(60);
  while (::ros::ok()) {
    ::ros::spinOnce();

    plugin->run_one();

    rate.sleep();
  }

  return 0;
}
<commit_msg>changing ros frequency to 1000, since now it can handle it!<commit_after>#include <grl/ros/KukaLBRiiwaROSPlugin.hpp>

using namespace grl::ros;

int main(int argc, char **argv) {

  ros::init(argc,argv,"kuka_lbr_ros_bridge");

  if(!ros::master::check())
  {
    std::cerr << "WARNING: roscore does not appear to be running\n";
  }

  std::shared_ptr<KukaLBRiiwaROSPlugin> plugin(std::make_shared<KukaLBRiiwaROSPlugin>());
  plugin->construct();

  ::ros::Rate rate(1000);
  while (::ros::ok()) {
    ::ros::spinOnce();

    plugin->run_one();

    rate.sleep();
  }

  return 0;
}
<|endoftext|>


<commit_before>/*
    Copyright (c) 2016 Martin Buck
    Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"),
    to deal in the Software without restriction, including without limitation the rights to
    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
    and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
    The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
    DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
    OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/

#define CATCH_CONFIG_MAIN
#include "../dependencies/Catch.h" //https://github.com/philsquared/Catch

#include <cmath>
#include <vector>

#include "flaggedT.h"

using namespace std;
using namespace flaggedT;

#define DELTA 0.01

TEST_CASE("FlaggedT") {
    SECTION("NonNull") {
        int* i = nullptr;
        REQUIRE_THROWS(NonNull<int*>::make_non_null(std::move(i)));

        int* i2 = new int(3);
        auto nn = NonNull<int*>::make_non_null(std::move(i2));
        auto i2s = NonNull<int*>::own(std::move(nn));
        delete i2s;
    }

    SECTION("Sorted") {
        std::vector<int> unsorted({1,7,8,14,3});

        REQUIRE(!std::is_sorted(unsorted.begin(), unsorted.end()));

        auto sorted = Sorted<std::vector<int>>(std::move(unsorted));
        REQUIRE(std::is_sorted(sorted.get_data().begin(), sorted.get_data().end()));
    }

    SECTION("UNIQUE") {
        std::vector<int> duped({1,1,2,2,3,3,7,9,11});

        auto unduped = Unique<std::vector<int>>(std::move(duped));
        REQUIRE(unduped.get_data().size() == 6);
    }

    SECTION("UNIQUESORTED") {
        std::vector<int> dupedUnsorted({11,9,7,3,3,2,2,1,1});

        auto fixed = UniqueAndSorted<std::vector<int>>(std::move(dupedUnsorted));
        REQUIRE(std::is_sorted(fixed.get_data().begin(), fixed.get_data().end()));
        REQUIRE(fixed.get_data().size() == 6);
    }
}
<commit_msg>added examples<commit_after>/*
    Copyright (c) 2016 Martin Buck
    Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"),
    to deal in the Software without restriction, including without limitation the rights to
    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
    and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
    The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
    DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
    OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/

#define CATCH_CONFIG_MAIN
#include "../dependencies/Catch.h" //https://github.com/philsquared/Catch

#include <cmath>
#include <vector>

#include "flaggedT.h"

using namespace std;
using namespace flaggedT;

//examples (move these to example files) [also the example test case]
//generator
NonNull<std::unique_ptr<int>> safe_generator() {
    return NonNull<std::unique_ptr<int>>::make_non_null(std::unique_ptr<int>(new int(5)));
}

int no_need_to_check_for_null(NonNull<std::unique_ptr<int>>&& in) {
    return *(in.get_data().get()) + 1;
}
//examples (move these to example files) [also the example test case]

TEST_CASE("FlaggedT") {
    SECTION("NonNull") {
        int* i = nullptr;
        REQUIRE_THROWS(NonNull<int*>::make_non_null(std::move(i)));

        int* i2 = new int(3);
        auto nn = NonNull<int*>::make_non_null(std::move(i2));
        auto i2s = NonNull<int*>::own(std::move(nn));
        delete i2s;
    }

    SECTION("Sorted") {
        std::vector<int> unsorted({1,7,8,14,3});

        REQUIRE(!std::is_sorted(unsorted.begin(), unsorted.end()));

        auto sorted = Sorted<std::vector<int>>(std::move(unsorted));
        REQUIRE(std::is_sorted(sorted.get_data().begin(), sorted.get_data().end()));
    }

    SECTION("UNIQUE") {
        std::vector<int> duped({1,1,2,2,3,3,7,9,11});

        auto unduped = Unique<std::vector<int>>(std::move(duped));
        REQUIRE(unduped.get_data().size() == 6);
    }

    SECTION("UNIQUESORTED") {
        std::vector<int> dupedUnsorted({11,9,7,3,3,2,2,1,1});

        auto fixed = UniqueAndSorted<std::vector<int>>(std::move(dupedUnsorted));
        REQUIRE(std::is_sorted(fixed.get_data().begin(), fixed.get_data().end()));
        REQUIRE(fixed.get_data().size() == 6);
    }

    SECTION("Move this to an example file") {
        auto tmp = safe_generator();
        auto res = no_need_to_check_for_null(std::move(tmp));
    }
}
<|endoftext|>


<commit_before><commit_msg>fix compilation warning<commit_after><|endoftext|>


<commit_before>#include <qt/hardwaresigntxdialog.h>
#include <qt/forms/ui_hardwaresigntxdialog.h>
#include <qt/walletmodel.h>
#include <qt/qtumhwitool.h>
#include <qt/waitmessagebox.h>
#include <qt/hardwarekeystoredialog.h>
#include <qt/guiconstants.h>
#include <qt/guiutil.h>
#include <qt/derivationpathdialog.h>

#include <QMessageBox>

class HardwareSignTxDialogPriv
{
public:
    HardwareSignTxDialogPriv(QObject *parent)
    {
        tool = new QtumHwiTool(parent);
    }

    WalletModel* model = 0;
    QtumHwiTool* tool = 0;
    QString psbt;
    QString hexTx;
    bool complete = false;
};

HardwareSignTxDialog::HardwareSignTxDialog(const QString &tx, QWidget *parent) :
    QDialog(parent),
    ui(new Ui::HardwareSignTxDialog)
{
    // Init variables
    ui->setupUi(this);
    d = new HardwareSignTxDialogPriv(this);
    ui->textEditTxData->setText(tx);
    ui->textEditTxData->setReadOnly(tx != "");
    ui->textEditTxDetails->setReadOnly(true);

    setStyleSheet("");

    // Connect slots
    connect(ui->textEditTxData, &QTextEdit::textChanged, this, &HardwareSignTxDialog::txChanged);
}

HardwareSignTxDialog::~HardwareSignTxDialog()
{
    delete ui;
    delete d;
}

void HardwareSignTxDialog::on_cancelButton_clicked()
{
    QDialog::reject();
}

void HardwareSignTxDialog::setModel(WalletModel *model)
{
    d->model = model;
    d->tool->setModel(model);
    txChanged();
    if(!d->model->wallet().privateKeysDisabled())
    {
        ui->textEditTxData->setEnabled(false);
        ui->textEditTxDetails->setEnabled(false);
        ui->importButton->setEnabled(false);
        ui->signButton->setEnabled(false);
        ui->sendButton->setEnabled(false);
    }
}

void HardwareSignTxDialog::txChanged()
{
    QString psbt = ui->textEditTxData->toPlainText().trimmed();
    QString decoded;
    if(psbt != d->psbt)
    {
        d->psbt = psbt;
        d->hexTx = "";
        d->complete = false;
        bool isOk = d->tool->decodePsbt(psbt, decoded);
        ui->textEditTxDetails->setText(decoded);
        ui->signButton->setEnabled(isOk);
        ui->sendButton->setEnabled(false);
    }
}

void HardwareSignTxDialog::on_signButton_clicked()
{
    if(askDevice())
    {
        WaitMessageBox dlg(tr("Ledger Status"), tr("Confirm Transaction on your Ledger device..."), [this]() {
            QString fingerprint = d->model->getFingerprint();
            QString psbt = d->psbt;
            d->hexTx = "";
            d->complete = false;
            bool ret = d->tool->signTx(fingerprint, psbt);
            if(ret) ret &= d->tool->finalizePsbt(psbt, d->hexTx, d->complete);
            if(d->complete)
            {
                ui->sendButton->setEnabled(true);
            }
        }, this);

        dlg.exec();

        if(!d->complete)
        {
            QMessageBox::warning(this, tr("Sign failed"), tr("The transaction has no a complete set of signatures."));
        }
    }
}

void HardwareSignTxDialog::on_sendButton_clicked()
{
    if(d->tool->sendRawTransaction(d->hexTx))
        QDialog::accept();
}

bool HardwareSignTxDialog::askDevice()
{
    // Check if the HWI tool exist
    QString hwiToolPath = GUIUtil::getHwiToolPath();
    if(!QFile::exists(hwiToolPath))
    {
        QMessageBox msgBox(this);
        msgBox.setWindowTitle(tr("HWI tool not found"));
        msgBox.setTextFormat(Qt::RichText);
        msgBox.setText(tr("HWI tool not found at path \"%1\".
Please download it from %2 and add the path to the settings.").arg(hwiToolPath, QTUM_HWI_TOOL));
        msgBox.setStandardButtons(QMessageBox::Ok);
        msgBox.exec();
        return false;
    }

    // Ask for ledger
    QString fingerprint = d->model->getFingerprint();
    QString title = tr("Connect Ledger");
    QString message = tr("Please insert your Ledger (%1). Verify the cable is connected and that no other application is using it.\n\nTry to connect again?");
    if(HardwareKeystoreDialog::AskDevice(fingerprint, title, message.arg(fingerprint), this))
    {
        d->model->setFingerprint(fingerprint);
        return true;
    }

    d->model->setFingerprint("");
    return false;
}

void HardwareSignTxDialog::on_importButton_clicked()
{
    bool rescan, importPKH, importP2SH, importBech32;
    if(importAddressesData(rescan, importPKH, importP2SH, importBech32))
    {
        d->model->importAddressesData(rescan, importPKH, importP2SH, importBech32);
        QDialog::accept();
    }
}

bool HardwareSignTxDialog::importAddressesData(bool &rescan, bool &importPKH, bool &importP2SH, bool &importBech32)
{
    // Init import addresses data
    bool ret = true;
    rescan = false;
    importPKH = false;
    importP2SH = false;
    importBech32 = false;

    // Get list to import
    DerivationPathDialog dlg(this);
    ret &= dlg.exec() == QDialog::Accepted;
    if(ret) ret &= dlg.importAddressesData(rescan, importPKH, importP2SH, importBech32);

    // Ask for device
    bool fDevice = importPKH || importP2SH || importBech32;
    if(fDevice) ret &= askDevice();

    return ret;
}
<commit_msg>Update send tx button for hw<commit_after>#if defined(HAVE_CONFIG_H)
#include <config/bitcoin-config.h>
#endif

#include <qt/hardwaresigntxdialog.h>
#include <qt/forms/ui_hardwaresigntxdialog.h>
#include <qt/walletmodel.h>
#include <qt/qtumhwitool.h>
#include <qt/waitmessagebox.h>
#include <qt/hardwarekeystoredialog.h>
#include <qt/guiconstants.h>
#include <qt/guiutil.h>
#include <qt/derivationpathdialog.h>
#include <qt/sendcoinsdialog.h>

#include <QMessageBox>

class HardwareSignTxDialogPriv
{
public:
    HardwareSignTxDialogPriv(QObject *parent)
    {
        tool = new QtumHwiTool(parent);
    }

    WalletModel* model = 0;
    QtumHwiTool* tool = 0;
    QString psbt;
    QString hexTx;
    bool complete = false;
};

HardwareSignTxDialog::HardwareSignTxDialog(const QString &tx, QWidget *parent) :
    QDialog(parent),
    ui(new Ui::HardwareSignTxDialog)
{
    // Init variables
    ui->setupUi(this);
    d = new HardwareSignTxDialogPriv(this);
    ui->textEditTxData->setText(tx);
    ui->textEditTxData->setReadOnly(tx != "");
    ui->textEditTxDetails->setReadOnly(true);

    setStyleSheet("");

    // Connect slots
    connect(ui->textEditTxData, &QTextEdit::textChanged, this, &HardwareSignTxDialog::txChanged);
}

HardwareSignTxDialog::~HardwareSignTxDialog()
{
    delete ui;
    delete d;
}

void HardwareSignTxDialog::on_cancelButton_clicked()
{
    QDialog::reject();
}

void HardwareSignTxDialog::setModel(WalletModel *model)
{
    d->model = model;
    d->tool->setModel(model);
    txChanged();
    if(!d->model->wallet().privateKeysDisabled())
    {
        ui->textEditTxData->setEnabled(false);
        ui->textEditTxDetails->setEnabled(false);
        ui->importButton->setEnabled(false);
        ui->signButton->setEnabled(false);
        ui->sendButton->setEnabled(false);
    }
}

void HardwareSignTxDialog::txChanged()
{
    QString psbt = ui->textEditTxData->toPlainText().trimmed();
    QString decoded;
    if(psbt != d->psbt)
    {
        d->psbt = psbt;
        d->hexTx = "";
        d->complete = false;
        bool isOk = d->tool->decodePsbt(psbt, decoded);
        ui->textEditTxDetails->setText(decoded);
        ui->signButton->setEnabled(isOk);
        ui->sendButton->setEnabled(false);
    }
}

void HardwareSignTxDialog::on_signButton_clicked()
{
    if(askDevice())
    {
        WaitMessageBox dlg(tr("Ledger Status"), tr("Confirm Transaction on your Ledger device..."), [this]() {
            QString fingerprint = d->model->getFingerprint();
            QString psbt = d->psbt;
            d->hexTx = "";
            d->complete = false;
            bool ret = d->tool->signTx(fingerprint, psbt);
            if(ret) ret &= d->tool->finalizePsbt(psbt, d->hexTx, d->complete);
            if(d->complete)
            {
                ui->sendButton->setEnabled(true);
            }
        }, this);

        dlg.exec();

        if(!d->complete)
        {
            QMessageBox::warning(this, tr("Sign failed"), tr("The transaction has no a complete set of signatures."));
        }
    }
}

void HardwareSignTxDialog::on_sendButton_clicked()
{
    QString questionString = tr("Are you sure you want to broadcast the transaction?
");
    SendConfirmationDialog confirmationDialog(tr("Confirm broadcast transaction."), questionString, "", "", SEND_CONFIRM_DELAY, tr("Send"), this);
    confirmationDialog.exec();
    QMessageBox::StandardButton retval = (QMessageBox::StandardButton)confirmationDialog.result();
    if(retval == QMessageBox::Yes)
    {
        if(d->tool->sendRawTransaction(d->hexTx))
        {
            QDialog::accept();
        }
        else
        {
            QString errorMessage = d->tool->errorMessage();
            if(errorMessage.isEmpty()) errorMessage = tr("Unknown transaction error");
            QMessageBox::warning(this, tr("Broadcast transaction"), errorMessage);
        }
    }
}

bool HardwareSignTxDialog::askDevice()
{
    // Check if the HWI tool exist
    QString hwiToolPath = GUIUtil::getHwiToolPath();
    if(!QFile::exists(hwiToolPath))
    {
        QMessageBox msgBox(this);
        msgBox.setWindowTitle(tr("HWI tool not found"));
        msgBox.setTextFormat(Qt::RichText);
        msgBox.setText(tr("HWI tool not found at path \"%1\".
Please download it from %2 and add the path to the settings.").arg(hwiToolPath, QTUM_HWI_TOOL));
        msgBox.setStandardButtons(QMessageBox::Ok);
        msgBox.exec();
        return false;
    }

    // Ask for ledger
    QString fingerprint = d->model->getFingerprint();
    QString title = tr("Connect Ledger");
    QString message = tr("Please insert your Ledger (%1). Verify the cable is connected and that no other application is using it.\n\nTry to connect again?");
    if(HardwareKeystoreDialog::AskDevice(fingerprint, title, message.arg(fingerprint), this))
    {
        d->model->setFingerprint(fingerprint);
        return true;
    }

    d->model->setFingerprint("");
    return false;
}

void HardwareSignTxDialog::on_importButton_clicked()
{
    bool rescan, importPKH, importP2SH, importBech32;
    if(importAddressesData(rescan, importPKH, importP2SH, importBech32))
    {
        d->model->importAddressesData(rescan, importPKH, importP2SH, importBech32);
        QDialog::accept();
    }
}

bool HardwareSignTxDialog::importAddressesData(bool &rescan, bool &importPKH, bool &importP2SH, bool &importBech32)
{
    // Init import addresses data
    bool ret = true;
    rescan = false;
    importPKH = false;
    importP2SH = false;
    importBech32 = false;

    // Get list to import
    DerivationPathDialog dlg(this);
    ret &= dlg.exec() == QDialog::Accepted;
    if(ret) ret &= dlg.importAddressesData(rescan, importPKH, importP2SH, importBech32);

    // Ask for device
    bool fDevice = importPKH || importP2SH || importBech32;
    if(fDevice) ret &= askDevice();

    return ret;
}
<|endoftext|>


<commit_before>//
//  libavg - Media Playback Engine.
//  Copyright (C) 2003-2014 Ulrich von Zadow
//
//  This library is free software; you can redistribute it and/or
//  modify it under the terms of the GNU Lesser General Public
//  License as published by the Free Software Foundation; either
//  version 2 of the License, or (at your option) any later version.
//
//  This library is distributed in the hope that it will be useful,
//  but WITHOUT ANY WARRANTY; without even the implied warranty of
//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
//  Lesser General Public License for more details.
//
//  You should have received a copy of the GNU Lesser General Public
//  License along with this library; if not, write to the Free Software
//  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
//
//  Current versions can be found at www.libavg.de
//

#include "FBO.h"

#include "OGLHelper.h"
#include "GLContext.h"
#include "Filterfliprgb.h"
#include "GLTexture.h"
#include "PBO.h"

#include "../base/Exception.h"
#include "../base/StringHelper.h"
#include "../base/ObjectCounter.h"

#include <stdio.h>

using namespace std;
using namespace boost;

namespace avg {

#ifndef GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS
#define GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT
#endif

#ifdef AVG_ENABLE_EGL
#define GL_DEPTH_STENCIL_EXT GL_DEPTH24_STENCIL8_OES
#endif

FBO::FBO(const FBOInfo& fboInfo, const vector<GLTexturePtr>& pTex)
    : FBOInfo(fboInfo)
{
    ObjectCounter::get()->incRef(&typeid(*this));
    m_pTextures = pTex;
    init();
}

FBO::~FBO()
{
    ObjectCounter::get()->decRef(&typeid(*this));

    unsigned oldFBOID;
    glGetIntegerv(GL_FRAMEBUFFER_BINDING, (GLint*)&oldFBOID);
    glproc::BindFramebuffer(GL_FRAMEBUFFER, m_FBO);

    for (unsigned i=0; i<m_pTextures.size(); ++i) {
        glproc::FramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0+i,
                GL_TEXTURE_2D, 0, 0);
    }

    GLContext* pContext = GLContext::getCurrent();
    if (pContext) {
        bool bMultisample = (getMultisampleSamples() > 1);
        if (getUsePackedDepthStencil() && isPackedDepthStencilSupported()) {
            glproc::DeleteRenderbuffers(1, &m_StencilBuffer);
            glproc::FramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,
                    GL_RENDERBUFFER, 0);
            glproc::FramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT,
                    GL_RENDERBUFFER, 0);
            if (bMultisample) {
                glproc::BindFramebuffer(GL_FRAMEBUFFER, m_OutputFBO);
                glproc::FramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
                        GL_TEXTURE_2D, 0, 0);
            }
        } else if (getUseStencil()) {
            glproc::DeleteRenderbuffers(1, &m_StencilBuffer);
            glproc::FramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT,
                    GL_RENDERBUFFER, 0);
        }
        pContext->returnFBOToCache(m_FBO);
        if (bMultisample) {
            glproc::DeleteRenderbuffers(1, &m_ColorBuffer);
            pContext->returnFBOToCache(m_OutputFBO);
        }
        GLContext::checkError("~FBO");
    }
}

void FBO::activate() const
{
    glproc::BindFramebuffer(GL_FRAMEBUFFER, m_FBO);
    GLContext::checkError("FBO::activate: BindFramebuffer()");
    checkError("activate");
}

void FBO::copyToDestTexture() const
{
#ifndef AVG_ENABLE_EGL
    if (getMultisampleSamples() != 1) {
        // Copy Multisample FBO to destination fbo
        glproc::BindFramebuffer(GL_READ_FRAMEBUFFER_EXT, m_FBO);
        glproc::BindFramebuffer(GL_DRAW_FRAMEBUFFER_EXT, m_OutputFBO);
        IntPoint size = getSize();
        glproc::BlitFramebuffer(0, 0, size.x, size.y, 0, 0, size.x, size.y,
                GL_COLOR_BUFFER_BIT, GL_LINEAR);
        glproc::BindFramebuffer(GL_FRAMEBUFFER, 0);
    }
#endif
    if (getMipmap()) {
        for (unsigned i=0; i< m_pTextures.size(); ++i) {
            m_pTextures[i]->generateMipmaps();
        }
    }
}

BitmapPtr FBO::getImage(int i) const
{
    GLContext* pContext = GLContext::getCurrent();
    if (pContext->getMemoryMode() == MM_PBO) {
        moveToPBO(i);
        return getImageFromPBO();
    } else {
        IntPoint size = getSize();
        PixelFormat pf = getPF();
        BitmapPtr pBmp(new Bitmap(size, pf));
        glproc::BindFramebuffer(GL_FRAMEBUFFER, m_OutputFBO);
        glReadPixels(0, 0, size.x, size.y, GLTexture::getGLFormat(pf),
                GLTexture::getGLType(pf), pBmp->getPixels());
        GLContext::checkError("FBO::getImage ReadPixels()");
        return pBmp;
    }
}

void FBO::moveToPBO(int i) const
{
    AVG_ASSERT(GLContext::getCurrent()->getMemoryMode() == MM_PBO);
#ifndef AVG_ENABLE_EGL
    // Get data directly from the FBO using glReadBuffer. At least on NVidia/Linux, this
    // is faster than reading stuff from the texture.
    copyToDestTexture();
    glproc::BindFramebuffer(GL_FRAMEBUFFER, m_OutputFBO);

    m_pOutputPBO->activate();
    GLContext::checkError("FBO::moveToPBO BindBuffer()");
    glReadBuffer(GL_COLOR_ATTACHMENT0+i);
    GLContext::checkError("FBO::moveToPBO ReadBuffer()");

    IntPoint size = getSize();
    PixelFormat pf = getPF();
    glReadPixels(0, 0, size.x, size.y, GLTexture::getGLFormat(pf),
            GLTexture::getGLType(pf), 0);
    GLContext::checkError("FBO::moveToPBO ReadPixels()");
#endif
}

BitmapPtr FBO::getImageFromPBO() const
{
#ifdef AVG_ENABLE_EGL
    AVG_ASSERT(false);
    return BitmapPtr();
#else
    AVG_ASSERT(GLContext::getCurrent()->getMemoryMode() == MM_PBO);
    m_pOutputPBO->activate();
    GLContext::checkError("FBO::getImageFromPBO BindBuffer()");

    IntPoint size = getSize();
    PixelFormat pf = getPF();
    BitmapPtr pBmp(new Bitmap(size, pf));
    void * pPBOPixels = glproc::MapBuffer(GL_PIXEL_PACK_BUFFER_EXT, GL_READ_ONLY);
    GLContext::checkError("FBO::getImageFromPBO MapBuffer()");
    Bitmap PBOBitmap(size, pf, (unsigned char *)pPBOPixels,
            size.x*getBytesPerPixel(pf), false);
    pBmp->copyPixels(PBOBitmap);
    glproc::UnmapBuffer(GL_PIXEL_PACK_BUFFER_EXT);
    GLContext::checkError("FBO::getImageFromPBO UnmapBuffer()");
    return pBmp;
#endif
}

GLTexturePtr FBO::getTex(int i) const
{
    return m_pTextures[i];
}

void FBO::init()
{
    GLContext* pContext = GLContext::getCurrent();
    if (getUsePackedDepthStencil() && !isPackedDepthStencilSupported()) {
        throw Exception(AVG_ERR_UNSUPPORTED, "OpenGL implementation does not support offscreen cropping (GL_EXT_packed_depth_stencil).");
    }
    unsigned numSamples = getMultisampleSamples();
    if (numSamples > 1 && !isMultisampleFBOSupported()) {
        throw Exception(AVG_ERR_UNSUPPORTED, "OpenGL implementation does not support multisample offscreen rendering (GL_EXT_framebuffer_multisample).");
    }
#ifndef AVG_ENABLE_EGL
    if (GLContext::getCurrent()->getMemoryMode() == MM_PBO) {
        m_pOutputPBO = PBOPtr(new PBO(getSize(), getPF(), GL_STREAM_READ));
    }
#endif

    m_FBO = pContext->genFBO();
    GLContext::checkError("FBO::init: GenFramebuffers()");

    glproc::BindFramebuffer(GL_FRAMEBUFFER, m_FBO);
    GLContext::checkError("FBO::init: BindFramebuffer()");

    IntPoint glSize = m_pTextures[0]->getGLSize();
    if (numSamples == 1) {
        for (unsigned i=0; i<m_pTextures.size(); ++i) {
            glproc::FramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0+i,
                    GL_TEXTURE_2D, m_pTextures[i]->getID(), 0);
            GLContext::checkError("FBO: glFramebufferTexture2D()");
        }
        if (getUsePackedDepthStencil()) {
            glproc::GenRenderbuffers(1, &m_StencilBuffer);
            glproc::BindRenderbuffer(GL_RENDERBUFFER, m_StencilBuffer);
            glproc::RenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_STENCIL_EXT,
                    glSize.x, glSize.y);
            glproc::FramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,
                    GL_RENDERBUFFER, m_StencilBuffer);
            glproc::FramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT,
                    GL_RENDERBUFFER, m_StencilBuffer);
            GLContext::checkError("FBO::init: FramebufferRenderbuffer(DEPTH_STENCIL)");
        } else if (getUseStencil()) {
            glproc::GenRenderbuffers(1, &m_StencilBuffer);
            glproc::BindRenderbuffer(GL_RENDERBUFFER, m_StencilBuffer);
            glproc::RenderbufferStorage(GL_RENDERBUFFER, GL_STENCIL_INDEX8,
                    glSize.x, glSize.y);
            glproc::FramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT,
                    GL_RENDERBUFFER, m_StencilBuffer);
            GLContext::checkError("FBO::init: FramebufferRenderbuffer(STENCIL)");
        }
        m_OutputFBO = m_FBO;
    } else {
#ifdef AVG_ENABLE_EGL
        AVG_ASSERT(false);
#else
        glproc::GenRenderbuffers(1, &m_ColorBuffer);
        glproc::BindRenderbuffer(GL_RENDERBUFFER, m_ColorBuffer);
        GLContext::enableErrorLog(false);
        glproc::RenderbufferStorageMultisample(GL_RENDERBUFFER, numSamples, GL_RGBA8,
                glSize.x, glSize.y);
        GLContext::enableErrorLog(true);
        GLenum err = glGetError();
        if (err == GL_INVALID_VALUE) {
            glproc::BindFramebuffer(GL_FRAMEBUFFER, 0);
            glproc::DeleteFramebuffers(1, &m_FBO);
            glproc::DeleteRenderbuffers(1, &m_ColorBuffer);
            m_pOutputPBO = PBOPtr();
            throwMultisampleError();
        }
        GLContext::checkError("FBO::init: RenderbufferStorageMultisample");
        glproc::FramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
                GL_RENDERBUFFER, m_ColorBuffer);
        GLContext::checkError("FBO::init: FramebufferRenderbuffer");
        if (getUsePackedDepthStencil()) {
            glproc::GenRenderbuffers(1, &m_StencilBuffer);
            glproc::BindRenderbuffer(GL_RENDERBUFFER, m_StencilBuffer);
            glproc::RenderbufferStorageMultisample(GL_RENDERBUFFER, numSamples,
                    GL_DEPTH_STENCIL_EXT, glSize.x, glSize.y);
            GLenum err = glGetError();
            if (err == GL_INVALID_OPERATION) {
                glproc::BindFramebuffer(GL_FRAMEBUFFER, 0);
                glproc::DeleteFramebuffers(1, &m_FBO);
                glproc::DeleteRenderbuffers(1, &m_ColorBuffer);
                m_pOutputPBO = PBOPtr();
                throwMultisampleError();
            }
            glproc::FramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,
                    GL_RENDERBUFFER, m_StencilBuffer);
            glproc::FramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT,
                    GL_RENDERBUFFER, m_StencilBuffer);
            GLContext::checkError("FBO::init: FramebufferRenderbuffer(STENCIL)");
        } else {
            AVG_ASSERT_MSG(!getUseStencil(),
                "Multisample FBO with stencil & not depth buffers not implemented yet.");
        }
        checkError("init multisample");
        m_OutputFBO = pContext->genFBO();
        glproc::BindFramebuffer(GL_FRAMEBUFFER, m_OutputFBO);
        glproc::FramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
                GL_TEXTURE_2D, m_pTextures[0]->getID(), 0);

        GLContext::checkError("FBO::init: Multisample init");
#endif
    }

    checkError("init");
    glproc::BindFramebuffer(GL_FRAMEBUFFER, 0);
}

void FBO::checkError(const string& sContext)
{
    GLenum status = glproc::CheckFramebufferStatus(GL_FRAMEBUFFER);
    string sErr;
    switch (status) {
        case GL_FRAMEBUFFER_COMPLETE:
            return;
        case GL_FRAMEBUFFER_UNSUPPORTED:
            sErr = "GL_FRAMEBUFFER_UNSUPPORTED";
            throw Exception(AVG_ERR_UNSUPPORTED, string("Framebuffer error: ")+sErr);
            break;
        case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT:
            sErr = "GL_INCOMPLETE_ATTACHMENT";
            break;
        case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT:
            sErr = "GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT";
            break;
        case GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS:
            sErr = "GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS";
            break;
#ifndef AVG_ENABLE_EGL
        case GL_FRAMEBUFFER_INCOMPLETE_FORMATS_EXT:
            sErr = "GL_FRAMEBUFFER_INCOMPLETE_FORMATS_EXT";
            break;
        case GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_EXT:
            sErr = "GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_EXT";
            break;
        case GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER_EXT:
            sErr = "GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER_EXT";
            break;
        case GL_FRAMEBUFFER_BINDING_EXT:
            sErr = "GL_FRAMEBUFFER_BINDING_EXT";
            break;
#endif
        default:
            sErr = "Unknown error";
            break;
    }
    cerr << "Framebuffer error (" << sContext << "): " << sErr << endl;
    AVG_ASSERT(false);
}

}

<commit_msg>No need to unattach textures from FBOs before deletion.<commit_after>//
//  libavg - Media Playback Engine.
//  Copyright (C) 2003-2014 Ulrich von Zadow
//
//  This library is free software; you can redistribute it and/or
//  modify it under the terms of the GNU Lesser General Public
//  License as published by the Free Software Foundation; either
//  version 2 of the License, or (at your option) any later version.
//
//  This library is distributed in the hope that it will be useful,
//  but WITHOUT ANY WARRANTY; without even the implied warranty of
//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
//  Lesser General Public License for more details.
//
//  You should have received a copy of the GNU Lesser General Public
//  License along with this library; if not, write to the Free Software
//  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
//
//  Current versions can be found at www.libavg.de
//

#include "FBO.h"

#include "OGLHelper.h"
#include "GLContext.h"
#include "Filterfliprgb.h"
#include "GLTexture.h"
#include "PBO.h"

#include "../base/Exception.h"
#include "../base/StringHelper.h"
#include "../base/ObjectCounter.h"

#include <stdio.h>

using namespace std;
using namespace boost;

namespace avg {

#ifndef GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS
#define GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT
#endif

#ifdef AVG_ENABLE_EGL
#define GL_DEPTH_STENCIL_EXT GL_DEPTH24_STENCIL8_OES
#endif

FBO::FBO(const FBOInfo& fboInfo, const vector<GLTexturePtr>& pTex)
    : FBOInfo(fboInfo)
{
    ObjectCounter::get()->incRef(&typeid(*this));
    m_pTextures = pTex;
    init();
}

FBO::~FBO()
{
    ObjectCounter::get()->decRef(&typeid(*this));

    unsigned oldFBOID;
    glGetIntegerv(GL_FRAMEBUFFER_BINDING, (GLint*)&oldFBOID);
    glproc::BindFramebuffer(GL_FRAMEBUFFER, m_FBO);

    GLContext* pContext = GLContext::getCurrent();
    if (pContext) {
        bool bMultisample = (getMultisampleSamples() > 1);
        if (getUsePackedDepthStencil() && isPackedDepthStencilSupported()) {
            glproc::DeleteRenderbuffers(1, &m_StencilBuffer);
            glproc::FramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,
                    GL_RENDERBUFFER, 0);
            glproc::FramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT,
                    GL_RENDERBUFFER, 0);
            if (bMultisample) {
                glproc::BindFramebuffer(GL_FRAMEBUFFER, m_OutputFBO);
                glproc::FramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
                        GL_TEXTURE_2D, 0, 0);
            }
        } else if (getUseStencil()) {
            glproc::DeleteRenderbuffers(1, &m_StencilBuffer);
            glproc::FramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT,
                    GL_RENDERBUFFER, 0);
        }
        pContext->returnFBOToCache(m_FBO);
        if (bMultisample) {
            glproc::DeleteRenderbuffers(1, &m_ColorBuffer);
            pContext->returnFBOToCache(m_OutputFBO);
        }
        GLContext::checkError("~FBO");
    }
}

void FBO::activate() const
{
    glproc::BindFramebuffer(GL_FRAMEBUFFER, m_FBO);
    GLContext::checkError("FBO::activate: BindFramebuffer()");
    checkError("activate");
}

void FBO::copyToDestTexture() const
{
#ifndef AVG_ENABLE_EGL
    if (getMultisampleSamples() != 1) {
        // Copy Multisample FBO to destination fbo
        glproc::BindFramebuffer(GL_READ_FRAMEBUFFER_EXT, m_FBO);
        glproc::BindFramebuffer(GL_DRAW_FRAMEBUFFER_EXT, m_OutputFBO);
        IntPoint size = getSize();
        glproc::BlitFramebuffer(0, 0, size.x, size.y, 0, 0, size.x, size.y,
                GL_COLOR_BUFFER_BIT, GL_LINEAR);
        glproc::BindFramebuffer(GL_FRAMEBUFFER, 0);
    }
#endif
    if (getMipmap()) {
        for (unsigned i=0; i< m_pTextures.size(); ++i) {
            m_pTextures[i]->generateMipmaps();
        }
    }
}

BitmapPtr FBO::getImage(int i) const
{
    GLContext* pContext = GLContext::getCurrent();
    if (pContext->getMemoryMode() == MM_PBO) {
        moveToPBO(i);
        return getImageFromPBO();
    } else {
        IntPoint size = getSize();
        PixelFormat pf = getPF();
        BitmapPtr pBmp(new Bitmap(size, pf));
        glproc::BindFramebuffer(GL_FRAMEBUFFER, m_OutputFBO);
        glReadPixels(0, 0, size.x, size.y, GLTexture::getGLFormat(pf),
                GLTexture::getGLType(pf), pBmp->getPixels());
        GLContext::checkError("FBO::getImage ReadPixels()");
        return pBmp;
    }
}

void FBO::moveToPBO(int i) const
{
    AVG_ASSERT(GLContext::getCurrent()->getMemoryMode() == MM_PBO);
#ifndef AVG_ENABLE_EGL
    // Get data directly from the FBO using glReadBuffer. At least on NVidia/Linux, this
    // is faster than reading stuff from the texture.
    copyToDestTexture();
    glproc::BindFramebuffer(GL_FRAMEBUFFER, m_OutputFBO);

    m_pOutputPBO->activate();
    GLContext::checkError("FBO::moveToPBO BindBuffer()");
    glReadBuffer(GL_COLOR_ATTACHMENT0+i);
    GLContext::checkError("FBO::moveToPBO ReadBuffer()");

    IntPoint size = getSize();
    PixelFormat pf = getPF();
    glReadPixels(0, 0, size.x, size.y, GLTexture::getGLFormat(pf),
            GLTexture::getGLType(pf), 0);
    GLContext::checkError("FBO::moveToPBO ReadPixels()");
#endif
}

BitmapPtr FBO::getImageFromPBO() const
{
#ifdef AVG_ENABLE_EGL
    AVG_ASSERT(false);
    return BitmapPtr();
#else
    AVG_ASSERT(GLContext::getCurrent()->getMemoryMode() == MM_PBO);
    m_pOutputPBO->activate();
    GLContext::checkError("FBO::getImageFromPBO BindBuffer()");

    IntPoint size = getSize();
    PixelFormat pf = getPF();
    BitmapPtr pBmp(new Bitmap(size, pf));
    void * pPBOPixels = glproc::MapBuffer(GL_PIXEL_PACK_BUFFER_EXT, GL_READ_ONLY);
    GLContext::checkError("FBO::getImageFromPBO MapBuffer()");
    Bitmap PBOBitmap(size, pf, (unsigned char *)pPBOPixels,
            size.x*getBytesPerPixel(pf), false);
    pBmp->copyPixels(PBOBitmap);
    glproc::UnmapBuffer(GL_PIXEL_PACK_BUFFER_EXT);
    GLContext::checkError("FBO::getImageFromPBO UnmapBuffer()");
    return pBmp;
#endif
}

GLTexturePtr FBO::getTex(int i) const
{
    return m_pTextures[i];
}

void FBO::init()
{
    GLContext* pContext = GLContext::getCurrent();
    if (getUsePackedDepthStencil() && !isPackedDepthStencilSupported()) {
        throw Exception(AVG_ERR_UNSUPPORTED, "OpenGL implementation does not support offscreen cropping (GL_EXT_packed_depth_stencil).");
    }
    unsigned numSamples = getMultisampleSamples();
    if (numSamples > 1 && !isMultisampleFBOSupported()) {
        throw Exception(AVG_ERR_UNSUPPORTED, "OpenGL implementation does not support multisample offscreen rendering (GL_EXT_framebuffer_multisample).");
    }
#ifndef AVG_ENABLE_EGL
    if (GLContext::getCurrent()->getMemoryMode() == MM_PBO) {
        m_pOutputPBO = PBOPtr(new PBO(getSize(), getPF(), GL_STREAM_READ));
    }
#endif

    m_FBO = pContext->genFBO();
    GLContext::checkError("FBO::init: GenFramebuffers()");

    glproc::BindFramebuffer(GL_FRAMEBUFFER, m_FBO);
    GLContext::checkError("FBO::init: BindFramebuffer()");

    IntPoint glSize = m_pTextures[0]->getGLSize();
    if (numSamples == 1) {
        for (unsigned i=0; i<m_pTextures.size(); ++i) {
            glproc::FramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0+i,
                    GL_TEXTURE_2D, m_pTextures[i]->getID(), 0);
            GLContext::checkError("FBO: glFramebufferTexture2D()");
        }
        if (getUsePackedDepthStencil()) {
            glproc::GenRenderbuffers(1, &m_StencilBuffer);
            glproc::BindRenderbuffer(GL_RENDERBUFFER, m_StencilBuffer);
            glproc::RenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_STENCIL_EXT,
                    glSize.x, glSize.y);
            glproc::FramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,
                    GL_RENDERBUFFER, m_StencilBuffer);
            glproc::FramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT,
                    GL_RENDERBUFFER, m_StencilBuffer);
            GLContext::checkError("FBO::init: FramebufferRenderbuffer(DEPTH_STENCIL)");
        } else if (getUseStencil()) {
            glproc::GenRenderbuffers(1, &m_StencilBuffer);
            glproc::BindRenderbuffer(GL_RENDERBUFFER, m_StencilBuffer);
            glproc::RenderbufferStorage(GL_RENDERBUFFER, GL_STENCIL_INDEX8,
                    glSize.x, glSize.y);
            glproc::FramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT,
                    GL_RENDERBUFFER, m_StencilBuffer);
            GLContext::checkError("FBO::init: FramebufferRenderbuffer(STENCIL)");
        }
        m_OutputFBO = m_FBO;
    } else {
#ifdef AVG_ENABLE_EGL
        AVG_ASSERT(false);
#else
        glproc::GenRenderbuffers(1, &m_ColorBuffer);
        glproc::BindRenderbuffer(GL_RENDERBUFFER, m_ColorBuffer);
        GLContext::enableErrorLog(false);
        glproc::RenderbufferStorageMultisample(GL_RENDERBUFFER, numSamples, GL_RGBA8,
                glSize.x, glSize.y);
        GLContext::enableErrorLog(true);
        GLenum err = glGetError();
        if (err == GL_INVALID_VALUE) {
            glproc::BindFramebuffer(GL_FRAMEBUFFER, 0);
            glproc::DeleteFramebuffers(1, &m_FBO);
            glproc::DeleteRenderbuffers(1, &m_ColorBuffer);
            m_pOutputPBO = PBOPtr();
            throwMultisampleError();
        }
        GLContext::checkError("FBO::init: RenderbufferStorageMultisample");
        glproc::FramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
                GL_RENDERBUFFER, m_ColorBuffer);
        GLContext::checkError("FBO::init: FramebufferRenderbuffer");
        if (getUsePackedDepthStencil()) {
            glproc::GenRenderbuffers(1, &m_StencilBuffer);
            glproc::BindRenderbuffer(GL_RENDERBUFFER, m_StencilBuffer);
            glproc::RenderbufferStorageMultisample(GL_RENDERBUFFER, numSamples,
                    GL_DEPTH_STENCIL_EXT, glSize.x, glSize.y);
            GLenum err = glGetError();
            if (err == GL_INVALID_OPERATION) {
                glproc::BindFramebuffer(GL_FRAMEBUFFER, 0);
                glproc::DeleteFramebuffers(1, &m_FBO);
                glproc::DeleteRenderbuffers(1, &m_ColorBuffer);
                m_pOutputPBO = PBOPtr();
                throwMultisampleError();
            }
            glproc::FramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,
                    GL_RENDERBUFFER, m_StencilBuffer);
            glproc::FramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT,
                    GL_RENDERBUFFER, m_StencilBuffer);
            GLContext::checkError("FBO::init: FramebufferRenderbuffer(STENCIL)");
        } else {
            AVG_ASSERT_MSG(!getUseStencil(),
                "Multisample FBO with stencil & not depth buffers not implemented yet.");
        }
        checkError("init multisample");
        m_OutputFBO = pContext->genFBO();
        glproc::BindFramebuffer(GL_FRAMEBUFFER, m_OutputFBO);
        glproc::FramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
                GL_TEXTURE_2D, m_pTextures[0]->getID(), 0);

        GLContext::checkError("FBO::init: Multisample init");
#endif
    }

    checkError("init");
    glproc::BindFramebuffer(GL_FRAMEBUFFER, 0);
}

void FBO::checkError(const string& sContext)
{
    GLenum status = glproc::CheckFramebufferStatus(GL_FRAMEBUFFER);
    string sErr;
    switch (status) {
        case GL_FRAMEBUFFER_COMPLETE:
            return;
        case GL_FRAMEBUFFER_UNSUPPORTED:
            sErr = "GL_FRAMEBUFFER_UNSUPPORTED";
            throw Exception(AVG_ERR_UNSUPPORTED, string("Framebuffer error: ")+sErr);
            break;
        case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT:
            sErr = "GL_INCOMPLETE_ATTACHMENT";
            break;
        case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT:
            sErr = "GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT";
            break;
        case GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS:
            sErr = "GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS";
            break;
#ifndef AVG_ENABLE_EGL
        case GL_FRAMEBUFFER_INCOMPLETE_FORMATS_EXT:
            sErr = "GL_FRAMEBUFFER_INCOMPLETE_FORMATS_EXT";
            break;
        case GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_EXT:
            sErr = "GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_EXT";
            break;
        case GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER_EXT:
            sErr = "GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER_EXT";
            break;
        case GL_FRAMEBUFFER_BINDING_EXT:
            sErr = "GL_FRAMEBUFFER_BINDING_EXT";
            break;
#endif
        default:
            sErr = "Unknown error";
            break;
    }
    cerr << "Framebuffer error (" << sContext << "): " << sErr << endl;
    AVG_ASSERT(false);
}

}

<|endoftext|>


<commit_before>/*------------------------------------------------------------------------
* (The MIT License)
*
* Copyright (c) 2008-2012 Rhomobile, Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
* http://rhomobile.com
*------------------------------------------------------------------------*/

#include "rhodes/JNIRhodes.h"
#include "common/RhoConf.h"
#include "Push.h"
#include "sync/RhoconnectClientManager.h"
#include "sync/ILoginListener.h"

#include "logging/RhoLog.h"

#include "gcmpushclient.h"

//----------------------------------------------------------------------------------------------------------------------
extern "C" void Init_GCMPushClient()
{
    // create GCM push client
    RAWTRACEC("Init_GCMPushClient", "creating GCM client >>>>>>>>>>>>>>");

    rho::gcm::GcmPushClient* pClient = new rho::gcm::GcmPushClient();

    RAWTRACEC("Init_GCMPushClient", "adding GCM client >>>>>>>>>>>>>>>>");

    rho::push::CPushManager::getInstance()->addClient(pClient);

}
//----------------------------------------------------------------------------------------------------------------------

namespace rho { namespace gcm {

IMPLEMENT_LOGCLASS(GcmPushClient, "GcmPushClient");

//----------------------------------------------------------------------------------------------------------------------

const char* const GcmPushClient::s_GCM_FACADE_CLASS = "com.rhomobile.rhodes.gcm.GCMFacade";

//----------------------------------------------------------------------------------------------------------------------
void GcmPushClient::doRegister()
{
    LOG(TRACE) + "GcmPushRegister()";

    JNIEnv *env = jnienv();

    static jclass cls = rho_find_class(env, s_GCM_FACADE_CLASS);
    if (!cls) {
        LOG(ERROR) + "Cannot find class: " + s_GCM_FACADE_CLASS;
        return;
    }

    static jmethodID mid = env->GetStaticMethodID(cls, "Register", "(Ljava/lang/String;)V");
    if (!mid) {
        LOG(ERROR) + "Cannot get " + s_GCM_FACADE_CLASS + ".Register() method";
        return;
    }

    jhstring jhSenderId = rho_cast<jstring>(m_hashProps["senderId"]);

    env->CallStaticVoidMethod(cls, mid, jhSenderId.get());
}

//----------------------------------------------------------------------------------------------------------------------
void GcmPushClient::doUnregister()
{
    LOG(TRACE) + "GcmPushUnregister()";

    JNIEnv *env = jnienv();

    static jclass cls = rho_find_class(env, s_GCM_FACADE_CLASS);
    if (!cls) {
        LOG(ERROR) + "Cannot find class: " + s_GCM_FACADE_CLASS;
        return;
    }

    static jmethodID mid = env->GetStaticMethodID(cls, "Unregister", "()V");
    if (!mid) {
        LOG(ERROR) + "Cannot get " + s_GCM_FACADE_CLASS + ".Unregister() method";
        return;
    }

    env->CallStaticVoidMethod(cls, mid);
}
//----------------------------------------------------------------------------------------------------------------------
const String GcmPushClient::s_Type = "gcm";

GcmPushClient::GcmPushClient()
{
    CMethodResult result;
    setProperty("id", s_Type, result);
    setProperty("type", IPush::PUSH_TYPE_NATIVE, result);
    setProperty("senderId", RHOCONF().getString("Push.gcm.senderId"), result);

    LOG(TRACEC) + "request GCM registration >>>>>>>>>>>>>>>>";
    doRegister();
}

//----------------------------------------------------------------------------------------------------------------------

void GcmPushClient::getDeviceId(CMethodResult& result)
{
    String deviceId = m_hashProps["deviceId"];

    if(deviceId.length() != 0)
    {
        LOG(TRACE) + "GCM deviceId: " + deviceId;
        result.set(deviceId);
    }
    else
    {
        LOG(TRACE) + "Still waiting for GCM deviceId";
        m_deviceIdResult = result;
    }
}

//----------------------------------------------------------------------------------------------------------------------
void GcmPushClient::startNotifications(CMethodResult& result)
{
    LOG(TRACE) + "Start GCM push notifications";
    m_oResult = result;
}

//----------------------------------------------------------------------------------------------------------------------
void GcmPushClient::stopNotifications(CMethodResult& result)
{
    LOG(TRACE) + "Stop GCM push notifications";
    m_oResult = CMethodResult();
}

//----------------------------------------------------------------------------------------------------------------------
void GcmPushClient::setDeviceId(const String& deviceId)
{
    CMethodResult result;
    setProperty("deviceId", deviceId, result);

    LOG(TRACE) + "creating client register";
    rho::sync::RhoconnectClientManager::clientRegisterCreate(deviceId.c_str());

    getDeviceId(m_deviceIdResult);
    m_deviceIdResult = CMethodResult();

}

//----------------------------------------------------------------------------------------------------------------------
bool GcmPushClient::callBack(const String& json)
{
    LOG(TRACE) + "GCM push notification: " + json;

    m_oResult.setJSON(json);

    return true;
}

}}

<commit_msg>Android: Fix GCM push build<commit_after>/*------------------------------------------------------------------------
* (The MIT License)
*
* Copyright (c) 2008-2012 Rhomobile, Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
* http://rhomobile.com
*------------------------------------------------------------------------*/

#include "rhodes/JNIRhodes.h"
#include "common/RhoConf.h"
#include "Push.h"
#include "sync/RhoconnectClientManager.h"
#include "sync/ILoginListener.h"

#include "logging/RhoLog.h"

#include "gcmpushclient.h"

//----------------------------------------------------------------------------------------------------------------------
extern "C" void Init_GCMPushClient()
{
    // create GCM push client
    RAWTRACEC("Init_GCMPushClient", "creating GCM client >>>>>>>>>>>>>>");

    rho::gcm::GcmPushClient* pClient = new rho::gcm::GcmPushClient();

    RAWTRACEC("Init_GCMPushClient", "adding GCM client >>>>>>>>>>>>>>>>");

    rho::push::CPushManager::getInstance()->addClient(pClient);

}
//----------------------------------------------------------------------------------------------------------------------

namespace rho { namespace gcm {

IMPLEMENT_LOGCLASS(GcmPushClient, "GcmPushClient");

//----------------------------------------------------------------------------------------------------------------------

const char* const GcmPushClient::s_GCM_FACADE_CLASS = "com.rhomobile.rhodes.gcm.GCMFacade";

//----------------------------------------------------------------------------------------------------------------------
void GcmPushClient::doRegister()
{
    LOG(TRACE) + "GcmPushRegister()";

    JNIEnv *env = jnienv();

    static jclass cls = rho_find_class(env, s_GCM_FACADE_CLASS);
    if (!cls) {
        LOG(ERROR) + "Cannot find class: " + s_GCM_FACADE_CLASS;
        return;
    }

    static jmethodID mid = env->GetStaticMethodID(cls, "Register", "(Ljava/lang/String;)V");
    if (!mid) {
        LOG(ERROR) + "Cannot get " + s_GCM_FACADE_CLASS + ".Register() method";
        return;
    }

    jhstring jhSenderId = rho_cast<jstring>(m_hashProps["senderId"]);

    env->CallStaticVoidMethod(cls, mid, jhSenderId.get());
}

//----------------------------------------------------------------------------------------------------------------------
void GcmPushClient::doUnregister()
{
    LOG(TRACE) + "GcmPushUnregister()";

    JNIEnv *env = jnienv();

    static jclass cls = rho_find_class(env, s_GCM_FACADE_CLASS);
    if (!cls) {
        LOG(ERROR) + "Cannot find class: " + s_GCM_FACADE_CLASS;
        return;
    }

    static jmethodID mid = env->GetStaticMethodID(cls, "Unregister", "()V");
    if (!mid) {
        LOG(ERROR) + "Cannot get " + s_GCM_FACADE_CLASS + ".Unregister() method";
        return;
    }

    env->CallStaticVoidMethod(cls, mid);
}
//----------------------------------------------------------------------------------------------------------------------
const String GcmPushClient::s_Type = "gcm";

GcmPushClient::GcmPushClient()
{
    CMethodResult result;
    setProperty("id", s_Type, result);
    setProperty("type", IPush::PUSH_TYPE_NATIVE, result);
    setProperty("senderId", RHOCONF().getString("Push.gcm.senderId"), result);

    LOG(TRACE) + "request GCM registration >>>>>>>>>>>>>>>>";
    doRegister();
}

//----------------------------------------------------------------------------------------------------------------------

void GcmPushClient::getDeviceId(CMethodResult& result)
{
    String deviceId = m_hashProps["deviceId"];

    if(deviceId.length() != 0)
    {
        LOG(TRACE) + "GCM deviceId: " + deviceId;
        result.set(deviceId);
    }
    else
    {
        LOG(TRACE) + "Still waiting for GCM deviceId";
        m_deviceIdResult = result;
    }
}

//----------------------------------------------------------------------------------------------------------------------
void GcmPushClient::startNotifications(CMethodResult& result)
{
    LOG(TRACE) + "Start GCM push notifications";
    m_oResult = result;
}

//----------------------------------------------------------------------------------------------------------------------
void GcmPushClient::stopNotifications(CMethodResult& result)
{
    LOG(TRACE) + "Stop GCM push notifications";
    m_oResult = CMethodResult();
}

//----------------------------------------------------------------------------------------------------------------------
void GcmPushClient::setDeviceId(const String& deviceId)
{
    CMethodResult result;
    setProperty("deviceId", deviceId, result);

    LOG(TRACE) + "creating client register";
    rho::sync::RhoconnectClientManager::clientRegisterCreate(deviceId.c_str());

    getDeviceId(m_deviceIdResult);
    m_deviceIdResult = CMethodResult();

}

//----------------------------------------------------------------------------------------------------------------------
bool GcmPushClient::callBack(const String& json)
{
    LOG(TRACE) + "GCM push notification: " + json;

    m_oResult.setJSON(json);

    return true;
}

}}

<|endoftext|>


<commit_before>#include <algorithm>
#include <cctype>
#include <cstdarg>

#include "reader.h"

namespace
{

// The parameter is mutated, and therefore must be passed by value.
std::string ToUpper(std::string s)
{
  std::transform(s.begin(), s.end(), s.begin(), ::toupper);
  return s;
}

} // namespace

namespace mclisp
{

const std::string ReadError::err_prefix_("Read Error: ");
const std::string BadTokenError::err_prefix_("Bad Token: ");

void Reader::AcceptToken(Token expected_token)
{
  Token token = lexer_.nextToken();
  if (token != expected_token)
    throw BadTokenError(token, expected_token);
}

Token Reader::AcceptTokens(std::set<Token> tokens)
{
  Token token = lexer_.nextToken();

  if (tokens.find(token) == tokens.end())
    throw BadTokenError(token, tokens);

  return token;
}

const Symbol& Reader::Intern(const std::string& name)
{
  return Intern(Symbol(ToUpper(name)));
}

const Symbol& Reader::Intern(const Symbol& symbol)
{
  auto pair = symbols_.emplace(symbol.name(), symbol);
  return pair.first->second;
}

void Reader::Init()
{

  // At the moment, this is pointless since the Symbols are copied/moved into
  // the symbols_ map. We could just as well wait for the reader to read NIL or
  // T and only intern them then. Symbol equality is implemented by delegating
  // to string= on Symbol::name, so this copying-intern doesn't break anything.
  // Once the allocator/gc are implemented, we should instead intern pointers to
  // symbols so we can implement Symbol equality as pointer equality.
  Intern(kNil);
  Intern(kT);
}

const Cons& Reader::ReadCons()
{
  const Sexp& car = Read();
  const Sexp* cdr = nullptr;
  Token token = AcceptTokens({kDot, kComma, kCloseParen});

  if (token == kDot)
  {
    cdr = &Read();
    AcceptToken(kCloseParen);
  }
  else if (token == kComma)
  {
    cdr = &ReadCons();
  }
  else if (token == kCloseParen)
    cdr = &kNil;

  conses_.emplace_front(car, *cdr);
  return conses_.front();
}

const Symbol& Reader::ReadSymbol()
{
  return Intern(lexer_.current_token());
}

const Sexp& Reader::Read()
{
  Token token = lexer_.nextToken();
  switch (token)
  {
    case kSymbol: return ReadSymbol();
    case kOpenParen: return ReadCons();
    case kEof: return kNil;
    default:
      throw ReadError("Expected start of Cons or Symbol, found: "
                      + std::to_string(token));
  }
}

} // namespace mclisp
<commit_msg>Add TODO reminder to return EOF object on EOF.<commit_after>#include <algorithm>
#include <cctype>
#include <cstdarg>

#include "reader.h"

namespace
{

// The parameter is mutated, and therefore must be passed by value.
std::string ToUpper(std::string s)
{
  std::transform(s.begin(), s.end(), s.begin(), ::toupper);
  return s;
}

} // namespace

namespace mclisp
{

const std::string ReadError::err_prefix_("Read Error: ");
const std::string BadTokenError::err_prefix_("Bad Token: ");

void Reader::AcceptToken(Token expected_token)
{
  Token token = lexer_.nextToken();
  if (token != expected_token)
    throw BadTokenError(token, expected_token);
}

Token Reader::AcceptTokens(std::set<Token> tokens)
{
  Token token = lexer_.nextToken();

  if (tokens.find(token) == tokens.end())
    throw BadTokenError(token, tokens);

  return token;
}

const Symbol& Reader::Intern(const std::string& name)
{
  return Intern(Symbol(ToUpper(name)));
}

const Symbol& Reader::Intern(const Symbol& symbol)
{
  auto pair = symbols_.emplace(symbol.name(), symbol);
  return pair.first->second;
}

void Reader::Init()
{

  // At the moment, this is pointless since the Symbols are copied/moved into
  // the symbols_ map. We could just as well wait for the reader to read NIL or
  // T and only intern them then. Symbol equality is implemented by delegating
  // to string= on Symbol::name, so this copying-intern doesn't break anything.
  // Once the allocator/gc are implemented, we should instead intern pointers to
  // symbols so we can implement Symbol equality as pointer equality.
  Intern(kNil);
  Intern(kT);
}

const Cons& Reader::ReadCons()
{
  const Sexp& car = Read();
  const Sexp* cdr = nullptr;
  Token token = AcceptTokens({kDot, kComma, kCloseParen});

  if (token == kDot)
  {
    cdr = &Read();
    AcceptToken(kCloseParen);
  }
  else if (token == kComma)
  {
    cdr = &ReadCons();
  }
  else if (token == kCloseParen)
    cdr = &kNil;

  conses_.emplace_front(car, *cdr);
  return conses_.front();
}

const Symbol& Reader::ReadSymbol()
{
  return Intern(lexer_.current_token());
}

const Sexp& Reader::Read()
{
  Token token = lexer_.nextToken();
  switch (token)
  {
    case kSymbol: return ReadSymbol();
    case kOpenParen: return ReadCons();
    case kEof: return kNil; // TODO: return Eof object.
    default:
      throw ReadError("Expected start of Cons or Symbol, found: "
                      + std::to_string(token));
  }
}

} // namespace mclisp
<|endoftext|>


<commit_before>#include "offeracceptdialogbtc.h"
#include "ui_offeracceptdialogbtc.h"
#include "init.h"
#include "util.h"
#include "offerpaydialog.h"
#include "guiconstants.h"
#include "guiutil.h"
#include "platformstyle.h"
#include "syscoingui.h"
#include <QMessageBox>
#include "rpcserver.h"
#include "pubkey.h"
#include "wallet/wallet.h"
#include "main.h"
#include <QDesktopServices>
#if QT_VERSION < 0x050000
#include <QUrl>
#else
#include <QUrlQuery>
#endif
#include <QPixmap>
#if defined(HAVE_CONFIG_H)
#include "config/syscoin-config.h" /* for USE_QRCODE */
#endif

#ifdef USE_QRCODE
#include <qrencode.h>
#endif
using namespace std;
#include <QNetworkAccessManager>
#include <QNetworkRequest>
#include <QNetworkReply>

extern const CRPCTable tableRPC;
OfferAcceptDialogBTC::OfferAcceptDialogBTC(const PlatformStyle *platformStyle, QString alias, QString offer, QString quantity, QString notes, QString title, QString currencyCode, QString qstrPrice, QString sellerAlias, QString address, QWidget *parent) :
    QDialog(parent),
    ui(new Ui::OfferAcceptDialogBTC), platformStyle(platformStyle), alias(alias), offer(offer), notes(notes), quantity(quantity), title(title), sellerAlias(sellerAlias), address(address)
{
    ui->setupUi(this);
	QString theme = GUIUtil::getThemeName();
	ui->aboutShadeBTC->setPixmap(QPixmap(":/images/" + theme + "/about_btc"));
	double dblPrice = qstrPrice.toDouble()*quantity.toUInt();
	string strfPrice = strprintf("%f", dblPrice);
	QString fprice = QString::fromStdString(strfPrice);
	string strCurrencyCode = currencyCode.toStdString();
	ui->escrowDisclaimer->setText(tr("Please note escrow is not available since you are paying in BTC, only SYS payments can be escrowed. "));
	ui->bitcoinInstructionLabel->setText(tr("After paying for this item, please enter the Bitcoin Transaction ID and click on the confirm button below. You may use the QR Code to the left to scan the payment request into your wallet or click on the Open BTC Wallet if you are on the desktop and have Bitcoin Core installed."));
	ui->acceptMessage->setText(tr("Are you sure you want to purchase %1 of '%2' from merchant: '%3'? To complete your purchase please pay %4 BTC using your Bitcoin wallet.").arg(quantity).arg(title).arg(sellerAlias).arg(fprice));
	string strPrice = strprintf("%f", dblPrice);
	price = QString::fromStdString(strPrice);

	if (!platformStyle->getImagesOnButtons())
	{
		ui->confirmButton->setIcon(QIcon());
		ui->openBtcWalletButton->setIcon(QIcon());
		ui->cancelButton->setIcon(QIcon());

	}
	else
	{
		ui->confirmButton->setIcon(platformStyle->SingleColorIcon(":/icons/" + theme + "/transaction_confirmed"));
		ui->openBtcWalletButton->setIcon(platformStyle->SingleColorIcon(":/icons/" + theme + "/send"));
		ui->cancelButton->setIcon(platformStyle->SingleColorIcon(":/icons/" + theme + "/quit"));
	}
	this->offerPaid = false;
	connect(ui->confirmButton, SIGNAL(clicked()), this, SLOT(acceptPayment()));
	connect(ui->openBtcWalletButton, SIGNAL(clicked()), this, SLOT(openBTCWallet()));

#ifdef USE_QRCODE
	QString message = "Payment for offer ID " + this->offer + " on Syscoin Decentralized Marketplace";
	QString uri = "bitcoin:" + this->address + "?amount=" + price + "&label=" + this->sellerAlias + "&message=" + GUIUtil::HtmlEscape(message);

	ui->lblQRCode->setText("");
    if(!uri.isEmpty())
    {
        // limit URI length
        if (uri.length() > MAX_URI_LENGTH)
        {
            ui->lblQRCode->setText(tr("Resulting URI too long, try to reduce the text for label / message."));
        } else {
            QRcode *code = QRcode_encodeString(uri.toUtf8().constData(), 0, QR_ECLEVEL_L, QR_MODE_8, 1);
            if (!code)
            {
                ui->lblQRCode->setText(tr("Error encoding URI into QR Code."));
                return;
            }
            QImage myImage = QImage(code->width + 8, code->width + 8, QImage::Format_RGB32);
            myImage.fill(0xffffff);
            unsigned char *p = code->data;
            for (int y = 0; y width; y++)
            {
                for (int x = 0; x width; x++)
                {
                    myImage.setPixel(x + 4, y + 4, ((*p & 1) ? 0x0 : 0xffffff));
                    p++;
                }
            }
            QRcode_free(code);
            ui->lblQRCode->setPixmap(QPixmap::fromImage(myImage).scaled(128, 128));
        }
    }
#endif
}
void OfferAcceptDialogBTC::on_cancelButton_clicked()
{
    reject();
}
OfferAcceptDialogBTC::~OfferAcceptDialogBTC()
{
    delete ui;
}

void OfferAcceptDialogBTC::acceptPayment()
{
	acceptOffer();
}
bool OfferAcceptDialogBTC::CheckPaymentInBTC(const QString &strBTCTxId, const QString& address, const QString& price)
{
	QNetworkAccessManager *nam = new QNetworkAccessManager(this);
	QUrl url("https://blockchain.info/tx/" + strBTCTxId + "?format=json");
	QNetworkRequest request(url);
	request.setHeader(QNetworkRequest::ContentTypeHeader, "application/json");
	QNetworkReply* reply = nam->get(request);
	reply->ignoreSslErrors();
	int totalTime = 0;
	while(!reply->isFinished())
	{
		qApp->processEvents();
		totalTime += 100;
		MilliSleep(100);
		if(totalTime > 30000)
			throw runtime_error("Timeout connecting to blockchain.info!");
	}
	if(reply->error() == QNetworkReply::NoError) {

		UniValue outerValue;
		bool read = outerValue.read(reply->readAll().toStdString());
		if (read)
		{
			LogPrintf("gotjson!\n");
			UniValue outerObj = outerValue.get_obj();
			UniValue ratesValue = find_value(outerObj, "rates");
			if (ratesValue.isArray())
			{
			}
		}
	}
	reply->deleteLater();
	return false;

}

bool OfferAcceptDialogBTC::lookup(const QString &lookupid, QString& address, QString& price)
{
	string strError;
	string strMethod = string("offerinfo");
	UniValue params(UniValue::VARR);
	UniValue result;
	params.push_back(lookupid.toStdString());

    try {
        result = tableRPC.execute(strMethod, params);

		if (result.type() == UniValue::VOBJ)
		{
			const UniValue &offerObj = result.get_obj();

			const string &strAddress = find_value(offerObj, "address").get_str();
			const string &strPrice = find_value(offerObj, "price").get_str();
			address = QString::fromStdString(strAddress);
			price = QString::fromStdString(strPrice);
			return true;
		}
	}
	catch (UniValue& objError)
	{
		QMessageBox::critical(this, windowTitle(),
			tr("Could not find this offer, please check the offer ID and that it has been confirmed by the blockchain: ") + lookupid,
				QMessageBox::Ok, QMessageBox::Ok);
		return true;

	}
	catch(std::exception& e)
	{
		QMessageBox::critical(this, windowTitle(),
			tr("There was an exception trying to locate this offer, please check the offer ID and that it has been confirmed by the blockchain: ") + QString::fromStdString(e.what()),
				QMessageBox::Ok, QMessageBox::Ok);
		return true;
	}
	return false;

}
// send offeraccept with offer guid/qty as params and then send offerpay with wtxid (first param of response) as param, using RPC commands.
void OfferAcceptDialogBTC::acceptOffer()
{
		QString address, price;
		if (ui->btctxidEdit->text().trimmed().isEmpty()) {
            ui->btctxidEdit->setText("");
            QMessageBox::information(this, windowTitle(),
            tr("Please enter a valid Bitcoin Transaction ID into the input box and try again"),
                QMessageBox::Ok, QMessageBox::Ok);
            return;
        }
		if(!lookup(this->offer, address, price))
		{
            QMessageBox::information(this, windowTitle(),
            tr("Could not find this offer, please check the offer ID and that it has been confirmed by the blockchain: ") + this->offer,
                QMessageBox::Ok, QMessageBox::Ok);
            return;
		}
		if(!CheckPaymentInBTC(ui->btctxidEdit->text().trimmed(), address, price))
		{
            QMessageBox::information(this, windowTitle(),
            tr("Could not find this payment, please check the Transaction ID and that it has been confirmed by the Bitcoin blockchain: ") + ui->btctxidEdit->text().trimmed(),
                QMessageBox::Ok, QMessageBox::Ok);
            return;
		}

		UniValue params(UniValue::VARR);
		UniValue valError;
		UniValue valResult;
		UniValue valId;
		UniValue result ;
		string strReply;
		string strError;

		string strMethod = string("offeraccept");
		if(this->quantity.toLong() <= 0)
		{
			QMessageBox::critical(this, windowTitle(),
				tr("Invalid quantity when trying to accept offer!"),
				QMessageBox::Ok, QMessageBox::Ok);
			return;
		}
		this->offerPaid = false;
		params.push_back(this->alias.toStdString());
		params.push_back(this->offer.toStdString());
		params.push_back(this->quantity.toStdString());
		params.push_back(this->notes.toStdString());
		params.push_back(ui->btctxidEdit->text().toStdString());

	    try {
            result = tableRPC.execute(strMethod, params);
			if (result.type() != UniValue::VNULL)
			{
				const UniValue &arr = result.get_array();
				string strResult = arr[0].get_str();
				QString offerAcceptTXID = QString::fromStdString(strResult);
				if(offerAcceptTXID != QString(""))
				{
					OfferPayDialog dlg(platformStyle, this->title, this->quantity, this->price, "BTC", this);
					dlg.exec();
					this->offerPaid = true;
					OfferAcceptDialogBTC::accept();
					return;

				}
			}
		}
		catch (UniValue& objError)
		{
			strError = find_value(objError, "message").get_str();
			QMessageBox::critical(this, windowTitle(),
			tr("Error accepting offer: \"%1\"").arg(QString::fromStdString(strError)),
				QMessageBox::Ok, QMessageBox::Ok);
			return;
		}
		catch(std::exception& e)
		{
			QMessageBox::critical(this, windowTitle(),
				tr("General exception when accepting offer"),
				QMessageBox::Ok, QMessageBox::Ok);
			return;
		}

}
void OfferAcceptDialogBTC::openBTCWallet()
{
	QString message = "Payment for offer ID " + this->offer + " on Syscoin Decentralized Marketplace";
	QString uri = "bitcoin:" + this->address + "?amount=" + price + "&label=" + this->sellerAlias + "&message=" + GUIUtil::HtmlEscape(message);
	QDesktopServices::openUrl(QUrl(uri, QUrl::TolerantMode));
}
bool OfferAcceptDialogBTC::getPaymentStatus()
{
	return this->offerPaid;
}
<commit_msg>work on CheckPaymentInBTC<commit_after>#include "offeracceptdialogbtc.h"
#include "ui_offeracceptdialogbtc.h"
#include "init.h"
#include "util.h"
#include "offerpaydialog.h"
#include "guiconstants.h"
#include "guiutil.h"
#include "platformstyle.h"
#include "syscoingui.h"
#include <QMessageBox>
#include "rpcserver.h"
#include "pubkey.h"
#include "wallet/wallet.h"
#include "main.h"
#include <QDesktopServices>
#if QT_VERSION < 0x050000
#include <QUrl>
#else
#include <QUrlQuery>
#endif
#include <QPixmap>
#if defined(HAVE_CONFIG_H)
#include "config/syscoin-config.h" /* for USE_QRCODE */
#endif

#ifdef USE_QRCODE
#include <qrencode.h>
#endif
using namespace std;
#include <QNetworkAccessManager>
#include <QNetworkRequest>
#include <QNetworkReply>

extern const CRPCTable tableRPC;
OfferAcceptDialogBTC::OfferAcceptDialogBTC(const PlatformStyle *platformStyle, QString alias, QString offer, QString quantity, QString notes, QString title, QString currencyCode, QString qstrPrice, QString sellerAlias, QString address, QWidget *parent) :
    QDialog(parent),
    ui(new Ui::OfferAcceptDialogBTC), platformStyle(platformStyle), alias(alias), offer(offer), notes(notes), quantity(quantity), title(title), sellerAlias(sellerAlias), address(address)
{
    ui->setupUi(this);
	QString theme = GUIUtil::getThemeName();
	ui->aboutShadeBTC->setPixmap(QPixmap(":/images/" + theme + "/about_btc"));
	double dblPrice = qstrPrice.toDouble()*quantity.toUInt();
	string strfPrice = strprintf("%f", dblPrice);
	QString fprice = QString::fromStdString(strfPrice);
	string strCurrencyCode = currencyCode.toStdString();
	ui->escrowDisclaimer->setText(tr("Please note escrow is not available since you are paying in BTC, only SYS payments can be escrowed. "));
	ui->bitcoinInstructionLabel->setText(tr("After paying for this item, please enter the Bitcoin Transaction ID and click on the confirm button below. You may use the QR Code to the left to scan the payment request into your wallet or click on the Open BTC Wallet if you are on the desktop and have Bitcoin Core installed."));
	ui->acceptMessage->setText(tr("Are you sure you want to purchase %1 of '%2' from merchant: '%3'? To complete your purchase please pay %4 BTC using your Bitcoin wallet.").arg(quantity).arg(title).arg(sellerAlias).arg(fprice));
	string strPrice = strprintf("%f", dblPrice);
	price = QString::fromStdString(strPrice);

	if (!platformStyle->getImagesOnButtons())
	{
		ui->confirmButton->setIcon(QIcon());
		ui->openBtcWalletButton->setIcon(QIcon());
		ui->cancelButton->setIcon(QIcon());

	}
	else
	{
		ui->confirmButton->setIcon(platformStyle->SingleColorIcon(":/icons/" + theme + "/transaction_confirmed"));
		ui->openBtcWalletButton->setIcon(platformStyle->SingleColorIcon(":/icons/" + theme + "/send"));
		ui->cancelButton->setIcon(platformStyle->SingleColorIcon(":/icons/" + theme + "/quit"));
	}
	this->offerPaid = false;
	connect(ui->confirmButton, SIGNAL(clicked()), this, SLOT(acceptPayment()));
	connect(ui->openBtcWalletButton, SIGNAL(clicked()), this, SLOT(openBTCWallet()));

#ifdef USE_QRCODE
	QString message = "Payment for offer ID " + this->offer + " on Syscoin Decentralized Marketplace";
	QString uri = "bitcoin:" + this->address + "?amount=" + price + "&label=" + this->sellerAlias + "&message=" + GUIUtil::HtmlEscape(message);

	ui->lblQRCode->setText("");
    if(!uri.isEmpty())
    {
        // limit URI length
        if (uri.length() > MAX_URI_LENGTH)
        {
            ui->lblQRCode->setText(tr("Resulting URI too long, try to reduce the text for label / message."));
        } else {
            QRcode *code = QRcode_encodeString(uri.toUtf8().constData(), 0, QR_ECLEVEL_L, QR_MODE_8, 1);
            if (!code)
            {
                ui->lblQRCode->setText(tr("Error encoding URI into QR Code."));
                return;
            }
            QImage myImage = QImage(code->width + 8, code->width + 8, QImage::Format_RGB32);
            myImage.fill(0xffffff);
            unsigned char *p = code->data;
            for (int y = 0; y width; y++)
            {
                for (int x = 0; x width; x++)
                {
                    myImage.setPixel(x + 4, y + 4, ((*p & 1) ? 0x0 : 0xffffff));
                    p++;
                }
            }
            QRcode_free(code);
            ui->lblQRCode->setPixmap(QPixmap::fromImage(myImage).scaled(128, 128));
        }
    }
#endif
}
void OfferAcceptDialogBTC::on_cancelButton_clicked()
{
    reject();
}
OfferAcceptDialogBTC::~OfferAcceptDialogBTC()
{
    delete ui;
}

void OfferAcceptDialogBTC::acceptPayment()
{
	acceptOffer();
}
bool OfferAcceptDialogBTC::CheckPaymentInBTC(const QString &strBTCTxId, const QString& address, const QString& price)
{
	QNetworkAccessManager *nam = new QNetworkAccessManager(this);
	QUrl url("https://blockchain.info/tx/" + strBTCTxId + "?format=json");
	QNetworkRequest request(url);
	request.setHeader(QNetworkRequest::ContentTypeHeader, "application/json");
	QNetworkReply* reply = nam->get(request);
	reply->ignoreSslErrors();
	CAmount value;
	CAmount price;
	if(!ParseMoney(price.toStdString(), price))
		return false;
	LogPrintf("price: %lld\n", price);
	int totalTime = 0;
	while(!reply->isFinished())
	{
		qApp->processEvents();
		totalTime += 100;
		MilliSleep(100);
		if(totalTime > 30000)
			throw runtime_error("Timeout connecting to blockchain.info!");
	}
	bool doubleSpend = false;
	if(reply->error() == QNetworkReply::NoError) {

		UniValue outerValue;
		bool read = outerValue.read(reply->readAll().toStdString());
		if (read)
		{
			LogPrintf("gotjson!\n");
			UniValue outerObj = outerValue.get_obj();
			UniValue doubleSpendValue = find_value(outerObj, "double_spend");
			if (doubleSpendValue.isBool())
			{
				doubleSpend = doubleSpendValue.get_bool();
				if(!doubleSpend)
					return false;
			}
			UniValue outputsValue = find_value(outerObj, "out");
			if (outputsValue.isArray())
			{
				UniValue outputs = outputsValue.get_array();
				for (unsigned int idx = 0; idx < outputs.size(); idx++) {
					const UniValue& output = outputs[idx];
					UniValue addressValue = find_value(output, "addr");
					if(addressValue.isStr())
					{
						LogPrintf("address: %s\n", address.toStdString().c_str());
						if(addressValue.get_str() == address.toStdString())
						{
							UniValue paymentValue = find_value(output, "value");
							LogPrintf("value: %lld\n", paymentValue.get_int64());
							if(paymentValue.isNum())
							{
								value += paymentValue.get_int64();
								if(value >= price)
									return true;
							}
						}

					}

				}
			}
		}
	}
	reply->deleteLater();
	return false;

}

bool OfferAcceptDialogBTC::lookup(const QString &lookupid, QString& address, QString& price)
{
	string strError;
	string strMethod = string("offerinfo");
	UniValue params(UniValue::VARR);
	UniValue result;
	params.push_back(lookupid.toStdString());

    try {
        result = tableRPC.execute(strMethod, params);

		if (result.type() == UniValue::VOBJ)
		{
			const UniValue &offerObj = result.get_obj();

			const string &strAddress = find_value(offerObj, "address").get_str();
			const string &strPrice = find_value(offerObj, "price").get_str();
			address = QString::fromStdString(strAddress);
			price = QString::fromStdString(strPrice);
			return true;
		}
	}
	catch (UniValue& objError)
	{
		QMessageBox::critical(this, windowTitle(),
			tr("Could not find this offer, please check the offer ID and that it has been confirmed by the blockchain: ") + lookupid,
				QMessageBox::Ok, QMessageBox::Ok);
		return true;

	}
	catch(std::exception& e)
	{
		QMessageBox::critical(this, windowTitle(),
			tr("There was an exception trying to locate this offer, please check the offer ID and that it has been confirmed by the blockchain: ") + QString::fromStdString(e.what()),
				QMessageBox::Ok, QMessageBox::Ok);
		return true;
	}
	return false;

}
// send offeraccept with offer guid/qty as params and then send offerpay with wtxid (first param of response) as param, using RPC commands.
void OfferAcceptDialogBTC::acceptOffer()
{
		QString address, price;
		if (ui->btctxidEdit->text().trimmed().isEmpty()) {
            ui->btctxidEdit->setText("");
            QMessageBox::information(this, windowTitle(),
            tr("Please enter a valid Bitcoin Transaction ID into the input box and try again"),
                QMessageBox::Ok, QMessageBox::Ok);
            return;
        }
		if(!lookup(this->offer, address, price))
		{
            QMessageBox::information(this, windowTitle(),
            tr("Could not find this offer, please check the offer ID and that it has been confirmed by the blockchain: ") + this->offer,
                QMessageBox::Ok, QMessageBox::Ok);
            return;
		}
		if(!CheckPaymentInBTC(ui->btctxidEdit->text().trimmed(), address, price))
		{
            QMessageBox::information(this, windowTitle(),
            tr("Could not find this payment, please check the Transaction ID and that it has been confirmed by the Bitcoin blockchain: ") + ui->btctxidEdit->text().trimmed(),
                QMessageBox::Ok, QMessageBox::Ok);
            return;
		}

		UniValue params(UniValue::VARR);
		UniValue valError;
		UniValue valResult;
		UniValue valId;
		UniValue result ;
		string strReply;
		string strError;

		string strMethod = string("offeraccept");
		if(this->quantity.toLong() <= 0)
		{
			QMessageBox::critical(this, windowTitle(),
				tr("Invalid quantity when trying to accept offer!"),
				QMessageBox::Ok, QMessageBox::Ok);
			return;
		}
		this->offerPaid = false;
		params.push_back(this->alias.toStdString());
		params.push_back(this->offer.toStdString());
		params.push_back(this->quantity.toStdString());
		params.push_back(this->notes.toStdString());
		params.push_back(ui->btctxidEdit->text().toStdString());

	    try {
            result = tableRPC.execute(strMethod, params);
			if (result.type() != UniValue::VNULL)
			{
				const UniValue &arr = result.get_array();
				string strResult = arr[0].get_str();
				QString offerAcceptTXID = QString::fromStdString(strResult);
				if(offerAcceptTXID != QString(""))
				{
					OfferPayDialog dlg(platformStyle, this->title, this->quantity, this->price, "BTC", this);
					dlg.exec();
					this->offerPaid = true;
					OfferAcceptDialogBTC::accept();
					return;

				}
			}
		}
		catch (UniValue& objError)
		{
			strError = find_value(objError, "message").get_str();
			QMessageBox::critical(this, windowTitle(),
			tr("Error accepting offer: \"%1\"").arg(QString::fromStdString(strError)),
				QMessageBox::Ok, QMessageBox::Ok);
			return;
		}
		catch(std::exception& e)
		{
			QMessageBox::critical(this, windowTitle(),
				tr("General exception when accepting offer"),
				QMessageBox::Ok, QMessageBox::Ok);
			return;
		}

}
void OfferAcceptDialogBTC::openBTCWallet()
{
	QString message = "Payment for offer ID " + this->offer + " on Syscoin Decentralized Marketplace";
	QString uri = "bitcoin:" + this->address + "?amount=" + price + "&label=" + this->sellerAlias + "&message=" + GUIUtil::HtmlEscape(message);
	QDesktopServices::openUrl(QUrl(uri, QUrl::TolerantMode));
}
bool OfferAcceptDialogBTC::getPaymentStatus()
{
	return this->offerPaid;
}
<|endoftext|>


<commit_before><commit_msg>Fix silly SoTransformerDragger bug. Basically only one instance of the dragger would work...<commit_after><|endoftext|>


<commit_before>// The MIT License (MIT)

// Copyright (c) 2012-2013 Danny Y., Rapptz

// Permission is hereby granted, free of charge, to any person obtaining a copy of
// this software and associated documentation files (the "Software"), to deal in
// the Software without restriction, including without limitation the rights to
// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
// the Software, and to permit persons to whom the Software is furnished to do so,
// subject to the following conditions:

// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.

// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

#include <catch.hpp>
#include <tuple>
#include <gears/utility/triple.hpp>

TEST_CASE("Triples", "[triple]") {
    constexpr gears::triple<int, float, char> a = {1, 2.f, '3'};
    static_assert(a.first  == 1  , "..");
    static_assert(a.second == 2.f, "..");
    static_assert(a.third  == '3', "..");
    static_assert(std::get<0>(a) == 1, "..");
    static_assert(std::get<1>(a) == 2.f, "..");
    static_assert(std::get<2>(a) == '3', "..");
    constexpr auto b = gears::make_triple(20, 3.f, 'b');
    static_assert(a != b, "..");
    static_assert(a < b, "..");
    static_assert(a <= b, "..");
    constexpr auto c = a;
    static_assert(a == c, "..");
}<commit_msg>Fix triple unit tests<commit_after>// The MIT License (MIT)

// Copyright (c) 2012-2013 Danny Y., Rapptz

// Permission is hereby granted, free of charge, to any person obtaining a copy of
// this software and associated documentation files (the "Software"), to deal in
// the Software without restriction, including without limitation the rights to
// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
// the Software, and to permit persons to whom the Software is furnished to do so,
// subject to the following conditions:

// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.

// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

#include <catch.hpp>
#include <tuple>
#include <gears/utility/triple.hpp>
#include <gears/adl/get.hpp>

namespace gu = gears::utility;

TEST_CASE("Triples", "[triple]") {
    constexpr gu::triple<int, float, char> a = {1, 2.f, '3'};
    static_assert(a.first  == 1  , "..");
    static_assert(a.second == 2.f, "..");
    static_assert(a.third  == '3', "..");
    static_assert(gears::adl::get<0>(a) == 1, "..");
    static_assert(gears::adl::get<1>(a) == 2.f, "..");
    static_assert(gears::adl::get<2>(a) == '3', "..");
    constexpr auto b = gu::make_triple(20, 3.f, 'b');
    static_assert(a != b, "..");
    static_assert(a < b, "..");
    static_assert(a <= b, "..");
    constexpr auto c = a;
    static_assert(a == c, "..");
}<|endoftext|>