<commit_before>/****************************************************************************
**
** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the Qt Mobility Components.
**
** $QT_BEGIN_LICENSE:LGPL$
** No Commercial Usage
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions
** contained in the Technology Preview License Agreement accompanying
** this package.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights.  These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
**
**
**
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/

#include "qnearfieldmanager_simulator_p.h"
#include "qnearfieldmanager.h"
#include "qnearfieldtarget_p.h"
#include "qnearfieldtagtype1.h"
#include "qndefmessage.h"

#include <mobilityconnection_p.h>
#include <QtGui/private/qsimulatordata_p.h>

#include <QtCore/QCoreApplication>

QTM_BEGIN_NAMESPACE

using namespace QtSimulatorPrivate;

namespace Simulator {

class TagType1 : public QNearFieldTagType1
{
public:
    TagType1(const QByteArray &uid, QObject *parent);
    ~TagType1();

    QByteArray uid() const;

    AccessMethods accessMethods() const;

    RequestId sendCommand(const QByteArray &command);
    bool waitForRequestCompleted(const RequestId &id, int msecs = 5000);

private:
    QByteArray m_uid;
};

TagType1::TagType1(const QByteArray &uid, QObject *parent)
:   QNearFieldTagType1(parent), m_uid(uid)
{
}

TagType1::~TagType1()
{
}

QByteArray TagType1::uid() const
{
    return m_uid;
}

QNearFieldTarget::AccessMethods TagType1::accessMethods() const
{
    return NdefAccess | TagTypeSpecificAccess;
}

QNearFieldTarget::RequestId TagType1::sendCommand(const QByteArray &command)
{
    quint16 crc = qNfcChecksum(command.constData(), command.length());

    RequestId id(new RequestIdPrivate);

    MobilityConnection *connection = MobilityConnection::instance();
    QByteArray response =
        RemoteMetacall<QByteArray>::call(connection->sendSocket(), WaitSync, "nfcSendCommand",
                                         command + char(crc & 0xff) + char(crc >> 8));

    if (response.isEmpty()) {
        QMetaObject::invokeMethod(this, "error", Qt::QueuedConnection,
                                  Q_ARG(QNearFieldTarget::Error, NoResponseError),
                                  Q_ARG(QNearFieldTarget::RequestId, id));
        return id;
    }

    // check crc
    if (qNfcChecksum(response.constData(), response.length()) != 0) {
        QMetaObject::invokeMethod(this, "error", Qt::QueuedConnection,
                                  Q_ARG(QNearFieldTarget::Error, ChecksumMismatchError),
                                  Q_ARG(QNearFieldTarget::RequestId, id));
        return id;
    }

    response.chop(2);

    QMetaObject::invokeMethod(this, "handleResponse", Qt::QueuedConnection,
                              Q_ARG(QNearFieldTarget::RequestId, id), Q_ARG(QByteArray, response));

    return id;
}

bool TagType1::waitForRequestCompleted(const RequestId &id, int msecs)
{
    QCoreApplication::sendPostedEvents(this, QEvent::MetaCall);

    return QNearFieldTagType1::waitForRequestCompleted(id, msecs);
}

class NfcConnection : public QObject
{
    Q_OBJECT

public:
    NfcConnection();
    virtual ~NfcConnection();

signals:
    void targetEnteringProximity(const QByteArray &uid);
    void targetLeavingProximity(const QByteArray &uid);
};

NfcConnection::NfcConnection()
:   QObject(MobilityConnection::instance())
{
    MobilityConnection *connection = MobilityConnection::instance();
    connection->addMessageHandler(this);

    RemoteMetacall<void>::call(connection->sendSocket(), NoSync, "setRequestsNfc");
}

NfcConnection::~NfcConnection()
{
}

}

QNearFieldManagerPrivateImpl::QNearFieldManagerPrivateImpl()
:   nfcConnection(new Simulator::NfcConnection)
{
    connect(nfcConnection, SIGNAL(targetEnteringProximity(QByteArray)),
            this, SLOT(targetEnteringProximity(QByteArray)));
    connect(nfcConnection, SIGNAL(targetLeavingProximity(QByteArray)),
            this, SLOT(targetLeavingProximity(QByteArray)));
}

QNearFieldManagerPrivateImpl::~QNearFieldManagerPrivateImpl()
{
    delete nfcConnection;
}

bool QNearFieldManagerPrivateImpl::isAvailable() const
{
    return true;
}

void QNearFieldManagerPrivateImpl::targetEnteringProximity(const QByteArray &uid)
{
    QNearFieldTarget *target = m_targets.value(uid);
    if (!target) {
        target = new Simulator::TagType1(uid, this);
        m_targets.insert(uid, target);
    }

    targetActivated(target);
}

void QNearFieldManagerPrivateImpl::targetLeavingProximity(const QByteArray &uid)
{
    QNearFieldTarget *target = m_targets.value(uid);
    if (!target) {
        m_targets.remove(uid);
        return;
    }

    targetDeactivated(target);
}

#include "qnearfieldmanager_simulator.moc"
#include "moc_qnearfieldmanager_simulator_p.cpp"

QTM_END_NAMESPACE
<commit_msg>Fix compile on Qt Simulator target.<commit_after>/****************************************************************************
**
** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the Qt Mobility Components.
**
** $QT_BEGIN_LICENSE:LGPL$
** No Commercial Usage
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions
** contained in the Technology Preview License Agreement accompanying
** this package.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights.  These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
**
**
**
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/

#include "qnearfieldmanager_simulator_p.h"
#include "qnearfieldmanager.h"
#include "qnearfieldtarget_p.h"
#include "qnearfieldtagtype1.h"
#include "qndefmessage.h"

#include <mobilityconnection_p.h>
#include <QtGui/private/qsimulatordata_p.h>

#include <QtCore/QCoreApplication>

QTM_BEGIN_NAMESPACE

using namespace QtSimulatorPrivate;

namespace Simulator {

class TagType1 : public QNearFieldTagType1
{
public:
    TagType1(const QByteArray &uid, QObject *parent);
    ~TagType1();

    QByteArray uid() const;

    AccessMethods accessMethods() const;

    RequestId sendCommand(const QByteArray &command);
    bool waitForRequestCompleted(const RequestId &id, int msecs = 5000);

private:
    QByteArray m_uid;
};

TagType1::TagType1(const QByteArray &uid, QObject *parent)
:   QNearFieldTagType1(parent), m_uid(uid)
{
}

TagType1::~TagType1()
{
}

QByteArray TagType1::uid() const
{
    return m_uid;
}

QNearFieldTarget::AccessMethods TagType1::accessMethods() const
{
    return NdefAccess | TagTypeSpecificAccess;
}

QNearFieldTarget::RequestId TagType1::sendCommand(const QByteArray &command)
{
    quint16 crc = qNfcChecksum(command.constData(), command.length());

    RequestId id(new RequestIdPrivate);

    MobilityConnection *connection = MobilityConnection::instance();
    QByteArray response =
        RemoteMetacall<QByteArray>::call(connection->sendSocket(), WaitSync, "nfcSendCommand",
                                         command + char(crc & 0xff) + char(crc >> 8));

    if (response.isEmpty()) {
        QMetaObject::invokeMethod(this, "error", Qt::QueuedConnection,
                                  Q_ARG(QNearFieldTarget::Error, NoResponseError),
                                  Q_ARG(QNearFieldTarget::RequestId, id));
        return id;
    }

    // check crc
    if (qNfcChecksum(response.constData(), response.length()) != 0) {
        QMetaObject::invokeMethod(this, "error", Qt::QueuedConnection,
                                  Q_ARG(QNearFieldTarget::Error, ChecksumMismatchError),
                                  Q_ARG(QNearFieldTarget::RequestId, id));
        return id;
    }

    response.chop(2);

    QMetaObject::invokeMethod(this, "handleResponse", Qt::QueuedConnection,
                              Q_ARG(QNearFieldTarget::RequestId, id), Q_ARG(QByteArray, response));

    return id;
}

bool TagType1::waitForRequestCompleted(const RequestId &id, int msecs)
{
    QCoreApplication::sendPostedEvents(this, QEvent::MetaCall);

    return QNearFieldTagType1::waitForRequestCompleted(id, msecs);
}

class NfcConnection : public QObject
{
    Q_OBJECT

public:
    NfcConnection();
    virtual ~NfcConnection();

signals:
    void targetEnteringProximity(const QByteArray &uid);
    void targetLeavingProximity(const QByteArray &uid);
};

NfcConnection::NfcConnection()
:   QObject(MobilityConnection::instance())
{
    MobilityConnection *connection = MobilityConnection::instance();
    connection->addMessageHandler(this);

    RemoteMetacall<void>::call(connection->sendSocket(), NoSync, "setRequestsNfc");
}

NfcConnection::~NfcConnection()
{
}

}

QNearFieldManagerPrivateImpl::QNearFieldManagerPrivateImpl()
:   nfcConnection(new Simulator::NfcConnection)
{
    connect(nfcConnection, SIGNAL(targetEnteringProximity(QByteArray)),
            this, SLOT(targetEnteringProximity(QByteArray)));
    connect(nfcConnection, SIGNAL(targetLeavingProximity(QByteArray)),
            this, SLOT(targetLeavingProximity(QByteArray)));
}

QNearFieldManagerPrivateImpl::~QNearFieldManagerPrivateImpl()
{
    delete nfcConnection;
}

bool QNearFieldManagerPrivateImpl::isAvailable() const
{
    return true;
}

void QNearFieldManagerPrivateImpl::targetEnteringProximity(const QByteArray &uid)
{
    QNearFieldTarget *target = m_targets.value(uid).data();
    if (!target) {
        target = new Simulator::TagType1(uid, this);
        m_targets.insert(uid, target);
    }

    targetActivated(target);
}

void QNearFieldManagerPrivateImpl::targetLeavingProximity(const QByteArray &uid)
{
    QNearFieldTarget *target = m_targets.value(uid).data();
    if (!target) {
        m_targets.remove(uid);
        return;
    }

    targetDeactivated(target);
}

#include "qnearfieldmanager_simulator.moc"
#include "moc_qnearfieldmanager_simulator_p.cpp"

QTM_END_NAMESPACE
<|endoftext|>


<commit_before>/*!
 *  Copyright (c) 2017 by Contributors
 * \file intrin_rule_llvm.cc
 */
#ifdef TVM_LLVM_VERSION

#include "./intrin_rule_llvm.h"
#include <tvm/ir.h>
#include <tvm/expr.h>
#include <tvm/api_registry.h>
#include <sstream>

namespace tvm {
namespace codegen {

inline void DispatchExternOCML(const TVMArgs& args, TVMRetValue* rv) {
  Expr e = args[0];
  using namespace ir;
  const Call* call = e.as<Call>();
  CHECK(call != nullptr);
  std::ostringstream intrinsic_name;
  intrinsic_name << "__ocml_" << call->name << "_f" << call->type.bits();
  *rv = Call::make(call->type, intrinsic_name.str(), call->args,
                   Call::PureExtern);
}

namespace llvm {

TVM_REGISTER_GLOBAL("tvm.intrin.rule.rocm.exp")
.set_body(DispatchExternOCML);

TVM_REGISTER_GLOBAL("tvm.intrin.rule.rocm.fma")
.set_body(DispatchExternOCML);

TVM_REGISTER_GLOBAL("tvm.intrin.rule.rocm.log")
.set_body(DispatchExternOCML);

TVM_REGISTER_GLOBAL("tvm.intrin.rule.rocm.sqrt")
.set_body(DispatchExternOCML);

TVM_REGISTER_GLOBAL("tvm.intrin.rule.rocm.pow")
.set_body(DispatchExternOCML);

}  // namespace llvm
}  // namespace codegen
}  // namespace tvm

#endif  // LLVM_VERSION
<commit_msg>[ROCM] remove fma dispatch (#591)<commit_after>/*!
 *  Copyright (c) 2017 by Contributors
 * \file intrin_rule_llvm.cc
 */
#ifdef TVM_LLVM_VERSION

#include "./intrin_rule_llvm.h"
#include <tvm/ir.h>
#include <tvm/expr.h>
#include <tvm/api_registry.h>
#include <sstream>

namespace tvm {
namespace codegen {

inline void DispatchExternOCML(const TVMArgs& args, TVMRetValue* rv) {
  Expr e = args[0];
  using namespace ir;
  const Call* call = e.as<Call>();
  CHECK(call != nullptr);
  std::ostringstream intrinsic_name;
  intrinsic_name << "__ocml_" << call->name << "_f" << call->type.bits();
  *rv = Call::make(call->type, intrinsic_name.str(), call->args,
                   Call::PureExtern);
}

namespace llvm {

TVM_REGISTER_GLOBAL("tvm.intrin.rule.rocm.exp")
.set_body(DispatchExternOCML);

// On AMD GPU, fma is slower than mac
// removing fma dispatch allows backend to generate faster mac instruction
TVM_REGISTER_GLOBAL("tvm.intrin.rule.rocm.fma")
.set_body(DispatchLLVMPureIntrin<::llvm::Intrinsic::fmuladd, 1>);

TVM_REGISTER_GLOBAL("tvm.intrin.rule.rocm.log")
.set_body(DispatchExternOCML);

TVM_REGISTER_GLOBAL("tvm.intrin.rule.rocm.sqrt")
.set_body(DispatchExternOCML);

TVM_REGISTER_GLOBAL("tvm.intrin.rule.rocm.pow")
.set_body(DispatchExternOCML);

}  // namespace llvm
}  // namespace codegen
}  // namespace tvm

#endif  // LLVM_VERSION
<|endoftext|>


<commit_before>// RUN: cat %s | %cling -Xclang -verify
// RUN: cat %s | %cling | FileCheck %s

#include "cling/Interpreter/Interpreter.h"
#include "cling/Interpreter/StoredValueRef.h"

cling::StoredValueRef V;
V // CHECK: (cling::StoredValueRef) <<<invalid>>> @0x{{.*}}

gCling->evaluate("1;", V);
V // CHECK: (cling::StoredValueRef) boxes [(int) 1]

long LongV = 17;
gCling->evaluate("LongV;", V);
V // CHECK: (cling::StoredValueRef) boxes [(long) 17]

int* IntP = (int*)0x12;
gCling->evaluate("IntP;", V);
V // CHECK: (cling::StoredValueRef) boxes [(int *) 0x12]

cling::StoredValueRef Result;
gCling->evaluate("V", Result);
Result // CHECK: (cling::StoredValueRef) boxes [(cling::StoredValueRef)]
V // CHECK: (cling::StoredValueRef) boxes [(int *) 0x12]

// Savannah #96277
gCling->evaluate("double sin(double); double one = sin(3.141/2);", V);
V // CHECK: (cling::StoredValueRef) boxes [(double) 1.000000e+00]

gCling->process("double sin(double); double one = sin(3.141/2);", &V);
V // CHECK: (cling::StoredValueRef) boxes [(double) 1.000000e+00]
one // CHECK: (double) 1.000
int one; // expected-error {{redefinition of 'one' with a different type: 'int' vs 'double'}} expected-note {{previous definition is here}}

// Make sure that PR#98434 doesn't get reintroduced.
void f(int);
gCling->evaluate("f // expected-error {{cannot initialize return object of type 'void (int)' with an lvalue of type 'void (int)'}}", V);
// end PR#98434
<commit_msg>Test r47166: return 12; as alterative to 12;<commit_after>// RUN: cat %s | %cling -Xclang -verify
// RUN: cat %s | %cling | FileCheck %s

#include "cling/Interpreter/Interpreter.h"
#include "cling/Interpreter/StoredValueRef.h"

cling::StoredValueRef V;
V // CHECK: (cling::StoredValueRef) <<<invalid>>> @0x{{.*}}

gCling->evaluate("return 1;", V);
V // CHECK: (cling::StoredValueRef) boxes [(int) 1]

long LongV = 17;
gCling->evaluate("LongV;", V);
V // CHECK: (cling::StoredValueRef) boxes [(long) 17]

int* IntP = (int*)0x12;
gCling->evaluate("IntP;", V);
V // CHECK: (cling::StoredValueRef) boxes [(int *) 0x12]

cling::StoredValueRef Result;
gCling->evaluate("V", Result);
Result // CHECK: (cling::StoredValueRef) boxes [(cling::StoredValueRef)]
V // CHECK: (cling::StoredValueRef) boxes [(int *) 0x12]

// Savannah #96277
gCling->evaluate("double sin(double); double one = sin(3.141/2);", V);
V // CHECK: (cling::StoredValueRef) boxes [(double) 1.000000e+00]

gCling->process("double sin(double); double one = sin(3.141/2);", &V);
V // CHECK: (cling::StoredValueRef) boxes [(double) 1.000000e+00]
one // CHECK: (double) 1.000
int one; // expected-error {{redefinition of 'one' with a different type: 'int' vs 'double'}} expected-note {{previous definition is here}}

// Make sure that PR#98434 doesn't get reintroduced.
void f(int);
gCling->evaluate("f // expected-error {{cannot initialize return object of type 'void (int)' with an lvalue of type 'void (int)'}}", V);
// end PR#98434
<|endoftext|>


<commit_before>/* BEGIN_COMMON_COPYRIGHT_HEADER
 * (c)LGPL2+
 *
 * LXQt - a lightweight, Qt based, desktop toolset
 * https://lxqt.org
 *
 * Copyright: 2010-2011 Razor team
 * Authors:
 *   Petr Vanek <petr@scribus.info>
 *
 * This program or library is free software; you can redistribute it
 * and/or modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.

 * You should have received a copy of the GNU Lesser General
 * Public License along with this library; if not, write to the
 * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
 * Boston, MA 02110-1301 USA
 *
 * END_COMMON_COPYRIGHT_HEADER */

#include <QDirIterator>
#include <QLineEdit>
#include <QTimer>

#include "mainwindow.h"
#include <QtDebug>
#include <QMessageBox>
#include <QStyledItemDelegate>
#include <QShortcut>
#include <QKeySequence>

#include <XdgDesktopFile>
#include <XdgIcon>
#include <XdgMenu>
#include <XmlHelper>

#include "qcategorizedview.h"
#include "qcategorydrawer.h"
#include "qcategorizedsortfilterproxymodel.h"

namespace LXQtConfig {

struct ConfigPaneData: public QSharedData
{
    QString id;
    QString category;
    XdgDesktopFile xdg;
};

class ConfigPane
{
public:
    ConfigPane(): d(new ConfigPaneData) { }
    ConfigPane(const ConfigPane &other): d(other.d) { }

    inline QString &id() const { return d->id; }
    inline XdgDesktopFile xdg() const { return d->xdg; }
    inline void setXdg(XdgDesktopFile xdg) { d->xdg = xdg; }
    inline QString &category() const { return d->category; }

    bool operator==(const ConfigPane &other) const
    {
        return d->id == other.id();
    }

private:
    QExplicitlySharedDataPointer<ConfigPaneData> d;
};

class ConfigPaneModel: public QAbstractListModel
{
public:
    ConfigPaneModel(): QAbstractListModel()
    {
        QString menuFile = XdgMenu::getMenuFileName(QStringLiteral("config.menu"));
        XdgMenu xdgMenu;
        xdgMenu.setEnvironments(QStringList() << QStringLiteral("X-LXQT") << QStringLiteral("LXQt") << QStringLiteral("LXDE"));
        bool res = xdgMenu.read(menuFile);
        if (!res)
        {
            QMessageBox::warning(nullptr, QStringLiteral("Parse error"), xdgMenu.errorString());
            return;
        }

        DomElementIterator it(xdgMenu.xml().documentElement() , QStringLiteral("Menu"));
        while(it.hasNext())
        {
            this->buildGroup(it.next());
        }
    }

    void buildGroup(const QDomElement& xml)
    {
        QString category;
        if (! xml.attribute(QStringLiteral("title")).isEmpty())
            category = xml.attribute(QStringLiteral("title"));
        else
            category = xml.attribute(QStringLiteral("name"));

        DomElementIterator it(xml , QStringLiteral("AppLink"));
        while(it.hasNext())
        {
            QDomElement x = it.next();

            XdgDesktopFile xdg;
            xdg.load(x.attribute(QStringLiteral("desktopFile")));

            ConfigPane pane;
            pane.id() = xdg.value(QStringLiteral("Icon")).toString();
            pane.category() = category;
            pane.setXdg(xdg);
            m_list.append(pane);
        }
    }

    void activateItem(const QModelIndex &index)
    {
        if (!index.isValid())
            return;
        m_list[index.row()].xdg().startDetached();
    }

    ~ConfigPaneModel() override { }

    int rowCount(const QModelIndex &parent = QModelIndex()) const override
    {
        return m_list.count();
    }

    bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole) override
    {
        return false;
    }

    QVariant data(const QModelIndex &index, int role) const override
    {
        if (role == Qt::DisplayRole || role == Qt::ToolTipRole)
            return m_list[index.row()].xdg().name();
        if (role == QCategorizedSortFilterProxyModel::CategoryDisplayRole)
            return m_list[index.row()].category();
        if (role == QCategorizedSortFilterProxyModel::CategorySortRole)
            return m_list[index.row()].category();
        if (role == Qt::UserRole)
            return m_list[index.row()].id();
        if (role == Qt::DecorationRole)
        {
            return m_list[index.row()].xdg().icon(XdgIcon::defaultApplicationIcon());
        }
        return QVariant();
    }

private:
    QList<ConfigPane> m_list;
};

}

class ConfigItemDelegate : public QStyledItemDelegate
{
public:
    ConfigItemDelegate(QCategorizedView* view) : mView(view) { }
    ~ConfigItemDelegate() override { }

    QSize sizeHint(const QStyleOptionViewItem& option, const QModelIndex& index) const override
    {
        /* We let Qt calculate the real cell size but consider the 4-px margin
           around each cell and try to add a 2-px margin around the selection
           rectangle for styles that, unlike Fusion, highlight the whole item. */
        QStyleOptionViewItem opt = option;
        int delta = opt.rect.width() - (mView->gridSize().width() - 8);
        if (delta > 0)
          opt.rect.adjust(delta/2, 0 , -delta/2, 0);
        QSize defaultSize = QStyledItemDelegate::sizeHint(opt, index);
        return QSize(qMin(defaultSize.width() + 4, mView->gridSize().width() - 8),
                     qMin(defaultSize.height() + 4, mView->gridSize().height() - 8));
    }

protected:
    void paint(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const override
    {
        if(!index.isValid())
            return;

        QStyleOptionViewItem opt = option;
        initStyleOption(&opt, index);

        const QSize & iconSize = option.decorationSize;
        QSize size(mView->gridSize().width() - 8, // 4-px margin around each cell
                   iconSize.height());
        // for having sharp non-scalable icons with HDPI
        int dpr = qApp->devicePixelRatio();
        if (dpr < 1) dpr = 1;
        QPixmap pixmap = opt.icon.pixmap(iconSize / dpr); // -> Qt doc -> QIcon::pixmap()
        if (dpr > 1 && pixmap.size() == iconSize) // exceptional (scalable or not from icon set)
            pixmap = opt.icon.pixmap(iconSize);
        opt.icon = QIcon(pixmap.copy(QRect(QPoint(0, 0), size * dpr)));
        opt.decorationSize = size;

        const QWidget* widget = opt.widget;
        QStyle* style = widget ? widget->style() : QApplication::style();
        style->drawControl(QStyle::CE_ItemViewItem, &opt, painter, widget);
    }

private:
    QCategorizedView *mView;
};

LXQtConfig::MainWindow::MainWindow() : QMainWindow()
{
    setupUi(this);
    view->installEventFilter(this);

    /* To always have the intended layout on startup,
       the listview should be shown after it's fully formed. */
    view->hide();

    model = new ConfigPaneModel();

    view->setViewMode(QListView::IconMode);
    view->setWordWrap(true);
    view->setUniformItemSizes(true);
    view->setCategoryDrawer(new QCategoryDrawerV3(view));

    connect(view, &QAbstractItemView::activated, [this] (const QModelIndex & index) { pendingActivation = index; });
    view->setFocus();

    QTimer::singleShot(0, [this] { setSizing(); });
    QTimer::singleShot(1, this, SLOT(load()));
    new QShortcut{QKeySequence{Qt::CTRL + Qt::Key_Q}, this, SLOT(close())};
}

void LXQtConfig::MainWindow::load()
{
    QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));

    proxyModel = new QCategorizedSortFilterProxyModel();
    proxyModel->setCategorizedModel(true);
    proxyModel->setSourceModel(model);

    view->setModel(proxyModel);
    view->setItemDelegate(new ConfigItemDelegate(view));

    view->show();

    QApplication::restoreOverrideCursor();
}

void LXQtConfig::MainWindow::activateItem()
{
    if (pendingActivation.isValid())
    {
        model->activateItem(pendingActivation);
        pendingActivation = QModelIndex{};
    }
}

/*Note: all this delayed activation is here to workaround the auto-repeated
 * Enter/Return key activation -> if the user keeps pressing the enter/return
 * we normaly will keep activating (spawning new processes) until the focus
 * isn't stolen from our window. New process is not spawned until the
 * (non-autorepeated) KeyRelease is delivered.
 *
 * ref https://github.com/lxqt/lxqt/issues/965
 */
bool LXQtConfig::MainWindow::eventFilter(QObject * watched, QEvent * event)
{
    if (view != watched)
        return false;
    switch (event->type())
    {
        case QEvent::KeyPress:
        case QEvent::KeyRelease:
            {
                QKeyEvent * ev = dynamic_cast<QKeyEvent *>(event);
                switch (ev->key())
                {
                    case Qt::Key_Enter:
                    case Qt::Key_Return:
                        if (QEvent::KeyRelease == ev->type() && !ev->isAutoRepeat())
                            activateItem();
                }
            }
            break;
        case QEvent::MouseButtonRelease:
            activateItem();
            break;
        default:
            //keep warnings quiet
            break;
    }
    return false;
}

void LXQtConfig::MainWindow::setSizing()
{
    // consult the style to know the icon size
    int iconSize = qBound(16, view->decorationSize().height(), 256);
    // DPR is automatically taken into account in setIconSize()
    // but wee need to consider it explicitly below
    int dpr = qApp->devicePixelRatio();
    if (dpr < 1) dpr = 1;
    iconSize *= dpr;
    /* To have an appropriate grid size, we suppose that
     *
     * (1) The text has 3 lines and each line has 16 chars (for languages like German), at most;
     * (2) The selection rect has a margin of 2 px, at most;
     * (3) There is, at most, a 3-px spacing between text and icon; and
     * (4) There is a 4-px margin around each cell.
     */
    QFontMetrics fm = fontMetrics();
    int textWidth = fm.averageCharWidth() * 16;
    int textHeight = fm.lineSpacing() * 3;
    QSize grid;
    grid.setWidth(qMax(iconSize, textWidth) + 4);
    grid.setHeight(iconSize + textHeight + 4 + 3);
    view->setGridSize(grid + QSize(8, 8));
}

bool LXQtConfig::MainWindow::event(QEvent * event)
{
    if (QEvent::StyleChange == event->type())
        setSizing();
    return QMainWindow::event(event);
}
<commit_msg>Updated the code for non-integer scale factors<commit_after>/* BEGIN_COMMON_COPYRIGHT_HEADER
 * (c)LGPL2+
 *
 * LXQt - a lightweight, Qt based, desktop toolset
 * https://lxqt.org
 *
 * Copyright: 2010-2011 Razor team
 * Authors:
 *   Petr Vanek <petr@scribus.info>
 *
 * This program or library is free software; you can redistribute it
 * and/or modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.

 * You should have received a copy of the GNU Lesser General
 * Public License along with this library; if not, write to the
 * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
 * Boston, MA 02110-1301 USA
 *
 * END_COMMON_COPYRIGHT_HEADER */

#include <QDirIterator>
#include <QLineEdit>
#include <QTimer>

#include "mainwindow.h"
#include <QtDebug>
#include <QMessageBox>
#include <QStyledItemDelegate>
#include <QShortcut>
#include <QKeySequence>

#include <XdgDesktopFile>
#include <XdgIcon>
#include <XdgMenu>
#include <XmlHelper>

#include "qcategorizedview.h"
#include "qcategorydrawer.h"
#include "qcategorizedsortfilterproxymodel.h"

namespace LXQtConfig {

struct ConfigPaneData: public QSharedData
{
    QString id;
    QString category;
    XdgDesktopFile xdg;
};

class ConfigPane
{
public:
    ConfigPane(): d(new ConfigPaneData) { }
    ConfigPane(const ConfigPane &other): d(other.d) { }

    inline QString &id() const { return d->id; }
    inline XdgDesktopFile xdg() const { return d->xdg; }
    inline void setXdg(XdgDesktopFile xdg) { d->xdg = xdg; }
    inline QString &category() const { return d->category; }

    bool operator==(const ConfigPane &other) const
    {
        return d->id == other.id();
    }

private:
    QExplicitlySharedDataPointer<ConfigPaneData> d;
};

class ConfigPaneModel: public QAbstractListModel
{
public:
    ConfigPaneModel(): QAbstractListModel()
    {
        QString menuFile = XdgMenu::getMenuFileName(QStringLiteral("config.menu"));
        XdgMenu xdgMenu;
        xdgMenu.setEnvironments(QStringList() << QStringLiteral("X-LXQT") << QStringLiteral("LXQt") << QStringLiteral("LXDE"));
        bool res = xdgMenu.read(menuFile);
        if (!res)
        {
            QMessageBox::warning(nullptr, QStringLiteral("Parse error"), xdgMenu.errorString());
            return;
        }

        DomElementIterator it(xdgMenu.xml().documentElement() , QStringLiteral("Menu"));
        while(it.hasNext())
        {
            this->buildGroup(it.next());
        }
    }

    void buildGroup(const QDomElement& xml)
    {
        QString category;
        if (! xml.attribute(QStringLiteral("title")).isEmpty())
            category = xml.attribute(QStringLiteral("title"));
        else
            category = xml.attribute(QStringLiteral("name"));

        DomElementIterator it(xml , QStringLiteral("AppLink"));
        while(it.hasNext())
        {
            QDomElement x = it.next();

            XdgDesktopFile xdg;
            xdg.load(x.attribute(QStringLiteral("desktopFile")));

            ConfigPane pane;
            pane.id() = xdg.value(QStringLiteral("Icon")).toString();
            pane.category() = category;
            pane.setXdg(xdg);
            m_list.append(pane);
        }
    }

    void activateItem(const QModelIndex &index)
    {
        if (!index.isValid())
            return;
        m_list[index.row()].xdg().startDetached();
    }

    ~ConfigPaneModel() override { }

    int rowCount(const QModelIndex &parent = QModelIndex()) const override
    {
        return m_list.count();
    }

    bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole) override
    {
        return false;
    }

    QVariant data(const QModelIndex &index, int role) const override
    {
        if (role == Qt::DisplayRole || role == Qt::ToolTipRole)
            return m_list[index.row()].xdg().name();
        if (role == QCategorizedSortFilterProxyModel::CategoryDisplayRole)
            return m_list[index.row()].category();
        if (role == QCategorizedSortFilterProxyModel::CategorySortRole)
            return m_list[index.row()].category();
        if (role == Qt::UserRole)
            return m_list[index.row()].id();
        if (role == Qt::DecorationRole)
        {
            return m_list[index.row()].xdg().icon(XdgIcon::defaultApplicationIcon());
        }
        return QVariant();
    }

private:
    QList<ConfigPane> m_list;
};

}

class ConfigItemDelegate : public QStyledItemDelegate
{
public:
    ConfigItemDelegate(QCategorizedView* view) : mView(view) { }
    ~ConfigItemDelegate() override { }

    QSize sizeHint(const QStyleOptionViewItem& option, const QModelIndex& index) const override
    {
        /* We let Qt calculate the real cell size but consider the 4-px margin
           around each cell and try to add a 2-px margin around the selection
           rectangle for styles that, unlike Fusion, highlight the whole item. */
        QStyleOptionViewItem opt = option;
        int delta = opt.rect.width() - (mView->gridSize().width() - 8);
        if (delta > 0)
          opt.rect.adjust(delta/2, 0 , -delta/2, 0);
        QSize defaultSize = QStyledItemDelegate::sizeHint(opt, index);
        return QSize(qMin(defaultSize.width() + 4, mView->gridSize().width() - 8),
                     qMin(defaultSize.height() + 4, mView->gridSize().height() - 8));
    }

protected:
    void paint(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const override
    {
        if(!index.isValid())
            return;

        QStyleOptionViewItem opt = option;
        initStyleOption(&opt, index);

        const QSize & iconSize = option.decorationSize;
        int size = qMin(mView->gridSize().width() - 8, // 4-px margin around each cell
                        iconSize.height());
        opt.decorationSize = QSize(size, size);

        const QWidget* widget = opt.widget;
        QStyle* style = widget ? widget->style() : QApplication::style();
        style->drawControl(QStyle::CE_ItemViewItem, &opt, painter, widget);
    }

private:
    QCategorizedView *mView;
};

LXQtConfig::MainWindow::MainWindow() : QMainWindow()
{
    setupUi(this);
    view->installEventFilter(this);

    /* To always have the intended layout on startup,
       the listview should be shown after it's fully formed. */
    view->hide();

    model = new ConfigPaneModel();

    view->setViewMode(QListView::IconMode);
    view->setWordWrap(true);
    view->setUniformItemSizes(true);
    view->setCategoryDrawer(new QCategoryDrawerV3(view));

    connect(view, &QAbstractItemView::activated, [this] (const QModelIndex & index) { pendingActivation = index; });
    view->setFocus();

    QTimer::singleShot(0, [this] { setSizing(); });
    QTimer::singleShot(1, this, SLOT(load()));
    new QShortcut{QKeySequence{Qt::CTRL + Qt::Key_Q}, this, SLOT(close())};
}

void LXQtConfig::MainWindow::load()
{
    QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));

    proxyModel = new QCategorizedSortFilterProxyModel();
    proxyModel->setCategorizedModel(true);
    proxyModel->setSourceModel(model);

    view->setModel(proxyModel);
    view->setItemDelegate(new ConfigItemDelegate(view));

    view->show();

    QApplication::restoreOverrideCursor();
}

void LXQtConfig::MainWindow::activateItem()
{
    if (pendingActivation.isValid())
    {
        model->activateItem(pendingActivation);
        pendingActivation = QModelIndex{};
    }
}

/*Note: all this delayed activation is here to workaround the auto-repeated
 * Enter/Return key activation -> if the user keeps pressing the enter/return
 * we normaly will keep activating (spawning new processes) until the focus
 * isn't stolen from our window. New process is not spawned until the
 * (non-autorepeated) KeyRelease is delivered.
 *
 * ref https://github.com/lxqt/lxqt/issues/965
 */
bool LXQtConfig::MainWindow::eventFilter(QObject * watched, QEvent * event)
{
    if (view != watched)
        return false;
    switch (event->type())
    {
        case QEvent::KeyPress:
        case QEvent::KeyRelease:
            {
                QKeyEvent * ev = dynamic_cast<QKeyEvent *>(event);
                switch (ev->key())
                {
                    case Qt::Key_Enter:
                    case Qt::Key_Return:
                        if (QEvent::KeyRelease == ev->type() && !ev->isAutoRepeat())
                            activateItem();
                }
            }
            break;
        case QEvent::MouseButtonRelease:
            activateItem();
            break;
        default:
            //keep warnings quiet
            break;
    }
    return false;
}

void LXQtConfig::MainWindow::setSizing()
{
    // consult the style to know the icon size
    int iconSize = qBound(16, view->decorationSize().height(), 256);
    /* To have an appropriate grid size, we suppose that
     *
     * (1) The text has 3 lines and each line has 16 chars (for languages like German), at most;
     * (2) The selection rect has a margin of 2 px, at most;
     * (3) There is, at most, a 3-px spacing between text and icon; and
     * (4) There is a 4-px margin around each cell.
     */
    QFontMetrics fm = fontMetrics();
    int textWidth = fm.averageCharWidth() * 16;
    int textHeight = fm.lineSpacing() * 3;
    QSize grid;
    grid.setWidth(qMax(iconSize, textWidth) + 4);
    grid.setHeight(iconSize + textHeight + 4 + 3);
    view->setGridSize(grid + QSize(8, 8));
}

bool LXQtConfig::MainWindow::event(QEvent * event)
{
    if (QEvent::StyleChange == event->type())
        setSizing();
    return QMainWindow::event(event);
}
<|endoftext|>


<commit_before>#include <ROOT/RConfig.h>
#include <ROOT/RDataFrame.hxx>
#include <ROOT/RMakeUnique.hxx>
#include <ROOT/RSqliteDS.hxx>
#include <ROOT/TSeq.hxx>

#include <TSystem.h>

#include <gtest/gtest.h>

#include <algorithm>
#include <memory>

using namespace ROOT::RDF;

constexpr auto fileName0 = "RSqliteDS_test.sqlite";
constexpr auto url0 = "https://root.cern.ch/files/RSqliteDS_test.sqlite";
constexpr auto url1 = "https://root.cern.ch/files/RSqliteDS_test.sqlite.404";
constexpr auto query0 = "SELECT * FROM test";
constexpr auto query1 = "SELECT fint + 1, freal/1.0 as fmyreal, NULL, 'X', fblob FROM test";
constexpr auto query2 = "SELECT fint, freal, fint FROM test";
constexpr auto query3 = "SELECT fint, freal, ftext, fblob FROM test";
constexpr auto epsilon = 0.001;

TEST(RSqliteDS, Basics)
{
   auto rdf = MakeSqliteDataFrame(fileName0, query0);
   EXPECT_EQ(1, *rdf.Min("fint"));
   EXPECT_EQ(2, *rdf.Max("fint"));

   EXPECT_THROW(MakeSqliteDataFrame(fileName0, ""), std::runtime_error);
   EXPECT_THROW(MakeSqliteDataFrame("", query0), std::runtime_error);
}

TEST(RSqliteDS, Snapshot)
{
   // Use query 3 to avoid storing a void * in the root file
   auto rdf = MakeSqliteDataFrame(fileName0, query3);

   constexpr auto fname = "datasource_sqlite_snapshot.root";
   auto rdf_root = rdf.Snapshot("tree", fname);

   auto fintVec = rdf_root->Take<Long64_t>("fint");
   auto frealVec = rdf_root->Take<double>("freal");
   auto ftextVec = rdf_root->Take<std::string>("ftext");
   auto fblobVec = rdf_root->Take<std::vector<unsigned char>>("fblob");

   EXPECT_EQ(2U, fintVec->size());
   EXPECT_EQ(2U, frealVec->size());
   EXPECT_EQ(2U, ftextVec->size());
   EXPECT_EQ(2U, fblobVec->size());

   EXPECT_EQ(1, (*fintVec)[0]);
   EXPECT_EQ(2, (*fintVec)[1]);
   EXPECT_NEAR(1.0, (*frealVec)[0], epsilon);
   EXPECT_NEAR(2.0, (*frealVec)[1], epsilon);
   EXPECT_EQ("1", (*ftextVec)[0]);
   EXPECT_EQ("2", (*ftextVec)[1]);
   EXPECT_EQ(1U, (*fblobVec)[0].size());
   EXPECT_EQ('1', (*fblobVec)[0][0]);
   EXPECT_EQ(1U, (*fblobVec)[1].size());
   EXPECT_EQ('2', (*fblobVec)[1][0]);

   gSystem->Unlink(fname);
}

TEST(RSqliteDS, ColTypeNames)
{
   RSqliteDS rds(fileName0, query0);

   auto colNames = rds.GetColumnNames();
   ASSERT_EQ(5U, colNames.size());
   std::sort(colNames.begin(), colNames.end());
   EXPECT_EQ("fblob", colNames[0]);
   EXPECT_EQ("fint", colNames[1]);
   EXPECT_EQ("fnull", colNames[2]);
   EXPECT_EQ("freal", colNames[3]);
   EXPECT_EQ("ftext", colNames[4]);

   EXPECT_TRUE(rds.HasColumn("fint"));
   EXPECT_TRUE(rds.HasColumn("freal"));
   EXPECT_TRUE(rds.HasColumn("ftext"));
   EXPECT_TRUE(rds.HasColumn("fblob"));
   EXPECT_TRUE(rds.HasColumn("fnull"));
   EXPECT_FALSE(rds.HasColumn("foo"));

   EXPECT_EQ("Long64_t", rds.GetTypeName("fint"));
   EXPECT_EQ("double", rds.GetTypeName("freal"));
   EXPECT_EQ("std::string", rds.GetTypeName("ftext"));
   EXPECT_EQ("std::vector<unsigned char>", rds.GetTypeName("fblob"));
   EXPECT_EQ("void *", rds.GetTypeName("fnull"));
   EXPECT_THROW(rds.GetTypeName("foo"), std::runtime_error);
}

TEST(RSqliteDS, ExprTypeNames)
{
   RSqliteDS rds(fileName0, query1);

   EXPECT_EQ("Long64_t", rds.GetTypeName("fint + 1"));
   EXPECT_EQ("double", rds.GetTypeName("fmyreal"));
   EXPECT_EQ("void *", rds.GetTypeName("NULL"));
   EXPECT_EQ("std::string", rds.GetTypeName("'X'"));
   EXPECT_EQ("std::vector<unsigned char>", rds.GetTypeName("fblob"));
   EXPECT_THROW(rds.GetTypeName("foo"), std::runtime_error);
}

TEST(RSqliteDS, DuplicateColumns)
{
   RSqliteDS rds(fileName0, query2);
   rds.SetNSlots(1);

   EXPECT_EQ("Long64_t", rds.GetTypeName("fint"));
   EXPECT_EQ("double", rds.GetTypeName("freal"));
   auto vals = rds.GetColumnReaders<Long64_t>("fint");
   rds.Initialise();
   auto ranges = rds.GetEntryRanges();
   ASSERT_EQ(1U, ranges.size());
   EXPECT_TRUE(rds.SetEntry(0, ranges[0].first));
   auto val = **vals[0];
   EXPECT_EQ(1, val);
}

TEST(RSqliteDS, ColumnReaders)
{
   RSqliteDS rds(fileName0, query0);
   const auto nSlots = 2U;
   rds.SetNSlots(nSlots);
   auto vals = rds.GetColumnReaders<Long64_t>("fint");
   rds.Initialise();
   auto ranges = rds.GetEntryRanges();
   EXPECT_EQ(1U, ranges.size());
   for (auto i : ROOT::TSeq<unsigned>(0, nSlots)) {
      EXPECT_TRUE(rds.SetEntry(i, ranges[0].first));
      auto val = **vals[i];
      EXPECT_EQ(1, val);
   }

   EXPECT_THROW(rds.GetColumnReaders<double>("fint"), std::runtime_error);
}

TEST(RSqliteDS, GetEntryRanges)
{
   RSqliteDS rds(fileName0, query0);
   rds.Initialise();
   auto ranges = rds.GetEntryRanges();
   ASSERT_EQ(1U, ranges.size());
   EXPECT_EQ(0U, ranges[0].first);
   EXPECT_EQ(1U, ranges[0].second);
   ranges = rds.GetEntryRanges();
   ASSERT_EQ(1U, ranges.size());
   EXPECT_EQ(1U, ranges[0].first);
   EXPECT_EQ(2U, ranges[0].second);
   ranges = rds.GetEntryRanges();
   EXPECT_EQ(0U, ranges.size());

   // New event loop
   rds.Initialise();
   ranges = rds.GetEntryRanges();
   EXPECT_EQ(1U, ranges.size());
   EXPECT_EQ(0U, ranges[0].first);
   EXPECT_EQ(1U, ranges[0].second);
}

TEST(RSqliteDS, SetEntry)
{
   RSqliteDS rds(fileName0, query0);
   rds.SetNSlots(1);
   auto vint = rds.GetColumnReaders<Long64_t>("fint");
   auto vreal = rds.GetColumnReaders<double>("freal");
   auto vtext = rds.GetColumnReaders<std::string>("ftext");
   auto vblob = rds.GetColumnReaders<std::vector<unsigned char>>("fblob");
   auto vnull = rds.GetColumnReaders<void *>("fnull");

   rds.Initialise();

   rds.GetEntryRanges();
   EXPECT_TRUE(rds.SetEntry(0, 0));
   EXPECT_EQ(1, **vint[0]);
   EXPECT_NEAR(1.0, **vreal[0], epsilon);
   EXPECT_EQ("1", **vtext[0]);
   EXPECT_EQ(1U, (**vblob[0]).size());
   EXPECT_EQ('1', (**vblob[0])[0]);
   EXPECT_EQ(nullptr, **vnull[0]);

   rds.GetEntryRanges();
   EXPECT_TRUE(rds.SetEntry(0, 1));
   EXPECT_EQ(2, **vint[0]);
   EXPECT_NEAR(2.0, **vreal[0], epsilon);
   EXPECT_EQ("2", **vtext[0]);
   EXPECT_EQ(1U, (**vblob[0]).size());
   EXPECT_EQ('2', (**vblob[0])[0]);
   EXPECT_EQ(nullptr, **vnull[0]);
}

#ifdef R__USE_IMT

TEST(RSqliteDS, IMT)
{
   using Blob_t = std::vector<unsigned char>;
   const auto nSlots = 4U;
   ROOT::EnableImplicitMT(nSlots);

   auto rdf = MakeSqliteDataFrame(fileName0, query0);
   EXPECT_EQ(3, *rdf.Sum("fint"));
   EXPECT_NEAR(3.0, *rdf.Sum("freal"), epsilon);
   auto sum_text = *rdf.Reduce([](std::string a, std::string b) { return a + b; }, "ftext");
   std::sort(sum_text.begin(), sum_text.end());
   EXPECT_EQ("12", sum_text);
   auto sum_blob = *rdf.Reduce(
      [](Blob_t a, Blob_t b) {
         a.insert(a.end(), b.begin(), b.end());
         return a;
      },
      "fblob");
   std::sort(sum_blob.begin(), sum_blob.end());

   ROOT::DisableImplicitMT();

   ASSERT_EQ(2U, sum_blob.size());
   EXPECT_EQ('1', sum_blob[0]);
   EXPECT_EQ('2', sum_blob[1]);
}

#endif // R__USE_IMT

TEST(RSqliteDS, Davix)
{
#ifdef R__HAS_DAVIX
   auto rdf = MakeSqliteDataFrame(url0, query0);
   EXPECT_EQ(1, *rdf.Min("fint"));
   EXPECT_EQ(2, *rdf.Max("fint"));

   EXPECT_THROW(MakeSqliteDataFrame(url1, query0), std::runtime_error);
#else
   EXPECT_THROW(MakeSqliteDataFrame(url0, query0), std::runtime_error);
#endif
}
<commit_msg>[DF] avoid to trigger HTTPS@macOS issue in sqlite ds unit test<commit_after>#include <ROOT/RConfig.h>
#include <ROOT/RDataFrame.hxx>
#include <ROOT/RMakeUnique.hxx>
#include <ROOT/RSqliteDS.hxx>
#include <ROOT/TSeq.hxx>

#include <TSystem.h>

#include <gtest/gtest.h>

#include <algorithm>
#include <memory>

using namespace ROOT::RDF;

constexpr auto fileName0 = "RSqliteDS_test.sqlite";
constexpr auto url0 = "http://root.cern.ch/files/RSqliteDS_test.sqlite";
constexpr auto url1 = "http://root.cern.ch/files/RSqliteDS_test.sqlite.404";
constexpr auto query0 = "SELECT * FROM test";
constexpr auto query1 = "SELECT fint + 1, freal/1.0 as fmyreal, NULL, 'X', fblob FROM test";
constexpr auto query2 = "SELECT fint, freal, fint FROM test";
constexpr auto query3 = "SELECT fint, freal, ftext, fblob FROM test";
constexpr auto epsilon = 0.001;

TEST(RSqliteDS, Basics)
{
   auto rdf = MakeSqliteDataFrame(fileName0, query0);
   EXPECT_EQ(1, *rdf.Min("fint"));
   EXPECT_EQ(2, *rdf.Max("fint"));

   EXPECT_THROW(MakeSqliteDataFrame(fileName0, ""), std::runtime_error);
   EXPECT_THROW(MakeSqliteDataFrame("", query0), std::runtime_error);
}

TEST(RSqliteDS, Snapshot)
{
   // Use query 3 to avoid storing a void * in the root file
   auto rdf = MakeSqliteDataFrame(fileName0, query3);

   constexpr auto fname = "datasource_sqlite_snapshot.root";
   auto rdf_root = rdf.Snapshot("tree", fname);

   auto fintVec = rdf_root->Take<Long64_t>("fint");
   auto frealVec = rdf_root->Take<double>("freal");
   auto ftextVec = rdf_root->Take<std::string>("ftext");
   auto fblobVec = rdf_root->Take<std::vector<unsigned char>>("fblob");

   EXPECT_EQ(2U, fintVec->size());
   EXPECT_EQ(2U, frealVec->size());
   EXPECT_EQ(2U, ftextVec->size());
   EXPECT_EQ(2U, fblobVec->size());

   EXPECT_EQ(1, (*fintVec)[0]);
   EXPECT_EQ(2, (*fintVec)[1]);
   EXPECT_NEAR(1.0, (*frealVec)[0], epsilon);
   EXPECT_NEAR(2.0, (*frealVec)[1], epsilon);
   EXPECT_EQ("1", (*ftextVec)[0]);
   EXPECT_EQ("2", (*ftextVec)[1]);
   EXPECT_EQ(1U, (*fblobVec)[0].size());
   EXPECT_EQ('1', (*fblobVec)[0][0]);
   EXPECT_EQ(1U, (*fblobVec)[1].size());
   EXPECT_EQ('2', (*fblobVec)[1][0]);

   gSystem->Unlink(fname);
}

TEST(RSqliteDS, ColTypeNames)
{
   RSqliteDS rds(fileName0, query0);

   auto colNames = rds.GetColumnNames();
   ASSERT_EQ(5U, colNames.size());
   std::sort(colNames.begin(), colNames.end());
   EXPECT_EQ("fblob", colNames[0]);
   EXPECT_EQ("fint", colNames[1]);
   EXPECT_EQ("fnull", colNames[2]);
   EXPECT_EQ("freal", colNames[3]);
   EXPECT_EQ("ftext", colNames[4]);

   EXPECT_TRUE(rds.HasColumn("fint"));
   EXPECT_TRUE(rds.HasColumn("freal"));
   EXPECT_TRUE(rds.HasColumn("ftext"));
   EXPECT_TRUE(rds.HasColumn("fblob"));
   EXPECT_TRUE(rds.HasColumn("fnull"));
   EXPECT_FALSE(rds.HasColumn("foo"));

   EXPECT_EQ("Long64_t", rds.GetTypeName("fint"));
   EXPECT_EQ("double", rds.GetTypeName("freal"));
   EXPECT_EQ("std::string", rds.GetTypeName("ftext"));
   EXPECT_EQ("std::vector<unsigned char>", rds.GetTypeName("fblob"));
   EXPECT_EQ("void *", rds.GetTypeName("fnull"));
   EXPECT_THROW(rds.GetTypeName("foo"), std::runtime_error);
}

TEST(RSqliteDS, ExprTypeNames)
{
   RSqliteDS rds(fileName0, query1);

   EXPECT_EQ("Long64_t", rds.GetTypeName("fint + 1"));
   EXPECT_EQ("double", rds.GetTypeName("fmyreal"));
   EXPECT_EQ("void *", rds.GetTypeName("NULL"));
   EXPECT_EQ("std::string", rds.GetTypeName("'X'"));
   EXPECT_EQ("std::vector<unsigned char>", rds.GetTypeName("fblob"));
   EXPECT_THROW(rds.GetTypeName("foo"), std::runtime_error);
}

TEST(RSqliteDS, DuplicateColumns)
{
   RSqliteDS rds(fileName0, query2);
   rds.SetNSlots(1);

   EXPECT_EQ("Long64_t", rds.GetTypeName("fint"));
   EXPECT_EQ("double", rds.GetTypeName("freal"));
   auto vals = rds.GetColumnReaders<Long64_t>("fint");
   rds.Initialise();
   auto ranges = rds.GetEntryRanges();
   ASSERT_EQ(1U, ranges.size());
   EXPECT_TRUE(rds.SetEntry(0, ranges[0].first));
   auto val = **vals[0];
   EXPECT_EQ(1, val);
}

TEST(RSqliteDS, ColumnReaders)
{
   RSqliteDS rds(fileName0, query0);
   const auto nSlots = 2U;
   rds.SetNSlots(nSlots);
   auto vals = rds.GetColumnReaders<Long64_t>("fint");
   rds.Initialise();
   auto ranges = rds.GetEntryRanges();
   EXPECT_EQ(1U, ranges.size());
   for (auto i : ROOT::TSeq<unsigned>(0, nSlots)) {
      EXPECT_TRUE(rds.SetEntry(i, ranges[0].first));
      auto val = **vals[i];
      EXPECT_EQ(1, val);
   }

   EXPECT_THROW(rds.GetColumnReaders<double>("fint"), std::runtime_error);
}

TEST(RSqliteDS, GetEntryRanges)
{
   RSqliteDS rds(fileName0, query0);
   rds.Initialise();
   auto ranges = rds.GetEntryRanges();
   ASSERT_EQ(1U, ranges.size());
   EXPECT_EQ(0U, ranges[0].first);
   EXPECT_EQ(1U, ranges[0].second);
   ranges = rds.GetEntryRanges();
   ASSERT_EQ(1U, ranges.size());
   EXPECT_EQ(1U, ranges[0].first);
   EXPECT_EQ(2U, ranges[0].second);
   ranges = rds.GetEntryRanges();
   EXPECT_EQ(0U, ranges.size());

   // New event loop
   rds.Initialise();
   ranges = rds.GetEntryRanges();
   EXPECT_EQ(1U, ranges.size());
   EXPECT_EQ(0U, ranges[0].first);
   EXPECT_EQ(1U, ranges[0].second);
}

TEST(RSqliteDS, SetEntry)
{
   RSqliteDS rds(fileName0, query0);
   rds.SetNSlots(1);
   auto vint = rds.GetColumnReaders<Long64_t>("fint");
   auto vreal = rds.GetColumnReaders<double>("freal");
   auto vtext = rds.GetColumnReaders<std::string>("ftext");
   auto vblob = rds.GetColumnReaders<std::vector<unsigned char>>("fblob");
   auto vnull = rds.GetColumnReaders<void *>("fnull");

   rds.Initialise();

   rds.GetEntryRanges();
   EXPECT_TRUE(rds.SetEntry(0, 0));
   EXPECT_EQ(1, **vint[0]);
   EXPECT_NEAR(1.0, **vreal[0], epsilon);
   EXPECT_EQ("1", **vtext[0]);
   EXPECT_EQ(1U, (**vblob[0]).size());
   EXPECT_EQ('1', (**vblob[0])[0]);
   EXPECT_EQ(nullptr, **vnull[0]);

   rds.GetEntryRanges();
   EXPECT_TRUE(rds.SetEntry(0, 1));
   EXPECT_EQ(2, **vint[0]);
   EXPECT_NEAR(2.0, **vreal[0], epsilon);
   EXPECT_EQ("2", **vtext[0]);
   EXPECT_EQ(1U, (**vblob[0]).size());
   EXPECT_EQ('2', (**vblob[0])[0]);
   EXPECT_EQ(nullptr, **vnull[0]);
}

#ifdef R__USE_IMT

TEST(RSqliteDS, IMT)
{
   using Blob_t = std::vector<unsigned char>;
   const auto nSlots = 4U;
   ROOT::EnableImplicitMT(nSlots);

   auto rdf = MakeSqliteDataFrame(fileName0, query0);
   EXPECT_EQ(3, *rdf.Sum("fint"));
   EXPECT_NEAR(3.0, *rdf.Sum("freal"), epsilon);
   auto sum_text = *rdf.Reduce([](std::string a, std::string b) { return a + b; }, "ftext");
   std::sort(sum_text.begin(), sum_text.end());
   EXPECT_EQ("12", sum_text);
   auto sum_blob = *rdf.Reduce(
      [](Blob_t a, Blob_t b) {
         a.insert(a.end(), b.begin(), b.end());
         return a;
      },
      "fblob");
   std::sort(sum_blob.begin(), sum_blob.end());

   ROOT::DisableImplicitMT();

   ASSERT_EQ(2U, sum_blob.size());
   EXPECT_EQ('1', sum_blob[0]);
   EXPECT_EQ('2', sum_blob[1]);
}

#endif // R__USE_IMT

TEST(RSqliteDS, Davix)
{
#ifdef R__HAS_DAVIX
   auto rdf = MakeSqliteDataFrame(url0, query0);
   EXPECT_EQ(1, *rdf.Min("fint"));
   EXPECT_EQ(2, *rdf.Max("fint"));

   EXPECT_THROW(MakeSqliteDataFrame(url1, query0), std::runtime_error);
#else
   EXPECT_THROW(MakeSqliteDataFrame(url0, query0), std::runtime_error);
#endif
}
<|endoftext|>


<commit_before>#include <vector>
#include <string>
#include <utility>
#include <map>
#include <boost/shared_ptr.hpp>

enum EEE {
    A, B
};

class Int {
    public:
        int i_;
        Int(int i): i_(i) { };
        Int(const Int & i): i_(i.i_) { };
};

class LibCppTest {
    private:
        int i;
    public:
        LibCppTest(): i(0) { };
        LibCppTest(int ii): i(ii) { };

        LibCppTest(const LibCppTest &o): i(o.i)  {
        };

        std::vector<Int> * integer_vector_ptr;
        Int * integer_ptr;

        bool operator<(const LibCppTest & other) const
        {
            return this->i < other.i;
        }
        bool operator==(const LibCppTest & other) const
        {
            return this->i == other.i;
        }

        int get() { return i; }

        std::pair<int, std::string> twist(std::pair<std::string, int> in)
        {
            return std::pair<int, std::string>(in.second, in.first);
        };

        std::vector<int> process(std::vector<int> & in)
        {
            in.push_back(42);
            return in;
        };
        std::pair<int, int> process2(std::pair<int, int> & in)
        {
            in.first = 42;
            in.second = 11;
            return in;
        };
        std::pair<LibCppTest, int> process3(std::pair<LibCppTest, int> & in)
        {
            in.second = 42;
            return std::pair<LibCppTest, int>(in.first, in.second);
        };

        std::pair<int, LibCppTest> process4(std::pair<int, LibCppTest> & in)
        {
            in.first = 42;
            return std::pair<int, LibCppTest>(in.first, in.second);
        };
        std::pair<LibCppTest, LibCppTest> process5(std::pair<LibCppTest, LibCppTest> & in)
        {
            in.first = 43;
            return std::pair<LibCppTest, LibCppTest>(in.second, in.first);
        };

        std::vector<std::pair<int, double> > process6(std::vector<std::pair<int, double> >& in) {
            in.push_back(std::pair<int,double>(7, 11.0));
            return std::vector<std::pair<int, double> > (in.rbegin(), in.rend());
        }

        std::pair<int, EEE> process7(std::pair<EEE, int> & in ) {
            return std::pair<int, EEE>(in.second, in.first);
        }

        std::vector<EEE> process8(std::vector<EEE> & in ) {
            return std::vector<EEE>(in.rbegin(), in.rend());
        }

        std::set<int> process9(std::set<int> & in ) {
            in.insert(42);
            return in;
        }

        std::set<EEE> process10(std::set<EEE> & in ) {
            in.insert(A);
            return in;
        }

        std::set<LibCppTest> process11(std::set<LibCppTest> & in ) {
            LibCppTest n(42);
            in.insert(n);
            return in;
        }

        std::map<int,float> process12(int i, float f)
        {
            std::map<int,float> map;
            map[i] = f;
            return map;
        }

        std::map<EEE, int> process13(EEE e, int i)
        {
            std::map<EEE,int> map;
            map[e] = i;
            return map;
        }

        std::map<int, EEE> process14(EEE e, int i)
        {
            std::map<int, EEE> map;
            map[i] = e;
            return map;
        }

        std::map<long int, LibCppTest> process15(int i)
        {
            std::map<long int, LibCppTest> map;
            map[i] = LibCppTest(i);
            return map;
        }

        float process16(std::map<int, float> in)
        {
            return in[42];

        }
        float process17(std::map<EEE, float> in)
        {
            return in[A];

        }

        int process18(std::map<int, LibCppTest> in)
        {
            return in[23].get();
        }

        void  process19(std::map<int, LibCppTest> & in)
        {
            LibCppTest v(12);
            in[23] = v;
        }

        void  process20(std::map<int, float> & in)
        {
            in[23] = 42.0;
        }

        void  process21(std::map<int, float> & in, std::map<int,int> & arg2)
        {
            in[1] = (float) arg2[42];
        }

        void  process22(std::set<int> & in, std::set<float> & arg2)
        {
            std::set<int>::iterator it = in.begin();
            int x = *it;
            in.erase(it);
            arg2.insert((float)x);
        }

        void  process23(std::vector<int> & in, std::vector<float> & arg2)
        {
            int x = *(in.rbegin());
            in.pop_back();
            arg2.push_back((float)x);
        }

        void  process24(std::pair<int, float> & in, std::pair<int,int> & arg2)
        {
            in.first = arg2.second;
            in.second = (float) arg2.first;
        }

        int process25(std::vector<Int> in)
        {
            int sum = 0;
            for (std::vector<Int>::const_iterator i = in.begin(); i != in.end(); ++i)
                sum += i->i_;
            return sum;
        }

        int process26(std::vector<std::vector<Int> > in)
        {
            int sum = 0;
            for (std::vector<std::vector<Int> >::const_iterator i = in.begin(); i != in.end(); ++i)
                sum += process25(*i);
            return sum;

        }

        int process27(std::vector<std::vector<std::vector<Int> > > in)
        {
            int sum = 0;
            for (std::vector<std::vector<std::vector<Int> > >::const_iterator i = in.begin(); i != in.end(); ++i)
                sum += process26(*i);
            return sum;

        }
        int process28(std::vector<std::vector<std::vector<std::vector<Int> > > > in)
        {
            int sum = 0;
            for (std::vector<std::vector<std::vector<std::vector<Int> > > >::const_iterator i = in.begin(); i != in.end(); ++i)
                sum += process27(*i);
            return sum;

        }
        void process29(std::vector<std::vector<Int> > & in)
        {
            for (std::vector<std::vector<Int> >::iterator i = in.begin(); i != in.end(); ++i)
            {
              i->push_back(42);
            }
        }
        void process30(std::vector<std::vector<std::vector<std::vector<Int> > > > & in)
        {
            for (std::vector<std::vector<std::vector<std::vector<Int> > > >::iterator i = in.begin(); i != in.end(); ++i)
            {
                std::vector<std::vector<Int> > newvec;
                std::vector<Int> newvec_inner;
                Int int_obj = Int(42);

                newvec_inner.push_back(int_obj);
                newvec.push_back(newvec_inner);

                i->push_back(newvec);
            }
        }

        int process31(const std::vector<int> & in)
        {
            int sum = 0;
            for (std::vector<int>::const_iterator i = in.begin(); i != in.end(); ++i)
                sum += *i;
            return sum;
        }

        int process32(const std::vector<std::vector<int> > & in)
        {
            int sum = 0;
            for (std::vector<std::vector<int> >::const_iterator i = in.begin(); i != in.end(); ++i)
                sum += process31(*i);
            return sum;
        }

        int process33(boost::shared_ptr<Int> in)
        {
            in->i_++;
            return in->i_;
        }

        boost::shared_ptr<Int> process34(boost::shared_ptr<Int> in)
        {
            in->i_++;
            return in;
        }

};
<commit_msg>[FIX] fixed invalid memory access introduced in commit ea0ad0014<commit_after>#include <vector>
#include <string>
#include <utility>
#include <map>
#include <boost/shared_ptr.hpp>

enum EEE {
    A, B
};

class Int {
    public:
        int i_;
        Int(int i): i_(i) { };
        Int(const Int & i): i_(i.i_) { };
};

class LibCppTest {
    private:
        int i;
    public:
        LibCppTest(): i(0), integer_ptr(0), integer_vector_ptr(0) { };
        LibCppTest(int ii): i(ii) { };

        LibCppTest(const LibCppTest &o): i(o.i)  {
        };

        std::vector<Int> * integer_vector_ptr;
        Int * integer_ptr;

        bool operator<(const LibCppTest & other) const
        {
            return this->i < other.i;
        }
        bool operator==(const LibCppTest & other) const
        {
            return this->i == other.i;
        }

        int get() { return i; }

        std::pair<int, std::string> twist(std::pair<std::string, int> in)
        {
            return std::pair<int, std::string>(in.second, in.first);
        };

        std::vector<int> process(std::vector<int> & in)
        {
            in.push_back(42);
            return in;
        };
        std::pair<int, int> process2(std::pair<int, int> & in)
        {
            in.first = 42;
            in.second = 11;
            return in;
        };
        std::pair<LibCppTest, int> process3(std::pair<LibCppTest, int> & in)
        {
            in.second = 42;
            return std::pair<LibCppTest, int>(in.first, in.second);
        };

        std::pair<int, LibCppTest> process4(std::pair<int, LibCppTest> & in)
        {
            in.first = 42;
            return std::pair<int, LibCppTest>(in.first, in.second);
        };
        std::pair<LibCppTest, LibCppTest> process5(std::pair<LibCppTest, LibCppTest> & in)
        {
            in.first = 43;
            return std::pair<LibCppTest, LibCppTest>(in.second, in.first);
        };

        std::vector<std::pair<int, double> > process6(std::vector<std::pair<int, double> >& in) {
            in.push_back(std::pair<int,double>(7, 11.0));
            return std::vector<std::pair<int, double> > (in.rbegin(), in.rend());
        }

        std::pair<int, EEE> process7(std::pair<EEE, int> & in ) {
            return std::pair<int, EEE>(in.second, in.first);
        }

        std::vector<EEE> process8(std::vector<EEE> & in ) {
            return std::vector<EEE>(in.rbegin(), in.rend());
        }

        std::set<int> process9(std::set<int> & in ) {
            in.insert(42);
            return in;
        }

        std::set<EEE> process10(std::set<EEE> & in ) {
            in.insert(A);
            return in;
        }

        std::set<LibCppTest> process11(std::set<LibCppTest> & in ) {
            LibCppTest n(42);
            in.insert(n);
            return in;
        }

        std::map<int,float> process12(int i, float f)
        {
            std::map<int,float> map;
            map[i] = f;
            return map;
        }

        std::map<EEE, int> process13(EEE e, int i)
        {
            std::map<EEE,int> map;
            map[e] = i;
            return map;
        }

        std::map<int, EEE> process14(EEE e, int i)
        {
            std::map<int, EEE> map;
            map[i] = e;
            return map;
        }

        std::map<long int, LibCppTest> process15(int i)
        {
            std::map<long int, LibCppTest> map;
            map[i] = LibCppTest(i);
            return map;
        }

        float process16(std::map<int, float> in)
        {
            return in[42];

        }
        float process17(std::map<EEE, float> in)
        {
            return in[A];

        }

        int process18(std::map<int, LibCppTest> in)
        {
            return in[23].get();
        }

        void  process19(std::map<int, LibCppTest> & in)
        {
            LibCppTest v(12);
            in[23] = v;
        }

        void  process20(std::map<int, float> & in)
        {
            in[23] = 42.0;
        }

        void  process21(std::map<int, float> & in, std::map<int,int> & arg2)
        {
            in[1] = (float) arg2[42];
        }

        void  process22(std::set<int> & in, std::set<float> & arg2)
        {
            std::set<int>::iterator it = in.begin();
            int x = *it;
            in.erase(it);
            arg2.insert((float)x);
        }

        void  process23(std::vector<int> & in, std::vector<float> & arg2)
        {
            int x = *(in.rbegin());
            in.pop_back();
            arg2.push_back((float)x);
        }

        void  process24(std::pair<int, float> & in, std::pair<int,int> & arg2)
        {
            in.first = arg2.second;
            in.second = (float) arg2.first;
        }

        int process25(std::vector<Int> in)
        {
            int sum = 0;
            for (std::vector<Int>::const_iterator i = in.begin(); i != in.end(); ++i)
                sum += i->i_;
            return sum;
        }

        int process26(std::vector<std::vector<Int> > in)
        {
            int sum = 0;
            for (std::vector<std::vector<Int> >::const_iterator i = in.begin(); i != in.end(); ++i)
                sum += process25(*i);
            return sum;

        }

        int process27(std::vector<std::vector<std::vector<Int> > > in)
        {
            int sum = 0;
            for (std::vector<std::vector<std::vector<Int> > >::const_iterator i = in.begin(); i != in.end(); ++i)
                sum += process26(*i);
            return sum;

        }
        int process28(std::vector<std::vector<std::vector<std::vector<Int> > > > in)
        {
            int sum = 0;
            for (std::vector<std::vector<std::vector<std::vector<Int> > > >::const_iterator i = in.begin(); i != in.end(); ++i)
                sum += process27(*i);
            return sum;

        }
        void process29(std::vector<std::vector<Int> > & in)
        {
            for (std::vector<std::vector<Int> >::iterator i = in.begin(); i != in.end(); ++i)
            {
              i->push_back(42);
            }
        }
        void process30(std::vector<std::vector<std::vector<std::vector<Int> > > > & in)
        {
            for (std::vector<std::vector<std::vector<std::vector<Int> > > >::iterator i = in.begin(); i != in.end(); ++i)
            {
                std::vector<std::vector<Int> > newvec;
                std::vector<Int> newvec_inner;
                Int int_obj = Int(42);

                newvec_inner.push_back(int_obj);
                newvec.push_back(newvec_inner);

                i->push_back(newvec);
            }
        }

        int process31(const std::vector<int> & in)
        {
            int sum = 0;
            for (std::vector<int>::const_iterator i = in.begin(); i != in.end(); ++i)
                sum += *i;
            return sum;
        }

        int process32(const std::vector<std::vector<int> > & in)
        {
            int sum = 0;
            for (std::vector<std::vector<int> >::const_iterator i = in.begin(); i != in.end(); ++i)
                sum += process31(*i);
            return sum;
        }

        int process33(boost::shared_ptr<Int> in)
        {
            in->i_++;
            return in->i_;
        }

        boost::shared_ptr<Int> process34(boost::shared_ptr<Int> in)
        {
            in->i_++;
            return in;
        }

};
<|endoftext|>


<commit_before>#include "window.h"
#include "map_window.h"
#include "inspection_window.h"
#include "equipment_window.h"
#include "game_engine.h"
#include "event.h"
#include "sprite_component.h"
#include "health_component.h"
#include "droppable_component.h"
#include "file_saver.h"
#include "file_loader.h"

void MapWindow::gainFocus ()
{
    //getEngine()->loadMap(50, 50);

    setTitle ("Map");

    m_mapXOffset = 1;
    m_mapYOffset = 9;
    m_mapStartX = 0;
    m_mapStartY = 0;
    m_mapWidth  = 0;
    m_mapHeight = 0;
    m_sidebarWidth = 20;
    m_sidebarXOffset = getWidth() - m_sidebarWidth;

    m_action = 'm';
    m_lastDraw = clock();
}

void MapWindow::redraw() {

    //clock_t l_clock = clock() - m_lastDraw;
    //double l_diff = static_cast<double> (l_clock/CLOCKS_PER_SEC);
    //if (l_diff < 0.01f) return;

    drawSeparators();
    drawMap();
    drawMessages();
    drawSidebar();
}

void MapWindow::resize() {
    setDimensions (0, 0, getEngine()->getGraphics()->getScreenWidth(), getEngine()->getGraphics()->getScreenHeight());
    m_sidebarXOffset = getWidth() - m_sidebarWidth - 1;
    m_mapWidth  = getWidth() - m_mapXOffset - m_sidebarWidth - 1;
    m_mapHeight = getHeight() - m_mapYOffset - 1;
}

void MapWindow::keyDown (unsigned char key) {
    Window::keyDown (key);

    if (key == 'w' || key == 'a' || key == 's' || key == 'd') {
        DIRECTION l_dir = Direction::None;
        switch (key) {
            case 'w': l_dir = Direction::North; break;
            case 'a': l_dir = Direction::West;  break;
            case 's': l_dir = Direction::South; break;
            case 'd': l_dir = Direction::East;  break;
        }

        if (m_action == 'm') {
            MoveEntityEvent* l_event = new MoveEntityEvent;
            l_event->entity = getEngine()->getEntities()->getPlayer();
            l_event->direction = l_dir;
            getEngine()->raiseEvent (l_event);
        }
        if (m_action == 'k') {
            AttackEntityEvent* l_event = new AttackEntityEvent;
            l_event->entity = getEngine()->getEntities()->getPlayer();
            l_event->direction = l_dir;
            getEngine()->raiseEvent (l_event);
        }
        if (m_action == 'i') {
            EntityHolder l_entities = getEngine()->getEntities()->findEntitiesToThe(l_dir, getEngine()->getEntities()->getPlayer());
            if (l_entities.size() > 0) {
                EntityId* l_target = new EntityId(*l_entities.begin());

                InspectionWindow* l_win = new InspectionWindow();
                l_win->initialise(getEngine(), l_target);
                getEngine()->getWindows()->pushWindow (l_win);
            }
        }
        if (m_action != 'i') getEngine()->swapTurn();
        m_action = 'm';
    }
    if (key == 27) {
        getEngine()->quit();
    }
    if (key == 'm' ||
        key == 'k' ||
        key == 'i') {
        m_action = key;
    }
    if (key == '.') {
        getEngine()->swapTurn();
    }
    if (key == 'p') {
        Location l_playerLoc = getEngine()->getEntities()->getLocation(getEngine()->getEntities()->getPlayer());
        EntityHolder l_entities = getEngine()->getEntities()->findEntitiesAt (l_playerLoc.x, l_playerLoc.y);
        bool foundSomethingAlready = false;
        for (EntityId l_entity : l_entities) {
            DroppableComponent* droppable = getEngine()->getComponents()->get<DroppableComponent>(l_entity);
            if (droppable) {
                if (!foundSomethingAlready) {
                    PickupEquipmentEvent* event = new PickupEquipmentEvent();
                    event->entity = getEngine()->getEntities()->getPlayer();
                    event->item = l_entity;
                    getEngine()->raiseEvent (event);
                    foundSomethingAlready = true;
                } else {
                    getEngine()->addMessage(INFO, "There's something else here...");
                    break;
                }
            }
        }
        if (!foundSomethingAlready) {
            getEngine()->addMessage(INFO, "There's nothing here...");
        }
    }
    if (key == 'E') {
        EquipmentWindow* l_win = new EquipmentWindow();
        l_win->initialise(getEngine());
        getEngine()->getWindows()->pushWindow (l_win);
    }
    if (key == 'S') {
        FileSaver saver;
        saver.initialise (getEngine());
        saver.saveState();
    }
}

void MapWindow::drawSeparators() {
    getEngine()->getGraphics()->drawBorder (m_mapYOffset-1, m_mapXOffset-1, m_mapHeight, m_mapWidth);
    getEngine()->getGraphics()->drawBorder (0, m_sidebarXOffset, getHeight()-2, m_sidebarWidth-1);
}

void MapWindow::drawMap() {
    Location l_player = getEngine()->getEntities()->getLocation(getEngine()->getEntities()->getPlayer());

    m_mapStartX = l_player.x - (m_mapWidth/2);
    m_mapStartY = l_player.y - (m_mapHeight/2);

    int xWidth = m_mapStartX + m_mapWidth;
    int yWidth = m_mapStartY + m_mapHeight;

    for (int yy = m_mapStartY; yy < yWidth; yy++) {
        for (int xx = m_mapStartX; xx < xWidth; xx++) {
            if (!getEngine()->isValidTile (xx, yy, getEngine()->getLevel())) continue;
            Tile& l_tile = getEngine()->getTile (xx, yy, getEngine()->getLevel());
            for (EntityId entity : l_tile.entities) {
                SpriteComponent* l_sprite= getEngine()->getComponents()->get<SpriteComponent> (entity);
                if (!l_sprite) continue;
                Color fgColor = l_sprite->fgColor;
                if (    xx < (int)l_player.x - 3 || xx > (int)l_player.x + 3
                    ||  yy < (int)l_player.y - 3 || yy > (int)l_player.y + 3) {
                    fgColor.Red()   *= 0.4;
                    fgColor.Green() *= 0.4;
                    fgColor.Blue()  *= 0.4;
                } else {
                    l_tile.lastVisited = getEngine()->getTurn();
                }
                if (l_tile.lastVisited > 0 && l_tile.lastVisited + 200 > getEngine()->getTurn()) {
                    drawTile (  yy + m_mapYOffset - m_mapStartY,
                                xx + m_mapXOffset - m_mapStartX,
                                l_sprite->sprite,
                                fgColor,
                                l_sprite->bgColor);
                }

            }
        }
    }

    return;
}

void MapWindow::drawMessages()
{
    std::vector<Message>& l_messages = getEngine()->getMessages();
    size_t ii = l_messages.size();
    size_t hh = m_mapYOffset-2;

    for (; ii > 0 && hh > 0; hh--, ii--) {
        Color fg;
        switch (l_messages[ii-1].severity) {
            case INFO: fg = Color (WHITE); break;
            case WARN: fg = Color (RED); break;
            case GOOD: fg = Color (GREEN); break;
            case CRIT: fg = Color (BLUE); break;
        }
        drawString (hh, 1, l_messages[ii-1].message.c_str(), fg);
    }
}

void MapWindow::drawSidebar ()
{
    // Current health
    drawString (2, m_sidebarXOffset+2, "Health:");
    EntityId player = getEngine()->getEntities()->getPlayer();
    HealthComponent* l_health = getEngine()->getComponents()->get<HealthComponent>(player);
    if (l_health) {
        drawProgressBar (m_sidebarXOffset+10, 2, l_health->health);

    }

    // Actions to take
    drawString (getHeight()-8, m_sidebarXOffset+2, "pickup Items");
    drawString (getHeight()-8, m_sidebarXOffset+2, "p", Color (GREEN));

    drawString (getHeight()-7, m_sidebarXOffset+2, "move (wasd)");
    drawString (getHeight()-7, m_sidebarXOffset+2, "m", Color (GREEN));
    if (m_action == 'm') drawString (getHeight()-7, m_sidebarXOffset+1, ">", Color (RED));

    drawString (getHeight()-6, m_sidebarXOffset+2, "attack (wasd)");
    drawString (getHeight()-6, m_sidebarXOffset+7, "k", Color (GREEN));
    if (m_action == 'k') drawString (getHeight()-6, m_sidebarXOffset+1, ">", Color (RED));

    drawString (getHeight()-5, m_sidebarXOffset+2, "inspect (wasd)");
    drawString (getHeight()-5, m_sidebarXOffset+2, "i", Color (GREEN));
    if (m_action == 'i') drawString (getHeight()-5, m_sidebarXOffset+1, ">", Color (RED));

    drawString (getHeight()-4, m_sidebarXOffset+2, "skip turn (.)");
    drawString (getHeight()-4, m_sidebarXOffset+13, ".", Color (GREEN));

    drawString (getHeight()-2, m_sidebarXOffset+2, "View Equipment");
    drawString (getHeight()-2, m_sidebarXOffset+7, "E", Color (GREEN));
}

void MapWindow::drawProgressBar (int x, int y, int value)
{
    float l_value = (float) value;
    Color l_color ((1.0f-(l_value/10.0f)), l_value/10.0f, 0);

    for (int xx = 0; xx < value; xx++) {
        drawTile (y, x+xx, 178, l_color, Color(BLACK));
    }
}
<commit_msg>Added Save hint to map window<commit_after>#include "window.h"
#include "map_window.h"
#include "inspection_window.h"
#include "equipment_window.h"
#include "game_engine.h"
#include "event.h"
#include "sprite_component.h"
#include "health_component.h"
#include "droppable_component.h"
#include "file_saver.h"
#include "file_loader.h"

void MapWindow::gainFocus ()
{
    //getEngine()->loadMap(50, 50);

    setTitle ("Map");

    m_mapXOffset = 1;
    m_mapYOffset = 9;
    m_mapStartX = 0;
    m_mapStartY = 0;
    m_mapWidth  = 0;
    m_mapHeight = 0;
    m_sidebarWidth = 20;
    m_sidebarXOffset = getWidth() - m_sidebarWidth;

    m_action = 'm';
    m_lastDraw = clock();
}

void MapWindow::redraw() {

    //clock_t l_clock = clock() - m_lastDraw;
    //double l_diff = static_cast<double> (l_clock/CLOCKS_PER_SEC);
    //if (l_diff < 0.01f) return;

    drawSeparators();
    drawMap();
    drawMessages();
    drawSidebar();
}

void MapWindow::resize() {
    setDimensions (0, 0, getEngine()->getGraphics()->getScreenWidth(), getEngine()->getGraphics()->getScreenHeight());
    m_sidebarXOffset = getWidth() - m_sidebarWidth - 1;
    m_mapWidth  = getWidth() - m_mapXOffset - m_sidebarWidth - 1;
    m_mapHeight = getHeight() - m_mapYOffset - 1;
}

void MapWindow::keyDown (unsigned char key) {
    Window::keyDown (key);

    if (key == 'w' || key == 'a' || key == 's' || key == 'd') {
        DIRECTION l_dir = Direction::None;
        switch (key) {
            case 'w': l_dir = Direction::North; break;
            case 'a': l_dir = Direction::West;  break;
            case 's': l_dir = Direction::South; break;
            case 'd': l_dir = Direction::East;  break;
        }

        if (m_action == 'm') {
            MoveEntityEvent* l_event = new MoveEntityEvent;
            l_event->entity = getEngine()->getEntities()->getPlayer();
            l_event->direction = l_dir;
            getEngine()->raiseEvent (l_event);
        }
        if (m_action == 'k') {
            AttackEntityEvent* l_event = new AttackEntityEvent;
            l_event->entity = getEngine()->getEntities()->getPlayer();
            l_event->direction = l_dir;
            getEngine()->raiseEvent (l_event);
        }
        if (m_action == 'i') {
            EntityHolder l_entities = getEngine()->getEntities()->findEntitiesToThe(l_dir, getEngine()->getEntities()->getPlayer());
            if (l_entities.size() > 0) {
                EntityId* l_target = new EntityId(*l_entities.begin());

                InspectionWindow* l_win = new InspectionWindow();
                l_win->initialise(getEngine(), l_target);
                getEngine()->getWindows()->pushWindow (l_win);
            }
        }
        if (m_action != 'i') getEngine()->swapTurn();
        m_action = 'm';
    }
    if (key == 27) {
        getEngine()->quit();
    }
    if (key == 'm' ||
        key == 'k' ||
        key == 'i') {
        m_action = key;
    }
    if (key == '.') {
        getEngine()->swapTurn();
    }
    if (key == 'p') {
        Location l_playerLoc = getEngine()->getEntities()->getLocation(getEngine()->getEntities()->getPlayer());
        EntityHolder l_entities = getEngine()->getEntities()->findEntitiesAt (l_playerLoc.x, l_playerLoc.y);
        bool foundSomethingAlready = false;
        for (EntityId l_entity : l_entities) {
            DroppableComponent* droppable = getEngine()->getComponents()->get<DroppableComponent>(l_entity);
            if (droppable) {
                if (!foundSomethingAlready) {
                    PickupEquipmentEvent* event = new PickupEquipmentEvent();
                    event->entity = getEngine()->getEntities()->getPlayer();
                    event->item = l_entity;
                    getEngine()->raiseEvent (event);
                    foundSomethingAlready = true;
                } else {
                    getEngine()->addMessage(INFO, "There's something else here...");
                    break;
                }
            }
        }
        if (!foundSomethingAlready) {
            getEngine()->addMessage(INFO, "There's nothing here...");
        }
    }
    if (key == 'E') {
        EquipmentWindow* l_win = new EquipmentWindow();
        l_win->initialise(getEngine());
        getEngine()->getWindows()->pushWindow (l_win);
    }
    if (key == 'S') {
        FileSaver saver;
        saver.initialise (getEngine());
        saver.saveState();
    }
}

void MapWindow::drawSeparators() {
    getEngine()->getGraphics()->drawBorder (m_mapYOffset-1, m_mapXOffset-1, m_mapHeight, m_mapWidth);
    getEngine()->getGraphics()->drawBorder (0, m_sidebarXOffset, getHeight()-2, m_sidebarWidth-1);
}

void MapWindow::drawMap() {
    Location l_player = getEngine()->getEntities()->getLocation(getEngine()->getEntities()->getPlayer());

    m_mapStartX = l_player.x - (m_mapWidth/2);
    m_mapStartY = l_player.y - (m_mapHeight/2);

    int xWidth = m_mapStartX + m_mapWidth;
    int yWidth = m_mapStartY + m_mapHeight;

    for (int yy = m_mapStartY; yy < yWidth; yy++) {
        for (int xx = m_mapStartX; xx < xWidth; xx++) {
            if (!getEngine()->isValidTile (xx, yy, getEngine()->getLevel())) continue;
            Tile& l_tile = getEngine()->getTile (xx, yy, getEngine()->getLevel());
            for (EntityId entity : l_tile.entities) {
                SpriteComponent* l_sprite= getEngine()->getComponents()->get<SpriteComponent> (entity);
                if (!l_sprite) continue;
                Color fgColor = l_sprite->fgColor;
                if (    xx < (int)l_player.x - 3 || xx > (int)l_player.x + 3
                    ||  yy < (int)l_player.y - 3 || yy > (int)l_player.y + 3) {
                    fgColor.Red()   *= 0.4;
                    fgColor.Green() *= 0.4;
                    fgColor.Blue()  *= 0.4;
                } else {
                    l_tile.lastVisited = getEngine()->getTurn();
                }
                if (l_tile.lastVisited > 0 && l_tile.lastVisited + 200 > getEngine()->getTurn()) {
                    drawTile (  yy + m_mapYOffset - m_mapStartY,
                                xx + m_mapXOffset - m_mapStartX,
                                l_sprite->sprite,
                                fgColor,
                                l_sprite->bgColor);
                }

            }
        }
    }

    return;
}

void MapWindow::drawMessages()
{
    std::vector<Message>& l_messages = getEngine()->getMessages();
    size_t ii = l_messages.size();
    size_t hh = m_mapYOffset-2;

    for (; ii > 0 && hh > 0; hh--, ii--) {
        Color fg;
        switch (l_messages[ii-1].severity) {
            case INFO: fg = Color (WHITE); break;
            case WARN: fg = Color (RED); break;
            case GOOD: fg = Color (GREEN); break;
            case CRIT: fg = Color (BLUE); break;
        }
        drawString (hh, 1, l_messages[ii-1].message.c_str(), fg);
    }
}

void MapWindow::drawSidebar ()
{
    // Current health
    drawString (2, m_sidebarXOffset+2, "Health:");
    EntityId player = getEngine()->getEntities()->getPlayer();
    HealthComponent* l_health = getEngine()->getComponents()->get<HealthComponent>(player);
    if (l_health) {
        drawProgressBar (m_sidebarXOffset+10, 2, l_health->health);

    }

    // Actions to take
    drawString (getHeight()-10, m_sidebarXOffset+2, "Save Game");
    drawString (getHeight()-10, m_sidebarXOffset+2, "S", Color (GREEN));

    drawString (getHeight()-8, m_sidebarXOffset+2, "pickup Items");
    drawString (getHeight()-8, m_sidebarXOffset+2, "p", Color (GREEN));

    drawString (getHeight()-7, m_sidebarXOffset+2, "move (wasd)");
    drawString (getHeight()-7, m_sidebarXOffset+2, "m", Color (GREEN));
    if (m_action == 'm') drawString (getHeight()-7, m_sidebarXOffset+1, ">", Color (RED));

    drawString (getHeight()-6, m_sidebarXOffset+2, "attack (wasd)");
    drawString (getHeight()-6, m_sidebarXOffset+7, "k", Color (GREEN));
    if (m_action == 'k') drawString (getHeight()-6, m_sidebarXOffset+1, ">", Color (RED));

    drawString (getHeight()-5, m_sidebarXOffset+2, "inspect (wasd)");
    drawString (getHeight()-5, m_sidebarXOffset+2, "i", Color (GREEN));
    if (m_action == 'i') drawString (getHeight()-5, m_sidebarXOffset+1, ">", Color (RED));

    drawString (getHeight()-4, m_sidebarXOffset+2, "skip turn (.)");
    drawString (getHeight()-4, m_sidebarXOffset+13, ".", Color (GREEN));

    drawString (getHeight()-2, m_sidebarXOffset+2, "View Equipment");
    drawString (getHeight()-2, m_sidebarXOffset+7, "E", Color (GREEN));
}

void MapWindow::drawProgressBar (int x, int y, int value)
{
    float l_value = (float) value;
    Color l_color ((1.0f-(l_value/10.0f)), l_value/10.0f, 0);

    for (int xx = 0; xx < value; xx++) {
        drawTile (y, x+xx, 178, l_color, Color(BLACK));
    }
}
<|endoftext|>


<commit_before>/*
 * Copyright (C) 2013 Frank Mertens.
 *
 * 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.
 */

#include <flux/IoMonitor.h>
#include <flux/Thread.h>
#include <flux/Process.h>
#include <flux/User.h>
#include "exceptions.h"
#include "ErrorLog.h"
#include "AccessLog.h"
#include "SystemLog.h"
#include "NodeConfig.h"
#include "WorkerPool.h"
#include "ServiceRegistry.h"
#include "DispatchInstance.h"
#include "ConnectionManager.h"
#include "NodeMaster.h"

namespace fluxnode
{

NodeMaster::NodeMaster()
{}

int NodeMaster::run(int argc, char **argv)
{
	SystemLog::open(String(argv[0])->baseName(), 0, LOG_DAEMON);

	Process::enableInterrupt(SIGINT);
	Process::enableInterrupt(SIGTERM);
	Process::enableInterrupt(SIGHUP);
	Thread::blockSignals(SignalSet::createFull());
	{
		Ref<SignalSet> signalSet = SignalSet::createEmpty();
		signalSet->insert(SIGINT);
		signalSet->insert(SIGTERM);
		signalSet->insert(SIGHUP);
		Thread::unblockSignals(signalSet);
	}

	while (true) {
		try {
			runNode(argc, argv);
		}
		catch (Interrupt &ex) {
			if (ex.signal() == SIGINT || ex.signal() == SIGTERM) break;
			if (ex.signal() == SIGHUP) continue;
			return ex.signal() + 128;
		}
	}

	return 0;
}

void NodeMaster::runNode(int argc, char **argv)
{
	nodeConfig()->load(argc, argv);

	if (nodeConfig()->daemon() && !Process::isDaemonized())
		Process::daemonize();

	errorLog()->open(nodeConfig()->errorLogConfig());
	// accessLog()->open(nodeConfig()->accessLogConfig());

	FLUXNODE_NOTICE() << "Starting..." << nl;

	Ref<DispatchInstance> dispatchInstance;
	for (int i = 0; i < nodeConfig()->serviceInstances()->size(); ++i) {
		if (nodeConfig()->serviceInstances()->at(i)->serviceName() == "Dispatch") {
			dispatchInstance = nodeConfig()->serviceInstances()->at(i);
			nodeConfig()->serviceInstances()->pop(i);
			--i;
		}
	}

	if (!dispatchInstance) {
		ServiceDefinition *dispatchService = serviceRegistry()->serviceByName("Dispatch");
		YasonObject *config = dispatchService->configPrototype();
		dispatchInstance = dispatchService->createInstance(config);
	}

	if (nodeConfig()->serviceInstances()->size() == 0)
	{
		FLUXNODE_WARNING() << "No service configured, falling back to Echo service" << nl;

		ServiceDefinition *echoService = serviceRegistry()->serviceByName("Echo");
		YasonObject *config = echoService->configPrototype();
		config->establish("host", "*");
		Ref<ServiceInstance> echoInstance = echoService->createInstance(config);
		nodeConfig()->serviceInstances()->append(echoInstance);
	}

	Ref<ConnectionManager> connectionManager = ConnectionManager::create(nodeConfig()->serviceWindow());

	dispatchInstance->workerPools_ = WorkerPools::create(nodeConfig()->serviceInstances()->size());
	for (int i = 0; i < nodeConfig()->serviceInstances()->size(); ++i)
		dispatchInstance->workerPools_->at(i) = WorkerPool::create(nodeConfig()->serviceInstances()->at(i), connectionManager->closedConnections());

	Ref<WorkerPool> dispatchPool = WorkerPool::create(dispatchInstance, connectionManager->closedConnections());

	typedef List< Ref<StreamSocket> > ListeningSockets;
	Ref<ListeningSockets> listeningSockets = ListeningSockets::create(nodeConfig()->address()->size());

	for (int i = 0; i < nodeConfig()->address()->size(); ++i) {
		Ref<StreamSocket> socket = StreamSocket::listen(nodeConfig()->address()->at(i));
		listeningSockets->at(i) = socket;
	}

	if (nodeConfig()->user() != "") {
		Ref<User> user = User::lookup(nodeConfig()->user());
		if (!user->exists()) throw UserError("No such user: \"" + nodeConfig()->user() + "\"");
		Process::setUserId(user->id());
	}

	FLUXNODE_DEBUG() << "Accepting connections with a service window of " << nodeConfig()->serviceWindow() << "s..." << nl;

	try {
		Ref<IoMonitor> ioMonitor = IoMonitor::create();
		while (true) {
			ioMonitor->readyAccept()->clear();
			for (int i = 0; i < listeningSockets->size(); ++i)
				ioMonitor->readyAccept()->insert(listeningSockets->at(i));
			int n = ioMonitor->wait(1);
			if (n > 0) {
				for (int i = 0; i < listeningSockets->size(); ++i) {
					StreamSocket *socket = listeningSockets->at(i);
					if (ioMonitor->readyAccept()->contains(socket)) {
						Ref<ClientConnection> client = ClientConnection::create(socket->accept());
						connectionManager->prioritize(client);
						FLUXNODE_DEBUG() << "Accepted connection from " << client->address() << " with priority " << client->priority() << nl;
						dispatchPool->dispatch(client);
					}
				}
			}
			connectionManager->cycle();
		}
	}
	catch (Interrupt &ex) {
		FLUXNODE_NOTICE() << "Shutting down..." << nl;
		dispatchInstance->workerPools_ = 0;
		throw ex;
	}
}

} // namespace fluxnode
<commit_msg>Fix: correctly pass name of daemon to syslog<commit_after>/*
 * Copyright (C) 2013 Frank Mertens.
 *
 * 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.
 */

#include <flux/IoMonitor.h>
#include <flux/Thread.h>
#include <flux/Process.h>
#include <flux/User.h>
#include "exceptions.h"
#include "ErrorLog.h"
#include "AccessLog.h"
#include "SystemLog.h"
#include "NodeConfig.h"
#include "WorkerPool.h"
#include "ServiceRegistry.h"
#include "DispatchInstance.h"
#include "ConnectionManager.h"
#include "NodeMaster.h"

namespace fluxnode
{

NodeMaster::NodeMaster()
{}

int NodeMaster::run(int argc, char **argv)
{
	SystemLog::open(String(argv[0])->fileName(), 0, LOG_DAEMON);

	Process::enableInterrupt(SIGINT);
	Process::enableInterrupt(SIGTERM);
	Process::enableInterrupt(SIGHUP);
	Thread::blockSignals(SignalSet::createFull());
	{
		Ref<SignalSet> signalSet = SignalSet::createEmpty();
		signalSet->insert(SIGINT);
		signalSet->insert(SIGTERM);
		signalSet->insert(SIGHUP);
		Thread::unblockSignals(signalSet);
	}

	while (true) {
		try {
			runNode(argc, argv);
		}
		catch (Interrupt &ex) {
			if (ex.signal() == SIGINT || ex.signal() == SIGTERM) break;
			if (ex.signal() == SIGHUP) continue;
			return ex.signal() + 128;
		}
	}

	return 0;
}

void NodeMaster::runNode(int argc, char **argv)
{
	nodeConfig()->load(argc, argv);

	if (nodeConfig()->daemon() && !Process::isDaemonized())
		Process::daemonize();

	errorLog()->open(nodeConfig()->errorLogConfig());
	// accessLog()->open(nodeConfig()->accessLogConfig());

	FLUXNODE_NOTICE() << "Starting..." << nl;

	Ref<DispatchInstance> dispatchInstance;
	for (int i = 0; i < nodeConfig()->serviceInstances()->size(); ++i) {
		if (nodeConfig()->serviceInstances()->at(i)->serviceName() == "Dispatch") {
			dispatchInstance = nodeConfig()->serviceInstances()->at(i);
			nodeConfig()->serviceInstances()->pop(i);
			--i;
		}
	}

	if (!dispatchInstance) {
		ServiceDefinition *dispatchService = serviceRegistry()->serviceByName("Dispatch");
		YasonObject *config = dispatchService->configPrototype();
		dispatchInstance = dispatchService->createInstance(config);
	}

	if (nodeConfig()->serviceInstances()->size() == 0)
	{
		FLUXNODE_WARNING() << "No service configured, falling back to Echo service" << nl;

		ServiceDefinition *echoService = serviceRegistry()->serviceByName("Echo");
		YasonObject *config = echoService->configPrototype();
		config->establish("host", "*");
		Ref<ServiceInstance> echoInstance = echoService->createInstance(config);
		nodeConfig()->serviceInstances()->append(echoInstance);
	}

	Ref<ConnectionManager> connectionManager = ConnectionManager::create(nodeConfig()->serviceWindow());

	dispatchInstance->workerPools_ = WorkerPools::create(nodeConfig()->serviceInstances()->size());
	for (int i = 0; i < nodeConfig()->serviceInstances()->size(); ++i)
		dispatchInstance->workerPools_->at(i) = WorkerPool::create(nodeConfig()->serviceInstances()->at(i), connectionManager->closedConnections());

	Ref<WorkerPool> dispatchPool = WorkerPool::create(dispatchInstance, connectionManager->closedConnections());

	typedef List< Ref<StreamSocket> > ListeningSockets;
	Ref<ListeningSockets> listeningSockets = ListeningSockets::create(nodeConfig()->address()->size());

	for (int i = 0; i < nodeConfig()->address()->size(); ++i) {
		Ref<StreamSocket> socket = StreamSocket::listen(nodeConfig()->address()->at(i));
		listeningSockets->at(i) = socket;
	}

	if (nodeConfig()->user() != "") {
		Ref<User> user = User::lookup(nodeConfig()->user());
		if (!user->exists()) throw UserError("No such user: \"" + nodeConfig()->user() + "\"");
		Process::setUserId(user->id());
	}

	FLUXNODE_DEBUG() << "Accepting connections with a service window of " << nodeConfig()->serviceWindow() << "s..." << nl;

	try {
		Ref<IoMonitor> ioMonitor = IoMonitor::create();
		while (true) {
			ioMonitor->readyAccept()->clear();
			for (int i = 0; i < listeningSockets->size(); ++i)
				ioMonitor->readyAccept()->insert(listeningSockets->at(i));
			int n = ioMonitor->wait(1);
			if (n > 0) {
				for (int i = 0; i < listeningSockets->size(); ++i) {
					StreamSocket *socket = listeningSockets->at(i);
					if (ioMonitor->readyAccept()->contains(socket)) {
						Ref<ClientConnection> client = ClientConnection::create(socket->accept());
						connectionManager->prioritize(client);
						FLUXNODE_DEBUG() << "Accepted connection from " << client->address() << " with priority " << client->priority() << nl;
						dispatchPool->dispatch(client);
					}
				}
			}
			connectionManager->cycle();
		}
	}
	catch (Interrupt &ex) {
		FLUXNODE_NOTICE() << "Shutting down..." << nl;
		dispatchInstance->workerPools_ = 0;
		throw ex;
	}
}

} // namespace fluxnode
<|endoftext|>