<commit_before>/*
  Q Light Controller Plus
  audio.cpp

  Copyright (c) Massimo Callegari

  Licensed under the Apache License, Version 2.0 (the "License");
  you may not use this file except in compliance with the License.
  You may obtain a copy of the License at

      http://www.apache.org/licenses/LICENSE-2.0.txt

  Unless required by applicable law or agreed to in writing, software
  distributed under the License is distributed on an "AS IS" BASIS,
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  See the License for the specific language governing permissions and
  limitations under the License.
*/

#include <QCoreApplication>
#include <QDomDocument>
#include <QDomElement>
#include <QDebug>
#include <QFile>

#include "audiodecoder.h"
#ifdef HAS_LIBSNDFILE
  #include "audiodecoder_sndfile.h"
#endif
#ifdef HAS_LIBMAD
  #include "audiodecoder_mad.h"
#endif

#include "audiorenderer.h"

#if QT_VERSION < QT_VERSION_CHECK(5, 0, 0)

 #if defined(__APPLE__) || defined(Q_OS_MAC)
   #include "audiorenderer_portaudio.h"
 #elif defined(WIN32) || defined(Q_OS_WIN)
   #include "audiorenderer_waveout.h"
 #else
   #include "audiorenderer_alsa.h"
 #endif
#else
 #include "audiorenderer_qt.h"
#endif

#include "audio.h"
#include "doc.h"

#define KXMLQLCAudioSource "Source"
#define KXMLQLCAudioDevice "Device"
#define KXMLQLCAudioStartTime "StartTime"
#define KXMLQLCAudioColor "Color"
#define KXMLQLCAudioLocked "Locked"

/*****************************************************************************
 * Initialization
 *****************************************************************************/

Audio::Audio(Doc* doc)
  : Function(doc, Function::Audio)
  , m_doc(doc)
  , m_decoder(NULL)
  , m_audio_out(NULL)
  , m_audioDevice(QString())
  , m_startTime(UINT_MAX)
  , m_color(96, 128, 83)
  , m_locked(false)
  , m_sourceFileName("")
  , m_audioDuration(0)
{
    setName(tr("New Audio"));

    // Listen to member Function removals
    connect(doc, SIGNAL(functionRemoved(quint32)),
            this, SLOT(slotFunctionRemoved(quint32)));
}

Audio::~Audio()
{
    if (m_audio_out != NULL)
    {
        m_audio_out->stop();
        delete m_audio_out;
    }
    if (m_decoder != NULL)
        delete m_decoder;
}

/*****************************************************************************
 * Copying
 *****************************************************************************/

Function* Audio::createCopy(Doc* doc, bool addToDoc)
{
    Q_ASSERT(doc != NULL);

    Function* copy = new Audio(doc);
    if (copy->copyFrom(this) == false)
    {
        delete copy;
        copy = NULL;
    }
    if (addToDoc == true && doc->addFunction(copy) == false)
    {
        delete copy;
        copy = NULL;
    }

    return copy;
}

bool Audio::copyFrom(const Function* function)
{
    const Audio* aud = qobject_cast<const Audio*> (function);
    if (aud == NULL)
        return false;

    setSourceFileName(aud->m_sourceFileName);
    m_audioDuration = aud->m_audioDuration;
    m_color = aud->m_color;

    return Function::copyFrom(function);
}

QStringList Audio::getCapabilities()
{
    QStringList cap;
#ifdef HAS_LIBSNDFILE
    cap << AudioDecoderSndFile::getSupportedFormats();
#endif
#ifdef HAS_LIBMAD
    cap << AudioDecoderMAD::getSupportedFormats();
#endif
    return cap;
}

/*********************************************************************
 * Properties
 *********************************************************************/
void Audio::setStartTime(quint32 time)
{
    m_startTime = time;
}

quint32 Audio::getStartTime() const
{
    return m_startTime;
}

qint64 Audio::totalDuration()
{
    return m_audioDuration;
}

void Audio::setColor(QColor color)
{
    m_color = color;
}

QColor Audio::getColor()
{
    return m_color;
}

void Audio::setLocked(bool locked)
{
    m_locked = locked;
}

bool Audio::isLocked()
{
    return m_locked;
}

bool Audio::setSourceFileName(QString filename)
{
    if (m_sourceFileName.isEmpty() == false)
    {
        // unload previous source
        if (m_decoder != NULL)
        {
            delete m_decoder;
            m_decoder = NULL;
        }
    }

    m_sourceFileName = filename;

    //QMessageBox::warning(0,"Warning", QString("File complete path: %1").arg(m_sourceFileName));

    if (QFile(m_sourceFileName).exists())
        setName(QFileInfo(m_sourceFileName).fileName());
    else
    {
        setName(tr("File not found"));
        m_audioDuration = 0;
        emit changed(id());
        return true;
    }

#ifdef HAS_LIBSNDFILE
    m_decoder = new AudioDecoderSndFile(m_sourceFileName);
    if (m_decoder->initialize() == false)
    {
        delete m_decoder;
        m_decoder = NULL;
    }
    else
    {
        m_audioDuration = m_decoder->totalTime();
        emit changed(id());
        return true;
    }
#endif
#ifdef HAS_LIBMAD
    m_decoder = new AudioDecoderMAD(m_sourceFileName);
    if (m_decoder->initialize() == false)
    {
        delete m_decoder;
        m_decoder = NULL;
    }
    else
    {
        m_audioDuration = m_decoder->totalTime();
        emit changed(id());
        return true;
    }
#endif
    return false;
}

QString Audio::getSourceFileName()
{
    return m_sourceFileName;
}

AudioDecoder* Audio::getAudioDecoder()
{
    return m_decoder;
}

void Audio::setAudioDevice(QString dev)
{
    m_audioDevice = dev;
}

QString Audio::audioDevice()
{
    return m_audioDevice;
}

void Audio::adjustAttribute(qreal fraction, int attributeIndex)
{
    if (m_audio_out != NULL && attributeIndex == Intensity)
        m_audio_out->adjustIntensity(fraction);
    Function::adjustAttribute(fraction, attributeIndex);
}

void Audio::slotEndOfStream()
{
    if (m_audio_out != NULL)
    {
        m_audio_out->stop();
        m_audio_out->deleteLater();
        m_audio_out = NULL;
        m_decoder->seek(0);
    }
    Function::postRun(NULL, QList<Universe *>());
}

void Audio::slotFunctionRemoved(quint32 fid)
{
    Q_UNUSED(fid)
}

/*********************************************************************
 * Save & Load
 *********************************************************************/

bool Audio::saveXML(QDomDocument* doc, QDomElement* wksp_root)
{
    QDomElement root;
    QDomText text;

    Q_ASSERT(doc != NULL);
    Q_ASSERT(wksp_root != NULL);

    /* Function tag */
    root = doc->createElement(KXMLQLCFunction);
    wksp_root->appendChild(root);

    /* Common attributes */
    saveXMLCommon(&root);

    /* Speed */
    saveXMLSpeed(doc, &root);

    QDomElement source = doc->createElement(KXMLQLCAudioSource);
    if (m_audioDevice.isEmpty() == false)
        source.setAttribute(KXMLQLCAudioDevice, m_audioDevice);

    text = doc->createTextNode(m_doc->normalizeComponentPath(m_sourceFileName));

    source.appendChild(text);
    root.appendChild(source);

    return true;
}

bool Audio::loadXML(const QDomElement& root)
{
    if (root.tagName() != KXMLQLCFunction)
    {
        qWarning() << Q_FUNC_INFO << "Function node not found";
        return false;
    }

    if (root.attribute(KXMLQLCFunctionType) != typeToString(Function::Audio))
    {
        qWarning() << Q_FUNC_INFO << root.attribute(KXMLQLCFunctionType)
                   << "is not Audio";
        return false;
    }

    QString fname = name();

    QDomNode node = root.firstChild();
    while (node.isNull() == false)
    {
        QDomElement tag = node.toElement();
        if (tag.tagName() == KXMLQLCAudioSource)
        {
            if (tag.hasAttribute(KXMLQLCAudioDevice))
                setAudioDevice(tag.attribute(KXMLQLCAudioDevice));
            if (tag.hasAttribute(KXMLQLCAudioStartTime))
                setStartTime(tag.attribute(KXMLQLCAudioStartTime).toUInt());
            if (tag.hasAttribute(KXMLQLCAudioColor))
                setColor(QColor(tag.attribute(KXMLQLCAudioColor)));
            if (tag.hasAttribute(KXMLQLCAudioLocked))
                setLocked(true);
            setSourceFileName(m_doc->denormalizeComponentPath(tag.text()));
        }
        else if (tag.tagName() == KXMLQLCFunctionSpeed)
        {
            loadXMLSpeed(tag);
        }
        node = node.nextSibling();
    }

    setName(fname);

    return true;
}

void Audio::postLoad()
{
}

/*********************************************************************
 * Running
 *********************************************************************/
void Audio::preRun(MasterTimer* timer)
{
    if (m_decoder != NULL)
    {
        m_decoder->seek(elapsed());
        AudioParameters ap = m_decoder->audioParameters();
#if QT_VERSION < QT_VERSION_CHECK(5, 0, 0)
 #if defined(__APPLE__) || defined(Q_OS_MAC)
        //m_audio_out = new AudioRendererCoreAudio();
        m_audio_out = new AudioRendererPortAudio(m_audioDevice);
 #elif defined(WIN32) || defined(Q_OS_WIN)
        m_audio_out = new AudioRendererWaveOut(m_audioDevice);
 #else
        m_audio_out = new AudioRendererAlsa(m_audioDevice);
 #endif
        m_audio_out->moveToThread(QCoreApplication::instance()->thread());
#else
        m_audio_out = new AudioRendererQt(m_audioDevice);
#endif
        m_audio_out->setDecoder(m_decoder);
        m_audio_out->initialize(ap.sampleRate(), ap.channels(), ap.format());
        m_audio_out->setFadeIn(fadeInSpeed());
        m_audio_out->start();
        m_audio_out->adjustIntensity(getAttributeValue(Intensity));
        connect(m_audio_out, SIGNAL(endOfStreamReached()),
                this, SLOT(slotEndOfStream()));
    }
    else
        return; // avoid this function to even start

    Function::preRun(timer);
}

void Audio::write(MasterTimer* timer, QList<Universe *> universes)
{
    Q_UNUSED(timer)
    Q_UNUSED(universes)

    incrementElapsed();

    if (fadeOutSpeed() != 0)
    {
        if (m_audio_out != NULL && totalDuration() - elapsed() <= fadeOutSpeed())
            m_audio_out->setFadeOut(fadeOutSpeed());
    }
}

void Audio::postRun(MasterTimer* timer, QList<Universe*> universes)
{
    Q_UNUSED(timer)
    Q_UNUSED(universes)
    slotEndOfStream();
}
<commit_msg>engine: fixed audio end of stream not stopping the running function<commit_after>/*
  Q Light Controller Plus
  audio.cpp

  Copyright (c) Massimo Callegari

  Licensed under the Apache License, Version 2.0 (the "License");
  you may not use this file except in compliance with the License.
  You may obtain a copy of the License at

      http://www.apache.org/licenses/LICENSE-2.0.txt

  Unless required by applicable law or agreed to in writing, software
  distributed under the License is distributed on an "AS IS" BASIS,
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  See the License for the specific language governing permissions and
  limitations under the License.
*/

#include <QCoreApplication>
#include <QDomDocument>
#include <QDomElement>
#include <QDebug>
#include <QFile>

#include "audiodecoder.h"
#ifdef HAS_LIBSNDFILE
  #include "audiodecoder_sndfile.h"
#endif
#ifdef HAS_LIBMAD
  #include "audiodecoder_mad.h"
#endif

#include "audiorenderer.h"

#if QT_VERSION < QT_VERSION_CHECK(5, 0, 0)

 #if defined(__APPLE__) || defined(Q_OS_MAC)
   #include "audiorenderer_portaudio.h"
 #elif defined(WIN32) || defined(Q_OS_WIN)
   #include "audiorenderer_waveout.h"
 #else
   #include "audiorenderer_alsa.h"
 #endif
#else
 #include "audiorenderer_qt.h"
#endif

#include "audio.h"
#include "doc.h"

#define KXMLQLCAudioSource "Source"
#define KXMLQLCAudioDevice "Device"
#define KXMLQLCAudioStartTime "StartTime"
#define KXMLQLCAudioColor "Color"
#define KXMLQLCAudioLocked "Locked"

/*****************************************************************************
 * Initialization
 *****************************************************************************/

Audio::Audio(Doc* doc)
  : Function(doc, Function::Audio)
  , m_doc(doc)
  , m_decoder(NULL)
  , m_audio_out(NULL)
  , m_audioDevice(QString())
  , m_startTime(UINT_MAX)
  , m_color(96, 128, 83)
  , m_locked(false)
  , m_sourceFileName("")
  , m_audioDuration(0)
{
    setName(tr("New Audio"));

    // Listen to member Function removals
    connect(doc, SIGNAL(functionRemoved(quint32)),
            this, SLOT(slotFunctionRemoved(quint32)));
}

Audio::~Audio()
{
    if (m_audio_out != NULL)
    {
        m_audio_out->stop();
        delete m_audio_out;
    }
    if (m_decoder != NULL)
        delete m_decoder;
}

/*****************************************************************************
 * Copying
 *****************************************************************************/

Function* Audio::createCopy(Doc* doc, bool addToDoc)
{
    Q_ASSERT(doc != NULL);

    Function* copy = new Audio(doc);
    if (copy->copyFrom(this) == false)
    {
        delete copy;
        copy = NULL;
    }
    if (addToDoc == true && doc->addFunction(copy) == false)
    {
        delete copy;
        copy = NULL;
    }

    return copy;
}

bool Audio::copyFrom(const Function* function)
{
    const Audio* aud = qobject_cast<const Audio*> (function);
    if (aud == NULL)
        return false;

    setSourceFileName(aud->m_sourceFileName);
    m_audioDuration = aud->m_audioDuration;
    m_color = aud->m_color;

    return Function::copyFrom(function);
}

QStringList Audio::getCapabilities()
{
    QStringList cap;
#ifdef HAS_LIBSNDFILE
    cap << AudioDecoderSndFile::getSupportedFormats();
#endif
#ifdef HAS_LIBMAD
    cap << AudioDecoderMAD::getSupportedFormats();
#endif
    return cap;
}

/*********************************************************************
 * Properties
 *********************************************************************/
void Audio::setStartTime(quint32 time)
{
    m_startTime = time;
}

quint32 Audio::getStartTime() const
{
    return m_startTime;
}

qint64 Audio::totalDuration()
{
    return m_audioDuration;
}

void Audio::setColor(QColor color)
{
    m_color = color;
}

QColor Audio::getColor()
{
    return m_color;
}

void Audio::setLocked(bool locked)
{
    m_locked = locked;
}

bool Audio::isLocked()
{
    return m_locked;
}

bool Audio::setSourceFileName(QString filename)
{
    if (m_sourceFileName.isEmpty() == false)
    {
        // unload previous source
        if (m_decoder != NULL)
        {
            delete m_decoder;
            m_decoder = NULL;
        }
    }

    m_sourceFileName = filename;

    //QMessageBox::warning(0,"Warning", QString("File complete path: %1").arg(m_sourceFileName));

    if (QFile(m_sourceFileName).exists())
        setName(QFileInfo(m_sourceFileName).fileName());
    else
    {
        setName(tr("File not found"));
        m_audioDuration = 0;
        emit changed(id());
        return true;
    }

#ifdef HAS_LIBSNDFILE
    m_decoder = new AudioDecoderSndFile(m_sourceFileName);
    if (m_decoder->initialize() == false)
    {
        delete m_decoder;
        m_decoder = NULL;
    }
    else
    {
        m_audioDuration = m_decoder->totalTime();
        emit changed(id());
        return true;
    }
#endif
#ifdef HAS_LIBMAD
    m_decoder = new AudioDecoderMAD(m_sourceFileName);
    if (m_decoder->initialize() == false)
    {
        delete m_decoder;
        m_decoder = NULL;
    }
    else
    {
        m_audioDuration = m_decoder->totalTime();
        emit changed(id());
        return true;
    }
#endif
    return false;
}

QString Audio::getSourceFileName()
{
    return m_sourceFileName;
}

AudioDecoder* Audio::getAudioDecoder()
{
    return m_decoder;
}

void Audio::setAudioDevice(QString dev)
{
    m_audioDevice = dev;
}

QString Audio::audioDevice()
{
    return m_audioDevice;
}

void Audio::adjustAttribute(qreal fraction, int attributeIndex)
{
    if (m_audio_out != NULL && attributeIndex == Intensity)
        m_audio_out->adjustIntensity(fraction);
    Function::adjustAttribute(fraction, attributeIndex);
}

void Audio::slotEndOfStream()
{
    if (m_audio_out != NULL)
    {
        m_audio_out->stop();
        m_audio_out->deleteLater();
        m_audio_out = NULL;
        m_decoder->seek(0);
    }
    Function::postRun(NULL, QList<Universe *>());

    if (!stopped())
        stop();
}

void Audio::slotFunctionRemoved(quint32 fid)
{
    Q_UNUSED(fid)
}

/*********************************************************************
 * Save & Load
 *********************************************************************/

bool Audio::saveXML(QDomDocument* doc, QDomElement* wksp_root)
{
    QDomElement root;
    QDomText text;

    Q_ASSERT(doc != NULL);
    Q_ASSERT(wksp_root != NULL);

    /* Function tag */
    root = doc->createElement(KXMLQLCFunction);
    wksp_root->appendChild(root);

    /* Common attributes */
    saveXMLCommon(&root);

    /* Speed */
    saveXMLSpeed(doc, &root);

    QDomElement source = doc->createElement(KXMLQLCAudioSource);
    if (m_audioDevice.isEmpty() == false)
        source.setAttribute(KXMLQLCAudioDevice, m_audioDevice);

    text = doc->createTextNode(m_doc->normalizeComponentPath(m_sourceFileName));

    source.appendChild(text);
    root.appendChild(source);

    return true;
}

bool Audio::loadXML(const QDomElement& root)
{
    if (root.tagName() != KXMLQLCFunction)
    {
        qWarning() << Q_FUNC_INFO << "Function node not found";
        return false;
    }

    if (root.attribute(KXMLQLCFunctionType) != typeToString(Function::Audio))
    {
        qWarning() << Q_FUNC_INFO << root.attribute(KXMLQLCFunctionType)
                   << "is not Audio";
        return false;
    }

    QString fname = name();

    QDomNode node = root.firstChild();
    while (node.isNull() == false)
    {
        QDomElement tag = node.toElement();
        if (tag.tagName() == KXMLQLCAudioSource)
        {
            if (tag.hasAttribute(KXMLQLCAudioDevice))
                setAudioDevice(tag.attribute(KXMLQLCAudioDevice));
            if (tag.hasAttribute(KXMLQLCAudioStartTime))
                setStartTime(tag.attribute(KXMLQLCAudioStartTime).toUInt());
            if (tag.hasAttribute(KXMLQLCAudioColor))
                setColor(QColor(tag.attribute(KXMLQLCAudioColor)));
            if (tag.hasAttribute(KXMLQLCAudioLocked))
                setLocked(true);
            setSourceFileName(m_doc->denormalizeComponentPath(tag.text()));
        }
        else if (tag.tagName() == KXMLQLCFunctionSpeed)
        {
            loadXMLSpeed(tag);
        }
        node = node.nextSibling();
    }

    setName(fname);

    return true;
}

void Audio::postLoad()
{
}

/*********************************************************************
 * Running
 *********************************************************************/
void Audio::preRun(MasterTimer* timer)
{
    if (m_decoder != NULL)
    {
        m_decoder->seek(elapsed());
        AudioParameters ap = m_decoder->audioParameters();
#if QT_VERSION < QT_VERSION_CHECK(5, 0, 0)
 #if defined(__APPLE__) || defined(Q_OS_MAC)
        //m_audio_out = new AudioRendererCoreAudio();
        m_audio_out = new AudioRendererPortAudio(m_audioDevice);
 #elif defined(WIN32) || defined(Q_OS_WIN)
        m_audio_out = new AudioRendererWaveOut(m_audioDevice);
 #else
        m_audio_out = new AudioRendererAlsa(m_audioDevice);
 #endif
        m_audio_out->moveToThread(QCoreApplication::instance()->thread());
#else
        m_audio_out = new AudioRendererQt(m_audioDevice);
#endif
        m_audio_out->setDecoder(m_decoder);
        m_audio_out->initialize(ap.sampleRate(), ap.channels(), ap.format());
        m_audio_out->setFadeIn(fadeInSpeed());
        m_audio_out->start();
        m_audio_out->adjustIntensity(getAttributeValue(Intensity));
        connect(m_audio_out, SIGNAL(endOfStreamReached()),
                this, SLOT(slotEndOfStream()));
    }

    Function::preRun(timer);
}

void Audio::write(MasterTimer* timer, QList<Universe *> universes)
{
    Q_UNUSED(timer)
    Q_UNUSED(universes)

    incrementElapsed();

    if (fadeOutSpeed() != 0)
    {
        if (m_audio_out != NULL && totalDuration() - elapsed() <= fadeOutSpeed())
            m_audio_out->setFadeOut(fadeOutSpeed());
    }
}

void Audio::postRun(MasterTimer* timer, QList<Universe*> universes)
{
    Q_UNUSED(timer)
    Q_UNUSED(universes)
    slotEndOfStream();
}
<|endoftext|>


<commit_before><commit_msg>config: wrap statefs_variant string in dquotes<commit_after><|endoftext|>


<commit_before><commit_msg>fcache: convert functions to methods<commit_after><|endoftext|>


<commit_before><commit_msg>Removed useless preprocessing<commit_after><|endoftext|>


<commit_before><commit_msg>Delete floppy.cpp<commit_after><|endoftext|>


<commit_before>#include <iomanip>
#include "server.hpp"
#include "tools.hpp"
#include "test_tool.hpp"

// 🍣🍣🍣  パーサ  🍣🍣🍣
void pcserver::parse(question_data const& problem, answer_type const& answer)
{
    // outputに本番サーバと同じ情報、outerrにそれ以外を吐く
    std::cerr << "TARGET CAPTURED...\n";
    test_tool::emulator emu(problem);
    std::cerr << "BODY SENSOR\n";
    auto const result = emu.start(answer);
    std::cerr << "EMULATED EMULATED EMULATED\n";

    output << "ACCEPTED " << std::setw(2) << std::setfill('0') << result.wrong << std::endl;
    sane = true;
}

<commit_msg>emulatorの例外を受け取るようにした<commit_after>#include <iomanip>
#include "server.hpp"
#include "tools.hpp"
#include "test_tool.hpp"

// 🍣🍣🍣  パーサ  🍣🍣🍣
void pcserver::parse(question_data const& problem, answer_type const& answer)
{
    // outputに本番サーバと同じ情報、outerrにそれ以外を吐く
    try {
        std::cerr << "TARGET CAPTURED...\n";
        test_tool::emulator emu(problem);
        std::cerr << "BODY SENSOR\n";
        auto const result = emu.start(answer);
        std::cerr << "EMULATED EMULATED EMULATED\n";
        output << "ACCEPTED " << std::setw(2) << std::setfill('0') << result.wrong << std::endl;
        sane = true;
    }
    catch(std::exception &e) {
        outerr << e.what() << std::endl;
    }
}

<|endoftext|>


<commit_before>// Copyright 2016 Strength in Numbers Foundation

#include "giftcardpage.h"
#include "ui_giftcardpage.h"

#include "giftcardtablemodel.h"
#include "optionsmodel.h"
#include "bitcoingui.h"
#include "creategiftdialog.h"
#include "csvmodelwriter.h"
#include "guiutil.h"
#include "paperwallet.h"

#include <QSortFilterProxyModel>
#include <QClipboard>
#include <QMessageBox>
#include <QMenu>
#include <QDir>
#include <QFile>
#include <QTextStream>
#include <QDesktopServices>     // dvd add for launching URL
#include <QUrl>                 // dvd add for launching URL

#ifdef USE_QRCODE
#include "qrcodedialog.h"
#endif

extern int VanityGen(int addrtype, char *prefix, char *pubKey, char *privKey);

GiftCardPage::GiftCardPage(Mode mode, Tabs tab, QWidget *parent) :
    QDialog(parent),
    ui(new Ui::GiftCardPage),
    model(0),
    optionsModel(0),
    mode(mode),
    tab(tab)
{
    ui->setupUi(this);

#ifdef Q_OS_MAC // Icons on push buttons are very uncommon on Mac
    ui->newAddressButton->setIcon(QIcon());
    ui->templateButton->setIcon(QIcon());
    ui->copyToClipboard->setIcon(QIcon());
    ui->deleteButton->setIcon(QIcon());
#endif

#ifndef USE_QRCODE
    ui->showQRCode->setVisible(false);
#endif

    switch(mode)
    {
    case ForSending:
        connect(ui->tableView, SIGNAL(doubleClicked(QModelIndex)), this, SLOT(accept()));
        ui->tableView->setEditTriggers(QAbstractItemView::NoEditTriggers);
        ui->tableView->setFocus();
        break;
    case ForEditing:
        ui->buttonBox->setVisible(false);
        break;
    }

    ui->labelExplanation->setVisible(true);
    ui->deleteButton->setVisible(true);
    ui->signMessage->setVisible(false);

//dvd considering adding a "Give" option from the right click

    // Context menu actions
    QAction *copyLabelAction = new QAction(tr("Copy &Label"), this);
    QAction *copyAddressAction = new QAction(ui->copyToClipboard->text(), this);
    QAction *editAction = new QAction(tr("&Edit"), this);
    QAction *showQRCodeAction = new QAction(ui->showQRCode->text(), this);
//    QAction *signMessageAction = new QAction(ui->signMessage->text(), this);
    QAction *verifyMessageAction = new QAction(ui->verifyMessage->text(), this);
    deleteAction = new QAction(ui->deleteButton->text(), this);

    // Build context menu
    contextMenu = new QMenu();
    contextMenu->addAction(copyAddressAction);
    contextMenu->addAction(copyLabelAction);
    contextMenu->addAction(editAction);
    contextMenu->addAction(deleteAction);
    contextMenu->addSeparator();
    contextMenu->addAction(showQRCodeAction);
    contextMenu->addAction(verifyMessageAction);

    // Connect signals for context menu actions
    connect(copyAddressAction, SIGNAL(triggered()), this, SLOT(on_copyToClipboard_clicked()));
    connect(copyLabelAction, SIGNAL(triggered()), this, SLOT(onCopyLabelAction()));
    connect(editAction, SIGNAL(triggered()), this, SLOT(onEditAction()));
    connect(deleteAction, SIGNAL(triggered()), this, SLOT(on_deleteButton_clicked()));
    connect(showQRCodeAction, SIGNAL(triggered()), this, SLOT(on_showQRCode_clicked()));
//    connect(signMessageAction, SIGNAL(triggered()), this, SLOT(on_signMessage_clicked()));
    connect(verifyMessageAction, SIGNAL(triggered()), this, SLOT(on_verifyMessage_clicked()));

    connect(ui->tableView, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(contextualMenu(QPoint)));

    // Pass through accept action from button box
    connect(ui->buttonBox, SIGNAL(accepted()), this, SLOT(accept()));

    // Set default filepath to save to
    filePath = QDir::homePath();
    printf("homePath = %s\n", filePath.toStdString().c_str());
}

GiftCardPage::~GiftCardPage()
{
    delete ui;
}

void GiftCardPage::setModel(GiftCardTableModel *model)
{
    this->model = model;
    if(!model)
        return;

    proxyModel = new QSortFilterProxyModel(this);
    proxyModel->setSourceModel(model);
    proxyModel->setDynamicSortFilter(true);
    proxyModel->setSortCaseSensitivity(Qt::CaseInsensitive);
    proxyModel->setFilterCaseSensitivity(Qt::CaseInsensitive);

    proxyModel->setFilterRole(GiftCardTableModel::TypeRole);
    proxyModel->setFilterFixedString(GiftCardTableModel::Gift);

    ui->tableView->setModel(proxyModel);
    ui->tableView->sortByColumn(0, Qt::AscendingOrder);

    // Set column widths
#if QT_VERSION < 0x050000
    ui->tableView->horizontalHeader()->resizeSection(
            GiftCardTableModel::Address, 333);
    ui->tableView->horizontalHeader()->setResizeMode(
            GiftCardTableModel::Label, QHeaderView::Stretch);
#else
    ui->tableView->horizontalHeader()->setSectionResizeMode(GiftCardTableModel::Label, QHeaderView::Stretch);
    ui->tableView->horizontalHeader()->setSectionResizeMode(GiftCardTableModel::Address, QHeaderView::ResizeToContents);
#endif

    connect(ui->tableView->selectionModel(), SIGNAL(selectionChanged(QItemSelection,QItemSelection)),
            this, SLOT(selectionChanged()));

    // Select row for newly created address
    connect(model, SIGNAL(rowsInserted(QModelIndex,int,int)),
            this, SLOT(selectNewAddress(QModelIndex,int,int)));

    selectionChanged();
}

void GiftCardPage::setOptionsModel(OptionsModel *optionsModel)
{
    this->optionsModel = optionsModel;
}

void GiftCardPage::on_copyToClipboard_clicked()
{
    GUIUtil::copyEntryData(ui->tableView, GiftCardTableModel::Address);
}

void GiftCardPage::onCopyLabelAction()
{
    GUIUtil::copyEntryData(ui->tableView, GiftCardTableModel::Label);
}

void GiftCardPage::onEditAction()
{
    if(!ui->tableView->selectionModel())
        return;
    QModelIndexList indexes = ui->tableView->selectionModel()->selectedRows();
    if(indexes.isEmpty())
        return;

    CreateGiftDialog dlg(CreateGiftDialog::EditGiftAddress);

    dlg.setModel(model);
    QModelIndex origIndex = proxyModel->mapToSource(indexes.at(0));
    dlg.loadRow(origIndex.row());
    dlg.exec();

}

void GiftCardPage::on_signMessage_clicked()
{
    QTableView *table = ui->tableView;
    QModelIndexList indexes = table->selectionModel()->selectedRows(GiftCardTableModel::Address);
    QString addr;

    foreach (QModelIndex index, indexes)
    {
        QVariant address = index.data();
        addr = address.toString();
    }

    emit signMessage(addr);
}

void GiftCardPage::on_verifyMessage_clicked()
{
    QTableView *table = ui->tableView;
    QModelIndexList indexes = table->selectionModel()->selectedRows(GiftCardTableModel::Address);
    QString addr;

    foreach (QModelIndex index, indexes)
    {
        QVariant address = index.data();
        addr = address.toString();
    }

    emit verifyMessage(addr);
}

void GiftCardPage::on_newAddressButton_clicked()
{
    char    strPubKey[256],
            strPrivKey[256];

    if(!model)
        return;

    printf("GiftCardPage::on_newAddressButton(): CreateGiftDialog\n");
    CreateGiftDialog dlg(CreateGiftDialog::NewGiftAddress);
    dlg.setModel(model);
    if(dlg.exec())
    {
        printf("GiftCardPage::on_newAddressButton(): dlg.exec()\n");
        newAddressToSelect = dlg.getAddress();
        QStringList giftKeys = newAddressToSelect.split(":");

        strcpy(strPubKey, giftKeys.at(0).toStdString().c_str());
        strcpy(strPrivKey, giftKeys.at(1).toStdString().c_str());
        printf("strPubKey = %s\tstrPrivKey = %s\n", strPubKey, strPrivKey);

//        QString appDirPath = QCoreApplication::applicationDirPath();
//        printf("appDirPath = %s\n", appDirPath.toStdString().c_str());

        QString defaultFileName = filePath + QDir::separator() + giftKeys.at(0) + ".html";

        QString fileName = GUIUtil::getSaveFileName(
                    this, tr("Save Gift* Card"), defaultFileName, tr(".html"));

        if (!fileName.isNull()) {
            PaperWallet pWallet = PaperWallet::PaperWallet(fileName, giftKeys.at(0), giftKeys.at(1), "");
            if (pWallet.genWallet()) {
                QFile file(fileName);
                if (file.exists()) {
                    // save the user selected folder for easy next use
                    QFileInfo fileInfo(file.fileName());
                    filePath = fileInfo.absolutePath();

                    // launch browser to display/print
                    QString url = "file://" + fileName;
                    QDesktopServices::openUrl(QUrl(url));
                }
            }
        }
    }
}

void GiftCardPage::on_templateButton_clicked()
{
    QMessageBox msgBox;

    msgBox.setWindowTitle("Update Templates");
    msgBox.setStandardButtons(QMessageBox::Ok);
    msgBox.setDefaultButton(QMessageBox::Ok);

    PaperWallet pWallet = PaperWallet("", "", "", "");

    if (pWallet.updateTemplates())
        msgBox.setText("Template Update Successful");
    else {
        msgBox.setText("Template Update Failed");
        msgBox.setInformativeText("Check your network connectivity and retry");
    }
    msgBox.exec();
}

void GiftCardPage::on_deleteButton_clicked()
{
    QTableView *table = ui->tableView;
    if(!table->selectionModel())
        return;
    QModelIndexList indexes = table->selectionModel()->selectedRows();
    if(!indexes.isEmpty())
    {
        table->model()->removeRow(indexes.at(0).row());
    }
}

void GiftCardPage::selectionChanged()
{
    // Set button states based on selected tab and selection
    QTableView *table = ui->tableView;
    if(!table->selectionModel())
        return;

    if(table->selectionModel()->hasSelection())
    {
        // In gift tab, allow deletion of selection
        ui->deleteButton->setEnabled(true);
        ui->deleteButton->setVisible(true);
        deleteAction->setEnabled(true);
        ui->signMessage->setEnabled(false);
        ui->signMessage->setVisible(false);
        ui->verifyMessage->setEnabled(true);
        ui->verifyMessage->setVisible(true);
        ui->copyToClipboard->setEnabled(true);
        ui->showQRCode->setEnabled(true);
    }
    else
    {
        ui->deleteButton->setEnabled(false);
        ui->showQRCode->setEnabled(false);
        ui->copyToClipboard->setEnabled(false);
        ui->signMessage->setEnabled(false);
        ui->verifyMessage->setEnabled(false);
    }
}

void GiftCardPage::done(int retval)
{
    QTableView *table = ui->tableView;
    if(!table->selectionModel() || !table->model())
        return;
    // When this is a tab/widget and not a model dialog, ignore "done"
    if(mode == ForEditing)
        return;

    // Figure out which address was selected, and return it
    QModelIndexList indexes = table->selectionModel()->selectedRows(GiftCardTableModel::Address);

    foreach (QModelIndex index, indexes)
    {
        QVariant address = table->model()->data(index);
        returnValue = address.toString();
    }

    if(returnValue.isEmpty())
    {
        // If no address entry selected, return rejected
        retval = Rejected;
    }

    QDialog::done(retval);
}

void GiftCardPage::exportClicked()
{
    // CSV is currently the only supported format
    QString filename = GUIUtil::getSaveFileName(
            this,
            tr("Export Address Book Data"), QString(),
            tr("Comma separated file (*.csv)"));

    if (filename.isNull()) return;

    CSVModelWriter writer(filename);

    // name, column, role
    writer.setModel(proxyModel);
    writer.addColumn("Label", GiftCardTableModel::Label, Qt::EditRole);
    writer.addColumn("Address", GiftCardTableModel::Address, Qt::EditRole);

    if(!writer.write())
    {
        QMessageBox::critical(this, tr("Error exporting"), tr("Could not write to file %1.").arg(filename),
                              QMessageBox::Abort, QMessageBox::Abort);
    }
}

void GiftCardPage::on_showQRCode_clicked()
{
#ifdef USE_QRCODE
    QTableView *table = ui->tableView;
    QModelIndexList indexes = table->selectionModel()->selectedRows(GiftCardTableModel::Address);

    foreach (QModelIndex index, indexes)
    {
        QString address = index.data().toString(), label = index.sibling(index.row(), 0).data(Qt::EditRole).toString();

        QRCodeDialog *dialog = new QRCodeDialog(address, label, tab == ReceivingTab, this);
        if(optionsModel)
            dialog->setModel(optionsModel);
        dialog->setAttribute(Qt::WA_DeleteOnClose);
        dialog->show();
    }
#endif
}

void GiftCardPage::contextualMenu(const QPoint &point)
{
    QModelIndex index = ui->tableView->indexAt(point);
    if(index.isValid())
    {
        contextMenu->exec(QCursor::pos());
    }
}

void GiftCardPage::selectNewAddress(const QModelIndex &parent, int begin, int end)
{
    QModelIndex idx = proxyModel->mapFromSource(model->index(begin, GiftCardTableModel::Address, parent));
    if(idx.isValid() && (idx.data(Qt::EditRole).toString() == newAddressToSelect))
    {
        // Select row of newly created address, once
        ui->tableView->setFocus();
        ui->tableView->selectRow(idx.row());
        newAddressToSelect.clear();
    }
}
<commit_msg>See previous commit :p<commit_after>// Copyright 2016 Strength in Numbers Foundation

#include "giftcardpage.h"
#include "ui_giftcardpage.h"

#include "giftcardtablemodel.h"
#include "optionsmodel.h"
#include "bitcoingui.h"
#include "creategiftdialog.h"
#include "csvmodelwriter.h"
#include "guiutil.h"
#include "paperwallet.h"

#include <QSortFilterProxyModel>
#include <QClipboard>
#include <QMessageBox>
#include <QMenu>
#include <QDir>
#include <QFile>
#include <QTextStream>
#include <QDesktopServices>     // dvd add for launching URL
#include <QUrl>                 // dvd add for launching URL

#ifdef USE_QRCODE
#include "qrcodedialog.h"
#endif

extern int VanityGen(int addrtype, char *prefix, char *pubKey, char *privKey);

GiftCardPage::GiftCardPage(Mode mode, Tabs tab, QWidget *parent) :
    QDialog(parent),
    ui(new Ui::GiftCardPage),
    model(0),
    optionsModel(0),
    mode(mode),
    tab(tab)
{
    ui->setupUi(this);

#ifdef Q_OS_MAC // Icons on push buttons are very uncommon on Mac
    ui->newAddressButton->setIcon(QIcon());
    ui->templateButton->setIcon(QIcon());
    ui->copyToClipboard->setIcon(QIcon());
    ui->deleteButton->setIcon(QIcon());
#endif

#ifndef USE_QRCODE
    ui->showQRCode->setVisible(false);
#endif

    switch(mode)
    {
    case ForSending:
        connect(ui->tableView, SIGNAL(doubleClicked(QModelIndex)), this, SLOT(accept()));
        ui->tableView->setEditTriggers(QAbstractItemView::NoEditTriggers);
        ui->tableView->setFocus();
        break;
    case ForEditing:
        ui->buttonBox->setVisible(false);
        break;
    }

    ui->labelExplanation->setVisible(true);
    ui->deleteButton->setVisible(true);
    ui->signMessage->setVisible(false);

//dvd considering adding a "Give" option from the right click

    // Context menu actions
    QAction *copyLabelAction = new QAction(tr("Copy &Label"), this);
    QAction *copyAddressAction = new QAction(ui->copyToClipboard->text(), this);
    QAction *editAction = new QAction(tr("&Edit"), this);
    QAction *showQRCodeAction = new QAction(ui->showQRCode->text(), this);
//    QAction *signMessageAction = new QAction(ui->signMessage->text(), this);
    QAction *verifyMessageAction = new QAction(ui->verifyMessage->text(), this);
    deleteAction = new QAction(ui->deleteButton->text(), this);

    // Build context menu
    contextMenu = new QMenu();
    contextMenu->addAction(copyAddressAction);
    contextMenu->addAction(copyLabelAction);
    contextMenu->addAction(editAction);
    contextMenu->addAction(deleteAction);
    contextMenu->addSeparator();
    contextMenu->addAction(showQRCodeAction);
    contextMenu->addAction(verifyMessageAction);

    // Connect signals for context menu actions
    connect(copyAddressAction, SIGNAL(triggered()), this, SLOT(on_copyToClipboard_clicked()));
    connect(copyLabelAction, SIGNAL(triggered()), this, SLOT(onCopyLabelAction()));
    connect(editAction, SIGNAL(triggered()), this, SLOT(onEditAction()));
    connect(deleteAction, SIGNAL(triggered()), this, SLOT(on_deleteButton_clicked()));
    connect(showQRCodeAction, SIGNAL(triggered()), this, SLOT(on_showQRCode_clicked()));
//    connect(signMessageAction, SIGNAL(triggered()), this, SLOT(on_signMessage_clicked()));
    connect(verifyMessageAction, SIGNAL(triggered()), this, SLOT(on_verifyMessage_clicked()));

    connect(ui->tableView, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(contextualMenu(QPoint)));

    // Pass through accept action from button box
    connect(ui->buttonBox, SIGNAL(accepted()), this, SLOT(accept()));

    // Set default filepath to save to
    filePath = QDir::homePath();
    printf("homePath = %s\n", filePath.toStdString().c_str());
}

GiftCardPage::~GiftCardPage()
{
    delete ui;
}

void GiftCardPage::setModel(GiftCardTableModel *model)
{
    this->model = model;
    if(!model)
        return;

    proxyModel = new QSortFilterProxyModel(this);
    proxyModel->setSourceModel(model);
    proxyModel->setDynamicSortFilter(true);
    proxyModel->setSortCaseSensitivity(Qt::CaseInsensitive);
    proxyModel->setFilterCaseSensitivity(Qt::CaseInsensitive);

    proxyModel->setFilterRole(GiftCardTableModel::TypeRole);
    proxyModel->setFilterFixedString(GiftCardTableModel::Gift);

    ui->tableView->setModel(proxyModel);
    ui->tableView->sortByColumn(0, Qt::AscendingOrder);

    // Set column widths
#if QT_VERSION < 0x050000
    ui->tableView->horizontalHeader()->resizeSection(
            GiftCardTableModel::Address, 333);
    ui->tableView->horizontalHeader()->setResizeMode(
            GiftCardTableModel::Label, QHeaderView::Stretch);
#else
    ui->tableView->horizontalHeader()->setSectionResizeMode(GiftCardTableModel::Label, QHeaderView::Stretch);
    ui->tableView->horizontalHeader()->setSectionResizeMode(GiftCardTableModel::Address, QHeaderView::ResizeToContents);
#endif

    connect(ui->tableView->selectionModel(), SIGNAL(selectionChanged(QItemSelection,QItemSelection)),
            this, SLOT(selectionChanged()));

    // Select row for newly created address
    connect(model, SIGNAL(rowsInserted(QModelIndex,int,int)),
            this, SLOT(selectNewAddress(QModelIndex,int,int)));

    selectionChanged();
}

void GiftCardPage::setOptionsModel(OptionsModel *optionsModel)
{
    this->optionsModel = optionsModel;
}

void GiftCardPage::on_copyToClipboard_clicked()
{
    GUIUtil::copyEntryData(ui->tableView, GiftCardTableModel::Address);
}

void GiftCardPage::onCopyLabelAction()
{
    GUIUtil::copyEntryData(ui->tableView, GiftCardTableModel::Label);
}

void GiftCardPage::onEditAction()
{
    if(!ui->tableView->selectionModel())
        return;
    QModelIndexList indexes = ui->tableView->selectionModel()->selectedRows();
    if(indexes.isEmpty())
        return;

    CreateGiftDialog dlg(CreateGiftDialog::EditGiftAddress);

    dlg.setModel(model);
    QModelIndex origIndex = proxyModel->mapToSource(indexes.at(0));
    dlg.loadRow(origIndex.row());
    dlg.exec();

}

void GiftCardPage::on_signMessage_clicked()
{
    QTableView *table = ui->tableView;
    QModelIndexList indexes = table->selectionModel()->selectedRows(GiftCardTableModel::Address);
    QString addr;

    foreach (QModelIndex index, indexes)
    {
        QVariant address = index.data();
        addr = address.toString();
    }

    emit signMessage(addr);
}

void GiftCardPage::on_verifyMessage_clicked()
{
    QTableView *table = ui->tableView;
    QModelIndexList indexes = table->selectionModel()->selectedRows(GiftCardTableModel::Address);
    QString addr;

    foreach (QModelIndex index, indexes)
    {
        QVariant address = index.data();
        addr = address.toString();
    }

    emit verifyMessage(addr);
}

void GiftCardPage::on_newAddressButton_clicked()
{
    char    strPubKey[256],
            strPrivKey[256];

    if(!model)
        return;

    printf("GiftCardPage::on_newAddressButton(): CreateGiftDialog\n");
    CreateGiftDialog dlg(CreateGiftDialog::NewGiftAddress);
    dlg.setModel(model);
    if(dlg.exec())
    {
        printf("GiftCardPage::on_newAddressButton(): dlg.exec()\n");
        newAddressToSelect = dlg.getAddress();
        QStringList giftKeys = newAddressToSelect.split(":");

        strcpy(strPubKey, giftKeys.at(0).toStdString().c_str());
        strcpy(strPrivKey, giftKeys.at(1).toStdString().c_str());
        printf("strPubKey = %s\tstrPrivKey = %s\n", strPubKey, strPrivKey);

//        QString appDirPath = QCoreApplication::applicationDirPath();
//        printf("appDirPath = %s\n", appDirPath.toStdString().c_str());

        QString defaultFileName = filePath + QDir::separator() + giftKeys.at(0) + ".html";

        QString fileName = GUIUtil::getSaveFileName(
                    this, tr("Save Gift* Card"), defaultFileName, tr(".html"));

        if (!fileName.isNull()) {
            PaperWallet pWallet = PaperWallet(fileName, giftKeys.at(0), giftKeys.at(1), "");
            if (pWallet.genWallet()) {
                QFile file(fileName);
                if (file.exists()) {
                    // save the user selected folder for easy next use
                    QFileInfo fileInfo(file.fileName());
                    filePath = fileInfo.absolutePath();

                    // launch browser to display/print
                    QString url = "file://" + fileName;
                    QDesktopServices::openUrl(QUrl(url));
                }
            }
        }
    }
}

void GiftCardPage::on_templateButton_clicked()
{
    QMessageBox msgBox;

    msgBox.setWindowTitle("Update Templates");
    msgBox.setStandardButtons(QMessageBox::Ok);
    msgBox.setDefaultButton(QMessageBox::Ok);

    PaperWallet pWallet = PaperWallet("", "", "", "");

    if (pWallet.updateTemplates())
        msgBox.setText("Template Update Successful");
    else {
        msgBox.setText("Template Update Failed");
        msgBox.setInformativeText("Check your network connectivity and retry");
    }
    msgBox.exec();
}

void GiftCardPage::on_deleteButton_clicked()
{
    QTableView *table = ui->tableView;
    if(!table->selectionModel())
        return;
    QModelIndexList indexes = table->selectionModel()->selectedRows();
    if(!indexes.isEmpty())
    {
        table->model()->removeRow(indexes.at(0).row());
    }
}

void GiftCardPage::selectionChanged()
{
    // Set button states based on selected tab and selection
    QTableView *table = ui->tableView;
    if(!table->selectionModel())
        return;

    if(table->selectionModel()->hasSelection())
    {
        // In gift tab, allow deletion of selection
        ui->deleteButton->setEnabled(true);
        ui->deleteButton->setVisible(true);
        deleteAction->setEnabled(true);
        ui->signMessage->setEnabled(false);
        ui->signMessage->setVisible(false);
        ui->verifyMessage->setEnabled(true);
        ui->verifyMessage->setVisible(true);
        ui->copyToClipboard->setEnabled(true);
        ui->showQRCode->setEnabled(true);
    }
    else
    {
        ui->deleteButton->setEnabled(false);
        ui->showQRCode->setEnabled(false);
        ui->copyToClipboard->setEnabled(false);
        ui->signMessage->setEnabled(false);
        ui->verifyMessage->setEnabled(false);
    }
}

void GiftCardPage::done(int retval)
{
    QTableView *table = ui->tableView;
    if(!table->selectionModel() || !table->model())
        return;
    // When this is a tab/widget and not a model dialog, ignore "done"
    if(mode == ForEditing)
        return;

    // Figure out which address was selected, and return it
    QModelIndexList indexes = table->selectionModel()->selectedRows(GiftCardTableModel::Address);

    foreach (QModelIndex index, indexes)
    {
        QVariant address = table->model()->data(index);
        returnValue = address.toString();
    }

    if(returnValue.isEmpty())
    {
        // If no address entry selected, return rejected
        retval = Rejected;
    }

    QDialog::done(retval);
}

void GiftCardPage::exportClicked()
{
    // CSV is currently the only supported format
    QString filename = GUIUtil::getSaveFileName(
            this,
            tr("Export Address Book Data"), QString(),
            tr("Comma separated file (*.csv)"));

    if (filename.isNull()) return;

    CSVModelWriter writer(filename);

    // name, column, role
    writer.setModel(proxyModel);
    writer.addColumn("Label", GiftCardTableModel::Label, Qt::EditRole);
    writer.addColumn("Address", GiftCardTableModel::Address, Qt::EditRole);

    if(!writer.write())
    {
        QMessageBox::critical(this, tr("Error exporting"), tr("Could not write to file %1.").arg(filename),
                              QMessageBox::Abort, QMessageBox::Abort);
    }
}

void GiftCardPage::on_showQRCode_clicked()
{
#ifdef USE_QRCODE
    QTableView *table = ui->tableView;
    QModelIndexList indexes = table->selectionModel()->selectedRows(GiftCardTableModel::Address);

    foreach (QModelIndex index, indexes)
    {
        QString address = index.data().toString(), label = index.sibling(index.row(), 0).data(Qt::EditRole).toString();

        QRCodeDialog *dialog = new QRCodeDialog(address, label, tab == ReceivingTab, this);
        if(optionsModel)
            dialog->setModel(optionsModel);
        dialog->setAttribute(Qt::WA_DeleteOnClose);
        dialog->show();
    }
#endif
}

void GiftCardPage::contextualMenu(const QPoint &point)
{
    QModelIndex index = ui->tableView->indexAt(point);
    if(index.isValid())
    {
        contextMenu->exec(QCursor::pos());
    }
}

void GiftCardPage::selectNewAddress(const QModelIndex &parent, int begin, int end)
{
    QModelIndex idx = proxyModel->mapFromSource(model->index(begin, GiftCardTableModel::Address, parent));
    if(idx.isValid() && (idx.data(Qt::EditRole).toString() == newAddressToSelect))
    {
        // Select row of newly created address, once
        ui->tableView->setFocus();
        ui->tableView->selectRow(idx.row());
        newAddressToSelect.clear();
    }
}
<|endoftext|>


<commit_before>// Copyright (c) 2016 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 "modaloverlay.h"
#include "ui_modaloverlay.h"

#include "guiutil.h"

#include "chainparams.h"

#include <QResizeEvent>
#include <QPropertyAnimation>

ModalOverlay::ModalOverlay(QWidget *parent) :
QWidget(parent),
ui(new Ui::ModalOverlay),
bestHeaderHeight(0),
bestHeaderDate(QDateTime()),
layerIsVisible(false),
userClosed(false)
{
    ui->setupUi(this);
    connect(ui->closeButton, SIGNAL(clicked()), this, SLOT(closeClicked()));
    if (parent) {
        parent->installEventFilter(this);
        raise();
    }

    blockProcessTime.clear();
    setVisible(false);
}

ModalOverlay::~ModalOverlay()
{
    delete ui;
}

bool ModalOverlay::eventFilter(QObject * obj, QEvent * ev) {
    if (obj == parent()) {
        if (ev->type() == QEvent::Resize) {
            QResizeEvent * rev = static_cast<QResizeEvent*>(ev);
            resize(rev->size());
            if (!layerIsVisible)
                setGeometry(0, height(), width(), height());

        }
        else if (ev->type() == QEvent::ChildAdded) {
            raise();
        }
    }
    return QWidget::eventFilter(obj, ev);
}

//! Tracks parent widget changes
bool ModalOverlay::event(QEvent* ev) {
    if (ev->type() == QEvent::ParentAboutToChange) {
        if (parent()) parent()->removeEventFilter(this);
    }
    else if (ev->type() == QEvent::ParentChange) {
        if (parent()) {
            parent()->installEventFilter(this);
            raise();
        }
    }
    return QWidget::event(ev);
}

void ModalOverlay::setKnownBestHeight(int count, const QDateTime& blockDate)
{
    if (count > bestHeaderHeight) {
        bestHeaderHeight = count;
        bestHeaderDate = blockDate;
    }
}

void ModalOverlay::tipUpdate(int count, const QDateTime& blockDate, double nVerificationProgress)
{
    QDateTime currentDate = QDateTime::currentDateTime();

    // keep a vector of samples of verification progress at height
    blockProcessTime.push_front(qMakePair(currentDate.toMSecsSinceEpoch(), nVerificationProgress));

    // show progress speed if we have more then one sample
    if (blockProcessTime.size() >= 2)
    {
        double progressStart = blockProcessTime[0].second;
        double progressDelta = 0;
        double progressPerHour = 0;
        qint64 timeDelta = 0;
        qint64 remainingMSecs = 0;
        double remainingProgress = 1.0 - nVerificationProgress;
        for (int i = 1; i < blockProcessTime.size(); i++)
        {
            QPair<qint64, double> sample = blockProcessTime[i];

            // take first sample after 500 seconds or last available one
            if (sample.first < (currentDate.toMSecsSinceEpoch() - 500 * 1000) || i == blockProcessTime.size() - 1) {
                progressDelta = progressStart-sample.second;
                timeDelta = blockProcessTime[0].first - sample.first;
                progressPerHour = progressDelta/(double)timeDelta*1000*3600;
                remainingMSecs = remainingProgress / progressDelta * timeDelta;
                break;
            }
        }
        // show progress increase per hour
        ui->progressIncreasePerH->setText(QString::number(progressPerHour*100, 'f', 2)+"%");

        // show expected remaining time
        ui->expectedTimeLeft->setText(GUIUtil::formatNiceTimeOffset(remainingMSecs/1000.0));

        static const int MAX_SAMPLES = 5000;
        if (blockProcessTime.count() > MAX_SAMPLES)
            blockProcessTime.remove(MAX_SAMPLES, blockProcessTime.count()-MAX_SAMPLES);
    }

    // show the last block date
    ui->newestBlockDate->setText(blockDate.toString());

    // show the percentage done according to nVerificationProgress
    ui->percentageProgress->setText(QString::number(nVerificationProgress*100, 'f', 2)+"%");
    ui->progressBar->setValue(nVerificationProgress*100);

    if (!bestHeaderDate.isValid())
        // not syncing
        return;

    // estimate the number of headers left based on nPowTargetSpacing
    // and check if the gui is not aware of the the best header (happens rarely)
    int estimateNumHeadersLeft = bestHeaderDate.secsTo(currentDate) / Params().GetConsensus().nPowTargetSpacing;
    bool hasBestHeader = bestHeaderHeight >= count;

    // show remaining number of blocks
    if (estimateNumHeadersLeft < HEADER_HEIGHT_DELTA_SYNC && hasBestHeader) {
        ui->numberOfBlocksLeft->setText(QString::number(bestHeaderHeight - count));
    } else {
        ui->numberOfBlocksLeft->setText(tr("Unknown. Syncing Headers (%1)...").arg(bestHeaderHeight));
        ui->expectedTimeLeft->setText(tr("Unknown..."));
    }
}

void ModalOverlay::toggleVisibility()
{
    showHide(layerIsVisible, true);
    if (!layerIsVisible)
        userClosed = true;
}

void ModalOverlay::showHide(bool hide, bool userRequested)
{
    if ( (layerIsVisible && !hide) || (!layerIsVisible && hide) || (!hide && userClosed && !userRequested))
        return;

    if (!isVisible() && !hide)
        setVisible(true);

    setGeometry(0, hide ? 0 : height(), width(), height());

    QPropertyAnimation* animation = new QPropertyAnimation(this, "pos");
    animation->setDuration(300);
    animation->setStartValue(QPoint(0, hide ? 0 : this->height()));
    animation->setEndValue(QPoint(0, hide ? this->height() : 0));
    animation->setEasingCurve(QEasingCurve::OutQuad);
    animation->start(QAbstractAnimation::DeleteWhenStopped);
    layerIsVisible = !hide;
}

void ModalOverlay::closeClicked()
{
    showHide(true);
    userClosed = true;
}
<commit_msg>sync speed estimate<commit_after>// Copyright (c) 2016 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 "modaloverlay.h"
#include "ui_modaloverlay.h"

#include "guiutil.h"

#include "chainparams.h"

#include <QResizeEvent>
#include <QPropertyAnimation>

ModalOverlay::ModalOverlay(QWidget *parent) :
QWidget(parent),
ui(new Ui::ModalOverlay),
bestHeaderHeight(0),
bestHeaderDate(QDateTime()),
layerIsVisible(false),
userClosed(false)
{
    ui->setupUi(this);
    connect(ui->closeButton, SIGNAL(clicked()), this, SLOT(closeClicked()));
    if (parent) {
        parent->installEventFilter(this);
        raise();
    }

    blockProcessTime.clear();
    setVisible(false);
}

ModalOverlay::~ModalOverlay()
{
    delete ui;
}

bool ModalOverlay::eventFilter(QObject * obj, QEvent * ev) {
    if (obj == parent()) {
        if (ev->type() == QEvent::Resize) {
            QResizeEvent * rev = static_cast<QResizeEvent*>(ev);
            resize(rev->size());
            if (!layerIsVisible)
                setGeometry(0, height(), width(), height());

        }
        else if (ev->type() == QEvent::ChildAdded) {
            raise();
        }
    }
    return QWidget::eventFilter(obj, ev);
}

//! Tracks parent widget changes
bool ModalOverlay::event(QEvent* ev) {
    if (ev->type() == QEvent::ParentAboutToChange) {
        if (parent()) parent()->removeEventFilter(this);
    }
    else if (ev->type() == QEvent::ParentChange) {
        if (parent()) {
            parent()->installEventFilter(this);
            raise();
        }
    }
    return QWidget::event(ev);
}

void ModalOverlay::setKnownBestHeight(int count, const QDateTime& blockDate)
{
    if (count > bestHeaderHeight) {
        bestHeaderHeight = count;
        bestHeaderDate = blockDate;
    }
}

void ModalOverlay::tipUpdate(int count, const QDateTime& blockDate, double nVerificationProgress)
{
    QDateTime currentDate = QDateTime::currentDateTime();

    // keep a vector of samples of verification progress at height
    blockProcessTime.push_front(qMakePair(currentDate.toMSecsSinceEpoch(), nVerificationProgress));

    // show progress speed if we have more then one sample
    if (blockProcessTime.size() >= 2)
    {
        double progressStart = blockProcessTime[0].second;
        double progressDelta = 0;
        double progressPerHour = 0;
        qint64 timeDelta = 0;
        qint64 remainingMSecs = 0;
        double remainingProgress = 1.0 - nVerificationProgress;
        for (int i = 1; i < blockProcessTime.size(); i++)
        {
            QPair<qint64, double> sample = blockProcessTime[i];

            // take first sample after 500 seconds or last available one
            if (sample.first < (currentDate.toMSecsSinceEpoch() - 500 * 1000) || i == blockProcessTime.size() - 1) {
                progressDelta = progressStart-sample.second;
                timeDelta = blockProcessTime[0].first - sample.first;
                progressPerHour = progressDelta/(double)timeDelta*1000*3600;
                remainingMSecs = remainingProgress / progressDelta * timeDelta;
                break;
            }
        }
        // show progress increase per hour
        ui->progressIncreasePerH->setText(QString::number(progressPerHour*100, 'f', 2)+"%");

        // show expected remaining time
        ui->expectedTimeLeft->setText(GUIUtil::formatNiceTimeOffset(remainingMSecs/1000.0));

        static const int MAX_SAMPLES = 5000;
        if (blockProcessTime.count() > MAX_SAMPLES)
            blockProcessTime.remove(MAX_SAMPLES, blockProcessTime.count()-MAX_SAMPLES);
    }

    // show the last block date
    ui->newestBlockDate->setText(blockDate.toString());

    // show the percentage done according to nVerificationProgress
    ui->percentageProgress->setText(QString::number(nVerificationProgress*100, 'f', 2)+"%");
    ui->progressBar->setValue(nVerificationProgress*100);

    if (!bestHeaderDate.isValid())
        // not syncing
        return;

    // estimate the number of headers left based on nPowTargetSpacing
    // and check if the gui is not aware of the the best header (happens rarely)
    int64_t targetSpacing;

    if(count < Params().GetConsensus().nDiffChangeTarget ){
        Params().GetConsensus().nTargetSpacingRe;
    } else if (count < Params().GetConsensus().multiAlgoDiffChangeTarget){
        Params().GetConsensus().multiAlgoTargetSpacing;
    } else {
        Params().GetConsensus().multiAlgoTargetSpacingV4;
    }
    int estimateNumHeadersLeft = bestHeaderDate.secsTo(currentDate) / targetSpacing;
    bool hasBestHeader = bestHeaderHeight >= count;

    // show remaining number of blocks
    if (estimateNumHeadersLeft < HEADER_HEIGHT_DELTA_SYNC && hasBestHeader) {
        ui->numberOfBlocksLeft->setText(QString::number(bestHeaderHeight - count));
    } else {
        ui->numberOfBlocksLeft->setText(tr("Unknown. Syncing Headers (%1)...").arg(bestHeaderHeight));
        ui->expectedTimeLeft->setText(tr("Unknown..."));
    }
}

void ModalOverlay::toggleVisibility()
{
    showHide(layerIsVisible, true);
    if (!layerIsVisible)
        userClosed = true;
}

void ModalOverlay::showHide(bool hide, bool userRequested)
{
    if ( (layerIsVisible && !hide) || (!layerIsVisible && hide) || (!hide && userClosed && !userRequested))
        return;

    if (!isVisible() && !hide)
        setVisible(true);

    setGeometry(0, hide ? 0 : height(), width(), height());

    QPropertyAnimation* animation = new QPropertyAnimation(this, "pos");
    animation->setDuration(300);
    animation->setStartValue(QPoint(0, hide ? 0 : this->height()));
    animation->setEndValue(QPoint(0, hide ? this->height() : 0));
    animation->setEasingCurve(QEasingCurve::OutQuad);
    animation->start(QAbstractAnimation::DeleteWhenStopped);
    layerIsVisible = !hide;
}

void ModalOverlay::closeClicked()
{
    showHide(true);
    userClosed = true;
}
<|endoftext|>


<commit_before><commit_msg>new diagnostics for LRGs<commit_after><|endoftext|>


<commit_before>#include "optionsmodel.h"
#include "bitcoinunits.h"

#include "headers.h"
#include "init.h"

OptionsModel::OptionsModel(CWallet *wallet, QObject *parent) :
    QAbstractListModel(parent),
    wallet(wallet),
    nDisplayUnit(BitcoinUnits::BTC),
    bDisplayAddresses(false)
{
    // Read our specific settings from the wallet db
    CWalletDB walletdb(wallet->strWalletFile);
    walletdb.ReadSetting("nDisplayUnit", nDisplayUnit);
    walletdb.ReadSetting("bDisplayAddresses", bDisplayAddresses);
}

int OptionsModel::rowCount(const QModelIndex & parent) const
{
    return OptionIDRowCount;
}

QVariant OptionsModel::data(const QModelIndex & index, int role) const
{
    if(role == Qt::EditRole)
    {
        switch(index.row())
        {
        case StartAtStartup:
            return QVariant(GetStartOnSystemStartup());
        case MinimizeToTray:
            return QVariant(fMinimizeToTray);
        case MapPortUPnP:
            return QVariant(fUseUPnP);
        case MinimizeOnClose:
            return QVariant(fMinimizeOnClose);
        case ConnectSOCKS4:
            return QVariant(fUseProxy);
        case ProxyIP:
            return QVariant(QString::fromStdString(addrProxy.ToStringIP()));
        case ProxyPort:
            return QVariant(QString::fromStdString(addrProxy.ToStringPort()));
        case Fee:
            return QVariant(nTransactionFee);
        case DisplayUnit:
            return QVariant(nDisplayUnit);
        case DisplayAddresses:
            return QVariant(bDisplayAddresses);
        default:
            return QVariant();
        }
    }
    return QVariant();
}

bool OptionsModel::setData(const QModelIndex & index, const QVariant & value, int role)
{
    bool successful = true; /* set to false on parse error */
    if(role == Qt::EditRole)
    {
        CWalletDB walletdb(wallet->strWalletFile);
        switch(index.row())
        {
        case StartAtStartup:
            successful = SetStartOnSystemStartup(value.toBool());
            break;
        case MinimizeToTray:
            fMinimizeToTray = value.toBool();
            walletdb.WriteSetting("fMinimizeToTray", fMinimizeToTray);
            break;
        case MapPortUPnP:
            fUseUPnP = value.toBool();
            walletdb.WriteSetting("fUseUPnP", fUseUPnP);
#ifdef USE_UPNP
            MapPort(fUseUPnP);
#endif
            break;
        case MinimizeOnClose:
            fMinimizeOnClose = value.toBool();
            walletdb.WriteSetting("fMinimizeOnClose", fMinimizeOnClose);
            break;
        case ConnectSOCKS4:
            fUseProxy = value.toBool();
            walletdb.WriteSetting("fUseProxy", fUseProxy);
            break;
        case ProxyIP:
            {
                // Use CAddress to parse and check IP
                CNetAddr addr(value.toString().toStdString());
                if (addr.IsValid())
                {
                    addrProxy.SetIP(addr);
                    walletdb.WriteSetting("addrProxy", addrProxy);
                }
                else
                {
                    successful = false;
                }
            }
            break;
        case ProxyPort:
            {
                int nPort = atoi(value.toString().toAscii().data());
                if (nPort > 0 && nPort < std::numeric_limits<unsigned short>::max())
                {
                    addrProxy.SetPort(nPort);
                    walletdb.WriteSetting("addrProxy", addrProxy);
                }
                else
                {
                    successful = false;
                }
            }
            break;
        case Fee: {
            nTransactionFee = value.toLongLong();
            walletdb.WriteSetting("nTransactionFee", nTransactionFee);
            }
            break;
        case DisplayUnit: {
            int unit = value.toInt();
            nDisplayUnit = unit;
            walletdb.WriteSetting("nDisplayUnit", nDisplayUnit);
            emit displayUnitChanged(unit);
            }
        case DisplayAddresses: {
            bDisplayAddresses = value.toBool();
            walletdb.WriteSetting("bDisplayAddresses", bDisplayAddresses);
            }
        default:
            break;
        }
    }
    emit dataChanged(index, index);

    return successful;
}

qint64 OptionsModel::getTransactionFee()
{
    return nTransactionFee;
}

bool OptionsModel::getMinimizeToTray()
{
    return fMinimizeToTray;
}

bool OptionsModel::getMinimizeOnClose()
{
    return fMinimizeOnClose;
}

int OptionsModel::getDisplayUnit()
{
    return nDisplayUnit;
}

bool OptionsModel::getDisplayAddresses()
{
    return bDisplayAddresses;
}
<commit_msg>Remove erroneous ":" in front of port in options dialog (introduced with network refactor)<commit_after>#include "optionsmodel.h"
#include "bitcoinunits.h"

#include "headers.h"
#include "init.h"

OptionsModel::OptionsModel(CWallet *wallet, QObject *parent) :
    QAbstractListModel(parent),
    wallet(wallet),
    nDisplayUnit(BitcoinUnits::BTC),
    bDisplayAddresses(false)
{
    // Read our specific settings from the wallet db
    CWalletDB walletdb(wallet->strWalletFile);
    walletdb.ReadSetting("nDisplayUnit", nDisplayUnit);
    walletdb.ReadSetting("bDisplayAddresses", bDisplayAddresses);
}

int OptionsModel::rowCount(const QModelIndex & parent) const
{
    return OptionIDRowCount;
}

QVariant OptionsModel::data(const QModelIndex & index, int role) const
{
    if(role == Qt::EditRole)
    {
        switch(index.row())
        {
        case StartAtStartup:
            return QVariant(GetStartOnSystemStartup());
        case MinimizeToTray:
            return QVariant(fMinimizeToTray);
        case MapPortUPnP:
            return QVariant(fUseUPnP);
        case MinimizeOnClose:
            return QVariant(fMinimizeOnClose);
        case ConnectSOCKS4:
            return QVariant(fUseProxy);
        case ProxyIP:
            return QVariant(QString::fromStdString(addrProxy.ToStringIP()));
        case ProxyPort:
            return QVariant(addrProxy.GetPort());
        case Fee:
            return QVariant(nTransactionFee);
        case DisplayUnit:
            return QVariant(nDisplayUnit);
        case DisplayAddresses:
            return QVariant(bDisplayAddresses);
        default:
            return QVariant();
        }
    }
    return QVariant();
}

bool OptionsModel::setData(const QModelIndex & index, const QVariant & value, int role)
{
    bool successful = true; /* set to false on parse error */
    if(role == Qt::EditRole)
    {
        CWalletDB walletdb(wallet->strWalletFile);
        switch(index.row())
        {
        case StartAtStartup:
            successful = SetStartOnSystemStartup(value.toBool());
            break;
        case MinimizeToTray:
            fMinimizeToTray = value.toBool();
            walletdb.WriteSetting("fMinimizeToTray", fMinimizeToTray);
            break;
        case MapPortUPnP:
            fUseUPnP = value.toBool();
            walletdb.WriteSetting("fUseUPnP", fUseUPnP);
#ifdef USE_UPNP
            MapPort(fUseUPnP);
#endif
            break;
        case MinimizeOnClose:
            fMinimizeOnClose = value.toBool();
            walletdb.WriteSetting("fMinimizeOnClose", fMinimizeOnClose);
            break;
        case ConnectSOCKS4:
            fUseProxy = value.toBool();
            walletdb.WriteSetting("fUseProxy", fUseProxy);
            break;
        case ProxyIP:
            {
                // Use CAddress to parse and check IP
                CNetAddr addr(value.toString().toStdString());
                if (addr.IsValid())
                {
                    addrProxy.SetIP(addr);
                    walletdb.WriteSetting("addrProxy", addrProxy);
                }
                else
                {
                    successful = false;
                }
            }
            break;
        case ProxyPort:
            {
                int nPort = atoi(value.toString().toAscii().data());
                if (nPort > 0 && nPort < std::numeric_limits<unsigned short>::max())
                {
                    addrProxy.SetPort(nPort);
                    walletdb.WriteSetting("addrProxy", addrProxy);
                }
                else
                {
                    successful = false;
                }
            }
            break;
        case Fee: {
            nTransactionFee = value.toLongLong();
            walletdb.WriteSetting("nTransactionFee", nTransactionFee);
            }
            break;
        case DisplayUnit: {
            int unit = value.toInt();
            nDisplayUnit = unit;
            walletdb.WriteSetting("nDisplayUnit", nDisplayUnit);
            emit displayUnitChanged(unit);
            }
        case DisplayAddresses: {
            bDisplayAddresses = value.toBool();
            walletdb.WriteSetting("bDisplayAddresses", bDisplayAddresses);
            }
        default:
            break;
        }
    }
    emit dataChanged(index, index);

    return successful;
}

qint64 OptionsModel::getTransactionFee()
{
    return nTransactionFee;
}

bool OptionsModel::getMinimizeToTray()
{
    return fMinimizeToTray;
}

bool OptionsModel::getMinimizeOnClose()
{
    return fMinimizeOnClose;
}

int OptionsModel::getDisplayUnit()
{
    return nDisplayUnit;
}

bool OptionsModel::getDisplayAddresses()
{
    return bDisplayAddresses;
}
<|endoftext|>


<commit_before><commit_msg>remove diagnostics<commit_after><|endoftext|>


<commit_before>/* ************************
   Copyright Terrain Experts Inc.
   Terrain Experts Inc (TERREX) reserves all rights to this source code
   unless otherwise specified in writing by the President of TERREX.
   This copyright may be updated in the future, in which case that version
   supercedes this one.
   -------------------
   Terrex Experts Inc.
   4400 East Broadway #314
   Tucson, AZ  85711
   info@terrex.com
   Tel: (520) 323-7990
   ************************
   */

#include <stdlib.h>
#include <stdio.h>
#include <string.h>

#define OLDMODELSTYLE

/* trpage_model.cpp
    This source file contains the methods trpgModel and trpgModelTable.
    You should only modify this code if you want to add data to these classes.
    */

#include <trpage_geom.h>
#include <trpage_read.h>

/* Write Model class
    Represents a model reference.
    */
trpgModel::trpgModel()
{
    name = NULL;
    type = External;
    useCount = 0;
    diskRef = -1;
    handle = -1;
    writeHandle = false;
}

trpgModel::trpgModel(const trpgModel &in):
    trpgReadWriteable(in)
{
    if (in.name)
    {
        name = new char[strlen(in.name)+1];
        strcpy(name,in.name);
    }
    else
        name = NULL;

    type=in.type;
    useCount=in.useCount;
    diskRef=in.diskRef;
    handle = in.handle;
    writeHandle = in.writeHandle;
}

// Reset function
void trpgModel::Reset()
{
    if (name)
        delete [] name;
    name = NULL;
    useCount = 0;
    diskRef = -1;
    handle = -1;
    writeHandle = false;
}

trpgModel::~trpgModel()
{
    Reset();
}

// Set functions
void trpgModel::SetType(int t)
{
    type = t;
}

void trpgModel::SetName(const char *nm)
{
    if (name)
        delete [] name;

    if (nm)
    {
        name = new char[strlen(nm)+1];
        strcpy(name,nm);
    }
}
void trpgModel::SetReference(trpgDiskRef pos)
{
    diskRef = pos;
}
void trpgModel::SetNumTiles(int num)
{
    useCount = num;
}
void trpgModel::AddTile()
{
    useCount++;
}

// Validity check
bool trpgModel::isValid() const
{
    if (type == External && !name)
    {
        errMess.assign("Model is external with no name");
        return false;
    }

    return true;
}

// Copy from one to another
trpgModel& trpgModel::operator = (const trpgModel &in)
{
    if (name) {
        delete [] name;
        name = NULL;
    }

    type = in.type;
    if (in.name)
        SetName(in.name);
    diskRef = in.diskRef;
    useCount = in.useCount;
    writeHandle = in.writeHandle;
    handle = in.handle;
    return *this;
}

// Compare two models
int trpgModel::operator == (const trpgModel &in) const
{
    if (type != in.type)
        return 0;

    switch (type) {
    case Local:
        if (diskRef == in.diskRef)
            return 1;
        else
            return 0;
        break;
    case External:
        if (!name && !in.name)
            return 1;
        if (!name || !in.name)
            return 0;
        if (strcmp(name,in.name))
            return 0;
        break;
    }

    return 1;
}

// Write a model reference out
bool trpgModel::Write(trpgWriteBuffer &buf)
{
    if (!isValid())
        return false;

    // We will use two different tokens to track the
    // format used in terrapage 2.2, and older versions
    int tok = TRPGMODELREF;
    if(writeHandle)
        tok = TRPGMODELREF2;

// Nick messed up the model entries when checking into txv4; now we're
// a bit stuck because U3 dbs don't have models in the U2 viewer.
// This will force the old behavior.
#ifdef OLDMODELSTYLE
    buf.Begin(tok);
    buf.Add(type);
    //writeHandle is only set for terrapage 2.2, and we use the different token.
    if(writeHandle) {
        buf.Add((int)handle);
    }
    if (name)
        buf.Add(name);
    else
        buf.Add(diskRef);
    buf.Add(useCount);

#else
    buf.Begin(tok);
    if(writeHandle) {
        buf.Add((int)handle);
    }
    buf.Add(type);
    buf.Add(name);
    buf.Add(diskRef);
    buf.Add(useCount);
#endif
    buf.End();

    return true;
}

/*    *******************
    Model Read Methods
    *******************
    */
// Get methods
bool trpgModel::GetType(int &t)
{
    if (!isValid()) return false;
    t = type;
    return true;
}
bool trpgModel::GetName(char *str,int strLen) const
{
    if (!isValid()) return false;
    int len = (name ? strlen(name) : 0);
    strncpy(str,name,MIN(len,strLen)+1);
    return true;
}
bool trpgModel::GetNumTiles(int &ret) const
{
    if (!isValid()) return false;

    ret = useCount;
    return true;
}
bool trpgModel::GetReference(trpgDiskRef &ref) const
{
    if (!isValid() || type != Local) return false;
    ref = diskRef;
    return true;
}

bool trpgModel::Read(trpgReadBuffer &buf, bool hasHandle)
{
    // MD: added complexity here - written multiple ways by
    // mistake, unraveling the various cases.
    char tmpName[1024];

    try {
        buf.Get(type);
        // TerraPage 2.2 will store the unique handle after the type
        // we use a different token, so this is backwards compatible.
        if(hasHandle) {
            int32 tempHandle;
            if(buf.Get(tempHandle))
            {
                handle = tempHandle;
            }
            else
            {
                handle = -1;
            }
        }
        else
            handle = -1;

        if (type == Local) {
            // two possibilities:
            // name, diskRef, useCount
            // diskRef, useCount
            // diskRef + useCount = 12 bytes...
            if (buf.TestLimit(13))
            {
                buf.Get(tmpName,1023);
                SetName(tmpName);
            }
            buf.Get(diskRef);
            buf.Get(useCount);
        }
        else
        {
            // two possibilities:
            // name, diskRef, useCount
            // name, useCount
            buf.Get(tmpName,1023);
            SetName(tmpName);
            // useCount = 4 bytes...
            if (buf.TestLimit(5))
                buf.Get(diskRef);
            buf.Get(useCount);
        }
    }
    catch(...) {
        return false;
    }

    // going to make this fail if the buffer isn't empty.
    if (buf.TestLimit(1)) return false;

    return isValid();
}

/* Write Model Reference table
    Groups of models for the entire file.
    */

// Constructor
trpgModelTable::trpgModelTable()
{
}

trpgModelTable::~trpgModelTable()
{
}

// Reset function
void trpgModelTable::Reset()
{
    modelsMap.clear();
}

// Set functions
void trpgModelTable::SetNumModels(int /*no*/)
{
    // This method isn't needed with a map
    //models.resize(no);
}
void trpgModelTable::SetModel(int id,const trpgModel &mod)
{
    if (id < 0)
        return;

    modelsMap[id] = mod;
    //models[id] = mod;
}

int trpgModelTable::AddModel(trpgModel &mod)
{
    int hdl = modelsMap.size();
    if(mod.GetHandle()==-1) {
        modelsMap[hdl] = mod;
        return hdl;
    }
    modelsMap[mod.GetHandle()] = mod;
    return mod.GetHandle();
}

int trpgModelTable::FindAddModel(trpgModel &mod)
{

    ModelMapType::iterator itr = modelsMap.begin();
    for (  ; itr != modelsMap.end( ); itr++) {
        if(itr->second == mod) {
            return itr->first;
        }
    }
    return AddModel(mod);
}

bool trpgModelTable::FindByName(const char *name, unsigned int &mId)
{
    ModelMapType::const_iterator itr = modelsMap.begin();
    for (  ; itr != modelsMap.end( ); itr++) {
        char theName[1023];
        itr->second.GetName(theName,1023);
        if(strcmp(name,theName)==0) {
            mId = itr->first;
            return true;
        }
    }
    return false;
}

// Validity check
bool trpgModelTable::isValid() const
{
    ModelMapType::const_iterator itr = modelsMap.begin();
    for (  ; itr != modelsMap.end( ); itr++) {
        if(!itr->second.isValid()) {
            if(itr->second.getErrMess())
                errMess.assign(itr->second.getErrMess());
            return false;
        }
    }
    return true;
}

// Write out the model table
bool trpgModelTable::Write(trpgWriteBuffer &buf)
{
    if (!isValid())
        return false;

    buf.Begin(TRPGMODELTABLE);
    buf.Add((int32)modelsMap.size());
    ModelMapType::iterator itr = modelsMap.begin();
    for (  ; itr != modelsMap.end( ); itr++) {
        itr->second.Write(buf);
    }
    buf.End();

    return true;
}

/*    ***************
    Model Table Read methods
    ***************
    */

// Get methods
bool trpgModelTable::GetNumModels(int &nm) const
{
    if (!isValid())  return false;
    nm = modelsMap.size();
    return true;
}
bool trpgModelTable::GetModel(int id,trpgModel &model) const
{
    if (!isValid() || id < 0 ) //|| id >= models.size())
        return false;
    //model = models[id];
    ModelMapType::const_iterator itr = modelsMap.find(id);
    if(itr == modelsMap.end())    {
        return false;
    }
    model = itr->second;
    return true;
}
trpgModel *trpgModelTable::GetModelRef(int id)
{
    if (id < 0 ) //|| id >= models.size())
        return NULL;
    //return &models[id];
    ModelMapType::iterator itr = modelsMap.find(id);
    if(itr == modelsMap.end())    {
        return 0;
    }
    return &(itr->second);
}

bool trpgModelTable::Read(trpgReadBuffer &buf)
{
    int32 numModel;
    trpgToken tok;
    int32 len;
    bool status;

    try {
        buf.Get(numModel);
        for (int i=0;i<numModel;i++) {
            trpgModel model;
            buf.GetToken(tok,len);
            bool readHandle;
            if (tok == TRPGMODELREF)
                readHandle = false;
            else if (tok == TRPGMODELREF2)
                readHandle = true;
            else
                throw 1;
            buf.PushLimit(len);
            status = model.Read(buf,readHandle);
            buf.PopLimit();
            if (!status)  throw 1;
            AddModel(model);
        }
    }
    catch (...) {
        return false;
    }

    return isValid();
}
<commit_msg>Added null pointer handling<commit_after>/* ************************
   Copyright Terrain Experts Inc.
   Terrain Experts Inc (TERREX) reserves all rights to this source code
   unless otherwise specified in writing by the President of TERREX.
   This copyright may be updated in the future, in which case that version
   supercedes this one.
   -------------------
   Terrex Experts Inc.
   4400 East Broadway #314
   Tucson, AZ  85711
   info@terrex.com
   Tel: (520) 323-7990
   ************************
   */

#include <stdlib.h>
#include <stdio.h>
#include <string.h>

#define OLDMODELSTYLE

/* trpage_model.cpp
    This source file contains the methods trpgModel and trpgModelTable.
    You should only modify this code if you want to add data to these classes.
    */

#include <trpage_geom.h>
#include <trpage_read.h>

/* Write Model class
    Represents a model reference.
    */
trpgModel::trpgModel()
{
    name = NULL;
    type = External;
    useCount = 0;
    diskRef = -1;
    handle = -1;
    writeHandle = false;
}

trpgModel::trpgModel(const trpgModel &in):
    trpgReadWriteable(in)
{
    if (in.name)
    {
        name = new char[strlen(in.name)+1];
        strcpy(name,in.name);
    }
    else
        name = NULL;

    type=in.type;
    useCount=in.useCount;
    diskRef=in.diskRef;
    handle = in.handle;
    writeHandle = in.writeHandle;
}

// Reset function
void trpgModel::Reset()
{
    if (name)
        delete [] name;
    name = NULL;
    useCount = 0;
    diskRef = -1;
    handle = -1;
    writeHandle = false;
}

trpgModel::~trpgModel()
{
    Reset();
}

// Set functions
void trpgModel::SetType(int t)
{
    type = t;
}

void trpgModel::SetName(const char *nm)
{
    if (name)
        delete [] name;

    if (nm)
    {
        name = new char[strlen(nm)+1];
        strcpy(name,nm);
    }
}
void trpgModel::SetReference(trpgDiskRef pos)
{
    diskRef = pos;
}
void trpgModel::SetNumTiles(int num)
{
    useCount = num;
}
void trpgModel::AddTile()
{
    useCount++;
}

// Validity check
bool trpgModel::isValid() const
{
    if (type == External && !name)
    {
        errMess.assign("Model is external with no name");
        return false;
    }

    return true;
}

// Copy from one to another
trpgModel& trpgModel::operator = (const trpgModel &in)
{
    if (name) {
        delete [] name;
        name = NULL;
    }

    type = in.type;
    if (in.name)
        SetName(in.name);
    diskRef = in.diskRef;
    useCount = in.useCount;
    writeHandle = in.writeHandle;
    handle = in.handle;
    return *this;
}

// Compare two models
int trpgModel::operator == (const trpgModel &in) const
{
    if (type != in.type)
        return 0;

    switch (type) {
    case Local:
        if (diskRef == in.diskRef)
            return 1;
        else
            return 0;
        break;
    case External:
        if (!name && !in.name)
            return 1;
        if (!name || !in.name)
            return 0;
        if (strcmp(name,in.name))
            return 0;
        break;
    }

    return 1;
}

// Write a model reference out
bool trpgModel::Write(trpgWriteBuffer &buf)
{
    if (!isValid())
        return false;

    // We will use two different tokens to track the
    // format used in terrapage 2.2, and older versions
    int tok = TRPGMODELREF;
    if(writeHandle)
        tok = TRPGMODELREF2;

// Nick messed up the model entries when checking into txv4; now we're
// a bit stuck because U3 dbs don't have models in the U2 viewer.
// This will force the old behavior.
#ifdef OLDMODELSTYLE
    buf.Begin(tok);
    buf.Add(type);
    //writeHandle is only set for terrapage 2.2, and we use the different token.
    if(writeHandle) {
        buf.Add((int)handle);
    }
    if (name)
        buf.Add(name);
    else
        buf.Add(diskRef);
    buf.Add(useCount);

#else
    buf.Begin(tok);
    if(writeHandle) {
        buf.Add((int)handle);
    }
    buf.Add(type);
    buf.Add(name);
    buf.Add(diskRef);
    buf.Add(useCount);
#endif
    buf.End();

    return true;
}

/*    *******************
    Model Read Methods
    *******************
    */
// Get methods
bool trpgModel::GetType(int &t)
{
    if (!isValid()) return false;
    t = type;
    return true;
}
bool trpgModel::GetName(char *str,int strLen) const
{
    if (!isValid() || !name)
    {
        return false;
    }

    int len = strlen(name);
    strncpy(str,name,MIN(len,strLen)+1);

    return true;
}
bool trpgModel::GetNumTiles(int &ret) const
{
    if (!isValid()) return false;

    ret = useCount;
    return true;
}
bool trpgModel::GetReference(trpgDiskRef &ref) const
{
    if (!isValid() || type != Local) return false;
    ref = diskRef;
    return true;
}

bool trpgModel::Read(trpgReadBuffer &buf, bool hasHandle)
{
    // MD: added complexity here - written multiple ways by
    // mistake, unraveling the various cases.
    char tmpName[1024];

    try {
        buf.Get(type);
        // TerraPage 2.2 will store the unique handle after the type
        // we use a different token, so this is backwards compatible.
        if(hasHandle) {
            int32 tempHandle;
            if(buf.Get(tempHandle))
            {
                handle = tempHandle;
            }
            else
            {
                handle = -1;
            }
        }
        else
            handle = -1;

        if (type == Local) {
            // two possibilities:
            // name, diskRef, useCount
            // diskRef, useCount
            // diskRef + useCount = 12 bytes...
            if (buf.TestLimit(13))
            {
                buf.Get(tmpName,1023);
                SetName(tmpName);
            }
            buf.Get(diskRef);
            buf.Get(useCount);
        }
        else
        {
            // two possibilities:
            // name, diskRef, useCount
            // name, useCount
            buf.Get(tmpName,1023);
            SetName(tmpName);
            // useCount = 4 bytes...
            if (buf.TestLimit(5))
                buf.Get(diskRef);
            buf.Get(useCount);
        }
    }
    catch(...) {
        return false;
    }

    // going to make this fail if the buffer isn't empty.
    if (buf.TestLimit(1)) return false;

    return isValid();
}

/* Write Model Reference table
    Groups of models for the entire file.
    */

// Constructor
trpgModelTable::trpgModelTable()
{
}

trpgModelTable::~trpgModelTable()
{
}

// Reset function
void trpgModelTable::Reset()
{
    modelsMap.clear();
}

// Set functions
void trpgModelTable::SetNumModels(int /*no*/)
{
    // This method isn't needed with a map
    //models.resize(no);
}
void trpgModelTable::SetModel(int id,const trpgModel &mod)
{
    if (id < 0)
        return;

    modelsMap[id] = mod;
    //models[id] = mod;
}

int trpgModelTable::AddModel(trpgModel &mod)
{
    int hdl = modelsMap.size();
    if(mod.GetHandle()==-1) {
        modelsMap[hdl] = mod;
        return hdl;
    }
    modelsMap[mod.GetHandle()] = mod;
    return mod.GetHandle();
}

int trpgModelTable::FindAddModel(trpgModel &mod)
{

    ModelMapType::iterator itr = modelsMap.begin();
    for (  ; itr != modelsMap.end( ); itr++) {
        if(itr->second == mod) {
            return itr->first;
        }
    }
    return AddModel(mod);
}

bool trpgModelTable::FindByName(const char *name, unsigned int &mId)
{
    ModelMapType::const_iterator itr = modelsMap.begin();
    for (  ; itr != modelsMap.end( ); itr++) {
        char theName[1023];
        itr->second.GetName(theName,1023);
        if(strcmp(name,theName)==0) {
            mId = itr->first;
            return true;
        }
    }
    return false;
}

// Validity check
bool trpgModelTable::isValid() const
{
    ModelMapType::const_iterator itr = modelsMap.begin();
    for (  ; itr != modelsMap.end( ); itr++) {
        if(!itr->second.isValid()) {
            if(itr->second.getErrMess())
                errMess.assign(itr->second.getErrMess());
            return false;
        }
    }
    return true;
}

// Write out the model table
bool trpgModelTable::Write(trpgWriteBuffer &buf)
{
    if (!isValid())
        return false;

    buf.Begin(TRPGMODELTABLE);
    buf.Add((int32)modelsMap.size());
    ModelMapType::iterator itr = modelsMap.begin();
    for (  ; itr != modelsMap.end( ); itr++) {
        itr->second.Write(buf);
    }
    buf.End();

    return true;
}

/*    ***************
    Model Table Read methods
    ***************
    */

// Get methods
bool trpgModelTable::GetNumModels(int &nm) const
{
    if (!isValid())  return false;
    nm = modelsMap.size();
    return true;
}
bool trpgModelTable::GetModel(int id,trpgModel &model) const
{
    if (!isValid() || id < 0 ) //|| id >= models.size())
        return false;
    //model = models[id];
    ModelMapType::const_iterator itr = modelsMap.find(id);
    if(itr == modelsMap.end())    {
        return false;
    }
    model = itr->second;
    return true;
}
trpgModel *trpgModelTable::GetModelRef(int id)
{
    if (id < 0 ) //|| id >= models.size())
        return NULL;
    //return &models[id];
    ModelMapType::iterator itr = modelsMap.find(id);
    if(itr == modelsMap.end())    {
        return 0;
    }
    return &(itr->second);
}

bool trpgModelTable::Read(trpgReadBuffer &buf)
{
    int32 numModel;
    trpgToken tok;
    int32 len;
    bool status;

    try {
        buf.Get(numModel);
        for (int i=0;i<numModel;i++) {
            trpgModel model;
            buf.GetToken(tok,len);
            bool readHandle;
            if (tok == TRPGMODELREF)
                readHandle = false;
            else if (tok == TRPGMODELREF2)
                readHandle = true;
            else
                throw 1;
            buf.PushLimit(len);
            status = model.Read(buf,readHandle);
            buf.PopLimit();
            if (!status)  throw 1;
            AddModel(model);
        }
    }
    catch (...) {
        return false;
    }

    return isValid();
}
<|endoftext|>