<commit_before>// Copyright (c) 2011-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.

#if defined(HAVE_CONFIG_H)
#include <config/bitcoin-config.h>
#endif

#include <qt/addressbookpage.h>
#include <qt/forms/ui_addressbookpage.h>

#include <qt/addresstablemodel.h>
#include <qt/bitcoingui.h>
#include <qt/csvmodelwriter.h>
#include <qt/editaddressdialog.h>
#include <qt/guiutil.h>
#include <qt/platformstyle.h>

#include <QIcon>
#include <QMenu>
#include <QMessageBox>
#include <QSortFilterProxyModel>

class AddressBookSortFilterProxyModel final : public QSortFilterProxyModel {
    const QString m_type;

public:
    AddressBookSortFilterProxyModel(const QString &type, QObject *parent)
        : QSortFilterProxyModel(parent), m_type(type) {
        setDynamicSortFilter(true);
        setFilterCaseSensitivity(Qt::CaseInsensitive);
        setSortCaseSensitivity(Qt::CaseInsensitive);
    }

protected:
    bool filterAcceptsRow(int row, const QModelIndex &parent) const {
        auto model = sourceModel();
        auto label = model->index(row, AddressTableModel::Label, parent);

        if (model->data(label, AddressTableModel::TypeRole).toString() !=
            m_type) {
            return false;
        }

        auto address = model->index(row, AddressTableModel::Address, parent);

        if (filterRegExp().indexIn(model->data(address).toString()) < 0 &&
            filterRegExp().indexIn(model->data(label).toString()) < 0) {
            return false;
        }

        return true;
    }
};

AddressBookPage::AddressBookPage(const PlatformStyle *platformStyle, Mode _mode,
                                 Tabs _tab, QWidget *parent)
    : QDialog(parent), ui(new Ui::AddressBookPage), model(0), mode(_mode),
      tab(_tab) {
    ui->setupUi(this);

    if (!platformStyle->getImagesOnButtons()) {
        ui->newAddress->setIcon(QIcon());
        ui->copyAddress->setIcon(QIcon());
        ui->deleteAddress->setIcon(QIcon());
        ui->exportButton->setIcon(QIcon());
    } else {
        ui->newAddress->setIcon(platformStyle->SingleColorIcon(":/icons/add"));
        ui->copyAddress->setIcon(
            platformStyle->SingleColorIcon(":/icons/editcopy"));
        ui->deleteAddress->setIcon(
            platformStyle->SingleColorIcon(":/icons/remove"));
        ui->exportButton->setIcon(
            platformStyle->SingleColorIcon(":/icons/export"));
    }

    switch (mode) {
        case ForSelection:
            switch (tab) {
                case SendingTab:
                    setWindowTitle(tr("Choose the address to send coins to"));
                    break;
                case ReceivingTab:
                    setWindowTitle(
                        tr("Choose the address to receive coins with"));
                    break;
            }
            connect(ui->tableView, SIGNAL(doubleClicked(QModelIndex)), this,
                    SLOT(accept()));
            ui->tableView->setEditTriggers(QAbstractItemView::NoEditTriggers);
            ui->tableView->setFocus();
            ui->closeButton->setText(tr("C&hoose"));
            ui->exportButton->hide();
            break;
        case ForEditing:
            switch (tab) {
                case SendingTab:
                    setWindowTitle(tr("Sending addresses"));
                    break;
                case ReceivingTab:
                    setWindowTitle(tr("Receiving addresses"));
                    break;
            }
            break;
    }
    switch (tab) {
        case SendingTab:
            ui->labelExplanation->setText(
                tr("These are your Bitcoin addresses for sending payments. "
                   "Always check the amount and the receiving address before "
                   "sending coins."));
            ui->deleteAddress->setVisible(true);
            ui->newAddress->setVisible(true);
            break;
        case ReceivingTab:
            ui->labelExplanation->setText(
                tr("These are your Bitcoin addresses for receiving payments. "
                   "It is recommended to use a new receiving address for each "
                   "transaction."));
            ui->deleteAddress->setVisible(false);
            ui->newAddress->setVisible(false);
            break;
    }

    // Context menu actions
    QAction *copyAddressAction = new QAction(tr("&Copy Address"), this);
    QAction *copyLabelAction = new QAction(tr("Copy &Label"), this);
    QAction *editAction = new QAction(tr("&Edit"), this);
    deleteAction = new QAction(ui->deleteAddress->text(), this);

    // Build context menu
    contextMenu = new QMenu(this);
    contextMenu->addAction(copyAddressAction);
    contextMenu->addAction(copyLabelAction);
    contextMenu->addAction(editAction);
    if (tab == SendingTab) {
        contextMenu->addAction(deleteAction);
    }
    contextMenu->addSeparator();

    // Connect signals for context menu actions
    connect(copyAddressAction, SIGNAL(triggered()), this,
            SLOT(on_copyAddress_clicked()));
    connect(copyLabelAction, SIGNAL(triggered()), this,
            SLOT(onCopyLabelAction()));
    connect(editAction, SIGNAL(triggered()), this, SLOT(onEditAction()));
    connect(deleteAction, SIGNAL(triggered()), this,
            SLOT(on_deleteAddress_clicked()));

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

    connect(ui->closeButton, SIGNAL(clicked()), this, SLOT(accept()));
}

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

void AddressBookPage::setModel(AddressTableModel *_model) {
    this->model = _model;
    if (!_model) {
        return;
    }

    auto type = tab == ReceivingTab ? AddressTableModel::Receive
                                    : AddressTableModel::Send;
    proxyModel = new AddressBookSortFilterProxyModel(type, this);
    proxyModel->setSourceModel(_model);

    connect(ui->searchLineEdit, SIGNAL(textChanged(QString)), proxyModel,
            SLOT(setFilterWildcard(QString)));

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

    // Set column widths
    ui->tableView->horizontalHeader()->setSectionResizeMode(
        AddressTableModel::Label, QHeaderView::Stretch);
    ui->tableView->horizontalHeader()->setSectionResizeMode(
        AddressTableModel::Address, QHeaderView::ResizeToContents);

    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 AddressBookPage::on_copyAddress_clicked() {
    GUIUtil::copyEntryData(ui->tableView, AddressTableModel::Address);
}

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

void AddressBookPage::onEditAction() {
    if (!model) {
        return;
    }

    if (!ui->tableView->selectionModel()) {
        return;
    }
    QModelIndexList indexes = ui->tableView->selectionModel()->selectedRows();
    if (indexes.isEmpty()) {
        return;
    }

    EditAddressDialog dlg(tab == SendingTab
                              ? EditAddressDialog::EditSendingAddress
                              : EditAddressDialog::EditReceivingAddress,
                          this);
    dlg.setModel(model);
    QModelIndex origIndex = proxyModel->mapToSource(indexes.at(0));
    dlg.loadRow(origIndex.row());
    dlg.exec();
}

void AddressBookPage::on_newAddress_clicked() {
    if (!model) {
        return;
    }

    if (tab == ReceivingTab) {
        return;
    }

    EditAddressDialog dlg(EditAddressDialog::NewSendingAddress, this);
    dlg.setModel(model);
    if (dlg.exec()) {
        newAddressToSelect = dlg.getAddress();
    }
}

void AddressBookPage::on_deleteAddress_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 AddressBookPage::selectionChanged() {
    // Set button states based on selected tab and selection
    QTableView *table = ui->tableView;
    if (!table->selectionModel()) {
        return;
    }

    if (table->selectionModel()->hasSelection()) {
        switch (tab) {
            case SendingTab:
                // In sending tab, allow deletion of selection
                ui->deleteAddress->setEnabled(true);
                ui->deleteAddress->setVisible(true);
                deleteAction->setEnabled(true);
                break;
            case ReceivingTab:
                // Deleting receiving addresses, however, is not allowed
                ui->deleteAddress->setEnabled(false);
                ui->deleteAddress->setVisible(false);
                deleteAction->setEnabled(false);
                break;
        }
        ui->copyAddress->setEnabled(true);
    } else {
        ui->deleteAddress->setEnabled(false);
        ui->copyAddress->setEnabled(false);
    }
}

void AddressBookPage::done(int retval) {
    QTableView *table = ui->tableView;
    if (!table->selectionModel() || !table->model()) {
        return;
    }

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

    for (const 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 AddressBookPage::on_exportButton_clicked() {
    // CSV is currently the only supported format
    QString filename =
        GUIUtil::getSaveFileName(this, tr("Export Address List"), QString(),
                                 tr("Comma separated file (*.csv)"), nullptr);

    if (filename.isNull()) {
        return;
    }

    CSVModelWriter writer(filename);

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

    if (!writer.write()) {
        QMessageBox::critical(this, tr("Exporting Failed"),
                              tr("There was an error trying to save the "
                                 "address list to %1. Please try again.")
                                  .arg(filename));
    }
}

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

void AddressBookPage::selectNewAddress(const QModelIndex &parent, int begin,
                                       int /*end*/) {
    QModelIndex idx = proxyModel->mapFromSource(
        model->index(begin, AddressTableModel::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>Update qt/addressbookpage.cpp to use Qt5 connect syntax<commit_after>// Copyright (c) 2011-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.

#if defined(HAVE_CONFIG_H)
#include <config/bitcoin-config.h>
#endif

#include <qt/addressbookpage.h>
#include <qt/forms/ui_addressbookpage.h>

#include <qt/addresstablemodel.h>
#include <qt/bitcoingui.h>
#include <qt/csvmodelwriter.h>
#include <qt/editaddressdialog.h>
#include <qt/guiutil.h>
#include <qt/platformstyle.h>

#include <QIcon>
#include <QMenu>
#include <QMessageBox>
#include <QSortFilterProxyModel>

class AddressBookSortFilterProxyModel final : public QSortFilterProxyModel {
    const QString m_type;

public:
    AddressBookSortFilterProxyModel(const QString &type, QObject *parent)
        : QSortFilterProxyModel(parent), m_type(type) {
        setDynamicSortFilter(true);
        setFilterCaseSensitivity(Qt::CaseInsensitive);
        setSortCaseSensitivity(Qt::CaseInsensitive);
    }

protected:
    bool filterAcceptsRow(int row, const QModelIndex &parent) const {
        auto model = sourceModel();
        auto label = model->index(row, AddressTableModel::Label, parent);

        if (model->data(label, AddressTableModel::TypeRole).toString() !=
            m_type) {
            return false;
        }

        auto address = model->index(row, AddressTableModel::Address, parent);

        if (filterRegExp().indexIn(model->data(address).toString()) < 0 &&
            filterRegExp().indexIn(model->data(label).toString()) < 0) {
            return false;
        }

        return true;
    }
};

AddressBookPage::AddressBookPage(const PlatformStyle *platformStyle, Mode _mode,
                                 Tabs _tab, QWidget *parent)
    : QDialog(parent), ui(new Ui::AddressBookPage), model(0), mode(_mode),
      tab(_tab) {
    ui->setupUi(this);

    if (!platformStyle->getImagesOnButtons()) {
        ui->newAddress->setIcon(QIcon());
        ui->copyAddress->setIcon(QIcon());
        ui->deleteAddress->setIcon(QIcon());
        ui->exportButton->setIcon(QIcon());
    } else {
        ui->newAddress->setIcon(platformStyle->SingleColorIcon(":/icons/add"));
        ui->copyAddress->setIcon(
            platformStyle->SingleColorIcon(":/icons/editcopy"));
        ui->deleteAddress->setIcon(
            platformStyle->SingleColorIcon(":/icons/remove"));
        ui->exportButton->setIcon(
            platformStyle->SingleColorIcon(":/icons/export"));
    }

    switch (mode) {
        case ForSelection:
            switch (tab) {
                case SendingTab:
                    setWindowTitle(tr("Choose the address to send coins to"));
                    break;
                case ReceivingTab:
                    setWindowTitle(
                        tr("Choose the address to receive coins with"));
                    break;
            }
            connect(ui->tableView, &QTableView::doubleClicked, this,
                    &QDialog::accept);
            ui->tableView->setEditTriggers(QAbstractItemView::NoEditTriggers);
            ui->tableView->setFocus();
            ui->closeButton->setText(tr("C&hoose"));
            ui->exportButton->hide();
            break;
        case ForEditing:
            switch (tab) {
                case SendingTab:
                    setWindowTitle(tr("Sending addresses"));
                    break;
                case ReceivingTab:
                    setWindowTitle(tr("Receiving addresses"));
                    break;
            }
            break;
    }
    switch (tab) {
        case SendingTab:
            ui->labelExplanation->setText(
                tr("These are your Bitcoin addresses for sending payments. "
                   "Always check the amount and the receiving address before "
                   "sending coins."));
            ui->deleteAddress->setVisible(true);
            ui->newAddress->setVisible(true);
            break;
        case ReceivingTab:
            ui->labelExplanation->setText(
                tr("These are your Bitcoin addresses for receiving payments. "
                   "It is recommended to use a new receiving address for each "
                   "transaction."));
            ui->deleteAddress->setVisible(false);
            ui->newAddress->setVisible(false);
            break;
    }

    // Context menu actions
    QAction *copyAddressAction = new QAction(tr("&Copy Address"), this);
    QAction *copyLabelAction = new QAction(tr("Copy &Label"), this);
    QAction *editAction = new QAction(tr("&Edit"), this);
    deleteAction = new QAction(ui->deleteAddress->text(), this);

    // Build context menu
    contextMenu = new QMenu(this);
    contextMenu->addAction(copyAddressAction);
    contextMenu->addAction(copyLabelAction);
    contextMenu->addAction(editAction);
    if (tab == SendingTab) {
        contextMenu->addAction(deleteAction);
    }
    contextMenu->addSeparator();

    // Connect signals for context menu actions
    connect(copyAddressAction, &QAction::triggered, this,
            &AddressBookPage::on_copyAddress_clicked);
    connect(copyLabelAction, &QAction::triggered, this,
            &AddressBookPage::onCopyLabelAction);
    connect(editAction, &QAction::triggered, this,
            &AddressBookPage::onEditAction);
    connect(deleteAction, &QAction::triggered, this,
            &AddressBookPage::on_deleteAddress_clicked);

    connect(ui->tableView, &QWidget::customContextMenuRequested, this,
            &AddressBookPage::contextualMenu);

    connect(ui->closeButton, &QPushButton::clicked, this, &QDialog::accept);
}

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

void AddressBookPage::setModel(AddressTableModel *_model) {
    this->model = _model;
    if (!_model) {
        return;
    }

    auto type = tab == ReceivingTab ? AddressTableModel::Receive
                                    : AddressTableModel::Send;
    proxyModel = new AddressBookSortFilterProxyModel(type, this);
    proxyModel->setSourceModel(_model);

    connect(ui->searchLineEdit, &QLineEdit::textChanged, proxyModel,
            &QSortFilterProxyModel::setFilterWildcard);

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

    // Set column widths
    ui->tableView->horizontalHeader()->setSectionResizeMode(
        AddressTableModel::Label, QHeaderView::Stretch);
    ui->tableView->horizontalHeader()->setSectionResizeMode(
        AddressTableModel::Address, QHeaderView::ResizeToContents);

    connect(ui->tableView->selectionModel(),
            &QItemSelectionModel::selectionChanged, this,
            &AddressBookPage::selectionChanged);

    // Select row for newly created address
    connect(_model, &AddressTableModel::rowsInserted, this,
            &AddressBookPage::selectNewAddress);

    selectionChanged();
}

void AddressBookPage::on_copyAddress_clicked() {
    GUIUtil::copyEntryData(ui->tableView, AddressTableModel::Address);
}

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

void AddressBookPage::onEditAction() {
    if (!model) {
        return;
    }

    if (!ui->tableView->selectionModel()) {
        return;
    }
    QModelIndexList indexes = ui->tableView->selectionModel()->selectedRows();
    if (indexes.isEmpty()) {
        return;
    }

    EditAddressDialog dlg(tab == SendingTab
                              ? EditAddressDialog::EditSendingAddress
                              : EditAddressDialog::EditReceivingAddress,
                          this);
    dlg.setModel(model);
    QModelIndex origIndex = proxyModel->mapToSource(indexes.at(0));
    dlg.loadRow(origIndex.row());
    dlg.exec();
}

void AddressBookPage::on_newAddress_clicked() {
    if (!model) {
        return;
    }

    if (tab == ReceivingTab) {
        return;
    }

    EditAddressDialog dlg(EditAddressDialog::NewSendingAddress, this);
    dlg.setModel(model);
    if (dlg.exec()) {
        newAddressToSelect = dlg.getAddress();
    }
}

void AddressBookPage::on_deleteAddress_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 AddressBookPage::selectionChanged() {
    // Set button states based on selected tab and selection
    QTableView *table = ui->tableView;
    if (!table->selectionModel()) {
        return;
    }

    if (table->selectionModel()->hasSelection()) {
        switch (tab) {
            case SendingTab:
                // In sending tab, allow deletion of selection
                ui->deleteAddress->setEnabled(true);
                ui->deleteAddress->setVisible(true);
                deleteAction->setEnabled(true);
                break;
            case ReceivingTab:
                // Deleting receiving addresses, however, is not allowed
                ui->deleteAddress->setEnabled(false);
                ui->deleteAddress->setVisible(false);
                deleteAction->setEnabled(false);
                break;
        }
        ui->copyAddress->setEnabled(true);
    } else {
        ui->deleteAddress->setEnabled(false);
        ui->copyAddress->setEnabled(false);
    }
}

void AddressBookPage::done(int retval) {
    QTableView *table = ui->tableView;
    if (!table->selectionModel() || !table->model()) {
        return;
    }

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

    for (const 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 AddressBookPage::on_exportButton_clicked() {
    // CSV is currently the only supported format
    QString filename =
        GUIUtil::getSaveFileName(this, tr("Export Address List"), QString(),
                                 tr("Comma separated file (*.csv)"), nullptr);

    if (filename.isNull()) {
        return;
    }

    CSVModelWriter writer(filename);

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

    if (!writer.write()) {
        QMessageBox::critical(this, tr("Exporting Failed"),
                              tr("There was an error trying to save the "
                                 "address list to %1. Please try again.")
                                  .arg(filename));
    }
}

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

void AddressBookPage::selectNewAddress(const QModelIndex &parent, int begin,
                                       int /*end*/) {
    QModelIndex idx = proxyModel->mapFromSource(
        model->index(begin, AddressTableModel::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) 2011-2020 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#if defined(HAVE_CONFIG_H)
#include <config/bitcoin-config.h>
#endif

#include <qt/addressbookpage.h>
#include <qt/forms/ui_addressbookpage.h>

#include <qt/addresstablemodel.h>
#include <qt/csvmodelwriter.h>
#include <qt/editaddressdialog.h>
#include <qt/guiutil.h>
#include <qt/platformstyle.h>

#include <QIcon>
#include <QMenu>
#include <QMessageBox>
#include <QSortFilterProxyModel>

class AddressBookSortFilterProxyModel final : public QSortFilterProxyModel
{
    const QString m_type;

public:
    AddressBookSortFilterProxyModel(const QString& type, QObject* parent)
        : QSortFilterProxyModel(parent)
        , m_type(type)
    {
        setDynamicSortFilter(true);
        setFilterCaseSensitivity(Qt::CaseInsensitive);
        setSortCaseSensitivity(Qt::CaseInsensitive);
    }

protected:
    bool filterAcceptsRow(int row, const QModelIndex& parent) const override
    {
        auto model = sourceModel();
        auto label = model->index(row, AddressTableModel::Label, parent);

        if (model->data(label, AddressTableModel::TypeRole).toString() != m_type) {
            return false;
        }

        auto address = model->index(row, AddressTableModel::Address, parent);

        if (filterRegExp().indexIn(model->data(address).toString()) < 0 &&
            filterRegExp().indexIn(model->data(label).toString()) < 0) {
            return false;
        }

        return true;
    }
};

AddressBookPage::AddressBookPage(const PlatformStyle *platformStyle, Mode _mode, Tabs _tab, QWidget *parent) :
    QDialog(parent, GUIUtil::dialog_flags),
    ui(new Ui::AddressBookPage),
    model(nullptr),
    mode(_mode),
    tab(_tab)
{
    ui->setupUi(this);

    if (!platformStyle->getImagesOnButtons()) {
        ui->newAddress->setIcon(QIcon());
        ui->copyAddress->setIcon(QIcon());
        ui->deleteAddress->setIcon(QIcon());
        ui->exportButton->setIcon(QIcon());
    } else {
        ui->newAddress->setIcon(platformStyle->SingleColorIcon(":/icons/add"));
        ui->copyAddress->setIcon(platformStyle->SingleColorIcon(":/icons/editcopy"));
        ui->deleteAddress->setIcon(platformStyle->SingleColorIcon(":/icons/remove"));
        ui->exportButton->setIcon(platformStyle->SingleColorIcon(":/icons/export"));
    }

    switch(mode)
    {
    case ForSelection:
        switch(tab)
        {
        case SendingTab: setWindowTitle(tr("Choose the address to send coins to")); break;
        case ReceivingTab: setWindowTitle(tr("Choose the address to receive coins with")); break;
        }
        connect(ui->tableView, &QTableView::doubleClicked, this, &QDialog::accept);
        ui->tableView->setEditTriggers(QAbstractItemView::NoEditTriggers);
        ui->tableView->setFocus();
        ui->closeButton->setText(tr("C&hoose"));
        ui->exportButton->hide();
        break;
    case ForEditing:
        switch(tab)
        {
        case SendingTab: setWindowTitle(tr("Sending addresses")); break;
        case ReceivingTab: setWindowTitle(tr("Receiving addresses")); break;
        }
        break;
    }
    switch(tab)
    {
    case SendingTab:
        ui->labelExplanation->setText(tr("These are your Bitcoin addresses for sending payments. Always check the amount and the receiving address before sending coins."));
        ui->deleteAddress->setVisible(true);
        ui->newAddress->setVisible(true);
        break;
    case ReceivingTab:
        ui->labelExplanation->setText(tr("These are your Bitcoin addresses for receiving payments. Use the 'Create new receiving address' button in the receive tab to create new addresses.\nSigning is only possible with addresses of the type 'legacy'."));
        ui->deleteAddress->setVisible(false);
        ui->newAddress->setVisible(false);
        break;
    }

    // Context menu actions
    QAction *copyAddressAction = new QAction(tr("&Copy Address"), this);
    QAction *copyLabelAction = new QAction(tr("Copy &Label"), this);
    QAction *editAction = new QAction(tr("&Edit"), this);

    // Build context menu
    contextMenu = new QMenu(this);
    contextMenu->addAction(copyAddressAction);
    contextMenu->addAction(copyLabelAction);
    contextMenu->addAction(editAction);
    if (tab == SendingTab) {
        QAction* deleteAction = new QAction(ui->deleteAddress->text(), this);
        contextMenu->addAction(deleteAction);
        connect(deleteAction, &QAction::triggered, this, &AddressBookPage::on_deleteAddress_clicked);
    }
    contextMenu->addSeparator();

    // Connect signals for context menu actions
    connect(copyAddressAction, &QAction::triggered, this, &AddressBookPage::on_copyAddress_clicked);
    connect(copyLabelAction, &QAction::triggered, this, &AddressBookPage::onCopyLabelAction);
    connect(editAction, &QAction::triggered, this, &AddressBookPage::onEditAction);

    connect(ui->tableView, &QWidget::customContextMenuRequested, this, &AddressBookPage::contextualMenu);

    connect(ui->closeButton, &QPushButton::clicked, this, &QDialog::accept);

    GUIUtil::handleCloseWindowShortcut(this);
}

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

void AddressBookPage::setModel(AddressTableModel *_model)
{
    this->model = _model;
    if(!_model)
        return;

    auto type = tab == ReceivingTab ? AddressTableModel::Receive : AddressTableModel::Send;
    proxyModel = new AddressBookSortFilterProxyModel(type, this);
    proxyModel->setSourceModel(_model);

    connect(ui->searchLineEdit, &QLineEdit::textChanged, proxyModel, &QSortFilterProxyModel::setFilterWildcard);

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

    // Set column widths
    ui->tableView->horizontalHeader()->setSectionResizeMode(AddressTableModel::Label, QHeaderView::Stretch);
    ui->tableView->horizontalHeader()->setSectionResizeMode(AddressTableModel::Address, QHeaderView::ResizeToContents);

    connect(ui->tableView->selectionModel(), &QItemSelectionModel::selectionChanged,
        this, &AddressBookPage::selectionChanged);

    // Select row for newly created address
    connect(_model, &AddressTableModel::rowsInserted, this, &AddressBookPage::selectNewAddress);

    selectionChanged();
}

void AddressBookPage::on_copyAddress_clicked()
{
    GUIUtil::copyEntryData(ui->tableView, AddressTableModel::Address);
}

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

void AddressBookPage::onEditAction()
{
    if(!model)
        return;

    if(!ui->tableView->selectionModel())
        return;
    QModelIndexList indexes = ui->tableView->selectionModel()->selectedRows();
    if(indexes.isEmpty())
        return;

    EditAddressDialog dlg(
        tab == SendingTab ?
        EditAddressDialog::EditSendingAddress :
        EditAddressDialog::EditReceivingAddress, this);
    dlg.setModel(model);
    QModelIndex origIndex = proxyModel->mapToSource(indexes.at(0));
    dlg.loadRow(origIndex.row());
    dlg.exec();
}

void AddressBookPage::on_newAddress_clicked()
{
    if(!model)
        return;

    if (tab == ReceivingTab) {
        return;
    }

    EditAddressDialog dlg(EditAddressDialog::NewSendingAddress, this);
    dlg.setModel(model);
    if(dlg.exec())
    {
        newAddressToSelect = dlg.getAddress();
    }
}

void AddressBookPage::on_deleteAddress_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 AddressBookPage::selectionChanged()
{
    // Set button states based on selected tab and selection
    QTableView *table = ui->tableView;
    if(!table->selectionModel())
        return;

    if(table->selectionModel()->hasSelection())
    {
        switch(tab)
        {
        case SendingTab:
            // In sending tab, allow deletion of selection
            ui->deleteAddress->setEnabled(true);
            ui->deleteAddress->setVisible(true);
            break;
        case ReceivingTab:
            // Deleting receiving addresses, however, is not allowed
            ui->deleteAddress->setEnabled(false);
            ui->deleteAddress->setVisible(false);
            break;
        }
        ui->copyAddress->setEnabled(true);
    }
    else
    {
        ui->deleteAddress->setEnabled(false);
        ui->copyAddress->setEnabled(false);
    }
}

void AddressBookPage::done(int retval)
{
    QTableView *table = ui->tableView;
    if(!table->selectionModel() || !table->model())
        return;

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

    for (const 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 AddressBookPage::on_exportButton_clicked()
{
    // CSV is currently the only supported format
    QString filename = GUIUtil::getSaveFileName(this,
        tr("Export Address List"), QString(),
        tr("Comma separated file", "Name of CSV file format") + QLatin1String(" (*.csv)"), nullptr);

    if (filename.isNull())
        return;

    CSVModelWriter writer(filename);

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

    if(!writer.write()) {
        QMessageBox::critical(this, tr("Exporting Failed"),
            tr("There was an error trying to save the address list to %1. Please try again.").arg(filename));
    }
}

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

void AddressBookPage::selectNewAddress(const QModelIndex &parent, int begin, int /*end*/)
{
    QModelIndex idx = proxyModel->mapFromSource(model->index(begin, AddressTableModel::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>qt: Drop menu separator that separates nothing<commit_after>// Copyright (c) 2011-2020 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#if defined(HAVE_CONFIG_H)
#include <config/bitcoin-config.h>
#endif

#include <qt/addressbookpage.h>
#include <qt/forms/ui_addressbookpage.h>

#include <qt/addresstablemodel.h>
#include <qt/csvmodelwriter.h>
#include <qt/editaddressdialog.h>
#include <qt/guiutil.h>
#include <qt/platformstyle.h>

#include <QIcon>
#include <QMenu>
#include <QMessageBox>
#include <QSortFilterProxyModel>

class AddressBookSortFilterProxyModel final : public QSortFilterProxyModel
{
    const QString m_type;

public:
    AddressBookSortFilterProxyModel(const QString& type, QObject* parent)
        : QSortFilterProxyModel(parent)
        , m_type(type)
    {
        setDynamicSortFilter(true);
        setFilterCaseSensitivity(Qt::CaseInsensitive);
        setSortCaseSensitivity(Qt::CaseInsensitive);
    }

protected:
    bool filterAcceptsRow(int row, const QModelIndex& parent) const override
    {
        auto model = sourceModel();
        auto label = model->index(row, AddressTableModel::Label, parent);

        if (model->data(label, AddressTableModel::TypeRole).toString() != m_type) {
            return false;
        }

        auto address = model->index(row, AddressTableModel::Address, parent);

        if (filterRegExp().indexIn(model->data(address).toString()) < 0 &&
            filterRegExp().indexIn(model->data(label).toString()) < 0) {
            return false;
        }

        return true;
    }
};

AddressBookPage::AddressBookPage(const PlatformStyle *platformStyle, Mode _mode, Tabs _tab, QWidget *parent) :
    QDialog(parent, GUIUtil::dialog_flags),
    ui(new Ui::AddressBookPage),
    model(nullptr),
    mode(_mode),
    tab(_tab)
{
    ui->setupUi(this);

    if (!platformStyle->getImagesOnButtons()) {
        ui->newAddress->setIcon(QIcon());
        ui->copyAddress->setIcon(QIcon());
        ui->deleteAddress->setIcon(QIcon());
        ui->exportButton->setIcon(QIcon());
    } else {
        ui->newAddress->setIcon(platformStyle->SingleColorIcon(":/icons/add"));
        ui->copyAddress->setIcon(platformStyle->SingleColorIcon(":/icons/editcopy"));
        ui->deleteAddress->setIcon(platformStyle->SingleColorIcon(":/icons/remove"));
        ui->exportButton->setIcon(platformStyle->SingleColorIcon(":/icons/export"));
    }

    switch(mode)
    {
    case ForSelection:
        switch(tab)
        {
        case SendingTab: setWindowTitle(tr("Choose the address to send coins to")); break;
        case ReceivingTab: setWindowTitle(tr("Choose the address to receive coins with")); break;
        }
        connect(ui->tableView, &QTableView::doubleClicked, this, &QDialog::accept);
        ui->tableView->setEditTriggers(QAbstractItemView::NoEditTriggers);
        ui->tableView->setFocus();
        ui->closeButton->setText(tr("C&hoose"));
        ui->exportButton->hide();
        break;
    case ForEditing:
        switch(tab)
        {
        case SendingTab: setWindowTitle(tr("Sending addresses")); break;
        case ReceivingTab: setWindowTitle(tr("Receiving addresses")); break;
        }
        break;
    }
    switch(tab)
    {
    case SendingTab:
        ui->labelExplanation->setText(tr("These are your Bitcoin addresses for sending payments. Always check the amount and the receiving address before sending coins."));
        ui->deleteAddress->setVisible(true);
        ui->newAddress->setVisible(true);
        break;
    case ReceivingTab:
        ui->labelExplanation->setText(tr("These are your Bitcoin addresses for receiving payments. Use the 'Create new receiving address' button in the receive tab to create new addresses.\nSigning is only possible with addresses of the type 'legacy'."));
        ui->deleteAddress->setVisible(false);
        ui->newAddress->setVisible(false);
        break;
    }

    // Context menu actions
    QAction *copyAddressAction = new QAction(tr("&Copy Address"), this);
    QAction *copyLabelAction = new QAction(tr("Copy &Label"), this);
    QAction *editAction = new QAction(tr("&Edit"), this);

    // Build context menu
    contextMenu = new QMenu(this);
    contextMenu->addAction(copyAddressAction);
    contextMenu->addAction(copyLabelAction);
    contextMenu->addAction(editAction);
    if (tab == SendingTab) {
        QAction* deleteAction = new QAction(ui->deleteAddress->text(), this);
        contextMenu->addAction(deleteAction);
        connect(deleteAction, &QAction::triggered, this, &AddressBookPage::on_deleteAddress_clicked);
    }

    // Connect signals for context menu actions
    connect(copyAddressAction, &QAction::triggered, this, &AddressBookPage::on_copyAddress_clicked);
    connect(copyLabelAction, &QAction::triggered, this, &AddressBookPage::onCopyLabelAction);
    connect(editAction, &QAction::triggered, this, &AddressBookPage::onEditAction);

    connect(ui->tableView, &QWidget::customContextMenuRequested, this, &AddressBookPage::contextualMenu);
    connect(ui->closeButton, &QPushButton::clicked, this, &QDialog::accept);

    GUIUtil::handleCloseWindowShortcut(this);
}

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

void AddressBookPage::setModel(AddressTableModel *_model)
{
    this->model = _model;
    if(!_model)
        return;

    auto type = tab == ReceivingTab ? AddressTableModel::Receive : AddressTableModel::Send;
    proxyModel = new AddressBookSortFilterProxyModel(type, this);
    proxyModel->setSourceModel(_model);

    connect(ui->searchLineEdit, &QLineEdit::textChanged, proxyModel, &QSortFilterProxyModel::setFilterWildcard);

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

    // Set column widths
    ui->tableView->horizontalHeader()->setSectionResizeMode(AddressTableModel::Label, QHeaderView::Stretch);
    ui->tableView->horizontalHeader()->setSectionResizeMode(AddressTableModel::Address, QHeaderView::ResizeToContents);

    connect(ui->tableView->selectionModel(), &QItemSelectionModel::selectionChanged,
        this, &AddressBookPage::selectionChanged);

    // Select row for newly created address
    connect(_model, &AddressTableModel::rowsInserted, this, &AddressBookPage::selectNewAddress);

    selectionChanged();
}

void AddressBookPage::on_copyAddress_clicked()
{
    GUIUtil::copyEntryData(ui->tableView, AddressTableModel::Address);
}

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

void AddressBookPage::onEditAction()
{
    if(!model)
        return;

    if(!ui->tableView->selectionModel())
        return;
    QModelIndexList indexes = ui->tableView->selectionModel()->selectedRows();
    if(indexes.isEmpty())
        return;

    EditAddressDialog dlg(
        tab == SendingTab ?
        EditAddressDialog::EditSendingAddress :
        EditAddressDialog::EditReceivingAddress, this);
    dlg.setModel(model);
    QModelIndex origIndex = proxyModel->mapToSource(indexes.at(0));
    dlg.loadRow(origIndex.row());
    dlg.exec();
}

void AddressBookPage::on_newAddress_clicked()
{
    if(!model)
        return;

    if (tab == ReceivingTab) {
        return;
    }

    EditAddressDialog dlg(EditAddressDialog::NewSendingAddress, this);
    dlg.setModel(model);
    if(dlg.exec())
    {
        newAddressToSelect = dlg.getAddress();
    }
}

void AddressBookPage::on_deleteAddress_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 AddressBookPage::selectionChanged()
{
    // Set button states based on selected tab and selection
    QTableView *table = ui->tableView;
    if(!table->selectionModel())
        return;

    if(table->selectionModel()->hasSelection())
    {
        switch(tab)
        {
        case SendingTab:
            // In sending tab, allow deletion of selection
            ui->deleteAddress->setEnabled(true);
            ui->deleteAddress->setVisible(true);
            break;
        case ReceivingTab:
            // Deleting receiving addresses, however, is not allowed
            ui->deleteAddress->setEnabled(false);
            ui->deleteAddress->setVisible(false);
            break;
        }
        ui->copyAddress->setEnabled(true);
    }
    else
    {
        ui->deleteAddress->setEnabled(false);
        ui->copyAddress->setEnabled(false);
    }
}

void AddressBookPage::done(int retval)
{
    QTableView *table = ui->tableView;
    if(!table->selectionModel() || !table->model())
        return;

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

    for (const 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 AddressBookPage::on_exportButton_clicked()
{
    // CSV is currently the only supported format
    QString filename = GUIUtil::getSaveFileName(this,
        tr("Export Address List"), QString(),
        tr("Comma separated file", "Name of CSV file format") + QLatin1String(" (*.csv)"), nullptr);

    if (filename.isNull())
        return;

    CSVModelWriter writer(filename);

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

    if(!writer.write()) {
        QMessageBox::critical(this, tr("Exporting Failed"),
            tr("There was an error trying to save the address list to %1. Please try again.").arg(filename));
    }
}

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

void AddressBookPage::selectNewAddress(const QModelIndex &parent, int begin, int /*end*/)
{
    QModelIndex idx = proxyModel->mapFromSource(model->index(begin, AddressTableModel::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>/*
  This file is part of KDE Kontact.

  Copyright (C) 2003 Cornelius Schumacher <schumacher@kde.org>

  This program is free software; you can redistribute it and/or
  modify it under the terms of the GNU General Public
  License as published by the Free Software Foundation; either
  version 2 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
  General Public License for more details.

  You should have received a copy of the GNU General Public License
  along with this program; see the file COPYING.  If not, write to
  the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
  Boston, MA 02111-1307, USA.
 */

#include <qptrlist.h>
#include <qwidgetstack.h>
#include <qsignal.h>
#include <qobjectlist.h>
#include <qlabel.h>
#include <qpainter.h>
#include <qbitmap.h>
#include <qfontmetrics.h>
#include <qstyle.h>
#include <qframe.h>
#include <qdrawutil.h>

#include <kapplication.h>
#include <kconfig.h>
#include <klocale.h>
#include <kiconloader.h>
#include <sidebarextension.h>

#include <kdebug.h>

#include "mainwindow.h"

#include "plugin.h"

#include "iconsidepane.h"

using namespace Kontact;

EntryItem::EntryItem( QListBox *parent, Kontact::Plugin *plugin )
  : QListBoxItem( parent ),
    mPlugin( plugin )
{
  mPixmap = KGlobal::iconLoader()->loadIcon( plugin->icon(),
                                             KIcon::Desktop, 48 );
  setCustomHighlighting( true );
  setText( plugin->title() );
}

EntryItem::~EntryItem()
{
}

int EntryItem::width( const QListBox *listbox) const
{
  int w;
  if ( text().isEmpty() )
    w = mPixmap.width();
  else
    w = QMAX( mPixmap.width(), listbox->fontMetrics().width( text() ) );

  return w + 18;
}

int EntryItem::height( const QListBox *listbox) const
{
  int h;
  if ( text().isEmpty() )
    h =  mPixmap.height();
  else
    h = mPixmap.height() + listbox->fontMetrics().lineSpacing();

  return h + 4;
}

void EntryItem::paint( QPainter *p )
{
  QListBox *box = listBox();
  int w = box->viewport()->width();
  int y = 2;

  if ( !mPixmap.isNull() ) {
    int x = ( w - mPixmap.width() ) / 2;
    p->drawPixmap( x, y, mPixmap );
  }

  if ( !text().isEmpty() ) {
    QFontMetrics fm = p->fontMetrics();
    y += mPixmap.height() + fm.height() - fm.descent();
    int x = ( w - fm.width( text() ) ) / 2;
    p->drawText( x, y, text() );
  }
  // draw sunken
  if ( isCurrent() || isSelected() ) {
    QColorGroup group = box->colorGroup();
    group.setColor( QColorGroup::Dark, Qt::black );
    qDrawShadePanel( p, 1, 0, w - 2, height( box ),
                     group, true, 1, 0 );
  }
}

Navigator::Navigator( SidePaneBase *parent, const char *name)
  : KListBox( parent, name ), mSidePane( parent )
{
  setSelectionMode( KListBox::Single );

  viewport()->setBackgroundMode( PaletteDark );

  QPalette pal = palette();
  QColor gray = colorGroup().shadow();
  pal.setColor( QPalette::Normal, QColorGroup::Text, Qt::white );
  pal.setColor( QPalette::Inactive, QColorGroup::Text, Qt::white );
  pal.setColor( QPalette::Normal, QColorGroup::HighlightedText, Qt::white );
  pal.setColor( QPalette::Inactive, QColorGroup::HighlightedText, Qt::white );

  setPalette( pal );

  setHScrollBarMode( QScrollView::AlwaysOff );

  setAcceptDrops( true );

  connect( this, SIGNAL( currentChanged( QListBoxItem * ) ),
           SLOT( slotExecuted( QListBoxItem * ) ) );
}

QSize Navigator::sizeHint() const
{
  return QSize( 100, 100 );
}

void Navigator::updatePlugins( QValueList<Kontact::Plugin*> plugins )
{
  clear();

  int minWidth = 0;
  QValueList<Kontact::Plugin*>::ConstIterator end = plugins.end();
  QValueList<Kontact::Plugin*>::ConstIterator it = plugins.begin();
  for ( ; it != end; ++it ) {
    Kontact::Plugin *plugin = *it;
    if ( !plugin->showInSideBar() )
      continue;

    EntryItem *item = new EntryItem( this, plugin );

    if ( item->width( this ) > minWidth )
      minWidth = item->width( this );
  }

  parentWidget()->setFixedWidth( minWidth );
}

void Navigator::slotExecuted( QListBoxItem *item )
{
  if ( !item ) return;

  EntryItem *entry = static_cast<EntryItem *>( item );

  emit pluginActivated( entry->plugin() );
}

void Navigator::dragEnterEvent( QDragEnterEvent *event )
{
  kdDebug() << "Navigator::dragEnterEvent()" << endl;

  dragMoveEvent( event );
}

void Navigator::dragMoveEvent( QDragMoveEvent *event )
{
  kdDebug() << "Navigator::dragEnterEvent()" << endl;

  kdDebug() << "  Format: " << event->format() << endl;

  QListBoxItem *item = itemAt( event->pos() );

  if ( !item ) {
    event->accept( false );
    return;
  }

  EntryItem *entry = static_cast<EntryItem *>( item );

  kdDebug() << "  PLUGIN: " << entry->plugin()->identifier() << endl;

  event->accept( entry->plugin()->canDecodeDrag( event ) );
}

void Navigator::dropEvent( QDropEvent *event )
{
  kdDebug() << "Navigator::dropEvent()" << endl;

  QListBoxItem *item = itemAt( event->pos() );

  if ( !item ) {
    return;
  }

  EntryItem *entry = static_cast<EntryItem *>( item );

  kdDebug() << "  PLUGIN: " << entry->plugin()->identifier() << endl;

  // Make sure the part is loaded before calling processDropEvent.
  // Maybe it's better, if that would be done by the plugin.
  // Hmm, this doesn't work anyway.
  mSidePane->selectPlugin( entry->plugin() );

  entry->plugin()->processDropEvent( event );
}

IconSidePane::IconSidePane( Core *core, QWidget *parent, const char *name )
  : SidePaneBase( core, parent, name )
{
  mNavigator = new Navigator( this );
  connect( mNavigator, SIGNAL( pluginActivated( Kontact::Plugin * ) ),
           SIGNAL( pluginSelected( Kontact::Plugin * ) ) );

  setAcceptDrops( true );
}

IconSidePane::~IconSidePane()
{
}

void IconSidePane::updatePlugins()
{
  mNavigator->updatePlugins( core()->pluginList() );
}

void IconSidePane::selectPlugin( Kontact::Plugin *plugin )
{
  bool blocked = signalsBlocked();
  blockSignals( true );

  uint i;
  for ( i = 0; i < mNavigator->count(); ++i ) {
    EntryItem *item = static_cast<EntryItem *>( mNavigator->item( i ) );
    if ( item->plugin() == plugin ) {
      mNavigator->setCurrentItem( i );
      break;
    }
  }

  blockSignals( blocked );
}

void IconSidePane::selectPlugin( const QString &name )
{
  bool blocked = signalsBlocked();
  blockSignals( true );

  uint i;
  for ( i = 0; i < mNavigator->count(); ++i ) {
    EntryItem *item = static_cast<EntryItem *>( mNavigator->item( i ) );
    if ( item->plugin()->identifier() == name ) {
      mNavigator->setCurrentItem( i );
      break;
    }
  }

  blockSignals( blocked );
}

#include "iconsidepane.moc"

// vim: sw=2 sts=2 et tw=80
<commit_msg>Dark is too dark.<commit_after>/*
  This file is part of KDE Kontact.

  Copyright (C) 2003 Cornelius Schumacher <schumacher@kde.org>

  This program is free software; you can redistribute it and/or
  modify it under the terms of the GNU General Public
  License as published by the Free Software Foundation; either
  version 2 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
  General Public License for more details.

  You should have received a copy of the GNU General Public License
  along with this program; see the file COPYING.  If not, write to
  the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
  Boston, MA 02111-1307, USA.
 */

#include <qptrlist.h>
#include <qwidgetstack.h>
#include <qsignal.h>
#include <qobjectlist.h>
#include <qlabel.h>
#include <qpainter.h>
#include <qbitmap.h>
#include <qfontmetrics.h>
#include <qstyle.h>
#include <qframe.h>
#include <qdrawutil.h>

#include <kapplication.h>
#include <kconfig.h>
#include <klocale.h>
#include <kiconloader.h>
#include <sidebarextension.h>

#include <kdebug.h>

#include "mainwindow.h"

#include "plugin.h"

#include "iconsidepane.h"

using namespace Kontact;

EntryItem::EntryItem( QListBox *parent, Kontact::Plugin *plugin )
  : QListBoxItem( parent ),
    mPlugin( plugin )
{
  mPixmap = KGlobal::iconLoader()->loadIcon( plugin->icon(),
                                             KIcon::Desktop, 48 );
  setCustomHighlighting( true );
  setText( plugin->title() );
}

EntryItem::~EntryItem()
{
}

int EntryItem::width( const QListBox *listbox) const
{
  int w;
  if ( text().isEmpty() )
    w = mPixmap.width();
  else
    w = QMAX( mPixmap.width(), listbox->fontMetrics().width( text() ) );

  return w + 18;
}

int EntryItem::height( const QListBox *listbox) const
{
  int h;
  if ( text().isEmpty() )
    h =  mPixmap.height();
  else
    h = mPixmap.height() + listbox->fontMetrics().lineSpacing();

  return h + 4;
}

void EntryItem::paint( QPainter *p )
{
  QListBox *box = listBox();
  int w = box->viewport()->width();
  int y = 2;

  if ( !mPixmap.isNull() ) {
    int x = ( w - mPixmap.width() ) / 2;
    p->drawPixmap( x, y, mPixmap );
  }

  if ( !text().isEmpty() ) {
    QFontMetrics fm = p->fontMetrics();
    y += mPixmap.height() + fm.height() - fm.descent();
    int x = ( w - fm.width( text() ) ) / 2;
    p->drawText( x, y, text() );
  }
  // draw sunken
  if ( isCurrent() || isSelected() ) {
    QColorGroup group = box->colorGroup();
    group.setColor( QColorGroup::Dark, Qt::black );
    qDrawShadePanel( p, 1, 0, w - 2, height( box ),
                     group, true, 1, 0 );
  }
}

Navigator::Navigator( SidePaneBase *parent, const char *name)
  : KListBox( parent, name ), mSidePane( parent )
{
  setSelectionMode( KListBox::Single );

  viewport()->setBackgroundMode( PaletteMid );

  QPalette pal = palette();
  QColor gray = colorGroup().shadow();
  pal.setColor( QPalette::Normal, QColorGroup::Text, Qt::white );
  pal.setColor( QPalette::Inactive, QColorGroup::Text, Qt::white );
  pal.setColor( QPalette::Normal, QColorGroup::HighlightedText, Qt::white );
  pal.setColor( QPalette::Inactive, QColorGroup::HighlightedText, Qt::white );

  setPalette( pal );

  setHScrollBarMode( QScrollView::AlwaysOff );

  setAcceptDrops( true );

  connect( this, SIGNAL( currentChanged( QListBoxItem * ) ),
           SLOT( slotExecuted( QListBoxItem * ) ) );
}

QSize Navigator::sizeHint() const
{
  return QSize( 100, 100 );
}

void Navigator::updatePlugins( QValueList<Kontact::Plugin*> plugins )
{
  clear();

  int minWidth = 0;
  QValueList<Kontact::Plugin*>::ConstIterator end = plugins.end();
  QValueList<Kontact::Plugin*>::ConstIterator it = plugins.begin();
  for ( ; it != end; ++it ) {
    Kontact::Plugin *plugin = *it;
    if ( !plugin->showInSideBar() )
      continue;

    EntryItem *item = new EntryItem( this, plugin );

    if ( item->width( this ) > minWidth )
      minWidth = item->width( this );
  }

  parentWidget()->setFixedWidth( minWidth );
}

void Navigator::slotExecuted( QListBoxItem *item )
{
  if ( !item ) return;

  EntryItem *entry = static_cast<EntryItem *>( item );

  emit pluginActivated( entry->plugin() );
}

void Navigator::dragEnterEvent( QDragEnterEvent *event )
{
  kdDebug() << "Navigator::dragEnterEvent()" << endl;

  dragMoveEvent( event );
}

void Navigator::dragMoveEvent( QDragMoveEvent *event )
{
  kdDebug() << "Navigator::dragEnterEvent()" << endl;

  kdDebug() << "  Format: " << event->format() << endl;

  QListBoxItem *item = itemAt( event->pos() );

  if ( !item ) {
    event->accept( false );
    return;
  }

  EntryItem *entry = static_cast<EntryItem *>( item );

  kdDebug() << "  PLUGIN: " << entry->plugin()->identifier() << endl;

  event->accept( entry->plugin()->canDecodeDrag( event ) );
}

void Navigator::dropEvent( QDropEvent *event )
{
  kdDebug() << "Navigator::dropEvent()" << endl;

  QListBoxItem *item = itemAt( event->pos() );

  if ( !item ) {
    return;
  }

  EntryItem *entry = static_cast<EntryItem *>( item );

  kdDebug() << "  PLUGIN: " << entry->plugin()->identifier() << endl;

  // Make sure the part is loaded before calling processDropEvent.
  // Maybe it's better, if that would be done by the plugin.
  // Hmm, this doesn't work anyway.
  mSidePane->selectPlugin( entry->plugin() );

  entry->plugin()->processDropEvent( event );
}

IconSidePane::IconSidePane( Core *core, QWidget *parent, const char *name )
  : SidePaneBase( core, parent, name )
{
  mNavigator = new Navigator( this );
  connect( mNavigator, SIGNAL( pluginActivated( Kontact::Plugin * ) ),
           SIGNAL( pluginSelected( Kontact::Plugin * ) ) );

  setAcceptDrops( true );
}

IconSidePane::~IconSidePane()
{
}

void IconSidePane::updatePlugins()
{
  mNavigator->updatePlugins( core()->pluginList() );
}

void IconSidePane::selectPlugin( Kontact::Plugin *plugin )
{
  bool blocked = signalsBlocked();
  blockSignals( true );

  uint i;
  for ( i = 0; i < mNavigator->count(); ++i ) {
    EntryItem *item = static_cast<EntryItem *>( mNavigator->item( i ) );
    if ( item->plugin() == plugin ) {
      mNavigator->setCurrentItem( i );
      break;
    }
  }

  blockSignals( blocked );
}

void IconSidePane::selectPlugin( const QString &name )
{
  bool blocked = signalsBlocked();
  blockSignals( true );

  uint i;
  for ( i = 0; i < mNavigator->count(); ++i ) {
    EntryItem *item = static_cast<EntryItem *>( mNavigator->item( i ) );
    if ( item->plugin()->identifier() == name ) {
      mNavigator->setCurrentItem( i );
      break;
    }
  }

  blockSignals( blocked );
}

#include "iconsidepane.moc"

// vim: sw=2 sts=2 et tw=80
<|endoftext|>


<commit_before>#include "preferences.h"
#include <qcheckbox.h>
#include <qlineedit.h>
#include <qlabel.h>
#include <qlayout.h>
#include <qspinbox.h>
#include <klocale.h>
#include <qvbox.h>
#include <qframe.h>
#include <kconfig.h>
#include <kapp.h>
#include <kglobal.h>
#include <kstddirs.h>

Preferences *Preferences::_instance = 0;

Preferences::Preferences() : KDialogBase(KDialogBase::Tabbed, i18n("Preferences"),
                                         KDialogBase::Ok | KDialogBase::Cancel,
                                         KDialogBase::Ok)
{
  //----------------------------------------------------------------------
  // Saving
  //----------------------------------------------------------------------
  QVBox *autoSaveMenu = addVBoxPage(i18n("Saving"));

  QHBox *box3 = new QHBox(autoSaveMenu);
  new QLabel(i18n("File to save time information to"), box3, "save label");
  _saveFileW = new QLineEdit(box3, "_saveFileW");

  _doAutoSaveW = new QCheckBox(i18n("Automaticly save tasks"), autoSaveMenu, "_doAutoSaveW");
  connect(_doAutoSaveW, SIGNAL(clicked()),
          this, SLOT(autoSaveCheckBoxChanged()));

  QHBox *box2 = new QHBox(autoSaveMenu);
  _autoSaveLabelW = new QLabel(i18n("Minutes between each auto save"), box2,
                               "_autoSaveLabelW");
  _autoSaveValueW = new QSpinBox(1, 60*24, 1, box2, "_autoSaveValueW");

  //----------------------------------------------------------------------
  // Idle Detection Setup
  //----------------------------------------------------------------------
  idleMenu = addVBoxPage(i18n("Idle Detection"));

  _doIdleDetectionW = new QCheckBox(i18n("Try to detect idleness"),
                                   idleMenu,"_doIdleDetectionW");
  connect(_doIdleDetectionW, SIGNAL(clicked()),
          this, SLOT(idleDetectCheckBoxChanged()));

  QHBox *box1 = new QHBox(idleMenu);
  _idleDetectLabelW = new QLabel(i18n("Minutes before informing about idleness"), box1);
  _idleDetectValueW = new QSpinBox(1,60*24, 1, box1, "_idleDetectValueW");
}

Preferences *Preferences::instance()
{
  if (_instance == 0) {
    _instance = new Preferences();
  }
  return _instance;
}

void Preferences::disableIdleDetection()
{
  idleMenu->setEnabled(false);
}

//--------------------------------------------------------------------------------
//                            SLOTS
//--------------------------------------------------------------------------------

void Preferences::showDialog()
{

  // set all widgets
  _saveFileW->setText(_saveFileV);

  _doIdleDetectionW->setChecked(_doIdleDetectionV);
  _idleDetectValueW->setValue(_idleDetectValueV);

  _doAutoSaveW->setChecked(_doAutoSaveV);
  _autoSaveValueW->setValue(_autoSaveValueV);

  idleDetectCheckBoxChanged();
  show();
}

void Preferences::slotOk()
{
  _saveFileV = _saveFileW->text();
  _doIdleDetectionV = _doIdleDetectionW->isChecked();
  _idleDetectValueV = _idleDetectValueW->value();
  _doAutoSaveV    = _doAutoSaveW->isChecked();
  _autoSaveValueV = _autoSaveValueW->value();

  emitSignals();
  save();
  KDialogBase::slotOk();
}

void Preferences::slotCancel()
{
  KDialogBase::slotCancel();
}

void Preferences::idleDetectCheckBoxChanged()
{
  bool enabled = _doIdleDetectionW->isChecked();
  _idleDetectLabelW->setEnabled(enabled);
  _idleDetectValueW->setEnabled(enabled);
}

void Preferences::autoSaveCheckBoxChanged()
{
  bool enabled = _doAutoSaveW->isChecked();
  _autoSaveLabelW->setEnabled(enabled);
  _autoSaveValueW->setEnabled(enabled);
}

void Preferences::emitSignals()
{
  emit(saveFile(_saveFileV));
  emit(detectIdleness(_doIdleDetectionV));
  emit(idlenessTimeout(_idleDetectValueV));
  emit(autoSave(_doAutoSaveV));
  emit(autoSavePeriod(_autoSaveValueV));
  emit(setupChanged());
}

QString Preferences::saveFile()
{
  return _saveFileV;
}

bool Preferences::detectIdleness()
{
  return _doIdleDetectionV;
}

int Preferences::idlenessTimeout()
{
  return _idleDetectValueV;
}

bool Preferences::autoSave()
{
  return _doAutoSaveV;
}

int Preferences::autoSavePeriod()
{
  return _autoSaveValueV;
}

//--------------------------------------------------------------------------------
//                                  Load and Save
//--------------------------------------------------------------------------------
void Preferences::load()
{
  KConfig &config = *kapp->config();

  config.setGroup( QString::fromLatin1("Idle detection") );
  _doIdleDetectionV = config.readBoolEntry(QString::fromLatin1("enabled"), true );
  _idleDetectValueV = config.readNumEntry(QString::fromLatin1("period"), 15);

  config.setGroup( QString::fromLatin1("Saving") );
  _saveFileV      = config.readEntry(QString::fromLatin1("file"),
                                     locateLocal("appdata",
                                                 QString::fromLatin1("karmdata.txt")));
  _doAutoSaveV    = config.readBoolEntry(QString::fromLatin1("auto save"), true);
  _autoSaveValueV = config.readNumEntry(QString::fromLatin1("auto save period"), 5);

  emitSignals();
}

void Preferences::save()
{
  KConfig &config = *KGlobal::config();

  config.setGroup( QString::fromLatin1("Idle detection"));
  config.writeEntry( QString::fromLatin1("enabled"), _doIdleDetectionV);
  config.writeEntry( QString::fromLatin1("period"), _idleDetectValueV);

  config.setGroup( QString::fromLatin1("Saving"));
  config.writeEntry( QString::fromLatin1("file"), _saveFileV);
  config.writeEntry( QString::fromLatin1("auto save"), _doAutoSaveV);
  config.writeEntry( QString::fromLatin1("auto save period"), _autoSaveValueV);

  config.sync();

}

#include "preferences.moc"
<commit_msg>Fixed spelling: Automaticly->Automatically<commit_after>#include "preferences.h"
#include <qcheckbox.h>
#include <qlineedit.h>
#include <qlabel.h>
#include <qlayout.h>
#include <qspinbox.h>
#include <klocale.h>
#include <qvbox.h>
#include <qframe.h>
#include <kconfig.h>
#include <kapp.h>
#include <kglobal.h>
#include <kstddirs.h>

Preferences *Preferences::_instance = 0;

Preferences::Preferences() : KDialogBase(KDialogBase::Tabbed, i18n("Preferences"),
                                         KDialogBase::Ok | KDialogBase::Cancel,
                                         KDialogBase::Ok)
{
  //----------------------------------------------------------------------
  // Saving
  //----------------------------------------------------------------------
  QVBox *autoSaveMenu = addVBoxPage(i18n("Saving"));

  QHBox *box3 = new QHBox(autoSaveMenu);
  new QLabel(i18n("File to save time information to"), box3, "save label");
  _saveFileW = new QLineEdit(box3, "_saveFileW");

  _doAutoSaveW = new QCheckBox(i18n("Automatically save tasks"), autoSaveMenu, "_doAutoSaveW");
  connect(_doAutoSaveW, SIGNAL(clicked()),
          this, SLOT(autoSaveCheckBoxChanged()));

  QHBox *box2 = new QHBox(autoSaveMenu);
  _autoSaveLabelW = new QLabel(i18n("Minutes between each auto save"), box2,
                               "_autoSaveLabelW");
  _autoSaveValueW = new QSpinBox(1, 60*24, 1, box2, "_autoSaveValueW");

  //----------------------------------------------------------------------
  // Idle Detection Setup
  //----------------------------------------------------------------------
  idleMenu = addVBoxPage(i18n("Idle Detection"));

  _doIdleDetectionW = new QCheckBox(i18n("Try to detect idleness"),
                                   idleMenu,"_doIdleDetectionW");
  connect(_doIdleDetectionW, SIGNAL(clicked()),
          this, SLOT(idleDetectCheckBoxChanged()));

  QHBox *box1 = new QHBox(idleMenu);
  _idleDetectLabelW = new QLabel(i18n("Minutes before informing about idleness"), box1);
  _idleDetectValueW = new QSpinBox(1,60*24, 1, box1, "_idleDetectValueW");
}

Preferences *Preferences::instance()
{
  if (_instance == 0) {
    _instance = new Preferences();
  }
  return _instance;
}

void Preferences::disableIdleDetection()
{
  idleMenu->setEnabled(false);
}

//--------------------------------------------------------------------------------
//                            SLOTS
//--------------------------------------------------------------------------------

void Preferences::showDialog()
{

  // set all widgets
  _saveFileW->setText(_saveFileV);

  _doIdleDetectionW->setChecked(_doIdleDetectionV);
  _idleDetectValueW->setValue(_idleDetectValueV);

  _doAutoSaveW->setChecked(_doAutoSaveV);
  _autoSaveValueW->setValue(_autoSaveValueV);

  idleDetectCheckBoxChanged();
  show();
}

void Preferences::slotOk()
{
  _saveFileV = _saveFileW->text();
  _doIdleDetectionV = _doIdleDetectionW->isChecked();
  _idleDetectValueV = _idleDetectValueW->value();
  _doAutoSaveV    = _doAutoSaveW->isChecked();
  _autoSaveValueV = _autoSaveValueW->value();

  emitSignals();
  save();
  KDialogBase::slotOk();
}

void Preferences::slotCancel()
{
  KDialogBase::slotCancel();
}

void Preferences::idleDetectCheckBoxChanged()
{
  bool enabled = _doIdleDetectionW->isChecked();
  _idleDetectLabelW->setEnabled(enabled);
  _idleDetectValueW->setEnabled(enabled);
}

void Preferences::autoSaveCheckBoxChanged()
{
  bool enabled = _doAutoSaveW->isChecked();
  _autoSaveLabelW->setEnabled(enabled);
  _autoSaveValueW->setEnabled(enabled);
}

void Preferences::emitSignals()
{
  emit(saveFile(_saveFileV));
  emit(detectIdleness(_doIdleDetectionV));
  emit(idlenessTimeout(_idleDetectValueV));
  emit(autoSave(_doAutoSaveV));
  emit(autoSavePeriod(_autoSaveValueV));
  emit(setupChanged());
}

QString Preferences::saveFile()
{
  return _saveFileV;
}

bool Preferences::detectIdleness()
{
  return _doIdleDetectionV;
}

int Preferences::idlenessTimeout()
{
  return _idleDetectValueV;
}

bool Preferences::autoSave()
{
  return _doAutoSaveV;
}

int Preferences::autoSavePeriod()
{
  return _autoSaveValueV;
}

//--------------------------------------------------------------------------------
//                                  Load and Save
//--------------------------------------------------------------------------------
void Preferences::load()
{
  KConfig &config = *kapp->config();

  config.setGroup( QString::fromLatin1("Idle detection") );
  _doIdleDetectionV = config.readBoolEntry(QString::fromLatin1("enabled"), true );
  _idleDetectValueV = config.readNumEntry(QString::fromLatin1("period"), 15);

  config.setGroup( QString::fromLatin1("Saving") );
  _saveFileV      = config.readEntry(QString::fromLatin1("file"),
                                     locateLocal("appdata",
                                                 QString::fromLatin1("karmdata.txt")));
  _doAutoSaveV    = config.readBoolEntry(QString::fromLatin1("auto save"), true);
  _autoSaveValueV = config.readNumEntry(QString::fromLatin1("auto save period"), 5);

  emitSignals();
}

void Preferences::save()
{
  KConfig &config = *KGlobal::config();

  config.setGroup( QString::fromLatin1("Idle detection"));
  config.writeEntry( QString::fromLatin1("enabled"), _doIdleDetectionV);
  config.writeEntry( QString::fromLatin1("period"), _idleDetectValueV);

  config.setGroup( QString::fromLatin1("Saving"));
  config.writeEntry( QString::fromLatin1("file"), _saveFileV);
  config.writeEntry( QString::fromLatin1("auto save"), _doAutoSaveV);
  config.writeEntry( QString::fromLatin1("auto save period"), _autoSaveValueV);

  config.sync();

}

#include "preferences.moc"
<|endoftext|>


<commit_before>/*
 * ServeStream: A HTTP stream browser/player for Android
 * Copyright 2013 William Seemann
 *
 * 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
 *
 * 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.
 */

//#define LOG_NDEBUG 0
#define LOG_TAG "MediaMetadataRetrieverJNI"

#include <assert.h>
#include <android/log.h>
#include <mediametadataretriever.h>
#include "jni.h"

extern "C" {
	#include "libavcodec/avcodec.h"
	#include "libavformat/avformat.h"
}

using namespace std;

struct fields_t {
    jfieldID context;
};

static fields_t fields;
static const char* const kClassPathName = "net/sourceforge/servestream/media/MediaMetadataRetriever";

void jniThrowException(JNIEnv* env, const char* className,
    const char* msg) {
    jclass exception = env->FindClass(className);
    env->ThrowNew(exception, msg);
}

static void process_media_retriever_call(JNIEnv *env, int opStatus, const char* exception, const char *message)
{
    if (opStatus == -1) {
        jniThrowException(env, "java/lang/IllegalStateException", NULL);
    } else if (opStatus != 0) {
        if (strlen(message) > 230) {
            // If the message is too long, don't bother displaying the status code.
            jniThrowException( env, exception, message);
        } else {
            char msg[256];
            // Append the status code to the message.
            sprintf(msg, "%s: status = 0x%X", message, opStatus);
            jniThrowException( env, exception, msg);
        }
    }
}

static MediaMetadataRetriever* getRetriever(JNIEnv* env, jobject thiz)
{
    // No lock is needed, since it is called internally by other methods that are protected
    MediaMetadataRetriever* retriever = (MediaMetadataRetriever*) env->GetIntField(thiz, fields.context);
    return retriever;
}

static void setRetriever(JNIEnv* env, jobject thiz, int retriever)
{
    // No lock is needed, since it is called internally by other methods that are protected
    MediaMetadataRetriever *old = (MediaMetadataRetriever*) env->GetIntField(thiz, fields.context);
    env->SetIntField(thiz, fields.context, retriever);
}

extern "C" JNIEXPORT void JNICALL
Java_net_sourceforge_servestream_media_MediaMetadataRetriever_setDataSource(JNIEnv *env, jobject thiz, jstring path) {
	//__android_log_write(ANDROID_LOG_INFO, LOG_TAG, "setDataSource");
    MediaMetadataRetriever* retriever = getRetriever(env, thiz);
    if (retriever == 0) {
        jniThrowException(env, "java/lang/IllegalStateException", "No retriever available");
        return;
    }

    if (!path) {
        jniThrowException(env, "java/lang/IllegalArgumentException", "Null pointer");
        return;
    }

    const char *tmp = env->GetStringUTFChars(path, NULL);
    if (!tmp) {  // OutOfMemoryError exception already thrown
        return;
    }

    process_media_retriever_call(
            env,
            retriever->setDataSource(tmp),
            "java/lang/RuntimeException",
            "setDataSource failed");

    env->ReleaseStringUTFChars(path, tmp);
    tmp = NULL;
}

extern "C" JNIEXPORT jbyteArray JNICALL
Java_net_sourceforge_servestream_media_MediaMetadataRetriever_getEmbeddedPicture(JNIEnv *env, jobject thiz)
{
   //__android_log_write(ANDROID_LOG_INFO, LOG_TAG, "getEmbeddedPicture");
   MediaMetadataRetriever* retriever = getRetriever(env, thiz);
   if (retriever == 0) {
       jniThrowException(env, "java/lang/IllegalStateException", "No retriever available");
       return NULL;
   }

   AVPacket* packet = retriever->extractAlbumArt();

   if (packet) {
	   int size = packet->size;
	   uint8_t* data = packet->data;
	   jbyteArray array = env->NewByteArray(size);
	   if (!array) {  // OutOfMemoryError exception has already been thrown.
		   //__android_log_print(ANDROID_LOG_ERROR, LOG_TAG, "getEmbeddedPicture: OutOfMemoryError is thrown.");
       } else {
       	   //__android_log_print(ANDROID_LOG_INFO, LOG_TAG, "getEmbeddedPicture: Found album art.");
    	   jbyte* bytes = env->GetByteArrayElements(array, NULL);
           if (bytes != NULL) {
        	   memcpy(bytes, data, size);
               env->ReleaseByteArrayElements(array, bytes, 0);
               return array;
           }
       }
   }

   //__android_log_write(ANDROID_LOG_INFO, LOG_TAG, "getEmbeddedPicture: Call to getEmbeddedPicture failed.");
   return NULL;
}

extern "C" JNIEXPORT jobject JNICALL
Java_net_sourceforge_servestream_media_MediaMetadataRetriever_extractMetadata(JNIEnv *env, jobject thiz, jstring jkey)
{
	//__android_log_write(ANDROID_LOG_INFO, LOG_TAG, "extractMetadata");
    MediaMetadataRetriever* retriever = getRetriever(env, thiz);
    if (retriever == 0) {
        jniThrowException(env, "java/lang/IllegalStateException", "No retriever available");
        return NULL;
    }

    if (!jkey) {
        jniThrowException(env, "java/lang/IllegalArgumentException", "Null pointer");
        return NULL;
    }

    const char *key = env->GetStringUTFChars(jkey, NULL);
    if (!key) {  // OutOfMemoryError exception already thrown
        return NULL;
    }

    const char* value = retriever->extractMetadata(key);
    if (!value) {
    	//__android_log_write(ANDROID_LOG_INFO, LOG_TAG, "extractMetadata: Metadata is not found");
        return NULL;
    }
    //__android_log_print(ANDROID_LOG_INFO, LOG_TAG, "extractMetadata: value (%s) for keyCode(%s)", value, key);
    env->ReleaseStringUTFChars(jkey, key);
    return env->NewStringUTF(value);
}

extern "C" JNIEXPORT void JNICALL
Java_net_sourceforge_servestream_media_MediaMetadataRetriever_release(JNIEnv *env, jobject thiz)
{
    __android_log_write(ANDROID_LOG_INFO, LOG_TAG, "release");
    //Mutex::Autolock lock(sLock);
    MediaMetadataRetriever* retriever = getRetriever(env, thiz);
    delete retriever;
    setRetriever(env, thiz, 0);
}

extern "C" JNIEXPORT void JNICALL
Java_net_sourceforge_servestream_media_MediaMetadataRetriever_native_1finalize(JNIEnv *env, jobject thiz)
{
	//__android_log_write(ANDROID_LOG_INFO, LOG_TAG, "native_finalize");
    // No lock is needed, since Java_net_sourceforge_servestream_media_MediaMetadataRetriever_release() is protected
	Java_net_sourceforge_servestream_media_MediaMetadataRetriever_release(env, thiz);
}

extern "C" JNIEXPORT void JNICALL
Java_net_sourceforge_servestream_media_MediaMetadataRetriever_native_1init(JNIEnv *env, jobject thiz)
{
    __android_log_write(ANDROID_LOG_INFO, LOG_TAG, "native_init");
    jclass clazz = env->FindClass(kClassPathName);
    if (clazz == NULL) {
        return;
    }

    fields.context = env->GetFieldID(clazz, "mNativeContext", "I");
    if (fields.context == NULL) {
        return;
    }

    // Initialize libavformat and register all the muxers, demuxers and protocols.
	av_register_all();
	avformat_network_init();
}

extern "C" JNIEXPORT void JNICALL
Java_net_sourceforge_servestream_media_MediaMetadataRetriever_native_1setup(JNIEnv *env, jobject thiz)
{
    __android_log_write(ANDROID_LOG_INFO, LOG_TAG, "native_setup");
    MediaMetadataRetriever* retriever = new MediaMetadataRetriever();
    if (retriever == 0) {
        jniThrowException(env, "java/lang/RuntimeException", "Out of memory");
        return;
    }
    setRetriever(env, thiz, (int)retriever);
}
<commit_msg>Check to ensure we aren't reading some random block of memory, throw an IllegalArgumentException if setDataSource fails<commit_after>/*
 * ServeStream: A HTTP stream browser/player for Android
 * Copyright 2013 William Seemann
 *
 * 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
 *
 * 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.
 */

//#define LOG_NDEBUG 0
#define LOG_TAG "MediaMetadataRetrieverJNI"

#include <assert.h>
#include <android/log.h>
#include <mediametadataretriever.h>
#include "jni.h"

extern "C" {
	#include "libavcodec/avcodec.h"
	#include "libavformat/avformat.h"
}

using namespace std;

struct fields_t {
    jfieldID context;
};

static fields_t fields;
static const char* const kClassPathName = "net/sourceforge/servestream/media/MediaMetadataRetriever";

void jniThrowException(JNIEnv* env, const char* className,
    const char* msg) {
    jclass exception = env->FindClass(className);
    env->ThrowNew(exception, msg);
}

static void process_media_retriever_call(JNIEnv *env, int opStatus, const char* exception, const char *message)
{
    if (opStatus == -2) {
        jniThrowException(env, "java/lang/IllegalStateException", NULL);
    } else if (opStatus == -1) {
        if (strlen(message) > 230) {
            // If the message is too long, don't bother displaying the status code.
            jniThrowException( env, exception, message);
        } else {
            char msg[256];
            // Append the status code to the message.
            sprintf(msg, "%s: status = 0x%X", message, opStatus);
            jniThrowException( env, exception, msg);
        }
    }
}

static MediaMetadataRetriever* getRetriever(JNIEnv* env, jobject thiz)
{
    // No lock is needed, since it is called internally by other methods that are protected
    MediaMetadataRetriever* retriever = (MediaMetadataRetriever*) env->GetIntField(thiz, fields.context);
    return retriever;
}

static void setRetriever(JNIEnv* env, jobject thiz, int retriever)
{
    // No lock is needed, since it is called internally by other methods that are protected
    MediaMetadataRetriever *old = (MediaMetadataRetriever*) env->GetIntField(thiz, fields.context);
    env->SetIntField(thiz, fields.context, retriever);
}

extern "C" JNIEXPORT void JNICALL
Java_net_sourceforge_servestream_media_MediaMetadataRetriever_setDataSource(JNIEnv *env, jobject thiz, jstring path) {
	//__android_log_write(ANDROID_LOG_INFO, LOG_TAG, "setDataSource");
    MediaMetadataRetriever* retriever = getRetriever(env, thiz);
    if (retriever == 0) {
        jniThrowException(env, "java/lang/IllegalStateException", "No retriever available");
        return;
    }

    if (!path) {
        jniThrowException(env, "java/lang/IllegalArgumentException", "Null pointer");
        return;
    }

    const char *tmp = env->GetStringUTFChars(path, NULL);
    if (!tmp) {  // OutOfMemoryError exception already thrown
        return;
    }

    // Don't let somebody trick us in to reading some random block of memory
    if (strncmp("mem://", tmp, 6) == 0) {
        jniThrowException(env, "java/lang/IllegalArgumentException", "Invalid pathname");
        return;
    }

    process_media_retriever_call(
            env,
            retriever->setDataSource(tmp),
            "java/lang/IllegalArgumentException",
            "setDataSource failed");

    env->ReleaseStringUTFChars(path, tmp);
    tmp = NULL;
}

extern "C" JNIEXPORT jbyteArray JNICALL
Java_net_sourceforge_servestream_media_MediaMetadataRetriever_getEmbeddedPicture(JNIEnv *env, jobject thiz)
{
   //__android_log_write(ANDROID_LOG_INFO, LOG_TAG, "getEmbeddedPicture");
   MediaMetadataRetriever* retriever = getRetriever(env, thiz);
   if (retriever == 0) {
       jniThrowException(env, "java/lang/IllegalStateException", "No retriever available");
       return NULL;
   }

   AVPacket* packet = retriever->extractAlbumArt();

   if (packet) {
	   int size = packet->size;
	   uint8_t* data = packet->data;
	   jbyteArray array = env->NewByteArray(size);
	   if (!array) {  // OutOfMemoryError exception has already been thrown.
		   //__android_log_print(ANDROID_LOG_ERROR, LOG_TAG, "getEmbeddedPicture: OutOfMemoryError is thrown.");
       } else {
       	   //__android_log_print(ANDROID_LOG_INFO, LOG_TAG, "getEmbeddedPicture: Found album art.");
    	   jbyte* bytes = env->GetByteArrayElements(array, NULL);
           if (bytes != NULL) {
        	   memcpy(bytes, data, size);
               env->ReleaseByteArrayElements(array, bytes, 0);
               return array;
           }
       }
   }

   //__android_log_write(ANDROID_LOG_INFO, LOG_TAG, "getEmbeddedPicture: Call to getEmbeddedPicture failed.");
   return NULL;
}

extern "C" JNIEXPORT jobject JNICALL
Java_net_sourceforge_servestream_media_MediaMetadataRetriever_extractMetadata(JNIEnv *env, jobject thiz, jstring jkey)
{
	//__android_log_write(ANDROID_LOG_INFO, LOG_TAG, "extractMetadata");
    MediaMetadataRetriever* retriever = getRetriever(env, thiz);
    if (retriever == 0) {
        jniThrowException(env, "java/lang/IllegalStateException", "No retriever available");
        return NULL;
    }

    if (!jkey) {
        jniThrowException(env, "java/lang/IllegalArgumentException", "Null pointer");
        return NULL;
    }

    const char *key = env->GetStringUTFChars(jkey, NULL);
    if (!key) {  // OutOfMemoryError exception already thrown
        return NULL;
    }

    const char* value = retriever->extractMetadata(key);
    if (!value) {
    	//__android_log_write(ANDROID_LOG_INFO, LOG_TAG, "extractMetadata: Metadata is not found");
        return NULL;
    }
    //__android_log_print(ANDROID_LOG_INFO, LOG_TAG, "extractMetadata: value (%s) for keyCode(%s)", value, key);
    env->ReleaseStringUTFChars(jkey, key);
    return env->NewStringUTF(value);
}

extern "C" JNIEXPORT void JNICALL
Java_net_sourceforge_servestream_media_MediaMetadataRetriever_release(JNIEnv *env, jobject thiz)
{
    __android_log_write(ANDROID_LOG_INFO, LOG_TAG, "release");
    //Mutex::Autolock lock(sLock);
    MediaMetadataRetriever* retriever = getRetriever(env, thiz);
    delete retriever;
    setRetriever(env, thiz, 0);
}

extern "C" JNIEXPORT void JNICALL
Java_net_sourceforge_servestream_media_MediaMetadataRetriever_native_1finalize(JNIEnv *env, jobject thiz)
{
	//__android_log_write(ANDROID_LOG_INFO, LOG_TAG, "native_finalize");
    // No lock is needed, since Java_net_sourceforge_servestream_media_MediaMetadataRetriever_release() is protected
	Java_net_sourceforge_servestream_media_MediaMetadataRetriever_release(env, thiz);
}

extern "C" JNIEXPORT void JNICALL
Java_net_sourceforge_servestream_media_MediaMetadataRetriever_native_1init(JNIEnv *env, jobject thiz)
{
    __android_log_write(ANDROID_LOG_INFO, LOG_TAG, "native_init");
    jclass clazz = env->FindClass(kClassPathName);
    if (clazz == NULL) {
        return;
    }

    fields.context = env->GetFieldID(clazz, "mNativeContext", "I");
    if (fields.context == NULL) {
        return;
    }

    // Initialize libavformat and register all the muxers, demuxers and protocols.
	av_register_all();
	avformat_network_init();
}

extern "C" JNIEXPORT void JNICALL
Java_net_sourceforge_servestream_media_MediaMetadataRetriever_native_1setup(JNIEnv *env, jobject thiz)
{
    __android_log_write(ANDROID_LOG_INFO, LOG_TAG, "native_setup");
    MediaMetadataRetriever* retriever = new MediaMetadataRetriever();
    if (retriever == 0) {
        jniThrowException(env, "java/lang/RuntimeException", "Out of memory");
        return;
    }
    setRetriever(env, thiz, (int)retriever);
}
<|endoftext|>


<commit_before>#include <iostream>
#include <string>
#define CPPHTTPLIB_OPENSSL_SUPPORT
#include "httplib.h"
using namespace std;
void helloword(const httplib::Request& req, httplib::Response& rsp)
{
    printf("httplib server recv a req: %s %s\n ", req.path.c_str(), req.remote_addr.c_str());
    // std::string str = R "(
 武汉, 加油！
)";
    // std::string s1 = R "a(C:\Users\Administrator\Desktop\RWtest\write.txt)a";
    std::string s= R"foo(
C:\Users\Administrator\Desktop\RWtes
    )foo";
    const char* s1 = R"foo(

    <meta charset="utf-8">

 武汉, 加油！

)foo";
    rsp.set_content(s, "text/html"); //最后一个参数是正文类型
    rsp.status = 200;
}
void helloword1(const httplib::Request& req, httplib::Response& rsp)
{
    printf("httplib server recv a req: %s %s\n ", req.path.c_str(), req.remote_addr.c_str());
    // std::string str = R "(
 武汉, 加油！
)";
    // std::string s1 = R "a(C:\Users\Administrator\Desktop\RWtest\write.txt)a";
    std::string s= R"foo(
C:\Users\Administrator\Desktop\RWtes
    )foo";
    const char* s1 = R"AAA(

    <meta charset="utf-8">

 武汉, 加油！

)AAA";
    rsp.set_content(s1, "text/html"); //最后一个参数是正文类型
    rsp.status = 200;
}
int main(int argc, char** argv)
{
    httplib::SSLServer srv;
    srv.Get("/", helloword1);
    srv.Get("^/.*$", helloword);

    srv.listen("0.0.0.0", 9000);

    getchar();
    return 0;
}<commit_msg>github ci aarch64 try fix Could NOT find OpenSSL remove CPPHTTPLIB_OPENSSL_SUPPORT<commit_after>#include <iostream>
#include <string>
// #define CPPHTTPLIB_OPENSSL_SUPPORT
#include "httplib.h"
using namespace std;
void helloword(const httplib::Request& req, httplib::Response& rsp)
{
    printf("httplib server recv a req: %s %s\n ", req.path.c_str(), req.remote_addr.c_str());
    // std::string str = R "(
 武汉, 加油！
)";
    // std::string s1 = R "a(C:\Users\Administrator\Desktop\RWtest\write.txt)a";
    std::string s= R"foo(
C:\Users\Administrator\Desktop\RWtes
    )foo";
    const char* s1 = R"foo(

    <meta charset="utf-8">

 武汉, 加油！

)foo";
    rsp.set_content(s, "text/html"); //最后一个参数是正文类型
    rsp.status = 200;
}
void helloword1(const httplib::Request& req, httplib::Response& rsp)
{
    printf("httplib server recv a req: %s %s\n ", req.path.c_str(), req.remote_addr.c_str());
    // std::string str = R "(
 武汉, 加油！
)";
    // std::string s1 = R "a(C:\Users\Administrator\Desktop\RWtest\write.txt)a";
    std::string s= R"foo(
C:\Users\Administrator\Desktop\RWtes
    )foo";
    const char* s1 = R"AAA(

    <meta charset="utf-8">

 武汉, 加油！

)AAA";
    rsp.set_content(s1, "text/html"); //最后一个参数是正文类型
    rsp.status = 200;
}
int main(int argc, char** argv)
{
    httplib::SSLServer srv;
    srv.Get("/", helloword1);
    srv.Get("^/.*$", helloword);

    srv.listen("0.0.0.0", 9000);

    getchar();
    return 0;
}<|endoftext|>