<commit_before>/*
 * format_data.cc
 *
 *  Created on: Feb 8, 2015
 *      Author: liao
 */
#include <cstring>
#include <cerrno>
#include <sstream>
#include <fstream>
#include "sys/stat.h"
#include "simple_log.h"
#include "format_data.h"

const static int SPLIT_SIZE = 1;
const static int ENDL_SIZE = 1;
static uint32_t dict_hash_function_seed = 5381;

FormatLine::FormatLine(int key_size, int value_size) {
    _key_size = key_size;
    _value_size = value_size;
    status = 0;
    next_index = -1;
}

int FormatLine::deserialize(char *buffer, int size) {
    char tmp_key[_key_size];
    bzero(tmp_key, _key_size);
    char tmp_value[_value_size];
    bzero(tmp_value, _value_size);
    char tmp_status[1];
    bzero(tmp_status, 1);
    char tmp_next_index[MAX_LINE_DIGIT];
    bzero(tmp_next_index, MAX_LINE_DIGIT);

    if (sscanf(buffer, get_format().c_str(), tmp_key, tmp_value, tmp_status, tmp_next_index) != 4) {
        LOG_ERROR("deserialize FAIL which input :%s", buffer);
        return -1;
    }

    key.assign(tmp_key);
    value.assign(tmp_value);
    status = atoi(tmp_status);
    next_index = atoi(tmp_next_index);
    return 0;
}

int FormatLine::serialize(char *result, int size) {
    std::string line_format = get_format();
    char line[size + 1];
    bzero(line, size + 1);

    std::stringstream status_ss;
    status_ss << status;
    std::stringstream next_index_ss;
    next_index_ss << next_index;
    snprintf(line, size + 1, line_format.c_str(), key.c_str(), value.c_str(), status_ss.str().c_str(), next_index_ss.str().c_str());
    memcpy(result, line, size);
    return 0;
}

// key \t value \t status \t next_index \n
std::string FormatLine::get_format() {
    std::stringstream line_format;
    line_format << "%" << _key_size << "s\t%" << _value_size << "s\t%1s\t%" << MAX_LINE_DIGIT << "s\n";
    return line_format.str();
};

int FormatLine::get_line_size() {
    return _key_size + SPLIT_SIZE + _value_size + SPLIT_SIZE + sizeof(char) + SPLIT_SIZE + MAX_LINE_DIGIT + ENDL_SIZE;
}

// MurmurHash2 from redis (dict.c)
uint32_t FormatLine::get_key_hash() {
    int len = key.size();
    uint32_t seed = dict_hash_function_seed;
    const uint32_t m = 0x5bd1e995;
    const int r = 24;

    /* Initialize the hash to a 'random' value */
    uint32_t h = seed ^ len;

    /* Mix 4 bytes at a time into the hash */
    const unsigned char *data = (const unsigned char *)key.c_str();

    while(len >= 4) {
        uint32_t k = *(uint32_t*)data;

        k *= m;
        k ^= k >> r;
        k *= m;

        h *= m;
        h ^= k;

        data += 4;
        len -= 4;
    }

    /* Handle the last few bytes of the input array  */
    switch(len) {
    case 3: h ^= data[2] << 16;
    case 2: h ^= data[1] << 8;
    case 1: h ^= data[0]; h *= m;
    };

    /* Do a few final mixes of the hash to ensure the last few
     * bytes are well-incorporated. */
    h ^= h >> 13;
    h *= m;
    h ^= h >> 15;

    return (unsigned int)h;
}

bool FormatLine::is_delete() {
    return status == IS_DELETE_NODE;
}

bool FormatLine::key_equal(std::string &input) {
//    LOG_DEBUG("GET KEY which input:%s, actual:%s", input.c_str(), key.c_str());
    return input == key;
}

int FormatLine::write_to(std::fstream &fs, uint32_t line_index) {
    size_t line_size = this->get_line_size();
    char line[line_size];
    bzero(line, line_size);
    this->serialize(line, line_size);

    size_t offset = line_index * line_size;
    fs.seekp(offset);
    fs.write(line, line_size);
    if (!fs || !fs.good()) {
        LOG_ERROR("fs not valid after write which offset:%u", offset);
        return -1;
    }
    return 0;
}

FormatData::~FormatData() {
    if (fs) {
        fs.close();
    }
    if (ext_fs) {
        ext_fs.close();
    }
}

int FormatData::init(FormatDataConfig &_config) {
    config = _config;
    std::string file_path = config.dir + config.file_name;
    fs.open(file_path.c_str(), std::fstream::out | std::fstream::in);
    FormatLine fline(config.key_limit_size, config.value_limit_size);
    if (!fs) {
        LOG_INFO("FILE NOT FOUND WE WILL create it:%s", file_path.c_str());
        size_t file_size = config.hash_size * fline.get_line_size();
        std::ofstream create_fs(file_path.c_str());
        create_fs.seekp(file_size);
        create_fs.write("\n", 1);
        create_fs.close();

        fs.open(file_path.c_str(), std::fstream::out | std::fstream::in);
        if (!fs) {
            LOG_ERROR("open file error for path:%s", file_path.c_str());
            return -1;
        }

    }

    std::string ext_file_path = config.dir + config.file_name + ".ext";
    ext_fs.open(ext_file_path.c_str(), std::fstream::out | std::fstream::in);
    if (!ext_fs) {
        LOG_INFO("FILE NOT FOUND WE WILL create it:%s", ext_file_path.c_str());
        std::ofstream create_fs(ext_file_path.c_str(), std::fstream::app);
        create_fs.close();

        ext_fs.open(ext_file_path.c_str(), std::fstream::out | std::fstream::in);
        if (!ext_fs) {
            LOG_ERROR("ext_fs open fail in init! which path:%s", ext_file_path.c_str());
            return -1;
        }
    }

    this->config.key_limit_size = config.key_limit_size;
    this->config.value_limit_size = config.value_limit_size;

    struct stat tmp_stat;
    if(stat(ext_file_path.c_str(), &tmp_stat) != 0){
        LOG_WARN("Oops  stats ext file failed [path:%s][errno:%s]", ext_file_path.c_str(), strerror(errno));
        return -1;
    }
    this->ext_write_index = tmp_stat.st_size / fline.get_line_size();
    return 0;
}

int FormatData::update(std::string &key, std::string &value, bool is_delete) {
    if (key.size() > config.key_limit_size) {
        LOG_ERROR("key SIZE REACH LIMIT which size:%d, limit:%d", key.size(), config.key_limit_size);
        return -1;
    }
    if (value.size() > config.value_limit_size) {
        LOG_ERROR("value SIZE REACH LIMIT which size:%d, limit:%d", value.size(), config.value_limit_size);
        return -1;
    }

    FormatLine update_node(config.key_limit_size, config.value_limit_size);
    update_node.key = key;
    update_node.value = value;

    uint32_t hash = update_node.get_key_hash();
    uint32_t line_index = hash % config.hash_size;

    int ret = this->get_by_index(line_index, update_node);
    if (ret == GET_RET_OF_FAIL) {
        return ret;
    }

    if (ret == GET_RET_OF_NOFOUND) {
        update_node.write_to(fs, line_index);
        return 0;
    }

    if (update_node.key_equal(key)) { // update
        if (!is_delete) {
            update_node.value = value;
        } else {
            update_node.status = FormatLine::IS_DELETE_NODE;
        }
        update_node.write_to(fs, line_index);
        return 0;
    }

    int32_t current_index = -1;
    bool update_bucket = true;
    FormatLine ext_fnode(config.key_limit_size, config.value_limit_size);

    // FIND INSERT OR UPDATE POSTION
    int32_t next_index = update_node.next_index;
    while (next_index != -1) {
        int ret = get_next_ext_nodex(next_index, ext_fnode);
        if (ret != 0) {
            return ret;
        }
        if (ext_fnode.key_equal(key)) {
            if (!is_delete) {
                ext_fnode.value = value;
            } else {
                ext_fnode.status = FormatLine::IS_DELETE_NODE;
            }
            return ext_fnode.write_to(ext_fs, next_index);
        }
        update_bucket = false;
        current_index = next_index;
        next_index = ext_fnode.next_index;
    }

    // write for data file
    // 1. insert new node
    FormatLine new_ext_fnode(config.key_limit_size, config.value_limit_size);
    new_ext_fnode.key = key;
    new_ext_fnode.value = value;
    new_ext_fnode.write_to(ext_fs, ext_write_index);

    // 2. update preposition node
    if (update_bucket) { // 2.1 update hash bucket node
        update_node.next_index = ext_write_index;
        update_node.write_to(fs, line_index);
    } else {             // 2.2 update hash data node
        ext_fnode.next_index = ext_write_index;
        ext_fnode.write_to(ext_fs, current_index);
    }
    ext_write_index++;

    return 0;
}

int FormatData::get_next_ext_nodex(int32_t next_index, FormatLine &ext_fnode) {
    int line_size = ext_fnode.get_line_size();
    size_t ext_offset = next_index * line_size;
    char ext_node[line_size];
    bzero(ext_node, line_size);
    ext_fs.seekg(ext_offset);
    ext_fs.read(ext_node, line_size);
    if (!ext_fs) {
        LOG_ERROR("EXT FS not valid after read! which next_index:%d", next_index);
        return -1;
    }
    return ext_fnode.deserialize(ext_node, line_size);
}

int FormatData::get(std::string &key, std::string &value) {
    FormatLine format_line(config.key_limit_size, config.value_limit_size);
    format_line.key = key;
    int line_size = format_line.get_line_size();
    uint32_t hash = format_line.get_key_hash();
    uint32_t line_index = hash % config.hash_size;

    LOG_DEBUG("GET FOR KEY:%s, hash:%u, line_index:%u", key.c_str(), hash, line_index);
    int ret = this->get_by_index(line_index, format_line);
    if (ret != 0) {
        return ret;
    }

    if (format_line.key_equal(key)) {
        value = format_line.value;
        return 0;
    }
    int32_t next_index = format_line.next_index;
    FormatLine ext_fnode(config.key_limit_size, config.value_limit_size);
    while(next_index != -1) {
        int ret = get_next_ext_nodex(next_index, ext_fnode);
        if (ret != 0) {
            return ret;
        }
        if (ext_fnode.key_equal(key)) {
            value = ext_fnode.value;
            return 0;
        }
        next_index = ext_fnode.next_index;

    }

    return GET_RET_OF_NOFOUND;
}

int FormatData::get_by_index(uint32_t &line_index, FormatLine &fline) {
    size_t line_size = fline.get_line_size();
    size_t offset = line_index * line_size;
    if (!fs) {
        LOG_ERROR("FS not valid!");
        return -1;
    }
    fs.seekg(offset, fs.beg);
    if (fs.eof()) {
        LOG_DEBUG("FS REACH EOF ON OFFSET:%u", offset);
        return GET_RET_OF_NOFOUND;
    }
    if (!fs || !fs.good()) {
        LOG_ERROR("FS not valid! after seekg offset:%u", offset);
        return -1;
    }
    char line[line_size];
    bzero(line, line_size);
    fs.read(line, line_size);
    if (!fs) {
        LOG_ERROR("FS not valid! after read offset:%u, line_size:%u", offset, line_size);
        return -1;
    }
    fs.seekg(0, fs.end);
    char empty_key[fline._key_size];
    bzero(empty_key, fline._key_size);
    if (memcmp(line, empty_key, fline._key_size) == 0) {
        return GET_RET_OF_NOFOUND;
    }

    LOG_DEBUG("READ LINE : %s FOR LINE INDE:%u, offset:%u", line, line_index, offset);

    int ret = fline.deserialize(line, line_size);
    if (ret != 0) {
        LOG_ERROR("FLINE deserialize fail for line:%s", line);
        return ret;
    }

    if (fline.is_delete()) {
        LOG_DEBUG("fline is delete");
        return GET_RET_OF_DELETED;
    }

    return 0;
}
<commit_msg>code factor<commit_after>/*
 * format_data.cc
 *
 *  Created on: Feb 8, 2015
 *      Author: liao
 */
#include <cstring>
#include <cerrno>
#include <sstream>
#include <fstream>
#include "sys/stat.h"
#include "simple_log.h"
#include "format_data.h"

const static int SPLIT_SIZE = 1;
const static int ENDL_SIZE = 1;
static uint32_t dict_hash_function_seed = 5381;

FormatLine::FormatLine(int key_size, int value_size) {
    _key_size = key_size;
    _value_size = value_size;
    status = 0;
    next_index = -1;
}

int FormatLine::deserialize(char *buffer, int size) {
    char tmp_key[_key_size];
    bzero(tmp_key, _key_size);
    char tmp_value[_value_size];
    bzero(tmp_value, _value_size);
    char tmp_status[1];
    bzero(tmp_status, 1);
    char tmp_next_index[MAX_LINE_DIGIT];
    bzero(tmp_next_index, MAX_LINE_DIGIT);

    if (sscanf(buffer, get_format().c_str(), tmp_key, tmp_value, tmp_status, tmp_next_index) != 4) {
        LOG_ERROR("deserialize FAIL which input :%s", buffer);
        return -1;
    }

    key.assign(tmp_key);
    value.assign(tmp_value);
    status = atoi(tmp_status);
    next_index = atoi(tmp_next_index);
    return 0;
}

int FormatLine::serialize(char *result, int size) {
    std::string line_format = get_format();
    char line[size + 1];
    bzero(line, size + 1);

    std::stringstream status_ss;
    status_ss << status;
    std::stringstream next_index_ss;
    next_index_ss << next_index;
    snprintf(line, size + 1, line_format.c_str(), key.c_str(), value.c_str(), status_ss.str().c_str(), next_index_ss.str().c_str());
    memcpy(result, line, size);
    return 0;
}

// key \t value \t status \t next_index \n
std::string FormatLine::get_format() {
    std::stringstream line_format;
    line_format << "%" << _key_size << "s\t%" << _value_size << "s\t%1s\t%" << MAX_LINE_DIGIT << "s\n";
    return line_format.str();
};

int FormatLine::get_line_size() {
    return _key_size + SPLIT_SIZE + _value_size + SPLIT_SIZE + sizeof(char) + SPLIT_SIZE + MAX_LINE_DIGIT + ENDL_SIZE;
}

// MurmurHash2 from redis (dict.c)
uint32_t FormatLine::get_key_hash() {
    int len = key.size();
    uint32_t seed = dict_hash_function_seed;
    const uint32_t m = 0x5bd1e995;
    const int r = 24;

    /* Initialize the hash to a 'random' value */
    uint32_t h = seed ^ len;

    /* Mix 4 bytes at a time into the hash */
    const unsigned char *data = (const unsigned char *)key.c_str();

    while(len >= 4) {
        uint32_t k = *(uint32_t*)data;

        k *= m;
        k ^= k >> r;
        k *= m;

        h *= m;
        h ^= k;

        data += 4;
        len -= 4;
    }

    /* Handle the last few bytes of the input array  */
    switch(len) {
    case 3: h ^= data[2] << 16;
    case 2: h ^= data[1] << 8;
    case 1: h ^= data[0]; h *= m;
    };

    /* Do a few final mixes of the hash to ensure the last few
     * bytes are well-incorporated. */
    h ^= h >> 13;
    h *= m;
    h ^= h >> 15;

    return (unsigned int)h;
}

bool FormatLine::is_delete() {
    return status == IS_DELETE_NODE;
}

bool FormatLine::key_equal(std::string &input) {
//    LOG_DEBUG("GET KEY which input:%s, actual:%s", input.c_str(), key.c_str());
    return input == key;
}

int FormatLine::write_to(std::fstream &fs, uint32_t line_index) {
    size_t line_size = this->get_line_size();
    char line[line_size];
    bzero(line, line_size);
    this->serialize(line, line_size);

    size_t offset = line_index * line_size;
    fs.seekp(offset);
    fs.write(line, line_size);
    if (!fs || !fs.good()) {
        LOG_ERROR("fs not valid after write which offset:%u", offset);
        return -1;
    }
    return 0;
}

FormatData::~FormatData() {
    if (fs) {
        fs.close();
    }
    if (ext_fs) {
        ext_fs.close();
    }
}

int FormatData::init(FormatDataConfig &_config) {
    config = _config;
    std::string file_path = config.dir + config.file_name;
    fs.open(file_path.c_str(), std::fstream::out | std::fstream::in);
    FormatLine fline(config.key_limit_size, config.value_limit_size);
    if (!fs) {
        LOG_INFO("FILE NOT FOUND WE WILL create it:%s", file_path.c_str());
        size_t file_size = config.hash_size * fline.get_line_size();
        std::ofstream create_fs(file_path.c_str());
        create_fs.seekp(file_size);
        create_fs.write("\n", 1);
        create_fs.close();

        fs.open(file_path.c_str(), std::fstream::out | std::fstream::in);
        if (!fs) {
            LOG_ERROR("open file error for path:%s", file_path.c_str());
            return -1;
        }

    }

    std::string ext_file_path = config.dir + config.file_name + ".ext";
    ext_fs.open(ext_file_path.c_str(), std::fstream::out | std::fstream::in);
    if (!ext_fs) {
        LOG_INFO("FILE NOT FOUND WE WILL create it:%s", ext_file_path.c_str());
        std::ofstream create_fs(ext_file_path.c_str(), std::fstream::app);
        create_fs.close();

        ext_fs.open(ext_file_path.c_str(), std::fstream::out | std::fstream::in);
        if (!ext_fs) {
            LOG_ERROR("ext_fs open fail in init! which path:%s", ext_file_path.c_str());
            return -1;
        }
    }

    this->config.key_limit_size = config.key_limit_size;
    this->config.value_limit_size = config.value_limit_size;

    struct stat tmp_stat;
    if(stat(ext_file_path.c_str(), &tmp_stat) != 0){
        LOG_WARN("Oops  stats ext file failed [path:%s][errno:%s]", ext_file_path.c_str(), strerror(errno));
        return -1;
    }
    this->ext_write_index = tmp_stat.st_size / fline.get_line_size();
    return 0;
}

int FormatData::update(std::string &key, std::string &value, bool is_delete) {
    if (key.size() > config.key_limit_size) {
        LOG_ERROR("key SIZE REACH LIMIT which size:%d, limit:%d", key.size(), config.key_limit_size);
        return -1;
    }
    if (value.size() > config.value_limit_size) {
        LOG_ERROR("value SIZE REACH LIMIT which size:%d, limit:%d", value.size(), config.value_limit_size);
        return -1;
    }

    FormatLine bucket_node(config.key_limit_size, config.value_limit_size);
    bucket_node.key = key;
    bucket_node.value = value;

    uint32_t hash = bucket_node.get_key_hash();
    uint32_t line_index = hash % config.hash_size;

    int ret = this->get_by_index(line_index, bucket_node);
    if (ret == GET_RET_OF_FAIL) {
        return ret;
    }

    if (ret == GET_RET_OF_NOFOUND) {
        return bucket_node.write_to(fs, line_index);
    }

    if (bucket_node.key_equal(key)) { // update
        if (!is_delete) {
            bucket_node.value = value;
        } else {
            bucket_node.status = FormatLine::IS_DELETE_NODE;
        }
        return bucket_node.write_to(fs, line_index);
    }

    int32_t current_index = -1;
    bool update_bucket = true;
    FormatLine ext_fnode(config.key_limit_size, config.value_limit_size);

    // FIND INSERT OR UPDATE POSTION
    int32_t next_index = bucket_node.next_index;
    while (next_index != -1) {
        int ret = get_next_ext_nodex(next_index, ext_fnode);
        if (ret != 0) {
            return ret;
        }
        if (ext_fnode.key_equal(key)) {
            if (!is_delete) {
                ext_fnode.value = value;
            } else {
                ext_fnode.status = FormatLine::IS_DELETE_NODE;
            }
            return ext_fnode.write_to(ext_fs, next_index);
        }
        update_bucket = false;
        current_index = next_index;
        next_index = ext_fnode.next_index;
    }

    // write for data file
    // 1. insert new node
    FormatLine new_ext_fnode(config.key_limit_size, config.value_limit_size);
    new_ext_fnode.key = key;
    new_ext_fnode.value = value;
    ret = new_ext_fnode.write_to(ext_fs, ext_write_index);
    if (ret != 0) {
        return ret;
    }

    // 2. update preposition node
    if (update_bucket) { // 2.1 update hash bucket node
        bucket_node.next_index = ext_write_index;
        ret = bucket_node.write_to(fs, line_index);
    } else {             // 2.2 update hash data node
        ext_fnode.next_index = ext_write_index;
        ret = ext_fnode.write_to(ext_fs, current_index);
    }
    ext_write_index++;

    return ret;
}

int FormatData::get_next_ext_nodex(int32_t next_index, FormatLine &ext_fnode) {
    int line_size = ext_fnode.get_line_size();
    size_t ext_offset = next_index * line_size;
    char ext_node[line_size];
    bzero(ext_node, line_size);
    ext_fs.seekg(ext_offset);
    ext_fs.read(ext_node, line_size);
    if (!ext_fs) {
        LOG_ERROR("EXT FS not valid after read! which next_index:%d", next_index);
        return -1;
    }
    return ext_fnode.deserialize(ext_node, line_size);
}

int FormatData::get(std::string &key, std::string &value) {
    FormatLine format_line(config.key_limit_size, config.value_limit_size);
    format_line.key = key;
    int line_size = format_line.get_line_size();
    uint32_t hash = format_line.get_key_hash();
    uint32_t line_index = hash % config.hash_size;

    LOG_DEBUG("GET FOR KEY:%s, hash:%u, line_index:%u", key.c_str(), hash, line_index);
    int ret = this->get_by_index(line_index, format_line);
    if (ret != 0) {
        return ret;
    }

    if (format_line.key_equal(key)) {
        value = format_line.value;
        return 0;
    }
    int32_t next_index = format_line.next_index;
    FormatLine ext_fnode(config.key_limit_size, config.value_limit_size);
    while(next_index != -1) {
        int ret = get_next_ext_nodex(next_index, ext_fnode);
        if (ret != 0) {
            return ret;
        }
        if (ext_fnode.key_equal(key)) {
            value = ext_fnode.value;
            return 0;
        }
        next_index = ext_fnode.next_index;

    }

    return GET_RET_OF_NOFOUND;
}

int FormatData::get_by_index(uint32_t &line_index, FormatLine &fline) {
    size_t line_size = fline.get_line_size();
    size_t offset = line_index * line_size;
    if (!fs) {
        LOG_ERROR("FS not valid!");
        return -1;
    }
    fs.seekg(offset, fs.beg);
    if (fs.eof()) {
        LOG_DEBUG("FS REACH EOF ON OFFSET:%u", offset);
        return GET_RET_OF_NOFOUND;
    }
    if (!fs || !fs.good()) {
        LOG_ERROR("FS not valid! after seekg offset:%u", offset);
        return -1;
    }
    char line[line_size];
    bzero(line, line_size);
    fs.read(line, line_size);
    if (!fs) {
        LOG_ERROR("FS not valid! after read offset:%u, line_size:%u", offset, line_size);
        return -1;
    }
    fs.seekg(0, fs.end);
    char empty_key[fline._key_size];
    bzero(empty_key, fline._key_size);
    if (memcmp(line, empty_key, fline._key_size) == 0) {
        return GET_RET_OF_NOFOUND;
    }

    LOG_DEBUG("READ LINE : %s FOR LINE INDE:%u, offset:%u", line, line_index, offset);

    int ret = fline.deserialize(line, line_size);
    if (ret != 0) {
        LOG_ERROR("FLINE deserialize fail for line:%s", line);
        return ret;
    }

    if (fline.is_delete()) {
        LOG_DEBUG("fline is delete");
        return GET_RET_OF_DELETED;
    }

    return 0;
}
<|endoftext|>


<commit_before>// Copyright (c) 2011-2015 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#include <qt/walletview.h>

#include <qt/addressbookpage.h>
#include <qt/askpassphrasedialog.h>
#include <qt/bitcoingui.h>
#include <qt/clientmodel.h>
#include <qt/guiutil.h>
#include <qt/optionsmodel.h>
#include <qt/overviewpage.h>
#include <qt/receivecoinsdialog.h>
#include <qt/sendcoinsdialog.h>
#include <qt/signverifymessagedialog.h>
#include <qt/transactionrecord.h>
#include <qt/transactiontablemodel.h>
#include <qt/transactionview.h>
#include <qt/walletmodel.h>

#include <interfaces/node.h>
#include <ui_interface.h>

#include <QAction>
#include <QActionGroup>
#include <QFileDialog>
#include <QHBoxLayout>
#include <QLabel>
#include <QProgressDialog>
#include <QPushButton>
#include <QSettings>
#include <QVBoxLayout>

WalletView::WalletView(QWidget* parent) :
    QStackedWidget(parent),
    clientModel(nullptr),
    walletModel(nullptr)
{
    // Create tabs
    overviewPage = new OverviewPage();

    transactionsPage = new QWidget(this);
    QVBoxLayout *vbox = new QVBoxLayout();
    QHBoxLayout *hbox_buttons = new QHBoxLayout();
    transactionView = new TransactionView(this);
    vbox->addWidget(transactionView);
    QPushButton *exportButton = new QPushButton(tr("&Export"), this);
    exportButton->setToolTip(tr("Export the data in the current tab to a file"));
    hbox_buttons->addStretch();

    // Sum of selected transactions
    QLabel *transactionSumLabel = new QLabel(); // Label
    transactionSumLabel->setObjectName("transactionSumLabel"); // Label ID as CSS-reference
    transactionSumLabel->setText(tr("Selected amount:"));
    hbox_buttons->addWidget(transactionSumLabel);

    transactionSum = new QLabel(); // Amount
    transactionSum->setObjectName("transactionSum"); // Label ID as CSS-reference
    transactionSum->setMinimumSize(200, 8);
    transactionSum->setTextInteractionFlags(Qt::TextSelectableByMouse);

    GUIUtil::setFont({transactionSumLabel,
                      transactionSum,
                     }, GUIUtil::FontWeight::Bold, 14);
    GUIUtil::updateFonts();

    hbox_buttons->addWidget(transactionSum);

    hbox_buttons->addWidget(exportButton);
    vbox->addLayout(hbox_buttons);
    transactionsPage->setLayout(vbox);

    receiveCoinsPage = new ReceiveCoinsDialog();
    sendCoinsPage = new SendCoinsDialog();
    coinJoinCoinsPage = new SendCoinsDialog(true);

    usedSendingAddressesPage = new AddressBookPage(AddressBookPage::ForEditing, AddressBookPage::SendingTab, this);
    usedReceivingAddressesPage = new AddressBookPage(AddressBookPage::ForEditing, AddressBookPage::ReceivingTab, this);

    addWidget(overviewPage);
    addWidget(transactionsPage);
    addWidget(receiveCoinsPage);
    addWidget(sendCoinsPage);
    addWidget(coinJoinCoinsPage);

    QSettings settings;
    if (settings.value("fShowMasternodesTab").toBool()) {
        masternodeListPage = new MasternodeList();
        addWidget(masternodeListPage);
    }
    if (settings.value("fShowGovernanceTab").toBool()) {
        governanceListPage = new GovernanceList();
        addWidget(governanceListPage);
    }

    // Clicking on a transaction on the overview pre-selects the transaction on the transaction history page
    connect(overviewPage, &OverviewPage::transactionClicked, transactionView, static_cast<void (TransactionView::*)(const QModelIndex&)>(&TransactionView::focusTransaction));
    connect(overviewPage, &OverviewPage::outOfSyncWarningClicked, this, &WalletView::requestedSyncWarningInfo);

    // Highlight transaction after send
    connect(sendCoinsPage, &SendCoinsDialog::coinsSent, transactionView, static_cast<void (TransactionView::*)(const uint256&)>(&TransactionView::focusTransaction));
    connect(coinJoinCoinsPage, &SendCoinsDialog::coinsSent, transactionView, static_cast<void (TransactionView::*)(const uint256&)>(&TransactionView::focusTransaction));

    // Update wallet with sum of selected transactions
    connect(transactionView, &TransactionView::trxAmount, this, &WalletView::trxAmount);

    // Clicking on "Export" allows to export the transaction list
    connect(exportButton, &QPushButton::clicked, transactionView, &TransactionView::exportClicked);

    // Pass through messages from SendCoinsDialog
    connect(sendCoinsPage, &SendCoinsDialog::message, this, &WalletView::message);
    connect(coinJoinCoinsPage, &SendCoinsDialog::message, this, &WalletView::message);

    // Pass through messages from transactionView
    connect(transactionView, &TransactionView::message, this, &WalletView::message);

    GUIUtil::disableMacFocusRect(this);
}

WalletView::~WalletView()
{
}

void WalletView::setBitcoinGUI(BitcoinGUI *gui)
{
    if (gui)
    {
        // Clicking on a transaction on the overview page simply sends you to transaction history page
        connect(overviewPage, &OverviewPage::transactionClicked, gui, &BitcoinGUI::gotoHistoryPage);

        // Navigate to transaction history page after send
        connect(sendCoinsPage, &SendCoinsDialog::coinsSent, gui, &BitcoinGUI::gotoHistoryPage);
        connect(coinJoinCoinsPage, &SendCoinsDialog::coinsSent, gui, &BitcoinGUI::gotoHistoryPage);

        // Receive and report messages
        connect(this, &WalletView::message, [gui](const QString &title, const QString &message, unsigned int style) {
            gui->message(title, message, style);
        });

        // Pass through encryption status changed signals
        connect(this, &WalletView::encryptionStatusChanged, gui, &BitcoinGUI::updateWalletStatus);

        // Pass through transaction notifications
        connect(this, &WalletView::incomingTransaction, gui, &BitcoinGUI::incomingTransaction);

        // Connect HD enabled state signal
        connect(this, &WalletView::hdEnabledStatusChanged, gui, &BitcoinGUI::updateWalletStatus);
    }
}

void WalletView::setClientModel(ClientModel *_clientModel)
{
    this->clientModel = _clientModel;

    overviewPage->setClientModel(_clientModel);
    sendCoinsPage->setClientModel(_clientModel);
    coinJoinCoinsPage->setClientModel(_clientModel);
    QSettings settings;
    if (settings.value("fShowMasternodesTab").toBool()) {
        masternodeListPage->setClientModel(_clientModel);
    }
    if (settings.value("fShowGovernanceTab").toBool()) {
        governanceListPage->setClientModel(_clientModel);
    }
}

void WalletView::setWalletModel(WalletModel *_walletModel)
{
    this->walletModel = _walletModel;

    // Put transaction list in tabs
    transactionView->setModel(_walletModel);
    overviewPage->setWalletModel(_walletModel);
    QSettings settings;
    if (settings.value("fShowMasternodesTab").toBool()) {
        masternodeListPage->setWalletModel(_walletModel);
    }
    receiveCoinsPage->setModel(_walletModel);
    sendCoinsPage->setModel(_walletModel);
    coinJoinCoinsPage->setModel(_walletModel);
    usedReceivingAddressesPage->setModel(_walletModel ? _walletModel->getAddressTableModel() : nullptr);
    usedSendingAddressesPage->setModel(_walletModel ? _walletModel->getAddressTableModel() : nullptr);

    if (_walletModel)
    {
        // Receive and pass through messages from wallet model
        connect(_walletModel, &WalletModel::message, this, &WalletView::message);

        // Handle changes in encryption status
        connect(_walletModel, &WalletModel::encryptionStatusChanged, this, &WalletView::encryptionStatusChanged);
        updateEncryptionStatus();

        // update HD status
        Q_EMIT hdEnabledStatusChanged();

        // Balloon pop-up for new transaction
        connect(_walletModel->getTransactionTableModel(), &TransactionTableModel::rowsInserted, this, &WalletView::processNewTransaction);

        // Ask for passphrase if needed
        connect(_walletModel, &WalletModel::requireUnlock, this, &WalletView::unlockWallet);

        // Show progress dialog
        connect(_walletModel, &WalletModel::showProgress, this, &WalletView::showProgress);
    }
}

void WalletView::processNewTransaction(const QModelIndex& parent, int start, int /*end*/)
{
    // Prevent balloon-spam when initial block download is in progress
    if (!walletModel || !clientModel || clientModel->node().isInitialBlockDownload())
        return;

    TransactionTableModel *ttm = walletModel->getTransactionTableModel();
    if (!ttm || ttm->processingQueuedTransactions())
        return;

    QModelIndex index = ttm->index(start, 0, parent);
    QSettings settings;
    if (!settings.value("fShowCoinJoinPopups").toBool()) {
        QVariant nType = ttm->data(index, TransactionTableModel::TypeRole);
        if (nType == TransactionRecord::CoinJoinMixing ||
            nType == TransactionRecord::CoinJoinCollateralPayment ||
            nType == TransactionRecord::CoinJoinMakeCollaterals ||
            nType == TransactionRecord::CoinJoinCreateDenominations) return;
    }

    QString date = ttm->index(start, TransactionTableModel::Date, parent).data().toString();
    qint64 amount = ttm->index(start, TransactionTableModel::Amount, parent).data(Qt::EditRole).toULongLong();
    QString type = ttm->index(start, TransactionTableModel::Type, parent).data().toString();
    QString address = ttm->data(index, TransactionTableModel::AddressRole).toString();
    QString label = GUIUtil::HtmlEscape(ttm->data(index, TransactionTableModel::LabelRole).toString());

    Q_EMIT incomingTransaction(date, walletModel->getOptionsModel()->getDisplayUnit(), amount, type, address, label, GUIUtil::HtmlEscape(walletModel->getWalletName()));
}

void WalletView::gotoGovernancePage()
{
    QSettings settings;
    if (settings.value("fShowGovernanceTab").toBool()) {
        setCurrentWidget(governanceListPage);
    }
}

void WalletView::gotoOverviewPage()
{
    setCurrentWidget(overviewPage);
}

void WalletView::gotoHistoryPage()
{
    setCurrentWidget(transactionsPage);
}

void WalletView::gotoMasternodePage()
{
    QSettings settings;
    if (settings.value("fShowMasternodesTab").toBool()) {
        setCurrentWidget(masternodeListPage);
    }
}

void WalletView::gotoReceiveCoinsPage()
{
    setCurrentWidget(receiveCoinsPage);
}

void WalletView::gotoSendCoinsPage(QString addr)
{
    setCurrentWidget(sendCoinsPage);

    if (!addr.isEmpty()) {
        sendCoinsPage->setAddress(addr);
    }
}

void WalletView::gotoCoinJoinCoinsPage(QString addr)
{
    setCurrentWidget(coinJoinCoinsPage);

    if (!addr.isEmpty())
        coinJoinCoinsPage->setAddress(addr);
}

void WalletView::gotoSignMessageTab(QString addr)
{
    // calls show() in showTab_SM()
    SignVerifyMessageDialog* signVerifyMessageDialog = new SignVerifyMessageDialog(this);
    signVerifyMessageDialog->setAttribute(Qt::WA_DeleteOnClose);
    signVerifyMessageDialog->setModel(walletModel);
    signVerifyMessageDialog->showTab_SM(true);

    if (!addr.isEmpty())
        signVerifyMessageDialog->setAddress_SM(addr);
}

void WalletView::gotoVerifyMessageTab(QString addr)
{
    // calls show() in showTab_VM()
    SignVerifyMessageDialog* signVerifyMessageDialog = new SignVerifyMessageDialog(this);
    signVerifyMessageDialog->setAttribute(Qt::WA_DeleteOnClose);
    signVerifyMessageDialog->setModel(walletModel);
    signVerifyMessageDialog->showTab_VM(true);

    if (!addr.isEmpty())
        signVerifyMessageDialog->setAddress_VM(addr);
}

bool WalletView::handlePaymentRequest(const SendCoinsRecipient& recipient)
{
    return sendCoinsPage->handlePaymentRequest(recipient);
}

void WalletView::showOutOfSyncWarning(bool fShow)
{
    overviewPage->showOutOfSyncWarning(fShow);
}

void WalletView::updateEncryptionStatus()
{
    Q_EMIT encryptionStatusChanged();
}

void WalletView::encryptWallet()
{
    if(!walletModel)
        return;
    AskPassphraseDialog dlg(AskPassphraseDialog::Encrypt, this);
    dlg.setModel(walletModel);
    dlg.exec();

    updateEncryptionStatus();
}

void WalletView::backupWallet()
{
    QString filename = GUIUtil::getSaveFileName(this,
        tr("Backup Wallet"), QString(),
        tr("Wallet Data (*.dat)"), nullptr);

    if (filename.isEmpty())
        return;

    if (!walletModel->wallet().backupWallet(filename.toLocal8Bit().data())) {
        Q_EMIT message(tr("Backup Failed"), tr("There was an error trying to save the wallet data to %1.").arg(filename),
            CClientUIInterface::MSG_ERROR);
        }
    else {
        Q_EMIT message(tr("Backup Successful"), tr("The wallet data was successfully saved to %1.").arg(filename),
            CClientUIInterface::MSG_INFORMATION);
    }
}

void WalletView::changePassphrase()
{
    AskPassphraseDialog dlg(AskPassphraseDialog::ChangePass, this);
    dlg.setModel(walletModel);
    dlg.exec();
}

void WalletView::unlockWallet(bool fForMixingOnly)
{
    if(!walletModel)
        return;
    // Unlock wallet when requested by wallet model

    if (walletModel->getEncryptionStatus() == WalletModel::Locked || walletModel->getEncryptionStatus() == WalletModel::UnlockedForMixingOnly)
    {
        AskPassphraseDialog dlg(fForMixingOnly ? AskPassphraseDialog::UnlockMixing : AskPassphraseDialog::Unlock, this);
        dlg.setModel(walletModel);
        dlg.exec();
    }
}

void WalletView::lockWallet()
{
    if(!walletModel)
        return;

    walletModel->setWalletLocked(true);
}

void WalletView::usedSendingAddresses()
{
    if(!walletModel)
        return;

    GUIUtil::bringToFront(usedSendingAddressesPage);
}

void WalletView::usedReceivingAddresses()
{
    if(!walletModel)
        return;

    GUIUtil::bringToFront(usedReceivingAddressesPage);
}

void WalletView::showProgress(const QString &title, int nProgress)
{
    if (nProgress == 0) {
        progressDialog = new QProgressDialog(title, tr("Cancel"), 0, 100, this);
        GUIUtil::PolishProgressDialog(progressDialog);
        progressDialog->setWindowModality(Qt::ApplicationModal);
        progressDialog->setMinimumDuration(0);
        progressDialog->setAutoClose(false);
        progressDialog->setValue(0);
    } else if (nProgress == 100) {
        if (progressDialog) {
            progressDialog->close();
            progressDialog->deleteLater();
            progressDialog = nullptr;
        }
    } else if (progressDialog) {
        if (progressDialog->wasCanceled()) {
            getWalletModel()->wallet().abortRescan();
        } else {
            progressDialog->setValue(nProgress);
        }
    }
}

void WalletView::requestedSyncWarningInfo()
{
    Q_EMIT outOfSyncWarningClicked();
}

/** Update wallet with the sum of the selected transactions */
void WalletView::trxAmount(QString amount)
{
    transactionSum->setText(amount);
}
<commit_msg>fix(qt): fix crash when first enabling governance tab due to null-ptr deref (#4795)<commit_after>// Copyright (c) 2011-2015 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#include <qt/walletview.h>

#include <qt/addressbookpage.h>
#include <qt/askpassphrasedialog.h>
#include <qt/bitcoingui.h>
#include <qt/clientmodel.h>
#include <qt/guiutil.h>
#include <qt/optionsmodel.h>
#include <qt/overviewpage.h>
#include <qt/receivecoinsdialog.h>
#include <qt/sendcoinsdialog.h>
#include <qt/signverifymessagedialog.h>
#include <qt/transactionrecord.h>
#include <qt/transactiontablemodel.h>
#include <qt/transactionview.h>
#include <qt/walletmodel.h>

#include <interfaces/node.h>
#include <ui_interface.h>

#include <QAction>
#include <QActionGroup>
#include <QFileDialog>
#include <QHBoxLayout>
#include <QLabel>
#include <QProgressDialog>
#include <QPushButton>
#include <QSettings>
#include <QVBoxLayout>

WalletView::WalletView(QWidget* parent) :
    QStackedWidget(parent),
    clientModel(nullptr),
    walletModel(nullptr)
{
    // Create tabs
    overviewPage = new OverviewPage();

    transactionsPage = new QWidget(this);
    QVBoxLayout *vbox = new QVBoxLayout();
    QHBoxLayout *hbox_buttons = new QHBoxLayout();
    transactionView = new TransactionView(this);
    vbox->addWidget(transactionView);
    QPushButton *exportButton = new QPushButton(tr("&Export"), this);
    exportButton->setToolTip(tr("Export the data in the current tab to a file"));
    hbox_buttons->addStretch();

    // Sum of selected transactions
    QLabel *transactionSumLabel = new QLabel(); // Label
    transactionSumLabel->setObjectName("transactionSumLabel"); // Label ID as CSS-reference
    transactionSumLabel->setText(tr("Selected amount:"));
    hbox_buttons->addWidget(transactionSumLabel);

    transactionSum = new QLabel(); // Amount
    transactionSum->setObjectName("transactionSum"); // Label ID as CSS-reference
    transactionSum->setMinimumSize(200, 8);
    transactionSum->setTextInteractionFlags(Qt::TextSelectableByMouse);

    GUIUtil::setFont({transactionSumLabel,
                      transactionSum,
                     }, GUIUtil::FontWeight::Bold, 14);
    GUIUtil::updateFonts();

    hbox_buttons->addWidget(transactionSum);

    hbox_buttons->addWidget(exportButton);
    vbox->addLayout(hbox_buttons);
    transactionsPage->setLayout(vbox);

    receiveCoinsPage = new ReceiveCoinsDialog();
    sendCoinsPage = new SendCoinsDialog();
    coinJoinCoinsPage = new SendCoinsDialog(true);

    usedSendingAddressesPage = new AddressBookPage(AddressBookPage::ForEditing, AddressBookPage::SendingTab, this);
    usedReceivingAddressesPage = new AddressBookPage(AddressBookPage::ForEditing, AddressBookPage::ReceivingTab, this);

    addWidget(overviewPage);
    addWidget(transactionsPage);
    addWidget(receiveCoinsPage);
    addWidget(sendCoinsPage);
    addWidget(coinJoinCoinsPage);

    QSettings settings;
    if (settings.value("fShowMasternodesTab").toBool()) {
        masternodeListPage = new MasternodeList();
        addWidget(masternodeListPage);
    }
    if (settings.value("fShowGovernanceTab").toBool()) {
        governanceListPage = new GovernanceList();
        addWidget(governanceListPage);
    }

    // Clicking on a transaction on the overview pre-selects the transaction on the transaction history page
    connect(overviewPage, &OverviewPage::transactionClicked, transactionView, static_cast<void (TransactionView::*)(const QModelIndex&)>(&TransactionView::focusTransaction));
    connect(overviewPage, &OverviewPage::outOfSyncWarningClicked, this, &WalletView::requestedSyncWarningInfo);

    // Highlight transaction after send
    connect(sendCoinsPage, &SendCoinsDialog::coinsSent, transactionView, static_cast<void (TransactionView::*)(const uint256&)>(&TransactionView::focusTransaction));
    connect(coinJoinCoinsPage, &SendCoinsDialog::coinsSent, transactionView, static_cast<void (TransactionView::*)(const uint256&)>(&TransactionView::focusTransaction));

    // Update wallet with sum of selected transactions
    connect(transactionView, &TransactionView::trxAmount, this, &WalletView::trxAmount);

    // Clicking on "Export" allows to export the transaction list
    connect(exportButton, &QPushButton::clicked, transactionView, &TransactionView::exportClicked);

    // Pass through messages from SendCoinsDialog
    connect(sendCoinsPage, &SendCoinsDialog::message, this, &WalletView::message);
    connect(coinJoinCoinsPage, &SendCoinsDialog::message, this, &WalletView::message);

    // Pass through messages from transactionView
    connect(transactionView, &TransactionView::message, this, &WalletView::message);

    GUIUtil::disableMacFocusRect(this);
}

WalletView::~WalletView()
{
}

void WalletView::setBitcoinGUI(BitcoinGUI *gui)
{
    if (gui)
    {
        // Clicking on a transaction on the overview page simply sends you to transaction history page
        connect(overviewPage, &OverviewPage::transactionClicked, gui, &BitcoinGUI::gotoHistoryPage);

        // Navigate to transaction history page after send
        connect(sendCoinsPage, &SendCoinsDialog::coinsSent, gui, &BitcoinGUI::gotoHistoryPage);
        connect(coinJoinCoinsPage, &SendCoinsDialog::coinsSent, gui, &BitcoinGUI::gotoHistoryPage);

        // Receive and report messages
        connect(this, &WalletView::message, [gui](const QString &title, const QString &message, unsigned int style) {
            gui->message(title, message, style);
        });

        // Pass through encryption status changed signals
        connect(this, &WalletView::encryptionStatusChanged, gui, &BitcoinGUI::updateWalletStatus);

        // Pass through transaction notifications
        connect(this, &WalletView::incomingTransaction, gui, &BitcoinGUI::incomingTransaction);

        // Connect HD enabled state signal
        connect(this, &WalletView::hdEnabledStatusChanged, gui, &BitcoinGUI::updateWalletStatus);
    }
}

void WalletView::setClientModel(ClientModel *_clientModel)
{
    this->clientModel = _clientModel;

    if (overviewPage != nullptr) {
        overviewPage->setClientModel(_clientModel);
    }
    if (sendCoinsPage != nullptr) {
        sendCoinsPage->setClientModel(_clientModel);
    }
    if (coinJoinCoinsPage != nullptr) {
        coinJoinCoinsPage->setClientModel(_clientModel);
    }
    QSettings settings;
    if (settings.value("fShowMasternodesTab").toBool() && masternodeListPage != nullptr) {
        masternodeListPage->setClientModel(_clientModel);
    }
    if (settings.value("fShowGovernanceTab").toBool() && governanceListPage != nullptr) {
        governanceListPage->setClientModel(_clientModel);
    }
}

void WalletView::setWalletModel(WalletModel *_walletModel)
{
    this->walletModel = _walletModel;

    // Put transaction list in tabs
    transactionView->setModel(_walletModel);
    overviewPage->setWalletModel(_walletModel);
    QSettings settings;
    if (settings.value("fShowMasternodesTab").toBool()) {
        masternodeListPage->setWalletModel(_walletModel);
    }
    receiveCoinsPage->setModel(_walletModel);
    sendCoinsPage->setModel(_walletModel);
    coinJoinCoinsPage->setModel(_walletModel);
    usedReceivingAddressesPage->setModel(_walletModel ? _walletModel->getAddressTableModel() : nullptr);
    usedSendingAddressesPage->setModel(_walletModel ? _walletModel->getAddressTableModel() : nullptr);

    if (_walletModel)
    {
        // Receive and pass through messages from wallet model
        connect(_walletModel, &WalletModel::message, this, &WalletView::message);

        // Handle changes in encryption status
        connect(_walletModel, &WalletModel::encryptionStatusChanged, this, &WalletView::encryptionStatusChanged);
        updateEncryptionStatus();

        // update HD status
        Q_EMIT hdEnabledStatusChanged();

        // Balloon pop-up for new transaction
        connect(_walletModel->getTransactionTableModel(), &TransactionTableModel::rowsInserted, this, &WalletView::processNewTransaction);

        // Ask for passphrase if needed
        connect(_walletModel, &WalletModel::requireUnlock, this, &WalletView::unlockWallet);

        // Show progress dialog
        connect(_walletModel, &WalletModel::showProgress, this, &WalletView::showProgress);
    }
}

void WalletView::processNewTransaction(const QModelIndex& parent, int start, int /*end*/)
{
    // Prevent balloon-spam when initial block download is in progress
    if (!walletModel || !clientModel || clientModel->node().isInitialBlockDownload())
        return;

    TransactionTableModel *ttm = walletModel->getTransactionTableModel();
    if (!ttm || ttm->processingQueuedTransactions())
        return;

    QModelIndex index = ttm->index(start, 0, parent);
    QSettings settings;
    if (!settings.value("fShowCoinJoinPopups").toBool()) {
        QVariant nType = ttm->data(index, TransactionTableModel::TypeRole);
        if (nType == TransactionRecord::CoinJoinMixing ||
            nType == TransactionRecord::CoinJoinCollateralPayment ||
            nType == TransactionRecord::CoinJoinMakeCollaterals ||
            nType == TransactionRecord::CoinJoinCreateDenominations) return;
    }

    QString date = ttm->index(start, TransactionTableModel::Date, parent).data().toString();
    qint64 amount = ttm->index(start, TransactionTableModel::Amount, parent).data(Qt::EditRole).toULongLong();
    QString type = ttm->index(start, TransactionTableModel::Type, parent).data().toString();
    QString address = ttm->data(index, TransactionTableModel::AddressRole).toString();
    QString label = GUIUtil::HtmlEscape(ttm->data(index, TransactionTableModel::LabelRole).toString());

    Q_EMIT incomingTransaction(date, walletModel->getOptionsModel()->getDisplayUnit(), amount, type, address, label, GUIUtil::HtmlEscape(walletModel->getWalletName()));
}

void WalletView::gotoGovernancePage()
{
    QSettings settings;
    if (settings.value("fShowGovernanceTab").toBool()) {
        setCurrentWidget(governanceListPage);
    }
}

void WalletView::gotoOverviewPage()
{
    setCurrentWidget(overviewPage);
}

void WalletView::gotoHistoryPage()
{
    setCurrentWidget(transactionsPage);
}

void WalletView::gotoMasternodePage()
{
    QSettings settings;
    if (settings.value("fShowMasternodesTab").toBool()) {
        setCurrentWidget(masternodeListPage);
    }
}

void WalletView::gotoReceiveCoinsPage()
{
    setCurrentWidget(receiveCoinsPage);
}

void WalletView::gotoSendCoinsPage(QString addr)
{
    setCurrentWidget(sendCoinsPage);

    if (!addr.isEmpty()) {
        sendCoinsPage->setAddress(addr);
    }
}

void WalletView::gotoCoinJoinCoinsPage(QString addr)
{
    setCurrentWidget(coinJoinCoinsPage);

    if (!addr.isEmpty())
        coinJoinCoinsPage->setAddress(addr);
}

void WalletView::gotoSignMessageTab(QString addr)
{
    // calls show() in showTab_SM()
    SignVerifyMessageDialog* signVerifyMessageDialog = new SignVerifyMessageDialog(this);
    signVerifyMessageDialog->setAttribute(Qt::WA_DeleteOnClose);
    signVerifyMessageDialog->setModel(walletModel);
    signVerifyMessageDialog->showTab_SM(true);

    if (!addr.isEmpty())
        signVerifyMessageDialog->setAddress_SM(addr);
}

void WalletView::gotoVerifyMessageTab(QString addr)
{
    // calls show() in showTab_VM()
    SignVerifyMessageDialog* signVerifyMessageDialog = new SignVerifyMessageDialog(this);
    signVerifyMessageDialog->setAttribute(Qt::WA_DeleteOnClose);
    signVerifyMessageDialog->setModel(walletModel);
    signVerifyMessageDialog->showTab_VM(true);

    if (!addr.isEmpty())
        signVerifyMessageDialog->setAddress_VM(addr);
}

bool WalletView::handlePaymentRequest(const SendCoinsRecipient& recipient)
{
    return sendCoinsPage->handlePaymentRequest(recipient);
}

void WalletView::showOutOfSyncWarning(bool fShow)
{
    overviewPage->showOutOfSyncWarning(fShow);
}

void WalletView::updateEncryptionStatus()
{
    Q_EMIT encryptionStatusChanged();
}

void WalletView::encryptWallet()
{
    if(!walletModel)
        return;
    AskPassphraseDialog dlg(AskPassphraseDialog::Encrypt, this);
    dlg.setModel(walletModel);
    dlg.exec();

    updateEncryptionStatus();
}

void WalletView::backupWallet()
{
    QString filename = GUIUtil::getSaveFileName(this,
        tr("Backup Wallet"), QString(),
        tr("Wallet Data (*.dat)"), nullptr);

    if (filename.isEmpty())
        return;

    if (!walletModel->wallet().backupWallet(filename.toLocal8Bit().data())) {
        Q_EMIT message(tr("Backup Failed"), tr("There was an error trying to save the wallet data to %1.").arg(filename),
            CClientUIInterface::MSG_ERROR);
        }
    else {
        Q_EMIT message(tr("Backup Successful"), tr("The wallet data was successfully saved to %1.").arg(filename),
            CClientUIInterface::MSG_INFORMATION);
    }
}

void WalletView::changePassphrase()
{
    AskPassphraseDialog dlg(AskPassphraseDialog::ChangePass, this);
    dlg.setModel(walletModel);
    dlg.exec();
}

void WalletView::unlockWallet(bool fForMixingOnly)
{
    if(!walletModel)
        return;
    // Unlock wallet when requested by wallet model

    if (walletModel->getEncryptionStatus() == WalletModel::Locked || walletModel->getEncryptionStatus() == WalletModel::UnlockedForMixingOnly)
    {
        AskPassphraseDialog dlg(fForMixingOnly ? AskPassphraseDialog::UnlockMixing : AskPassphraseDialog::Unlock, this);
        dlg.setModel(walletModel);
        dlg.exec();
    }
}

void WalletView::lockWallet()
{
    if(!walletModel)
        return;

    walletModel->setWalletLocked(true);
}

void WalletView::usedSendingAddresses()
{
    if(!walletModel)
        return;

    GUIUtil::bringToFront(usedSendingAddressesPage);
}

void WalletView::usedReceivingAddresses()
{
    if(!walletModel)
        return;

    GUIUtil::bringToFront(usedReceivingAddressesPage);
}

void WalletView::showProgress(const QString &title, int nProgress)
{
    if (nProgress == 0) {
        progressDialog = new QProgressDialog(title, tr("Cancel"), 0, 100, this);
        GUIUtil::PolishProgressDialog(progressDialog);
        progressDialog->setWindowModality(Qt::ApplicationModal);
        progressDialog->setMinimumDuration(0);
        progressDialog->setAutoClose(false);
        progressDialog->setValue(0);
    } else if (nProgress == 100) {
        if (progressDialog) {
            progressDialog->close();
            progressDialog->deleteLater();
            progressDialog = nullptr;
        }
    } else if (progressDialog) {
        if (progressDialog->wasCanceled()) {
            getWalletModel()->wallet().abortRescan();
        } else {
            progressDialog->setValue(nProgress);
        }
    }
}

void WalletView::requestedSyncWarningInfo()
{
    Q_EMIT outOfSyncWarningClicked();
}

/** Update wallet with the sum of the selected transactions */
void WalletView::trxAmount(QString amount)
{
    transactionSum->setText(amount);
}
<|endoftext|>


<commit_before>/*
 * Qt4 bitcoin GUI.
 *
 * W.J. van der Laan 2011-2012
 * The Bitcoin Developers 2011-2013
 */
#include "walletview.h"
#include "bitcoingui.h"
#include "transactiontablemodel.h"
#include "addressbookpage.h"
#include "sendcoinsdialog.h"
#include "receivecoinsdialog.h"
#include "signverifymessagedialog.h"
#include "clientmodel.h"
#include "walletmodel.h"
#include "optionsmodel.h"
#include "transactionview.h"
#include "overviewpage.h"
#include "askpassphrasedialog.h"
#include "ui_interface.h"

#include <QHBoxLayout>
#include <QVBoxLayout>
#include <QAction>
#if QT_VERSION < 0x050000
#include <QDesktopServices>
#else
#include <QStandardPaths>
#endif
#include <QFileDialog>
#include <QPushButton>

WalletView::WalletView(QWidget *parent):
    QStackedWidget(parent),
    clientModel(0),
    walletModel(0)
{
    // Create tabs
    overviewPage = new OverviewPage();

    transactionsPage = new QWidget(this);
    QVBoxLayout *vbox = new QVBoxLayout();
    QHBoxLayout *hbox_buttons = new QHBoxLayout();
    transactionView = new TransactionView(this);
    vbox->addWidget(transactionView);
    QPushButton *exportButton = new QPushButton(tr("&Export"), this);
    exportButton->setToolTip(tr("Export the data in the current tab to a file"));
#ifndef Q_OS_MAC // Icons on push buttons are very uncommon on Mac
    exportButton->setIcon(QIcon(":/icons/export"));
#endif
    hbox_buttons->addStretch();
    hbox_buttons->addWidget(exportButton);
    vbox->addLayout(hbox_buttons);
    transactionsPage->setLayout(vbox);

    receiveCoinsPage = new ReceiveCoinsDialog();
    sendCoinsPage = new SendCoinsDialog();

    addWidget(overviewPage);
    addWidget(transactionsPage);
    addWidget(receiveCoinsPage);
    addWidget(sendCoinsPage);

    // Clicking on a transaction on the overview page simply sends you to transaction history page
    connect(overviewPage, SIGNAL(transactionClicked(QModelIndex)), transactionView, SLOT(focusTransaction(QModelIndex)));

    // Double-clicking on a transaction on the transaction history page shows details
    connect(transactionView, SIGNAL(doubleClicked(QModelIndex)), transactionView, SLOT(showDetails()));

    // Clicking on "Export" allows to export the transaction list
    connect(exportButton, SIGNAL(clicked()), transactionView, SLOT(exportClicked()));

    // Pass through messages from sendCoinsPage
    connect(sendCoinsPage, SIGNAL(message(QString,QString,unsigned int)), this, SIGNAL(message(QString,QString,unsigned int)));
}

WalletView::~WalletView()
{
}

void WalletView::setBitcoinGUI(BitcoinGUI *gui)
{
    if (gui)
    {
        // Clicking on a transaction on the overview page sends you to the transactions tab
        connect(overviewPage, SIGNAL(transactionClicked(QModelIndex)), gui, SLOT(gotoHistoryPage()));

        // Receive and report messages
        connect(this, SIGNAL(message(QString,QString,unsigned int)), gui, SLOT(message(QString,QString,unsigned int)));

        // Pass through encryption status changed signals
        connect(this, SIGNAL(encryptionStatusChanged(int)), gui, SLOT(setEncryptionStatus(int)));

        // Pass through transaction notifications
        connect(this, SIGNAL(incomingTransaction(QString,int,qint64,QString,QString)), gui, SLOT(incomingTransaction(QString,int,qint64,QString,QString)));
    }
}

void WalletView::setClientModel(ClientModel *clientModel)
{
    this->clientModel = clientModel;

    overviewPage->setClientModel(clientModel);
}

void WalletView::setWalletModel(WalletModel *walletModel)
{
    this->walletModel = walletModel;

    // Put transaction list in tabs
    transactionView->setModel(walletModel);
    overviewPage->setWalletModel(walletModel);
    receiveCoinsPage->setModel(walletModel);
    sendCoinsPage->setModel(walletModel);

    if (walletModel)
    {
        // Receive and report messages from wallet thread
        connect(walletModel, SIGNAL(message(QString,QString,unsigned int)), this, SIGNAL(message(QString,QString,unsigned int)));

        // Handle changes in encryption status
        connect(walletModel, SIGNAL(encryptionStatusChanged(int)), this, SIGNAL(encryptionStatusChanged(int)));
        updateEncryptionStatus();

        // Balloon pop-up for new transaction
        connect(walletModel->getTransactionTableModel(), SIGNAL(rowsInserted(QModelIndex,int,int)),
                this, SLOT(processNewTransaction(QModelIndex,int,int)));

        // Ask for passphrase if needed
        connect(walletModel, SIGNAL(requireUnlock()), this, SLOT(unlockWallet()));
    }
}

void WalletView::processNewTransaction(const QModelIndex& parent, int start, int /*end*/)
{
    // Prevent balloon-spam when initial block download is in progress
    if (!walletModel || !clientModel || clientModel->inInitialBlockDownload())
        return;

    TransactionTableModel *ttm = walletModel->getTransactionTableModel();

    QString date = ttm->index(start, TransactionTableModel::Date, parent).data().toString();
    qint64 amount = ttm->index(start, TransactionTableModel::Amount, parent).data(Qt::EditRole).toULongLong();
    QString type = ttm->index(start, TransactionTableModel::Type, parent).data().toString();
    QString address = ttm->index(start, TransactionTableModel::ToAddress, parent).data().toString();

    emit incomingTransaction(date, walletModel->getOptionsModel()->getDisplayUnit(), amount, type, address);
}

void WalletView::gotoOverviewPage()
{
    setCurrentWidget(overviewPage);
}

void WalletView::gotoHistoryPage()
{
    setCurrentWidget(transactionsPage);
}

void WalletView::gotoReceiveCoinsPage()
{
    setCurrentWidget(receiveCoinsPage);
}

void WalletView::gotoSendCoinsPage(QString addr)
{
    setCurrentWidget(sendCoinsPage);

    if (!addr.isEmpty())
        sendCoinsPage->setAddress(addr);
}

void WalletView::gotoSignMessageTab(QString addr)
{
    // calls show() in showTab_SM()
    SignVerifyMessageDialog *signVerifyMessageDialog = new SignVerifyMessageDialog(this);
    signVerifyMessageDialog->setAttribute(Qt::WA_DeleteOnClose);
    signVerifyMessageDialog->setModel(walletModel);
    signVerifyMessageDialog->showTab_SM(true);

    if (!addr.isEmpty())
        signVerifyMessageDialog->setAddress_SM(addr);
}

void WalletView::gotoVerifyMessageTab(QString addr)
{
    // calls show() in showTab_VM()
    SignVerifyMessageDialog *signVerifyMessageDialog = new SignVerifyMessageDialog(this);
    signVerifyMessageDialog->setAttribute(Qt::WA_DeleteOnClose);
    signVerifyMessageDialog->setModel(walletModel);
    signVerifyMessageDialog->showTab_VM(true);

    if (!addr.isEmpty())
        signVerifyMessageDialog->setAddress_VM(addr);
}

bool WalletView::handlePaymentRequest(const SendCoinsRecipient& recipient)
{
    return sendCoinsPage->handlePaymentRequest(recipient);
}

void WalletView::showOutOfSyncWarning(bool fShow)
{
    overviewPage->showOutOfSyncWarning(fShow);
}

void WalletView::updateEncryptionStatus()
{
    emit encryptionStatusChanged(walletModel->getEncryptionStatus());
}

void WalletView::encryptWallet(bool status)
{
    if(!walletModel)
        return;
    AskPassphraseDialog dlg(status ? AskPassphraseDialog::Encrypt : AskPassphraseDialog::Decrypt, this);
    dlg.setModel(walletModel);
    dlg.exec();

    updateEncryptionStatus();
}

void WalletView::backupWallet()
{
#if QT_VERSION < 0x050000
    QString saveDir = QDesktopServices::storageLocation(QDesktopServices::DocumentsLocation);
#else
    QString saveDir = QStandardPaths::writableLocation(QStandardPaths::DocumentsLocation);
#endif
    QString filename = QFileDialog::getSaveFileName(this, tr("Backup Wallet"), saveDir, tr("Wallet Data (*.dat)"));
    if (!filename.isEmpty()) {
        if (!walletModel->backupWallet(filename)) {
            emit message(tr("Backup Failed"), tr("There was an error trying to save the wallet data to the new location."),
                CClientUIInterface::MSG_ERROR);
        }
        else
            emit message(tr("Backup Successful"), tr("The wallet data was successfully saved to the new location."),
                CClientUIInterface::MSG_INFORMATION);
    }
}

void WalletView::changePassphrase()
{
    AskPassphraseDialog dlg(AskPassphraseDialog::ChangePass, this);
    dlg.setModel(walletModel);
    dlg.exec();
}

void WalletView::unlockWallet()
{
    if(!walletModel)
        return;
    // Unlock wallet when requested by wallet model
    if (walletModel->getEncryptionStatus() == WalletModel::Locked)
    {
        AskPassphraseDialog dlg(AskPassphraseDialog::Unlock, this);
        dlg.setModel(walletModel);
        dlg.exec();
    }
}

void WalletView::usedSendingAddresses()
{
    if(!walletModel)
        return;
    AddressBookPage *dlg = new AddressBookPage(AddressBookPage::ForEditing, AddressBookPage::SendingTab, this);
    dlg->setModel(walletModel->getAddressTableModel());
    dlg->setAttribute(Qt::WA_DeleteOnClose);
    dlg->show();
}

void WalletView::usedReceivingAddresses()
{
    if(!walletModel)
        return;
    AddressBookPage *dlg = new AddressBookPage(AddressBookPage::ForEditing, AddressBookPage::ReceivingTab, this);
    dlg->setModel(walletModel->getAddressTableModel());
    dlg->setAttribute(Qt::WA_DeleteOnClose);
    dlg->show();
}
<commit_msg>walletview: make backupWallet() use GUIUtil::getSaveFileName()<commit_after>/*
 * Qt4 bitcoin GUI.
 *
 * W.J. van der Laan 2011-2012
 * The Bitcoin Developers 2011-2013
 */
#include "walletview.h"
#include "bitcoingui.h"
#include "transactiontablemodel.h"
#include "addressbookpage.h"
#include "sendcoinsdialog.h"
#include "receivecoinsdialog.h"
#include "signverifymessagedialog.h"
#include "clientmodel.h"
#include "walletmodel.h"
#include "optionsmodel.h"
#include "transactionview.h"
#include "overviewpage.h"
#include "askpassphrasedialog.h"
#include "ui_interface.h"
#include "guiutil.h"

#include <QHBoxLayout>
#include <QVBoxLayout>
#include <QAction>
#include <QPushButton>

WalletView::WalletView(QWidget *parent):
    QStackedWidget(parent),
    clientModel(0),
    walletModel(0)
{
    // Create tabs
    overviewPage = new OverviewPage();

    transactionsPage = new QWidget(this);
    QVBoxLayout *vbox = new QVBoxLayout();
    QHBoxLayout *hbox_buttons = new QHBoxLayout();
    transactionView = new TransactionView(this);
    vbox->addWidget(transactionView);
    QPushButton *exportButton = new QPushButton(tr("&Export"), this);
    exportButton->setToolTip(tr("Export the data in the current tab to a file"));
#ifndef Q_OS_MAC // Icons on push buttons are very uncommon on Mac
    exportButton->setIcon(QIcon(":/icons/export"));
#endif
    hbox_buttons->addStretch();
    hbox_buttons->addWidget(exportButton);
    vbox->addLayout(hbox_buttons);
    transactionsPage->setLayout(vbox);

    receiveCoinsPage = new ReceiveCoinsDialog();
    sendCoinsPage = new SendCoinsDialog();

    addWidget(overviewPage);
    addWidget(transactionsPage);
    addWidget(receiveCoinsPage);
    addWidget(sendCoinsPage);

    // Clicking on a transaction on the overview page simply sends you to transaction history page
    connect(overviewPage, SIGNAL(transactionClicked(QModelIndex)), transactionView, SLOT(focusTransaction(QModelIndex)));

    // Double-clicking on a transaction on the transaction history page shows details
    connect(transactionView, SIGNAL(doubleClicked(QModelIndex)), transactionView, SLOT(showDetails()));

    // Clicking on "Export" allows to export the transaction list
    connect(exportButton, SIGNAL(clicked()), transactionView, SLOT(exportClicked()));

    // Pass through messages from sendCoinsPage
    connect(sendCoinsPage, SIGNAL(message(QString,QString,unsigned int)), this, SIGNAL(message(QString,QString,unsigned int)));
}

WalletView::~WalletView()
{
}

void WalletView::setBitcoinGUI(BitcoinGUI *gui)
{
    if (gui)
    {
        // Clicking on a transaction on the overview page sends you to the transactions tab
        connect(overviewPage, SIGNAL(transactionClicked(QModelIndex)), gui, SLOT(gotoHistoryPage()));

        // Receive and report messages
        connect(this, SIGNAL(message(QString,QString,unsigned int)), gui, SLOT(message(QString,QString,unsigned int)));

        // Pass through encryption status changed signals
        connect(this, SIGNAL(encryptionStatusChanged(int)), gui, SLOT(setEncryptionStatus(int)));

        // Pass through transaction notifications
        connect(this, SIGNAL(incomingTransaction(QString,int,qint64,QString,QString)), gui, SLOT(incomingTransaction(QString,int,qint64,QString,QString)));
    }
}

void WalletView::setClientModel(ClientModel *clientModel)
{
    this->clientModel = clientModel;

    overviewPage->setClientModel(clientModel);
}

void WalletView::setWalletModel(WalletModel *walletModel)
{
    this->walletModel = walletModel;

    // Put transaction list in tabs
    transactionView->setModel(walletModel);
    overviewPage->setWalletModel(walletModel);
    receiveCoinsPage->setModel(walletModel);
    sendCoinsPage->setModel(walletModel);

    if (walletModel)
    {
        // Receive and report messages from wallet thread
        connect(walletModel, SIGNAL(message(QString,QString,unsigned int)), this, SIGNAL(message(QString,QString,unsigned int)));

        // Handle changes in encryption status
        connect(walletModel, SIGNAL(encryptionStatusChanged(int)), this, SIGNAL(encryptionStatusChanged(int)));
        updateEncryptionStatus();

        // Balloon pop-up for new transaction
        connect(walletModel->getTransactionTableModel(), SIGNAL(rowsInserted(QModelIndex,int,int)),
                this, SLOT(processNewTransaction(QModelIndex,int,int)));

        // Ask for passphrase if needed
        connect(walletModel, SIGNAL(requireUnlock()), this, SLOT(unlockWallet()));
    }
}

void WalletView::processNewTransaction(const QModelIndex& parent, int start, int /*end*/)
{
    // Prevent balloon-spam when initial block download is in progress
    if (!walletModel || !clientModel || clientModel->inInitialBlockDownload())
        return;

    TransactionTableModel *ttm = walletModel->getTransactionTableModel();

    QString date = ttm->index(start, TransactionTableModel::Date, parent).data().toString();
    qint64 amount = ttm->index(start, TransactionTableModel::Amount, parent).data(Qt::EditRole).toULongLong();
    QString type = ttm->index(start, TransactionTableModel::Type, parent).data().toString();
    QString address = ttm->index(start, TransactionTableModel::ToAddress, parent).data().toString();

    emit incomingTransaction(date, walletModel->getOptionsModel()->getDisplayUnit(), amount, type, address);
}

void WalletView::gotoOverviewPage()
{
    setCurrentWidget(overviewPage);
}

void WalletView::gotoHistoryPage()
{
    setCurrentWidget(transactionsPage);
}

void WalletView::gotoReceiveCoinsPage()
{
    setCurrentWidget(receiveCoinsPage);
}

void WalletView::gotoSendCoinsPage(QString addr)
{
    setCurrentWidget(sendCoinsPage);

    if (!addr.isEmpty())
        sendCoinsPage->setAddress(addr);
}

void WalletView::gotoSignMessageTab(QString addr)
{
    // calls show() in showTab_SM()
    SignVerifyMessageDialog *signVerifyMessageDialog = new SignVerifyMessageDialog(this);
    signVerifyMessageDialog->setAttribute(Qt::WA_DeleteOnClose);
    signVerifyMessageDialog->setModel(walletModel);
    signVerifyMessageDialog->showTab_SM(true);

    if (!addr.isEmpty())
        signVerifyMessageDialog->setAddress_SM(addr);
}

void WalletView::gotoVerifyMessageTab(QString addr)
{
    // calls show() in showTab_VM()
    SignVerifyMessageDialog *signVerifyMessageDialog = new SignVerifyMessageDialog(this);
    signVerifyMessageDialog->setAttribute(Qt::WA_DeleteOnClose);
    signVerifyMessageDialog->setModel(walletModel);
    signVerifyMessageDialog->showTab_VM(true);

    if (!addr.isEmpty())
        signVerifyMessageDialog->setAddress_VM(addr);
}

bool WalletView::handlePaymentRequest(const SendCoinsRecipient& recipient)
{
    return sendCoinsPage->handlePaymentRequest(recipient);
}

void WalletView::showOutOfSyncWarning(bool fShow)
{
    overviewPage->showOutOfSyncWarning(fShow);
}

void WalletView::updateEncryptionStatus()
{
    emit encryptionStatusChanged(walletModel->getEncryptionStatus());
}

void WalletView::encryptWallet(bool status)
{
    if(!walletModel)
        return;
    AskPassphraseDialog dlg(status ? AskPassphraseDialog::Encrypt : AskPassphraseDialog::Decrypt, this);
    dlg.setModel(walletModel);
    dlg.exec();

    updateEncryptionStatus();
}

void WalletView::backupWallet()
{
    QString filename = GUIUtil::getSaveFileName(this,
        tr("Backup Wallet"), QString(),
        tr("Wallet Data (*.dat)"));

    if (filename.isEmpty())
        return;

    if (!walletModel->backupWallet(filename)) {
        emit message(tr("Backup Failed"), tr("There was an error trying to save the wallet data to %1.").arg(filename),
            CClientUIInterface::MSG_ERROR);
        }
    else {
        emit message(tr("Backup Successful"), tr("The wallet data was successfully saved to %1.").arg(filename),
            CClientUIInterface::MSG_INFORMATION);
    }
}

void WalletView::changePassphrase()
{
    AskPassphraseDialog dlg(AskPassphraseDialog::ChangePass, this);
    dlg.setModel(walletModel);
    dlg.exec();
}

void WalletView::unlockWallet()
{
    if(!walletModel)
        return;
    // Unlock wallet when requested by wallet model
    if (walletModel->getEncryptionStatus() == WalletModel::Locked)
    {
        AskPassphraseDialog dlg(AskPassphraseDialog::Unlock, this);
        dlg.setModel(walletModel);
        dlg.exec();
    }
}

void WalletView::usedSendingAddresses()
{
    if(!walletModel)
        return;
    AddressBookPage *dlg = new AddressBookPage(AddressBookPage::ForEditing, AddressBookPage::SendingTab, this);
    dlg->setModel(walletModel->getAddressTableModel());
    dlg->setAttribute(Qt::WA_DeleteOnClose);
    dlg->show();
}

void WalletView::usedReceivingAddresses()
{
    if(!walletModel)
        return;
    AddressBookPage *dlg = new AddressBookPage(AddressBookPage::ForEditing, AddressBookPage::ReceivingTab, this);
    dlg->setModel(walletModel->getAddressTableModel());
    dlg->setAttribute(Qt::WA_DeleteOnClose);
    dlg->show();
}
<|endoftext|>


<commit_before>// Copyright (c) the JPEG XL Project Authors. All rights reserved.
//
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

#include <stdio.h>

#include "jxl/encode.h"
#include "lib/jxl/base/file_io.h"
#include "lib/jxl/base/profiler.h"
#include "lib/jxl/jpeg/enc_jpeg_data.h"
#include "tools/box/box.h"
#include "tools/cjxl.h"
#include "tools/codec_config.h"

namespace jpegxl {
namespace tools {

int CompressJpegXlMain(int argc, const char* argv[]) {
  CommandLineParser cmdline;
  CompressArgs args;
  args.AddCommandLineOptions(&cmdline);

  if (!cmdline.Parse(argc, argv)) {
    // Parse already printed the actual error cause.
    fprintf(stderr, "Use '%s -h' for more information\n", argv[0]);
    return 1;
  }

  if (args.version) {
    fprintf(stdout, "cjxl %s\n",
            CodecConfigString(JxlEncoderVersion()).c_str());
    fprintf(stdout, "Copyright (c) the JPEG XL Project\n");
    return 0;
  }

  if (!args.quiet) {
    fprintf(stderr, "JPEG XL encoder %s\n",
            CodecConfigString(JxlEncoderVersion()).c_str());
  }

  if (cmdline.HelpFlagPassed()) {
    cmdline.PrintHelp();
    return 0;
  }

  if (!args.ValidateArgs(cmdline)) {
    // ValidateArgs already printed the actual error cause.
    fprintf(stderr, "Use '%s -h' for more information\n", argv[0]);
    return 1;
  }

  jxl::PaddedBytes compressed;

  jxl::ThreadPoolInternal pool(args.num_threads);
  jxl::CodecInOut io;
  double decode_mps = 0;
  JXL_RETURN_IF_ERROR(LoadAll(args, &pool, &io, &decode_mps));

  // need to validate again because now we know the input
  if (!args.ValidateArgsAfterLoad(cmdline, io)) {
    fprintf(stderr, "Use '%s -h' for more information\n", argv[0]);
    return 1;
  }
  if (!args.file_out && !args.quiet) {
    fprintf(stderr,
            "No output file specified.\n"
            "Encoding will be performed, but the result will be discarded.\n");
  }
  if (!CompressJxl(io, decode_mps, &pool, args, &compressed, !args.quiet)) {
    return 1;
  }

  if (args.use_container) {
    JpegXlContainer container;
    container.codestream = compressed.data();
    container.codestream_size = compressed.size();
    if (!io.blobs.exif.empty()) {
      container.exif = io.blobs.exif.data();
      container.exif_size = io.blobs.exif.size();
    }
    auto append_xml = [&container](const jxl::PaddedBytes& bytes) {
      if (bytes.empty()) return;
      container.xml.emplace_back(bytes.data(), bytes.size());
    };
    append_xml(io.blobs.xmp);
    if (!io.blobs.jumbf.empty()) {
      container.jumb = io.blobs.jumbf.data();
      container.jumb_size = io.blobs.jumbf.size();
    }
    jxl::PaddedBytes jpeg_data;
    if (io.Main().IsJPEG()) {
      jxl::jpeg::JPEGData data_in = *io.Main().jpeg_data;
      JXL_RETURN_IF_ERROR(EncodeJPEGData(data_in, &jpeg_data));
      container.jpeg_reconstruction = jpeg_data.data();
      container.jpeg_reconstruction_size = jpeg_data.size();
    }
    jxl::PaddedBytes container_file;
    if (!EncodeJpegXlContainerOneShot(container, &container_file)) {
      fprintf(stderr, "Failed to encode container format\n");
      return 1;
    }
    compressed.swap(container_file);
  }
  if (args.file_out) {
    if (!jxl::WriteFile(compressed, args.file_out)) {
      fprintf(stderr, "Failed to write to \"%s\"\n", args.file_out);
      return 1;
    }
  }

  if (args.print_profile == jxl::Override::kOn) {
    PROFILER_PRINT_RESULTS();
  }
  if (!args.quiet && cmdline.verbosity > 0) {
    jxl::CacheAligned::PrintStats();
  }
  return 0;
}

}  // namespace tools
}  // namespace jpegxl

int main(int argc, const char** argv) {
  return jpegxl::tools::CompressJpegXlMain(argc, argv);
}
<commit_msg>when using container, also show total size<commit_after>// Copyright (c) the JPEG XL Project Authors. All rights reserved.
//
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

#include <stdio.h>

#include "jxl/encode.h"
#include "lib/jxl/base/file_io.h"
#include "lib/jxl/base/profiler.h"
#include "lib/jxl/jpeg/enc_jpeg_data.h"
#include "tools/box/box.h"
#include "tools/cjxl.h"
#include "tools/codec_config.h"

namespace jpegxl {
namespace tools {

int CompressJpegXlMain(int argc, const char* argv[]) {
  CommandLineParser cmdline;
  CompressArgs args;
  args.AddCommandLineOptions(&cmdline);

  if (!cmdline.Parse(argc, argv)) {
    // Parse already printed the actual error cause.
    fprintf(stderr, "Use '%s -h' for more information\n", argv[0]);
    return 1;
  }

  if (args.version) {
    fprintf(stdout, "cjxl %s\n",
            CodecConfigString(JxlEncoderVersion()).c_str());
    fprintf(stdout, "Copyright (c) the JPEG XL Project\n");
    return 0;
  }

  if (!args.quiet) {
    fprintf(stderr, "JPEG XL encoder %s\n",
            CodecConfigString(JxlEncoderVersion()).c_str());
  }

  if (cmdline.HelpFlagPassed()) {
    cmdline.PrintHelp();
    return 0;
  }

  if (!args.ValidateArgs(cmdline)) {
    // ValidateArgs already printed the actual error cause.
    fprintf(stderr, "Use '%s -h' for more information\n", argv[0]);
    return 1;
  }

  jxl::PaddedBytes compressed;

  jxl::ThreadPoolInternal pool(args.num_threads);
  jxl::CodecInOut io;
  double decode_mps = 0;
  JXL_RETURN_IF_ERROR(LoadAll(args, &pool, &io, &decode_mps));

  // need to validate again because now we know the input
  if (!args.ValidateArgsAfterLoad(cmdline, io)) {
    fprintf(stderr, "Use '%s -h' for more information\n", argv[0]);
    return 1;
  }
  if (!args.file_out && !args.quiet) {
    fprintf(stderr,
            "No output file specified.\n"
            "Encoding will be performed, but the result will be discarded.\n");
  }
  if (!CompressJxl(io, decode_mps, &pool, args, &compressed, !args.quiet)) {
    return 1;
  }

  if (args.use_container) {
    JpegXlContainer container;
    container.codestream = compressed.data();
    container.codestream_size = compressed.size();
    if (!io.blobs.exif.empty()) {
      container.exif = io.blobs.exif.data();
      container.exif_size = io.blobs.exif.size();
    }
    auto append_xml = [&container](const jxl::PaddedBytes& bytes) {
      if (bytes.empty()) return;
      container.xml.emplace_back(bytes.data(), bytes.size());
    };
    append_xml(io.blobs.xmp);
    if (!io.blobs.jumbf.empty()) {
      container.jumb = io.blobs.jumbf.data();
      container.jumb_size = io.blobs.jumbf.size();
    }
    jxl::PaddedBytes jpeg_data;
    if (io.Main().IsJPEG()) {
      jxl::jpeg::JPEGData data_in = *io.Main().jpeg_data;
      JXL_RETURN_IF_ERROR(EncodeJPEGData(data_in, &jpeg_data));
      container.jpeg_reconstruction = jpeg_data.data();
      container.jpeg_reconstruction_size = jpeg_data.size();
    }
    jxl::PaddedBytes container_file;
    if (!EncodeJpegXlContainerOneShot(container, &container_file)) {
      fprintf(stderr, "Failed to encode container format\n");
      return 1;
    }
    compressed.swap(container_file);
    if (!args.quiet) {
      const size_t pixels = io.xsize() * io.ysize();
      const double bpp =
          static_cast<double>(compressed.size() * jxl::kBitsPerByte) / pixels;
      fprintf(stderr, "Including container: %zu bytes (%.3f bpp%s).\n",
              compressed.size(), bpp / io.frames.size(),
              io.frames.size() == 1 ? "" : "/frame");
    }
  }
  if (args.file_out) {
    if (!jxl::WriteFile(compressed, args.file_out)) {
      fprintf(stderr, "Failed to write to \"%s\"\n", args.file_out);
      return 1;
    }
  }

  if (args.print_profile == jxl::Override::kOn) {
    PROFILER_PRINT_RESULTS();
  }
  if (!args.quiet && cmdline.verbosity > 0) {
    jxl::CacheAligned::PrintStats();
  }
  return 0;
}

}  // namespace tools
}  // namespace jpegxl

int main(int argc, const char** argv) {
  return jpegxl::tools::CompressJpegXlMain(argc, argv);
}
<|endoftext|>


<commit_before>// Licensed GNU LGPL v2.1 or later: http://www.gnu.org/licenses/lgpl.html
#include "bsetool.hh"
#include <bse/bsemain.hh>
#include <bse/gslmagic.hh>
#include <bse/gslcommon.hh>
#include <bse/bseloader.hh>
#include <bse/gsldatahandle.hh>
#include <stdio.h>
#include <string.h>

using namespace Bse;
using namespace BseTool;

static String
magic_test (const ArgParser &ap)
{
  static const char *magic_presets[][2] = {
    /* some test entries, order is important for some cases */
    { "Berkeley DB 2.X Hash/Little Endian",	"12 lelong 0x061561", },
    { "MS-DOS executable (EXE)",		"0 string MZ", },
    { "ELF object file",			"0 string \177ELF", },
    { "Bourne shell script text",		"0,string,#!/bin/sh", },
    { "Bourne shell script text",		"0,string,#!\\ /bin/sh", },
    { "Bourne shell script text",		"0,string,#!\\t/bin/sh", },
    { "GIF image data",				"0,string,GIF8", },
    { "X window image dump (v7)",		("# .xwd files\n"
						 "0x04,ubelong,0x0000007"), },
    { "RIFF/WAVE audio",			("0 string RIFF\n"
						 "8 string WAVE"), },
    { "RIFF data",				"0 string RIFF", },
    { "GslWave file",				"0 string #GslWave\n", },
  };
  static const guint n_magic_presets = sizeof (magic_presets) / sizeof (magic_presets[0]);
  guint i;
  SfiRing *magic_list = NULL;
  gboolean test_open = FALSE;
  /* initialization */
  for (i = 0; i < n_magic_presets; i++)
    magic_list = sfi_ring_append (magic_list,
				  gsl_magic_create ((void*) magic_presets[i][0],
						    0,
						    0,
						    magic_presets[i][1]));
  if (ap["-t"] == "1")
    test_open = TRUE;

  for (const auto &file_name : ap.dynamics())
    {
      BseLoader *loader = bse_loader_match (file_name.c_str());
      GslMagic *magic = gsl_magic_list_match_file (magic_list, file_name.c_str());
      const uint l = file_name.size();
      char *pad;

      printout ("%s:", file_name);
      pad = g_strnfill (MAX (40, l) - l, ' ');
      printout ("%s", pad);
      g_free (pad);
      if (!magic && !loader)
        printout (" no magic/loader found");
      else
        {
          if (magic)
            printout (" MAGIC: %s", (char*) magic->data);
          if (loader)
            {
              if (test_open)
                {
                  BseWaveFileInfo *wfi;
                  Bse::Error error = Bse::Error::NONE;
                  printout ("\n  LOADER: %s\n", loader->name);
                  wfi = bse_wave_file_info_load (file_name.c_str(), &error);
                  if (wfi)
                    bse_wave_file_info_unref (wfi);
                  printout ("  ERROR: %s", bse_error_blurb (error));
                }
              else
                printout (" LOADER: %s", loader->name);
            }
        }
      printout ("\n");
    }
  return ""; // no error
}

static ArgDescription magic_options[] = {
  { "-t",        "",    "Test loading file info", "" },
  { "[file...]", "",    "Files to match against magics", "" },
};

static CommandRegistry magic_cmd (magic_options, magic_test, "magic", "Identify files via magic definitions");
<commit_msg>TOOLS: magictest: fix loader testing<commit_after>// Licensed GNU LGPL v2.1 or later: http://www.gnu.org/licenses/lgpl.html
#include "bsetool.hh"
#include <bse/bsemain.hh>
#include <bse/gslmagic.hh>
#include <bse/gslcommon.hh>
#include <bse/bseloader.hh>
#include <bse/gsldatahandle.hh>
#include <stdio.h>
#include <string.h>

using namespace Bse;
using namespace BseTool;

static String
magic_test (const ArgParser &ap)
{
  static const char *magic_presets[][2] = {
    /* some test entries, order is important for some cases */
    { "Berkeley DB 2.X Hash/Little Endian",	"12 lelong 0x061561", },
    { "MS-DOS executable (EXE)",		"0 string MZ", },
    { "ELF object file",			"0 string \177ELF", },
    { "Bourne shell script text",		"0,string,#!/bin/sh", },
    { "Bourne shell script text",		"0,string,#!\\ /bin/sh", },
    { "Bourne shell script text",		"0,string,#!\\t/bin/sh", },
    { "GIF image data",				"0,string,GIF8", },
    { "X window image dump (v7)",		("# .xwd files\n"
						 "0x04,ubelong,0x0000007"), },
    { "RIFF/WAVE audio",			("0 string RIFF\n"
						 "8 string WAVE"), },
    { "RIFF data",				"0 string RIFF", },
    { "GslWave file",				"0 string #GslWave\n", },
  };
  static const guint n_magic_presets = sizeof (magic_presets) / sizeof (magic_presets[0]);
  guint i;
  SfiRing *magic_list = NULL;
  gboolean test_open = FALSE;
  /* initialization */
  for (i = 0; i < n_magic_presets; i++)
    magic_list = sfi_ring_append (magic_list,
				  gsl_magic_create ((void*) magic_presets[i][0],
						    0,
						    0,
						    magic_presets[i][1]));
  if (ap["t"] == "1")
    test_open = TRUE;

  for (const auto &file_name : ap.dynamics())
    {
      BseLoader *loader = bse_loader_match (file_name.c_str());
      GslMagic *magic = gsl_magic_list_match_file (magic_list, file_name.c_str());
      const uint l = file_name.size();
      char *pad;

      printout ("%s:", file_name);
      pad = g_strnfill (MAX (40, l) - l, ' ');
      printout ("%s", pad);
      g_free (pad);
      if (!magic && !loader)
        printout (" no magic/loader found");
      else
        {
          if (magic)
            printout (" MAGIC: %s", (char*) magic->data);
          if (loader)
            {
              if (test_open)
                {
                  BseWaveFileInfo *wfi;
                  Bse::Error error = Bse::Error::NONE;
                  printout ("\n  LOADER: %s\n", loader->name);
                  wfi = bse_wave_file_info_load (file_name.c_str(), &error);
                  if (wfi)
                    bse_wave_file_info_unref (wfi);
                  if (error == Bse::Error::NONE)
                    printout ("  %s", bse_error_blurb (error));
                  else
                    printout ("  ERROR: %s", bse_error_blurb (error));
                }
              else
                printout (" LOADER: %s", loader->name);
            }
        }
      printout ("\n");
    }
  return ""; // no error
}

static ArgDescription magic_options[] = {
  { "-t",        "",    "Test loading file info", "" },
  { "[file...]", "",    "Files to match against magics", "" },
};

static CommandRegistry magic_cmd (magic_options, magic_test, "magic", "Identify files via magic definitions");
<|endoftext|>


<commit_before><commit_msg>fixed renaming area->region<commit_after><|endoftext|>


<commit_before>/* -*- Mode: C++; c-basic-offset: 2; tab-width: 2; indent-tabs-mode: nil -*-
 *
 * Quadra, an action puzzle game
 * Copyright (C) 1998-2000  Ludus Design
 *
 * This program 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.1 of the License, or (at your option) any later version.
 *
 * This program 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
 */

#ifdef UGS_LINUX_X11

#include <signal.h>
#define Font XFont
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <X11/xpm.h>
#undef Font
#include "debug.h"
#include "main.h"
#include "bitmap.h"
#include "sprite.h"
#include "video_x11.h"

RCSID("$Id$")

Video_X11_24::Video_X11_24(int w, int h, int b,
			   const char *wname,
			   Display* dpy,
			   Visual* vis):
  Video_X11(w, h, b, wname, dpy, vis, 24) {
  vfb = (unsigned char*)malloc(w * h);

  if(!vfb)
    (void)new Error("Could not allocate virtual frame buffer.");

  memset(vfb, 0, w*h);

}

Video_X11_24::~Video_X11_24() {
  if(vfb)
    free(vfb);
}

void Video_X11_24::flip() {

#pragma pack(1)
  struct Pixel3 {
    unsigned char red, green, blue;
  };

  struct PixelValue {
    Pixel3 pixel;
    unsigned char pad;
  };
#pragma pack()

  unsigned long* buf32;
  Pixel3* buf24;
  int x, y;

  if(newpal) {
    pal.set();
    newpal = false;
  }

  if(max_x > min_x) {
    if(image->bits_per_pixel == 24) {
      /* Conversion 8 bpp to 24bpp. */
      buf24 = (Pixel3*) image->data;
      for(y = 0; y < 480; y++)
        for(x = min_x[y]; x <= max_x[y]; x++)
          buf24[(y * width) + x] =
	    ((PixelValue*)(&colors[vfb[(y * width) +x]]))->pixel;
    } else {
      /* Conversion of the 8 bpp buffer to a 32 bpp buffer. */
      buf32 = (unsigned long*) image->data;
      for(y = 0; y < 480; y++)
        for(x = min_x[y]; x <= max_x[y]; x++)
          buf32[(y * width) + x] =
	    colors[vfb[(y * width) + x]];
    }

    /* reset the dirty rect */
    for(y = 0; y < 480; y++) {
      min_x[y] = vb->width;
      max_x[y] = 0;
    }
  }

  Video_X11::flip();

  framecount++;
}

void Video_X11_24::dosetpal(PALETTEENTRY pal[256], int size) {
  int i;

  for(i = 0; i < size; i++) {
    colors[i] = pal[i].peRed << 16;
    colors[i] += pal[i].peGreen << 8;
    colors[i] += pal[i].peBlue;
  }

  dirty(0, 0, width-1, height-1);
}

#endif /* UGS_LINUX_X11 */

<commit_msg>A simplified version of part of a patch for 64-bit compatibility from Gentoo.<commit_after>/* -*- Mode: C++; c-basic-offset: 2; tab-width: 2; indent-tabs-mode: nil -*-
 *
 * Quadra, an action puzzle game
 * Copyright (C) 1998-2000  Ludus Design
 *
 * This program 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.1 of the License, or (at your option) any later version.
 *
 * This program 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
 */

#ifdef UGS_LINUX_X11

#include <signal.h>
#define Font XFont
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <X11/xpm.h>
#undef Font
#include "debug.h"
#include "main.h"
#include "bitmap.h"
#include "sprite.h"
#include "video_x11.h"

RCSID("$Id$")

Video_X11_24::Video_X11_24(int w, int h, int b,
			   const char *wname,
			   Display* dpy,
			   Visual* vis):
  Video_X11(w, h, b, wname, dpy, vis, 24) {
  vfb = (unsigned char*)malloc(w * h);

  if(!vfb)
    (void)new Error("Could not allocate virtual frame buffer.");

  memset(vfb, 0, w*h);

}

Video_X11_24::~Video_X11_24() {
  if(vfb)
    free(vfb);
}

void Video_X11_24::flip() {

#pragma pack(1)
  struct Pixel3 {
    unsigned char red, green, blue;
  };

  struct PixelValue {
    Pixel3 pixel;
    unsigned char pad;
  };
#pragma pack()

  unsigned int* buf32;
  Pixel3* buf24;
  int x, y;

  if(newpal) {
    pal.set();
    newpal = false;
  }

  if(max_x > min_x) {
    if(image->bits_per_pixel == 24) {
      /* Conversion 8 bpp to 24bpp. */
      buf24 = (Pixel3*) image->data;
      for(y = 0; y < 480; y++)
        for(x = min_x[y]; x <= max_x[y]; x++)
          buf24[(y * width) + x] =
	    ((PixelValue*)(&colors[vfb[(y * width) +x]]))->pixel;
    } else {
      /* Conversion of the 8 bpp buffer to a 32 bpp buffer. */
      buf32 = reinterpret_cast<unsigned int*>(image->data);
      for(y = 0; y < 480; y++)
        for(x = min_x[y]; x <= max_x[y]; x++)
          buf32[(y * width) + x] =
	    colors[vfb[(y * width) + x]];
    }

    /* reset the dirty rect */
    for(y = 0; y < 480; y++) {
      min_x[y] = vb->width;
      max_x[y] = 0;
    }
  }

  Video_X11::flip();

  framecount++;
}

void Video_X11_24::dosetpal(PALETTEENTRY pal[256], int size) {
  int i;

  for(i = 0; i < size; i++) {
    colors[i] = pal[i].peRed << 16;
    colors[i] += pal[i].peGreen << 8;
    colors[i] += pal[i].peBlue;
  }

  dirty(0, 0, width-1, height-1);
}

#endif /* UGS_LINUX_X11 */

<|endoftext|>