<commit_before>//
// Sends a request to call hello() from within a worker.
//
// Uses SimpleAmqpClient (https://github.com/alanxz/SimpleAmqpClient) to
// connect to RabbitMQ and nlohmann/json (https://github.com/nlohmann/json) to
// create JSON.
//

#include <iostream>
#include <string>

// Access to https://github.com/alanxz/SimpleAmqpClient
#include <SimpleAmqpClient/SimpleAmqpClient.h>

// Access to https://github.com/nlohmann/json
#include <json.hpp>

// A convenience type alias.
using json = nlohmann::json;

int main(int argc, char** argv) {
	// Two arguments are required: name (string) and age (int).
	if (argc != 3) {
		std::cout << "usage: " << argv[0] << " NAME AGE\n";
		return 1;
	}

	// Parse the arguments.
	auto name = std::string(argv[1]);
	auto age = std::stoi(argv[2]);

	// Create a connection to our AMQP server (RabbitMQ).
	//
	// Technically, in AMQP, a single connection can contain multiple channels,
	// where channels that can be thought of as "lightweight connections that
	// share a single TCP connection"
	// (https://www.rabbitmq.com/tutorials/amqp-concepts.html).
	// However, the used AMQP library only allows creation of channels, not
	// connections.
	auto channel = AmqpClient::Channel::Create(
		/*host*/"localhost",
		/*port*/5672,
		/*username*/"guest",
		/*password*/"guest",
		/*vhost*/"/"
	);

	// Create a body of the message.
	//
	// This assumes that Celery uses JSON as a way of serializing and
	// de-serializing messages, which is the default.
	auto body = json{
		{name, age},    // args
		json::object(), // kwargs
		json::object()  // other data
	};

	// Create a message with the above body, serialized into a string.
	auto msg = AmqpClient::BasicMessage::Create(body.dump());

	// As said above, Celery by default uses JSON to serialize and de-serialize
	// message bodies.
	msg->ContentType("application/json");

	// Assume UTF-8.
	msg->ContentEncoding("utf-8");

	// Celery requires two headers: id and task. The former can be any string
	// you want (http://docs.celeryproject.org/en/latest/faq.html#can-i-specify-a-custom-task-id),
	// although Celery uses UUIDs. The latter has to be the name of the task,
	// as registered in the Python part.
	//
	// In a real world scenario, you would probably want generate a random ID ;-).
	msg->HeaderTable({
		{"id", "3149beef-be66-4b0e-ba47-2fc46e4edac3"},
		{"task", "tasks.hello"}
	});

	// Send the message to the 'celery' exchange (default) with the 'celery'
	// routing key (default). This effectively sends the message to the
	// 'celery' queue because 'celery' is a direct exchange
	// (https://www.rabbitmq.com/tutorials/amqp-concepts.html).
	channel->BasicPublish("celery", "celery", msg);

	return 0;
}
<commit_msg>en-2017-06-25: The ID should be unique.<commit_after>//
// Sends a request to call hello() from within a worker.
//
// Uses SimpleAmqpClient (https://github.com/alanxz/SimpleAmqpClient) to
// connect to RabbitMQ and nlohmann/json (https://github.com/nlohmann/json) to
// create JSON.
//

#include <iostream>
#include <string>

// Access to https://github.com/alanxz/SimpleAmqpClient
#include <SimpleAmqpClient/SimpleAmqpClient.h>

// Access to https://github.com/nlohmann/json
#include <json.hpp>

// A convenience type alias.
using json = nlohmann::json;

int main(int argc, char** argv) {
	// Two arguments are required: name (string) and age (int).
	if (argc != 3) {
		std::cout << "usage: " << argv[0] << " NAME AGE\n";
		return 1;
	}

	// Parse the arguments.
	auto name = std::string(argv[1]);
	auto age = std::stoi(argv[2]);

	// Create a connection to our AMQP server (RabbitMQ).
	//
	// Technically, in AMQP, a single connection can contain multiple channels,
	// where channels that can be thought of as "lightweight connections that
	// share a single TCP connection"
	// (https://www.rabbitmq.com/tutorials/amqp-concepts.html).
	// However, the used AMQP library only allows creation of channels, not
	// connections.
	auto channel = AmqpClient::Channel::Create(
		/*host*/"localhost",
		/*port*/5672,
		/*username*/"guest",
		/*password*/"guest",
		/*vhost*/"/"
	);

	// Create a body of the message.
	//
	// This assumes that Celery uses JSON as a way of serializing and
	// de-serializing messages, which is the default.
	auto body = json{
		{name, age},    // args
		json::object(), // kwargs
		json::object()  // other data
	};

	// Create a message with the above body, serialized into a string.
	auto msg = AmqpClient::BasicMessage::Create(body.dump());

	// As said above, Celery by default uses JSON to serialize and de-serialize
	// message bodies.
	msg->ContentType("application/json");

	// Assume UTF-8.
	msg->ContentEncoding("utf-8");

	// Celery requires two headers: id and task. The former can be any unique
	// string you want
	// (http://docs.celeryproject.org/en/latest/faq.html#can-i-specify-a-custom-task-id),
	// although Celery uses UUIDs. The latter has to be the name of the task,
	// as registered in the Python part.
	//
	// In a real world scenario, you would probably want generate a random ID ;-).
	msg->HeaderTable({
		{"id", "3149beef-be66-4b0e-ba47-2fc46e4edac3"},
		{"task", "tasks.hello"}
	});

	// Send the message to the 'celery' exchange (default) with the 'celery'
	// routing key (default). This effectively sends the message to the
	// 'celery' queue because 'celery' is a direct exchange
	// (https://www.rabbitmq.com/tutorials/amqp-concepts.html).
	channel->BasicPublish("celery", "celery", msg);

	return 0;
}
<|endoftext|>


<commit_before>#ifndef _RPC_SESSION_H
#define _RPC_SESSION_H

#include <string>
#include <vector>
#include <thread>
#include <memory>
#include <boost/asio.hpp>
#include "base/header.hpp"
#include "base/atimer.hpp"
#include "base/scope_guard.hpp"

namespace easyrpc
{

class rpc_session
{
public:
    rpc_session(const rpc_session&) = delete;
    rpc_session& operator=(const rpc_session&) = delete;
    rpc_session() : work_(ios_), socket_(ios_),
    timer_work_(timer_ios_), timer_(timer_ios_) {}

    ~rpc_session()
    {
        stop();
    }

    void connect(const std::string& ip, const std::string& port)
    {
        boost::asio::ip::tcp::resolver resolver(ios_);
        boost::asio::ip::tcp::resolver::query query(boost::asio::ip::tcp::v4(), ip, port);
        endpoint_iter_ = resolver.resolve(query);
    }

    void timeout(std::size_t timeout_milli)
    {
        timeout_milli_ = timeout_milli;
    }

    void run()
    {
        thread_ = std::make_unique<std::thread>([this]{ ios_.run(); });
        if (timeout_milli_ != 0)
        {
            timer_thread_ = std::make_unique<std::thread>([this]{ timer_ios_.run(); });
        }
    }

    void stop()
    {
        stop_ios_thread();
        stop_timer_thread();
    }

    std::vector<char> call(const std::string& protocol, const call_mode& mode, const std::string& body)
    {
        write(protocol, mode, body);
        return read();
    }

    void connect()
    {
        boost::asio::connect(socket_, endpoint_iter_);
    }

    void disconnect()
    {
        if (socket_.is_open())
        {
            boost::system::error_code ignore_ec;
            socket_.shutdown(boost::asio::socket_base::shutdown_both, ignore_ec);
            socket_.close(ignore_ec);
        }
    }

private:
    void write(const std::string& protocol, const call_mode& mode, const std::string& body)
    {
        unsigned int protocol_len = static_cast<unsigned int>(protocol.size());
        unsigned int body_len = static_cast<unsigned int>(body.size());
        if (protocol_len + body_len > max_buffer_len)
        {
            throw std::runtime_error("Send data is too big");
        }

        const auto& buffer = get_buffer(request_header{ protocol_len, body_len, mode }, protocol, body);
        write_impl(buffer);
    }

    std::vector<boost::asio::const_buffer> get_buffer(const request_header& head,
                                                      const std::string& protocol,
                                                      const std::string& body)
    {
        std::vector<boost::asio::const_buffer> buffer;
        buffer.emplace_back(boost::asio::buffer(&head, sizeof(request_header)));
        buffer.emplace_back(boost::asio::buffer(protocol));
        buffer.emplace_back(boost::asio::buffer(body));
        return buffer;
    }

    void write_impl(const std::vector<boost::asio::const_buffer>& buffer)
    {
        boost::system::error_code ec;
        boost::asio::write(socket_, buffer, ec);
        if (ec)
        {
            throw std::runtime_error(ec.message());
        }
    }

    std::vector<char> read()
    {
        start_timer();
        auto guard = make_guard([this]{ stop_timer(); });
        read_head();
        check_head();
        return read_body();
    }

    void read_head()
    {
        boost::system::error_code ec;
        boost::asio::read(socket_, boost::asio::buffer(head_), ec);
        if (ec)
        {
            throw std::runtime_error(ec.message());
        }
    }

    void check_head()
    {
        memcpy(&_res_head, head_, sizeof(head_));
        if (_res_head.body_len > max_buffer_len)
        {
            throw std::runtime_error("Body len is too big");
        }
    }

    std::vector<char> read_body()
    {
        body_.clear();
        body_.resize(_res_head.body_len);
        boost::system::error_code ec;
        boost::asio::read(socket_, boost::asio::buffer(body_), ec);
        if (ec)
        {
            throw std::runtime_error(ec.message());
        }
        return body_;
    }

    void start_timer()
    {
        if (timeout_milli_ == 0)
        {
            return;
        }

        timer_.bind([this]{ disconnect(); });
        timer_.set_single_shot(true);
        timer_.start(timeout_milli_);
    }

    void stop_timer()
    {
        if (timeout_milli_ == 0)
        {
            return;
        }
        timer_.stop();
    }

    void stop_ios_thread()
    {
        ios_.stop();
        if (thread_ != nullptr)
        {
            if (thread_->joinable())
            {
                thread_->join();
            }
        }
    }

    void stop_timer_thread()
    {
        timer_ios_.stop();
        if (timer_thread_ != nullptr)
        {
            if (timer_thread_->joinable())
            {
                timer_thread_->join();
            }
        }
    }

private:
    boost::asio::io_service ios_;
    boost::asio::io_service::work work_;
    boost::asio::ip::tcp::socket socket_;
    boost::asio::ip::tcp::resolver::iterator endpoint_iter_;
    std::unique_ptr<std::thread> thread_;
    char head_[response_header_len];
    response_header _res_head;
    std::vector<char> body_;
    boost::asio::io_service timer_ios_;
    boost::asio::io_service::work timer_work_;
    std::unique_ptr<std::thread> timer_thread_;
    atimer<> timer_;
    std::size_t timeout_milli_ = 0;
};

}

#endif
<commit_msg>Update<commit_after>#ifndef _RPC_SESSION_H
#define _RPC_SESSION_H

#include <string>
#include <vector>
#include <thread>
#include <memory>
#include <boost/asio.hpp>
#include "base/header.hpp"
#include "base/atimer.hpp"
#include "base/scope_guard.hpp"

namespace easyrpc
{

class rpc_session
{
public:
    rpc_session(const rpc_session&) = delete;
    rpc_session& operator=(const rpc_session&) = delete;
    rpc_session() : work_(ios_), socket_(ios_),
    timer_work_(timer_ios_), timer_(timer_ios_) {}

    ~rpc_session()
    {
        stop();
    }

    void connect(const std::string& ip, const std::string& port)
    {
        boost::asio::ip::tcp::resolver resolver(ios_);
        boost::asio::ip::tcp::resolver::query query(boost::asio::ip::tcp::v4(), ip, port);
        endpoint_iter_ = resolver.resolve(query);
    }

    void timeout(std::size_t timeout_milli)
    {
        timeout_milli_ = timeout_milli;
    }

    void run()
    {
        thread_ = std::make_unique<std::thread>([this]{ ios_.run(); });
        if (timeout_milli_ != 0)
        {
            timer_thread_ = std::make_unique<std::thread>([this]{ timer_ios_.run(); });
        }
    }

    void stop()
    {
        stop_ios_thread();
        stop_timer_thread();
    }

    std::vector<char> call(const std::string& protocol, const call_mode& mode, const std::string& body)
    {
        write(protocol, mode, body);
        return read();
    }

    void connect()
    {
        boost::asio::connect(socket_, endpoint_iter_);
    }

    void disconnect()
    {
        if (socket_.is_open())
        {
            boost::system::error_code ignore_ec;
            socket_.shutdown(boost::asio::socket_base::shutdown_both, ignore_ec);
            socket_.close(ignore_ec);
        }
    }

private:
    void write(const std::string& protocol, const call_mode& mode, const std::string& body)
    {
        unsigned int protocol_len = static_cast<unsigned int>(protocol.size());
        unsigned int body_len = static_cast<unsigned int>(body.size());
        if (protocol_len + body_len > max_buffer_len)
        {
            throw std::runtime_error("Send data is too big");
        }

        const auto& buffer = get_buffer(request_header{ protocol_len, body_len, mode }, protocol, body);
        write_impl(buffer);
    }

    std::vector<boost::asio::const_buffer> get_buffer(const request_header& head,
                                                      const std::string& protocol,
                                                      const std::string& body)
    {
        std::vector<boost::asio::const_buffer> buffer;
        buffer.emplace_back(boost::asio::buffer(&head, sizeof(request_header)));
        buffer.emplace_back(boost::asio::buffer(protocol));
        buffer.emplace_back(boost::asio::buffer(body));
        return buffer;
    }

    void write_impl(const std::vector<boost::asio::const_buffer>& buffer)
    {
        boost::system::error_code ec;
        boost::asio::write(socket_, buffer, ec);
        if (ec)
        {
            throw std::runtime_error(ec.message());
        }
    }

    std::vector<char> read()
    {
        start_timer();
        auto guard = make_guard([this]{ stop_timer(); });
        read_head();
        check_head();
        return read_body();
    }

    void read_head()
    {
        boost::system::error_code ec;
        boost::asio::read(socket_, boost::asio::buffer(head_), ec);
        if (ec)
        {
            throw std::runtime_error(ec.message());
        }
    }

    void check_head()
    {
        memcpy(&res_head_, head_, sizeof(head_));
        if (res_head_.body_len > max_buffer_len)
        {
            throw std::runtime_error("Body len is too big");
        }
    }

    std::vector<char> read_body()
    {
        body_.clear();
        body_.resize(res_head_.body_len);
        boost::system::error_code ec;
        boost::asio::read(socket_, boost::asio::buffer(body_), ec);
        if (ec)
        {
            throw std::runtime_error(ec.message());
        }
        return body_;
    }

    void start_timer()
    {
        if (timeout_milli_ == 0)
        {
            return;
        }

        timer_.bind([this]{ disconnect(); });
        timer_.set_single_shot(true);
        timer_.start(timeout_milli_);
    }

    void stop_timer()
    {
        if (timeout_milli_ == 0)
        {
            return;
        }
        timer_.stop();
    }

    void stop_ios_thread()
    {
        ios_.stop();
        if (thread_ != nullptr)
        {
            if (thread_->joinable())
            {
                thread_->join();
            }
        }
    }

    void stop_timer_thread()
    {
        timer_ios_.stop();
        if (timer_thread_ != nullptr)
        {
            if (timer_thread_->joinable())
            {
                timer_thread_->join();
            }
        }
    }

private:
    boost::asio::io_service ios_;
    boost::asio::io_service::work work_;
    boost::asio::ip::tcp::socket socket_;
    boost::asio::ip::tcp::resolver::iterator endpoint_iter_;
    std::unique_ptr<std::thread> thread_;
    char head_[response_header_len];
    response_header res_head_;
    std::vector<char> body_;
    boost::asio::io_service timer_ios_;
    boost::asio::io_service::work timer_work_;
    std::unique_ptr<std::thread> timer_thread_;
    atimer<> timer_;
    std::size_t timeout_milli_ = 0;
};

}

#endif
<|endoftext|>


<commit_before>//  Natron
//
/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
/*
 * Created by Alexandre GAUTHIER-FOICHAT on 6/1/2012.
 * contact: immarespond at gmail dot com
 *
 */

#include "ScaleSliderQWidget.h"

#include <cassert>
CLANG_DIAG_OFF(unused-private-field)
// /opt/local/include/QtGui/qmime.h:119:10: warning: private field 'type' is not used [-Wunused-private-field]
#include <QtGui/QPaintEvent>
CLANG_DIAG_ON(unused-private-field)
#include <QtGui/QMouseEvent>
#include <QtGui/QPainter>
#include <QStyleOption>

#include "Gui/ticks.h"

#define TICK_HEIGHT 7
#define SLIDER_WIDTH 4
#define SLIDER_HEIGHT 20

ScaleSliderQWidget::ScaleSliderQWidget(double bottom,
                                       double top,
                                       double initialPos,
                                       Natron::ScaleTypeEnum type,
                                       QWidget* parent)
    : QWidget(parent)
      , _zoomCtx()
      , _oldClick()
      , _minimum(bottom)
      , _maximum(top)
      , _type(type)
      , _value(initialPos)
      , _dragging(false)
      , _font( new QFont(NATRON_FONT_ALT, NATRON_FONT_SIZE_8) )
      , _textColor(200,200,200,255)
      , _scaleColor(100,100,100,255)
      , _sliderColor(97,83,30,255)
      , _initialized(false)
      , _mustInitializeSliderPosition(true)
      , _readOnly(false)
      , _ctrlDown(false)
      , _shiftDown(false)
      , _currentZoom(1.)
{
    setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Expanding);
    QSize sizeh = sizeHint();
    _zoomCtx.setScreenSize(sizeh.width(), sizeh.height());
    setFocusPolicy(Qt::ClickFocus);
}

QSize
ScaleSliderQWidget::sizeHint() const
{
    return QSize(150,30);
}

ScaleSliderQWidget::~ScaleSliderQWidget()
{
    delete _font;
}

void
ScaleSliderQWidget::mousePressEvent(QMouseEvent* e)
{
    if (!_readOnly) {
        QPoint newClick =  e->pos();

        _oldClick = newClick;
        QPointF newClick_opengl = _zoomCtx.toZoomCoordinates( newClick.x(),newClick.y() );

        seekInternal( newClick_opengl.x() );
    }
    QWidget::mousePressEvent(e);
}

void
ScaleSliderQWidget::mouseMoveEvent(QMouseEvent* e)
{
    if (!_readOnly) {
        QPoint newClick =  e->pos();
        QPointF newClick_opengl = _zoomCtx.toZoomCoordinates( newClick.x(),newClick.y() );

        seekInternal( newClick_opengl.x() );
    }
}

void
ScaleSliderQWidget::mouseReleaseEvent(QMouseEvent* e)
{
    emit editingFinished();
    QWidget::mouseReleaseEvent(e);
}

void
ScaleSliderQWidget::keyPressEvent(QKeyEvent* e)
{
    if (e->key() == Qt::Key_Control) {
        _ctrlDown = true;
        double scale = _shiftDown ? 100. : 10.;
        _currentZoom = scale;
        _zoomCtx.zoomx(_value, 0, scale);
        update();
    } else if (e->key() == Qt::Key_Shift) {
        _shiftDown = true;
        if (_ctrlDown) {
            _zoomCtx.zoomx(_value, 0, 10.);
            _currentZoom = 100.;
        }
        update();
    }
    QWidget::keyPressEvent(e);
}

void
ScaleSliderQWidget::keyReleaseEvent(QKeyEvent* e)
{
    if (e->key() == Qt::Key_Control) {
        _ctrlDown = false;
        _zoomCtx.zoomx(_value, 0, 1. / _currentZoom);
        _currentZoom = 1.;
        centerOn(_minimum, _maximum);
        return;
    } else if (e->key() == Qt::Key_Shift) {
        _shiftDown = false;
        if (_ctrlDown) {
            _zoomCtx.zoomx(_value, 0, 1. / 10.);
            _currentZoom = 10.;
        } else {
            _zoomCtx.zoomx(_value, 0, 1. / _currentZoom);
            centerOn(_minimum, _maximum);
            _currentZoom = 1.;
            return;
        }
        update();
    }
    QWidget::keyReleaseEvent(e);
}

void
ScaleSliderQWidget::seekScalePosition(double v)
{
    if (v < _minimum) {
        v = _minimum;
    }
    if (v > _maximum) {
        v = _maximum;
    }

    if ( (v == _value) && _initialized ) {
        return;
    }
    _value = v;
    if (_initialized) {
        update();
    }
}

void
ScaleSliderQWidget::seekInternal(double v)
{
    if (v < _minimum) {
        v = _minimum;
    }
    if (v > _maximum) {
        v = _maximum;
    }
    if (v == _value) {
        return;
    }
    _value = v;
    if (_initialized) {
        update();
    }
    emit positionChanged(v);
}

void
ScaleSliderQWidget::setMinimumAndMaximum(double min,
                                         double max)
{
    _minimum = min;
    _maximum = max;
    centerOn(_minimum, _maximum);
}

void
ScaleSliderQWidget::centerOn(double left,
                             double right)
{

    double w = right - left;
    _zoomCtx.fill(left - w * 0.05, right + w * 0.05, _zoomCtx.bottom(), _zoomCtx.top());

    update();
}

void
ScaleSliderQWidget::resizeEvent(QResizeEvent* e)
{
    _zoomCtx.setScreenSize(e->size().width(), e->size().height());
    QWidget::resizeEvent(e);
}

void
ScaleSliderQWidget::paintEvent(QPaintEvent* /*e*/)
{
    if (_mustInitializeSliderPosition) {
        centerOn(_minimum, _maximum);
        _mustInitializeSliderPosition = false;
        seekScalePosition(_value);
        _initialized = true;
    }

    ///fill the background with the appropriate style color
    QStyleOption opt;
    opt.init(this);
    QPainter p(this);
    style()->drawPrimitive(QStyle::PE_Widget, &opt, &p, this);

    QFontMetrics fontM(*_font);
    p.setPen(_scaleColor);

    QPointF btmLeft = _zoomCtx.toZoomCoordinates(0,height() - 1);
    QPointF topRight = _zoomCtx.toZoomCoordinates(width() - 1, 0);

    if ( btmLeft.x() == topRight.x() ) {
        return;
    }

    /*drawing X axis*/
    double lineYpos = height() - 1 - fontM.height()  - TICK_HEIGHT / 2;
    p.drawLine(0, lineYpos, width() - 1, lineYpos);

    double tickBottom = _zoomCtx.toZoomCoordinates( 0,height() - 1 - fontM.height() ).y();
    double tickTop = _zoomCtx.toZoomCoordinates(0,height() - 1 - fontM.height()  - TICK_HEIGHT).y();
    const double smallestTickSizePixel = 5.; // tick size (in pixels) for alpha = 0.
    const double largestTickSizePixel = 1000.; // tick size (in pixels) for alpha = 1.
    std::vector<double> acceptedDistances;
    acceptedDistances.push_back(1.);
    acceptedDistances.push_back(5.);
    acceptedDistances.push_back(10.);
    acceptedDistances.push_back(50.);
    const double rangePixel =  width();
    const double range_min = btmLeft.x();
    const double range_max =  topRight.x();
    const double range = range_max - range_min;
    double smallTickSize;
    bool half_tick;
    ticks_size(range_min, range_max, rangePixel, smallestTickSizePixel, &smallTickSize, &half_tick);
    int m1, m2;
    const int ticks_max = 1000;
    double offset;
    ticks_bounds(range_min, range_max, smallTickSize, half_tick, ticks_max, &offset, &m1, &m2);
    std::vector<int> ticks;
    ticks_fill(half_tick, ticks_max, m1, m2, &ticks);
    const double smallestTickSize = range * smallestTickSizePixel / rangePixel;
    const double largestTickSize = range * largestTickSizePixel / rangePixel;
    const double minTickSizeTextPixel = fontM.width( QString("00") ); // AXIS-SPECIFIC
    const double minTickSizeText = range * minTickSizeTextPixel / rangePixel;
    for (int i = m1; i <= m2; ++i) {
        double value = i * smallTickSize + offset;
        const double tickSize = ticks[i - m1] * smallTickSize;
        const double alpha = ticks_alpha(smallestTickSize, largestTickSize, tickSize);
        QColor color(_textColor);
        color.setAlphaF(alpha);
        QPen pen(color);
        pen.setWidthF(1.9);
        p.setPen(pen);

        QPointF tickBottomPos = _zoomCtx.toWidgetCoordinates(value, tickBottom);
        QPointF tickTopPos = _zoomCtx.toWidgetCoordinates(value, tickTop);

        p.drawLine(tickBottomPos,tickTopPos);

        if (tickSize > minTickSizeText) {
            const int tickSizePixel = rangePixel * tickSize / range;
            const QString s = QString::number(value);
            const int sSizePixel =  fontM.width(s);
            if (tickSizePixel > sSizePixel) {
                const int sSizeFullPixel = sSizePixel + minTickSizeTextPixel;
                double alphaText = 1.0; //alpha;
                if (tickSizePixel < sSizeFullPixel) {
                    // when the text size is between sSizePixel and sSizeFullPixel,
                    // draw it with a lower alpha
                    alphaText *= (tickSizePixel - sSizePixel) / (double)minTickSizeTextPixel;
                }
                QColor c = _readOnly || !isEnabled() ? Qt::black : _textColor;
                c.setAlphaF(alphaText);
                p.setFont(*_font);
                p.setPen(c);

                QPointF textPos = _zoomCtx.toWidgetCoordinates( value, btmLeft.y() );

                p.drawText(textPos, s);
            }
        }
    }
    double positionValue = _zoomCtx.toWidgetCoordinates(_value,0).x();
    QPointF sliderBottomLeft(positionValue - SLIDER_WIDTH / 2,height() - 1 - fontM.height() / 2);
    QPointF sliderTopRight(positionValue + SLIDER_WIDTH / 2,height() - 1 - fontM.height() / 2 - SLIDER_HEIGHT);

    /*draw the slider*/
    p.setPen(_sliderColor);
    p.fillRect(sliderBottomLeft.x(), sliderBottomLeft.y(), sliderTopRight.x() - sliderBottomLeft.x(), sliderTopRight.y() - sliderBottomLeft.y(),_sliderColor);

    /*draw a black rect around the slider for contrast*/
    p.setPen(Qt::black);

    p.drawLine( sliderBottomLeft.x(),sliderBottomLeft.y(),sliderBottomLeft.x(),sliderTopRight.y() );
    p.drawLine( sliderBottomLeft.x(),sliderTopRight.y(),sliderTopRight.x(),sliderTopRight.y() );
    p.drawLine( sliderTopRight.x(),sliderTopRight.y(),sliderTopRight.x(),sliderBottomLeft.y() );
    p.drawLine( sliderTopRight.x(),sliderBottomLeft.y(),sliderBottomLeft.x(),sliderBottomLeft.y() );
} // paintEvent

void
ScaleSliderQWidget::setReadOnly(bool ro)
{
    _readOnly = ro;
    update();
}

<commit_msg>Sliders are now aligned properly<commit_after>//  Natron
//
/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
/*
 * Created by Alexandre GAUTHIER-FOICHAT on 6/1/2012.
 * contact: immarespond at gmail dot com
 *
 */

#include "ScaleSliderQWidget.h"

#include <cassert>
CLANG_DIAG_OFF(unused-private-field)
// /opt/local/include/QtGui/qmime.h:119:10: warning: private field 'type' is not used [-Wunused-private-field]
#include <QtGui/QPaintEvent>
CLANG_DIAG_ON(unused-private-field)
#include <QtGui/QMouseEvent>
#include <QtGui/QPainter>
#include <QStyleOption>

#include "Gui/ticks.h"

#define TICK_HEIGHT 7
#define SLIDER_WIDTH 4
#define SLIDER_HEIGHT 15

ScaleSliderQWidget::ScaleSliderQWidget(double bottom,
                                       double top,
                                       double initialPos,
                                       Natron::ScaleTypeEnum type,
                                       QWidget* parent)
    : QWidget(parent)
      , _zoomCtx()
      , _oldClick()
      , _minimum(bottom)
      , _maximum(top)
      , _type(type)
      , _value(initialPos)
      , _dragging(false)
      , _font( new QFont(NATRON_FONT_ALT, NATRON_FONT_SIZE_8) )
      , _textColor(200,200,200,255)
      , _scaleColor(100,100,100,255)
      , _sliderColor(97,83,30,255)
      , _initialized(false)
      , _mustInitializeSliderPosition(true)
      , _readOnly(false)
      , _ctrlDown(false)
      , _shiftDown(false)
      , _currentZoom(1.)
{
    setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Expanding);
    QSize sizeh = sizeHint();
    _zoomCtx.setScreenSize(sizeh.width(), sizeh.height());
    setFocusPolicy(Qt::ClickFocus);
}

QSize
ScaleSliderQWidget::sizeHint() const
{
    return QSize(150,20);
}

ScaleSliderQWidget::~ScaleSliderQWidget()
{
    delete _font;
}

void
ScaleSliderQWidget::mousePressEvent(QMouseEvent* e)
{
    if (!_readOnly) {
        QPoint newClick =  e->pos();

        _oldClick = newClick;
        QPointF newClick_opengl = _zoomCtx.toZoomCoordinates( newClick.x(),newClick.y() );

        seekInternal( newClick_opengl.x() );
    }
    QWidget::mousePressEvent(e);
}

void
ScaleSliderQWidget::mouseMoveEvent(QMouseEvent* e)
{
    if (!_readOnly) {
        QPoint newClick =  e->pos();
        QPointF newClick_opengl = _zoomCtx.toZoomCoordinates( newClick.x(),newClick.y() );

        seekInternal( newClick_opengl.x() );
    }
}

void
ScaleSliderQWidget::mouseReleaseEvent(QMouseEvent* e)
{
    emit editingFinished();
    QWidget::mouseReleaseEvent(e);
}

void
ScaleSliderQWidget::keyPressEvent(QKeyEvent* e)
{
    if (e->key() == Qt::Key_Control) {
        _ctrlDown = true;
        double scale = _shiftDown ? 100. : 10.;
        _currentZoom = scale;
        _zoomCtx.zoomx(_value, 0, scale);
        update();
    } else if (e->key() == Qt::Key_Shift) {
        _shiftDown = true;
        if (_ctrlDown) {
            _zoomCtx.zoomx(_value, 0, 10.);
            _currentZoom = 100.;
        }
        update();
    }
    QWidget::keyPressEvent(e);
}

void
ScaleSliderQWidget::keyReleaseEvent(QKeyEvent* e)
{
    if (e->key() == Qt::Key_Control) {
        _ctrlDown = false;
        _zoomCtx.zoomx(_value, 0, 1. / _currentZoom);
        _currentZoom = 1.;
        centerOn(_minimum, _maximum);
        return;
    } else if (e->key() == Qt::Key_Shift) {
        _shiftDown = false;
        if (_ctrlDown) {
            _zoomCtx.zoomx(_value, 0, 1. / 10.);
            _currentZoom = 10.;
        } else {
            _zoomCtx.zoomx(_value, 0, 1. / _currentZoom);
            centerOn(_minimum, _maximum);
            _currentZoom = 1.;
            return;
        }
        update();
    }
    QWidget::keyReleaseEvent(e);
}

void
ScaleSliderQWidget::seekScalePosition(double v)
{
    if (v < _minimum) {
        v = _minimum;
    }
    if (v > _maximum) {
        v = _maximum;
    }

    if ( (v == _value) && _initialized ) {
        return;
    }
    _value = v;
    if (_initialized) {
        update();
    }
}

void
ScaleSliderQWidget::seekInternal(double v)
{
    if (v < _minimum) {
        v = _minimum;
    }
    if (v > _maximum) {
        v = _maximum;
    }
    if (v == _value) {
        return;
    }
    _value = v;
    if (_initialized) {
        update();
    }
    emit positionChanged(v);
}

void
ScaleSliderQWidget::setMinimumAndMaximum(double min,
                                         double max)
{
    _minimum = min;
    _maximum = max;
    centerOn(_minimum, _maximum);
}

void
ScaleSliderQWidget::centerOn(double left,
                             double right)
{

    double w = right - left;
    _zoomCtx.fill(left - w * 0.05, right + w * 0.05, _zoomCtx.bottom(), _zoomCtx.top());

    update();
}

void
ScaleSliderQWidget::resizeEvent(QResizeEvent* e)
{
    _zoomCtx.setScreenSize(e->size().width(), e->size().height());
    QWidget::resizeEvent(e);
}

void
ScaleSliderQWidget::paintEvent(QPaintEvent* /*e*/)
{
    if (_mustInitializeSliderPosition) {
        centerOn(_minimum, _maximum);
        _mustInitializeSliderPosition = false;
        seekScalePosition(_value);
        _initialized = true;
    }

    ///fill the background with the appropriate style color
    QStyleOption opt;
    opt.init(this);
    QPainter p(this);
    style()->drawPrimitive(QStyle::PE_Widget, &opt, &p, this);

    QFontMetrics fontM(*_font);
    p.setPen(_scaleColor);

    QPointF btmLeft = _zoomCtx.toZoomCoordinates(0,height() - 1);
    QPointF topRight = _zoomCtx.toZoomCoordinates(width() - 1, 0);

    if ( btmLeft.x() == topRight.x() ) {
        return;
    }

    /*drawing X axis*/
    double lineYpos = height() - 1 - fontM.height()  - TICK_HEIGHT / 2;
    p.drawLine(0, lineYpos, width() - 1, lineYpos);

    double tickBottom = _zoomCtx.toZoomCoordinates( 0,height() - 1 - fontM.height() ).y();
    double tickTop = _zoomCtx.toZoomCoordinates(0,height() - 1 - fontM.height()  - TICK_HEIGHT).y();
    const double smallestTickSizePixel = 5.; // tick size (in pixels) for alpha = 0.
    const double largestTickSizePixel = 1000.; // tick size (in pixels) for alpha = 1.
    std::vector<double> acceptedDistances;
    acceptedDistances.push_back(1.);
    acceptedDistances.push_back(5.);
    acceptedDistances.push_back(10.);
    acceptedDistances.push_back(50.);
    const double rangePixel =  width();
    const double range_min = btmLeft.x();
    const double range_max =  topRight.x();
    const double range = range_max - range_min;
    double smallTickSize;
    bool half_tick;
    ticks_size(range_min, range_max, rangePixel, smallestTickSizePixel, &smallTickSize, &half_tick);
    int m1, m2;
    const int ticks_max = 1000;
    double offset;
    ticks_bounds(range_min, range_max, smallTickSize, half_tick, ticks_max, &offset, &m1, &m2);
    std::vector<int> ticks;
    ticks_fill(half_tick, ticks_max, m1, m2, &ticks);
    const double smallestTickSize = range * smallestTickSizePixel / rangePixel;
    const double largestTickSize = range * largestTickSizePixel / rangePixel;
    const double minTickSizeTextPixel = fontM.width( QString("00") ); // AXIS-SPECIFIC
    const double minTickSizeText = range * minTickSizeTextPixel / rangePixel;
    for (int i = m1; i <= m2; ++i) {
        double value = i * smallTickSize + offset;
        const double tickSize = ticks[i - m1] * smallTickSize;
        const double alpha = ticks_alpha(smallestTickSize, largestTickSize, tickSize);
        QColor color(_textColor);
        color.setAlphaF(alpha);
        QPen pen(color);
        pen.setWidthF(1.9);
        p.setPen(pen);

        QPointF tickBottomPos = _zoomCtx.toWidgetCoordinates(value, tickBottom);
        QPointF tickTopPos = _zoomCtx.toWidgetCoordinates(value, tickTop);

        p.drawLine(tickBottomPos,tickTopPos);

        if (tickSize > minTickSizeText) {
            const int tickSizePixel = rangePixel * tickSize / range;
            const QString s = QString::number(value);
            const int sSizePixel =  fontM.width(s);
            if (tickSizePixel > sSizePixel) {
                const int sSizeFullPixel = sSizePixel + minTickSizeTextPixel;
                double alphaText = 1.0; //alpha;
                if (tickSizePixel < sSizeFullPixel) {
                    // when the text size is between sSizePixel and sSizeFullPixel,
                    // draw it with a lower alpha
                    alphaText *= (tickSizePixel - sSizePixel) / (double)minTickSizeTextPixel;
                }
                QColor c = _readOnly || !isEnabled() ? Qt::black : _textColor;
                c.setAlphaF(alphaText);
                p.setFont(*_font);
                p.setPen(c);

                QPointF textPos = _zoomCtx.toWidgetCoordinates( value, btmLeft.y() );

                p.drawText(textPos, s);
            }
        }
    }
    double positionValue = _zoomCtx.toWidgetCoordinates(_value,0).x();
    QPointF sliderBottomLeft(positionValue - SLIDER_WIDTH / 2,height() - 1 - fontM.height() / 2);
    QPointF sliderTopRight(positionValue + SLIDER_WIDTH / 2,height() - 1 - fontM.height() / 2 - SLIDER_HEIGHT);

    /*draw the slider*/
    p.setPen(_sliderColor);
    p.fillRect(sliderBottomLeft.x(), sliderBottomLeft.y(), sliderTopRight.x() - sliderBottomLeft.x(), sliderTopRight.y() - sliderBottomLeft.y(),_sliderColor);

    /*draw a black rect around the slider for contrast*/
    p.setPen(Qt::black);

    p.drawLine( sliderBottomLeft.x(),sliderBottomLeft.y(),sliderBottomLeft.x(),sliderTopRight.y() );
    p.drawLine( sliderBottomLeft.x(),sliderTopRight.y(),sliderTopRight.x(),sliderTopRight.y() );
    p.drawLine( sliderTopRight.x(),sliderTopRight.y(),sliderTopRight.x(),sliderBottomLeft.y() );
    p.drawLine( sliderTopRight.x(),sliderBottomLeft.y(),sliderBottomLeft.x(),sliderBottomLeft.y() );
} // paintEvent

void
ScaleSliderQWidget::setReadOnly(bool ro)
{
    _readOnly = ro;
    update();
}

<|endoftext|>


<commit_before>#include <QDebug>
#include <QSettings>
#include <QFileInfo>
#include <QDir>
#include <QThread>

#include <coreplugin/messagemanager.h>
#include <coreplugin/progressmanager/progressmanager.h>
#include <coreplugin/progressmanager/futureprogress.h>
#include <utils/macroexpander.h>

#include "CppcheckRunner.h"
#include "Constants.h"
#include "Settings.h"

using namespace QtcCppcheck::Internal;

namespace
{
  enum ErrorField
  {
    ErrorFieldFile = 0, ErrorFieldLine, ErrorFieldSeverity, ErrorFieldId,
    ErrorFieldMessage
  };

  QStringList includePaths (const QStringList& files)
  {
    QStringList paths;
    foreach (const QString& file, files)
    {
      QFileInfo info (file);
      QString current = QString (QLatin1String("-I")) + info.absolutePath ();
      if (!paths.contains(current))
      {
        paths << current;
      }
    }
    return paths;
  }

}

CppcheckRunner::CppcheckRunner(Settings *settings, QObject *parent) :
  QObject(parent), settings_ (settings), showOutput_ (false), showId_(false), futureInterface_ (NULL),
  maxArgumentsLength_ (0)
{
#ifdef __linux__
  QProcess getConf;
  getConf.start (QLatin1String("getconf ARG_MAX"));
  getConf.waitForFinished (2000);
  QByteArray argMax = getConf.readAllStandardOutput ().replace ("\n", "");
  maxArgumentsLength_ = std::max (argMax.toInt (), 32000);
#else
  maxArgumentsLength_ = 32767;
#endif
  Q_ASSERT (settings_ != NULL);

  connect (&process_, SIGNAL (readyReadStandardOutput()),
           SLOT (readOutput()));
  connect (&process_, SIGNAL (readyReadStandardError()),
           SLOT (readError()));
  connect (&process_, SIGNAL (started()),
           SLOT (started()));
  connect (&process_, SIGNAL (error(QProcess::ProcessError)),
           SLOT (error(QProcess::ProcessError)));
  connect (&process_, SIGNAL (finished(int, QProcess::ExitStatus)),
           SLOT (finished(int, QProcess::ExitStatus)));

  // Restart checking if got queue.
  connect (&process_, SIGNAL (finished(int, QProcess::ExitStatus)),
           SLOT (checkQueuedFiles ()));
}

CppcheckRunner::~CppcheckRunner()
{
  if (process_.isOpen())
  {
    process_.kill();
  }
  queueTimer_.stop ();
  settings_ = NULL;
  delete futureInterface_;
}

void CppcheckRunner::updateSettings()
{
  Q_ASSERT (settings_ != NULL);
  showOutput_ = settings_->showBinaryOutput ();
  showId_ = settings_->showId ();
  runArguments_.clear ();
  QString enabled = QLatin1String ("--enable=warning,style,performance,"
                                   "portability,information,missingInclude");
  // Overwrite enable with user parameters if present
  for(int i = runArguments_.size () - 1; i >= 0; --i)
  {
    if (runArguments_.at (i).startsWith (QLatin1String ("--enable")))
    {
      enabled = runArguments_.takeAt (i);
      break;
    }
  }
  if (settings_->checkUnused ())
  {
    enabled += QLatin1String (",unusedFunction");
  }
  else //TODO always check with threads but rescan for unused after finish?
  {
    runArguments_ << (QLatin1String ("-j ") +
                      QString::number (QThread::idealThreadCount ()));
  }
  runArguments_ << enabled;
  if (settings_->checkInconclusive ())
  {
    runArguments_ << QLatin1String ("--inconclusive");
  }
  runArguments_ << QLatin1String ("--template={file},{line},{severity},{id},{message}");
}

void CppcheckRunner::checkFiles(const QStringList &fileNames)
{
  Q_ASSERT (!fileNames.isEmpty ());
  fileCheckQueue_ += fileNames;
  fileCheckQueue_.removeDuplicates ();
  fileCheckQueue_.sort ();
  if (process_.isOpen ())
  {
    if (fileCheckQueue_ == currentlyCheckingFiles_)
    {
      process_.kill ();
      // Rechecking will be restarted on finish signal.
    }
    return;
  }
  // Delay helps to avoid double checking same file on editor change.
  const int checkDelayInMs = 200;
  if (!queueTimer_.isActive ())
  {
    queueTimer_.singleShot (checkDelayInMs, this, SLOT (checkQueuedFiles ()));
  }
}

void CppcheckRunner::stopChecking()
{
  fileCheckQueue_.clear ();
  if (process_.isOpen ())
  {
    process_.kill ();
  }
}

void CppcheckRunner::checkQueuedFiles()
{
  if (fileCheckQueue_.isEmpty ())
  {
    return;
  }
  QString binary = settings_->binaryFile ();
  if (binary.isEmpty ())
  {
    return;
  }
  // Pass custom params BEFORE most of runner's to shadow if some repeat.
  auto expander = Utils::globalMacroExpander();
  auto expanded = expander->expand (settings_->customParameters ());
  QStringList arguments (expanded.split (QLatin1Char (' '), QString::SkipEmptyParts));
  arguments += runArguments_;

  QStringList includes = includePaths (fileCheckQueue_);
  arguments += includes;
  arguments += fileCheckQueue_;
  currentlyCheckingFiles_ = fileCheckQueue_;
  fileCheckQueue_.clear ();

  int argumentLength = arguments.join (QLatin1Literal (" ")).length ();
  if (argumentLength >= maxArgumentsLength_) {
    if (fileListFileContents_ != currentlyCheckingFiles_) {
      fileListFileContents_ = currentlyCheckingFiles_;
      if (fileListFile_.open () && includeListFile_.open ()){
        QByteArray filesArg = fileListFileContents_.join (QLatin1String ("\n")).toLocal8Bit ();
        fileListFile_.write (filesArg);
        QByteArray includesArg = includes.join (QLatin1String ("\n")).toLocal8Bit ();
        includeListFile_.write (includesArg);
      }
      else {
        Core::MessageManager::write (tr ("Failed to write cppcheck's argument files"), Core::MessageManager::Silent);
        return;
      }
    }
    arguments = runArguments_;
    arguments << QString (QLatin1String("--file-list=%1")).arg (fileListFile_.fileName ());
    arguments << QString (QLatin1String("--includes-file=%1")).arg (includeListFile_.fileName ());
  }
  emit startedChecking (currentlyCheckingFiles_);
  if (showOutput_)
  {
    Core::MessageManager::write(QString("Starting CppChecker with:%1, %2").arg(binary,arguments.join(" ")), Core::MessageManager::WithFocus);
  }
  process_.start (binary, arguments);
}

void CppcheckRunner::readOutput()
{
  if (!showOutput_)
  {
    return;
  }
  process_.setReadChannel (QProcess::StandardOutput);

  while (!process_.atEnd ())
  {
    QByteArray rawLine = process_.readLine ();
    QString line = QString::fromUtf8 (rawLine).trimmed ();
    if (line.isEmpty ())
    {
      continue;
    }
    const QString progressSample = QLatin1String ("% done");
    // check futureInterface because read can be triggered before started..
    if (line.endsWith (progressSample) && futureInterface_ != NULL)
    {
      int percentEndIndex = line.length () - progressSample.length ();
      int percentStartIndex = line.lastIndexOf(QLatin1String (" "), percentEndIndex);
      int done = line.mid (percentStartIndex, percentEndIndex - percentStartIndex).toInt ();
      futureInterface_->setProgressValue (done);
    }
    Core::MessageManager::write (line, Core::MessageManager::Silent);
  }
}

void CppcheckRunner::readError()
{
  process_.setReadChannel (QProcess::StandardError);

  while (!process_.atEnd ())
  {
    QByteArray rawLine = process_.readLine ();
    QString line = QString::fromUtf8 (rawLine).trimmed ();
    if (line.isEmpty ())
    {
      continue;
    }
    if (showOutput_)
    {
      Core::MessageManager::write (line, Core::MessageManager::Silent);
    }
    QStringList details = line.split (QLatin1Char (','));
    if (details.size () <= ErrorFieldMessage)
    {
      continue;
    }
    QString file = QDir::fromNativeSeparators(details.at (ErrorFieldFile));
    int lineNumber = details.at (ErrorFieldLine).toInt ();
    char type = details.at (ErrorFieldSeverity).at (0).toLatin1 ();
    QString id = "";
    if (showId_)
    {
      id = details.at (ErrorFieldId);
    }
    QString description = line.mid (line.indexOf (details.at (ErrorFieldMessage)));
    emit newTask (type, id, description, file, lineNumber);
  }
}

void CppcheckRunner::started()
{
  if (showOutput_)
  {
    Core::MessageManager::write (tr ("Cppcheck started"), Core::MessageManager::Silent);
  }

  using namespace Core;
  delete futureInterface_;
  futureInterface_ = new QFutureInterface<void>;
  FutureProgress *progress = ProgressManager::addTask(futureInterface_->future(),
                                                      tr("Cppcheck"), Constants::TASK_CHECKING);
  connect (progress, SIGNAL(canceled ()), SLOT(stopChecking ()));
  futureInterface_->setProgressRange(0, 100); // %
  futureInterface_->reportStarted();
}

void CppcheckRunner::error(QProcess::ProcessError error)
{
  Q_UNUSED (error);
  if (showOutput_)
  {
    Core::MessageManager::write (tr ("Cppcheck error occured"), Core::MessageManager::Silent);
  }
  if (error == QProcess::FailedToStart)
  {
    finished (-1, QProcess::CrashExit);
  }
}

void CppcheckRunner::finished(int exitCode, QProcess::ExitStatus exitStatus)
{
  Q_UNUSED (exitCode);
  Q_UNUSED (exitStatus);
  if (futureInterface_ != NULL)
  {
    futureInterface_->reportFinished ();
  }
  process_.close ();
  if (showOutput_)
  {
    Core::MessageManager::write (tr("Cppcheck finished"), Core::MessageManager::Silent);
  }
}
<commit_msg>Fixed generation of wrong '--includes-file' option's file.<commit_after>#include <QDebug>
#include <QSettings>
#include <QFileInfo>
#include <QDir>
#include <QThread>

#include <coreplugin/messagemanager.h>
#include <coreplugin/progressmanager/progressmanager.h>
#include <coreplugin/progressmanager/futureprogress.h>
#include <utils/macroexpander.h>

#include "CppcheckRunner.h"
#include "Constants.h"
#include "Settings.h"

using namespace QtcCppcheck::Internal;

namespace
{
  enum ErrorField
  {
    ErrorFieldFile = 0, ErrorFieldLine, ErrorFieldSeverity, ErrorFieldId,
    ErrorFieldMessage
  };

  QStringList includePaths (const QStringList& files)
  {
    QStringList paths;
    foreach (const QString& file, files)
    {
      QFileInfo info (file);
      QString current = info.absolutePath ();
      if (!paths.contains(current))
      {
        paths << current;
      }
    }
    return paths;
  }

}

CppcheckRunner::CppcheckRunner(Settings *settings, QObject *parent) :
  QObject(parent), settings_ (settings), showOutput_ (false), showId_(false), futureInterface_ (NULL),
  maxArgumentsLength_ (0)
{
#ifdef __linux__
  QProcess getConf;
  getConf.start (QLatin1String("getconf ARG_MAX"));
  getConf.waitForFinished (2000);
  QByteArray argMax = getConf.readAllStandardOutput ().replace ("\n", "");
  maxArgumentsLength_ = std::max (argMax.toInt (), 32000);
#else
  maxArgumentsLength_ = 32767;
#endif
  Q_ASSERT (settings_ != NULL);

  connect (&process_, SIGNAL (readyReadStandardOutput()),
           SLOT (readOutput()));
  connect (&process_, SIGNAL (readyReadStandardError()),
           SLOT (readError()));
  connect (&process_, SIGNAL (started()),
           SLOT (started()));
  connect (&process_, SIGNAL (error(QProcess::ProcessError)),
           SLOT (error(QProcess::ProcessError)));
  connect (&process_, SIGNAL (finished(int, QProcess::ExitStatus)),
           SLOT (finished(int, QProcess::ExitStatus)));

  // Restart checking if got queue.
  connect (&process_, SIGNAL (finished(int, QProcess::ExitStatus)),
           SLOT (checkQueuedFiles ()));
}

CppcheckRunner::~CppcheckRunner()
{
  if (process_.isOpen())
  {
    process_.kill();
  }
  queueTimer_.stop ();
  settings_ = NULL;
  delete futureInterface_;
}

void CppcheckRunner::updateSettings()
{
  Q_ASSERT (settings_ != NULL);
  showOutput_ = settings_->showBinaryOutput ();
  showId_ = settings_->showId ();
  runArguments_.clear ();
  QString enabled = QLatin1String ("--enable=warning,style,performance,"
                                   "portability,information,missingInclude");
  // Overwrite enable with user parameters if present
  for(int i = runArguments_.size () - 1; i >= 0; --i)
  {
    if (runArguments_.at (i).startsWith (QLatin1String ("--enable")))
    {
      enabled = runArguments_.takeAt (i);
      break;
    }
  }
  if (settings_->checkUnused ())
  {
    enabled += QLatin1String (",unusedFunction");
  }
  else //TODO always check with threads but rescan for unused after finish?
  {
    runArguments_ << (QLatin1String ("-j ") +
                      QString::number (QThread::idealThreadCount ()));
  }
  runArguments_ << enabled;
  if (settings_->checkInconclusive ())
  {
    runArguments_ << QLatin1String ("--inconclusive");
  }
  runArguments_ << QLatin1String ("--template={file},{line},{severity},{id},{message}");
}

void CppcheckRunner::checkFiles(const QStringList &fileNames)
{
  Q_ASSERT (!fileNames.isEmpty ());
  fileCheckQueue_ += fileNames;
  fileCheckQueue_.removeDuplicates ();
  fileCheckQueue_.sort ();
  if (process_.isOpen ())
  {
    if (fileCheckQueue_ == currentlyCheckingFiles_)
    {
      process_.kill ();
      // Rechecking will be restarted on finish signal.
    }
    return;
  }
  // Delay helps to avoid double checking same file on editor change.
  const int checkDelayInMs = 200;
  if (!queueTimer_.isActive ())
  {
    queueTimer_.singleShot (checkDelayInMs, this, SLOT (checkQueuedFiles ()));
  }
}

void CppcheckRunner::stopChecking()
{
  fileCheckQueue_.clear ();
  if (process_.isOpen ())
  {
    process_.kill ();
  }
}

void CppcheckRunner::checkQueuedFiles()
{
  if (fileCheckQueue_.isEmpty ())
  {
    return;
  }
  QString binary = settings_->binaryFile ();
  if (binary.isEmpty ())
  {
    return;
  }
  // Pass custom params BEFORE most of runner's to shadow if some repeat.
  auto expander = Utils::globalMacroExpander();
  auto expanded = expander->expand (settings_->customParameters ());
  QStringList arguments (expanded.split (QLatin1Char (' '), QString::SkipEmptyParts));
  arguments += runArguments_;

  QStringList includes = includePaths (fileCheckQueue_);
  arguments += includes;
  arguments += fileCheckQueue_;
  currentlyCheckingFiles_ = fileCheckQueue_;
  fileCheckQueue_.clear ();

  int argumentLength = arguments.join (QLatin1Literal (" ")).length ();
  if (argumentLength >= maxArgumentsLength_) {
    if (fileListFileContents_ != currentlyCheckingFiles_) {
      fileListFileContents_ = currentlyCheckingFiles_;
      if (fileListFile_.open () && includeListFile_.open ()){
        QByteArray filesArg = fileListFileContents_.join (QLatin1String ("\n")).toLocal8Bit ();
        fileListFile_.write (filesArg);
        QByteArray includesArg = includes.join (QLatin1String ("\n")).toLocal8Bit ();
        includeListFile_.write (includesArg);
      }
      else {
        Core::MessageManager::write (tr ("Failed to write cppcheck's argument files"), Core::MessageManager::Silent);
        return;
      }
    }
    arguments = runArguments_;
    arguments << QString (QLatin1String("--file-list=%1")).arg (fileListFile_.fileName ());
    arguments << QString (QLatin1String("--includes-file=%1")).arg (includeListFile_.fileName ());
  }
  emit startedChecking (currentlyCheckingFiles_);
  if (showOutput_)
  {
    Core::MessageManager::write(QString("Starting CppChecker with:%1, %2").arg(binary,arguments.join(" ")), Core::MessageManager::WithFocus);
  }
  process_.start (binary, arguments);
}

void CppcheckRunner::readOutput()
{
  if (!showOutput_)
  {
    return;
  }
  process_.setReadChannel (QProcess::StandardOutput);

  while (!process_.atEnd ())
  {
    QByteArray rawLine = process_.readLine ();
    QString line = QString::fromUtf8 (rawLine).trimmed ();
    if (line.isEmpty ())
    {
      continue;
    }
    const QString progressSample = QLatin1String ("% done");
    // check futureInterface because read can be triggered before started..
    if (line.endsWith (progressSample) && futureInterface_ != NULL)
    {
      int percentEndIndex = line.length () - progressSample.length ();
      int percentStartIndex = line.lastIndexOf(QLatin1String (" "), percentEndIndex);
      int done = line.mid (percentStartIndex, percentEndIndex - percentStartIndex).toInt ();
      futureInterface_->setProgressValue (done);
    }
    Core::MessageManager::write (line, Core::MessageManager::Silent);
  }
}

void CppcheckRunner::readError()
{
  process_.setReadChannel (QProcess::StandardError);

  while (!process_.atEnd ())
  {
    QByteArray rawLine = process_.readLine ();
    QString line = QString::fromUtf8 (rawLine).trimmed ();
    if (line.isEmpty ())
    {
      continue;
    }
    if (showOutput_)
    {
      Core::MessageManager::write (line, Core::MessageManager::Silent);
    }
    QStringList details = line.split (QLatin1Char (','));
    if (details.size () <= ErrorFieldMessage)
    {
      continue;
    }
    QString file = QDir::fromNativeSeparators(details.at (ErrorFieldFile));
    int lineNumber = details.at (ErrorFieldLine).toInt ();
    char type = details.at (ErrorFieldSeverity).at (0).toLatin1 ();
    QString id = "";
    if (showId_)
    {
      id = details.at (ErrorFieldId);
    }
    QString description = line.mid (line.indexOf (details.at (ErrorFieldMessage)));
    emit newTask (type, id, description, file, lineNumber);
  }
}

void CppcheckRunner::started()
{
  if (showOutput_)
  {
    Core::MessageManager::write (tr ("Cppcheck started"), Core::MessageManager::Silent);
  }

  using namespace Core;
  delete futureInterface_;
  futureInterface_ = new QFutureInterface<void>;
  FutureProgress *progress = ProgressManager::addTask(futureInterface_->future(),
                                                      tr("Cppcheck"), Constants::TASK_CHECKING);
  connect (progress, SIGNAL(canceled ()), SLOT(stopChecking ()));
  futureInterface_->setProgressRange(0, 100); // %
  futureInterface_->reportStarted();
}

void CppcheckRunner::error(QProcess::ProcessError error)
{
  Q_UNUSED (error);
  if (showOutput_)
  {
    Core::MessageManager::write (tr ("Cppcheck error occured"), Core::MessageManager::Silent);
  }
  if (error == QProcess::FailedToStart)
  {
    finished (-1, QProcess::CrashExit);
  }
}

void CppcheckRunner::finished(int exitCode, QProcess::ExitStatus exitStatus)
{
  Q_UNUSED (exitCode);
  Q_UNUSED (exitStatus);
  if (futureInterface_ != NULL)
  {
    futureInterface_->reportFinished ();
  }
  process_.close ();
  if (showOutput_)
  {
    Core::MessageManager::write (tr("Cppcheck finished"), Core::MessageManager::Silent);
  }
}
<|endoftext|>


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

#include <absl/container/flat_hash_map.h>
#include <absl/strings/str_format.h>
#include <gmock/gmock.h>
#include <gtest/gtest.h>

#include <QApplication>
#include <QComboBox>
#include <QLineEdit>
#include <QListWidget>
#include <QStringLiteral>
#include <QTest>
#include <array>
#include <limits>
#include <string>

#include "ClientData/ScopeInfo.h"
#include "MizarBase/ThreadId.h"
#include "MizarWidgets/SamplingWithFrameTrackInputWidget.h"
#include "TestUtils/ContainerHelpers.h"

using orbit_mizar_base::TID;
using testing::ElementsAreArray;
using testing::NotNull;
using testing::Return;
using testing::ReturnRef;
using testing::UnorderedElementsAreArray;

using orbit_test_utils::MakeMap;

namespace {
class MockPairedData {
 public:
  MOCK_METHOD((const absl::flat_hash_map<TID, std::string>&), TidToNames, (), (const));
  MOCK_METHOD((const absl::flat_hash_map<TID, std::uint64_t>&), TidToCallstackSampleCounts, (),
              (const));
  MOCK_METHOD((const absl::flat_hash_map<uint64_t, orbit_client_data::ScopeInfo>), GetFrameTracks,
              (), (const));
};
}  // namespace

namespace orbit_mizar_widgets {

constexpr TID kTid(0x3EAD1);
constexpr TID kOtherTid(0x3EAD2);
const std::string kThreadName = "Thread";
const std::string kOtherThreadName = "Other Thread";
constexpr uint64_t kThreadSamplesCount = 5;
constexpr uint64_t kOtherThreadSamplesCount = 2;
const absl::flat_hash_map<TID, std::string> kTidToName = {{kTid, kThreadName},
                                                          {kOtherTid, kOtherThreadName}};

const absl::flat_hash_map<TID, uint64_t> kTidToCount = {{kTid, kThreadSamplesCount},
                                                        {kOtherTid, kOtherThreadSamplesCount}};
constexpr size_t kThreadCount = 2;

static std::string MakeThreadListItemString(std::string_view name, TID tid) {
  return absl::StrFormat("[%u] %s", *tid, name);
}

const std::vector<std::string> kThreadNamesSorted = {
    MakeThreadListItemString(kThreadName, kTid),
    MakeThreadListItemString(kOtherThreadName, kOtherTid)};
const QString kInputName = QStringLiteral("InputName");

constexpr size_t kFrameTracksCount = 3;
constexpr std::array<uint64_t, kFrameTracksCount> kScopeIds = {1, 2, 10};
constexpr std::array<std::string_view, kFrameTracksCount> kFrameTrackNames = {"Foo", "Boo",
                                                                              "Manual"};
constexpr std::array<orbit_client_data::ScopeType, kFrameTracksCount> kScopeInfoTypes = {
    orbit_client_data::ScopeType::kDynamicallyInstrumentedFunction,
    orbit_client_data::ScopeType::kDynamicallyInstrumentedFunction,
    orbit_client_data::ScopeType::kApiScope};
const absl::flat_hash_map<orbit_client_data::ScopeType, std::string> kScopeTypeToString = {
    {orbit_client_data::ScopeType::kDynamicallyInstrumentedFunction, "[ D]"},
    {orbit_client_data::ScopeType::kApiScope, "[MS]"}};
const std::vector<std::string> kExpectedFrameTrackListContent = {"[ D] Boo", "[ D] Foo",
                                                                 "[MS] Manual"};
constexpr std::array<uint64_t, kFrameTracksCount> kScopeIdsInExpectedOrder = {2, 1, 10};
const std::vector<orbit_client_data::ScopeInfo> kScopeInfos = [] {
  std::vector<orbit_client_data::ScopeInfo> result;
  for (size_t i = 0; i < kFrameTracksCount; ++i) {
    result.emplace_back(std::string(kFrameTrackNames[i]), kScopeInfoTypes[i]);
  }
  return result;
}();

const absl::flat_hash_map<uint64_t, orbit_client_data::ScopeInfo> kFrameTracks =
    MakeMap(kScopeIds, kScopeInfos);

constexpr const char* kOrgName = "The Orbit Authors";

class SamplingWithFrameTrackInputWidgetTest : public ::testing::Test {
 public:
  SamplingWithFrameTrackInputWidgetTest()
      : widget_(std::make_unique<SamplingWithFrameTrackInputWidgetTmpl<MockPairedData>>(nullptr)) {
    QApplication::setOrganizationName(kOrgName);
    QApplication::setApplicationName("SamplingWithFrameTrackInputWidgetTest.InitIsCorrect");

    EXPECT_CALL(data_, TidToNames).WillRepeatedly(ReturnRef(kTidToName));
    EXPECT_CALL(data_, TidToCallstackSampleCounts).WillRepeatedly(ReturnRef(kTidToCount));
    EXPECT_CALL(data_, GetFrameTracks).WillRepeatedly(Return(kFrameTracks));

    widget_->Init(data_, kInputName);

    // TODO(b/238058915) use ASSERT_THAT
    title_ = widget_->findChild<QLabel*>("title_");
    EXPECT_THAT(title_, NotNull());

    thread_list_ = widget_->findChild<QListWidget*>("thread_list_");
    EXPECT_THAT(thread_list_, NotNull());

    frame_track_list_ = widget_->findChild<QComboBox*>("frame_track_list_");
    EXPECT_THAT(thread_list_, NotNull());

    start_ms_ = widget_->findChild<QLineEdit*>("start_ms_");
    EXPECT_THAT(start_ms_, NotNull());
  }

  void SelectThreadListRow(int row) const {
    thread_list_->selectionModel()->select(thread_list_->model()->index(row, 0),
                                           QItemSelectionModel::Select);
  }

  void ClearThreadListSelection() const { thread_list_->selectionModel()->clearSelection(); }

  void ExpectSelectedTidsAre(std::initializer_list<TID> tids) const {
    EXPECT_THAT(widget_->MakeConfig().tids, UnorderedElementsAreArray(tids));
  }

  void ExpectSelectedFrameTrackIdIs(uint32_t scope_id) const {
    EXPECT_EQ(widget_->MakeConfig().frame_track_scope_id, scope_id);
  }

  void ExpectRelativeStartNsIs(uint64_t start_relative_ns_) const {
    EXPECT_EQ(widget_->MakeConfig().start_relative_ns, start_relative_ns_);
  }

  MockPairedData data_;
  std::unique_ptr<SamplingWithFrameTrackInputWidgetTmpl<MockPairedData>> widget_;
  QLabel* title_;
  QListWidget* thread_list_;
  QComboBox* frame_track_list_;
  QLineEdit* start_ms_;
};

TEST_F(SamplingWithFrameTrackInputWidgetTest, InitIsCorrect) {
  EXPECT_EQ(title_->text(), kInputName);

  EXPECT_EQ(thread_list_->count(), kThreadCount);
  for (int i = 0; i < thread_list_->count(); ++i) {
    QListWidgetItem* item = thread_list_->item(i);
    EXPECT_THAT(item, NotNull());
    EXPECT_EQ(item->text().toStdString(), kThreadNamesSorted[i]);
  }
}

TEST_F(SamplingWithFrameTrackInputWidgetTest, OnThreadSelectionChangedIsCorrect) {
  SelectThreadListRow(0);
  ExpectSelectedTidsAre({kTid});

  SelectThreadListRow(1);
  ExpectSelectedTidsAre({kTid, kOtherTid});

  ClearThreadListSelection();
  SelectThreadListRow(1);
  ExpectSelectedTidsAre({kOtherTid});
}

TEST_F(SamplingWithFrameTrackInputWidgetTest, OnFrameTrackSelectionChangedIsCorrect) {
  std::vector<std::string> frame_track_list_content;
  for (int i = 0; i < frame_track_list_->count(); ++i) {
    frame_track_list_content.push_back(frame_track_list_->itemText(i).toStdString());
  }
  EXPECT_THAT(frame_track_list_content, ElementsAreArray(frame_track_list_content));

  frame_track_list_->setCurrentIndex(0);
  ExpectSelectedFrameTrackIdIs(kScopeIdsInExpectedOrder[0]);

  frame_track_list_->setCurrentIndex(2);
  ExpectSelectedFrameTrackIdIs(kScopeIdsInExpectedOrder[2]);

  frame_track_list_->setCurrentIndex(1);
  ExpectSelectedFrameTrackIdIs(kScopeIdsInExpectedOrder[1]);
}

TEST_F(SamplingWithFrameTrackInputWidgetTest, OnStartMsChangedIsCorrect) {
  start_ms_->setText("");
  ExpectRelativeStartNsIs(0);

  start_ms_->setText("123");
  ExpectRelativeStartNsIs(123000);

  start_ms_->setText("0123");
  ExpectRelativeStartNsIs(123000);

  start_ms_->setText("99999999999999999999999999");
  ExpectRelativeStartNsIs(static_cast<uint64_t>(std::numeric_limits<uint64_t>::max()));

  start_ms_->setText("-0");
  ExpectRelativeStartNsIs(0);

  start_ms_->setText("-0");
  ExpectRelativeStartNsIs(0);
}

}  // namespace orbit_mizar_widgets<commit_msg>Use ASSERT_THAT for null checks in SamplingWithFrameTrackInputWidgetTest (#3895)<commit_after>// Copyright (c) 2022 The Orbit Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include <absl/container/flat_hash_map.h>
#include <absl/strings/str_format.h>
#include <gmock/gmock.h>
#include <gtest/gtest.h>

#include <QApplication>
#include <QComboBox>
#include <QLineEdit>
#include <QListWidget>
#include <QStringLiteral>
#include <QTest>
#include <array>
#include <limits>
#include <string>

#include "ClientData/ScopeInfo.h"
#include "MizarBase/ThreadId.h"
#include "MizarWidgets/SamplingWithFrameTrackInputWidget.h"
#include "TestUtils/ContainerHelpers.h"

using orbit_mizar_base::TID;
using testing::ElementsAreArray;
using testing::NotNull;
using testing::Return;
using testing::ReturnRef;
using testing::UnorderedElementsAreArray;

using orbit_test_utils::MakeMap;

namespace {
class MockPairedData {
 public:
  MOCK_METHOD((const absl::flat_hash_map<TID, std::string>&), TidToNames, (), (const));
  MOCK_METHOD((const absl::flat_hash_map<TID, std::uint64_t>&), TidToCallstackSampleCounts, (),
              (const));
  MOCK_METHOD((const absl::flat_hash_map<uint64_t, orbit_client_data::ScopeInfo>), GetFrameTracks,
              (), (const));
};
}  // namespace

namespace orbit_mizar_widgets {

constexpr TID kTid(0x3EAD1);
constexpr TID kOtherTid(0x3EAD2);
const std::string kThreadName = "Thread";
const std::string kOtherThreadName = "Other Thread";
constexpr uint64_t kThreadSamplesCount = 5;
constexpr uint64_t kOtherThreadSamplesCount = 2;
const absl::flat_hash_map<TID, std::string> kTidToName = {{kTid, kThreadName},
                                                          {kOtherTid, kOtherThreadName}};

const absl::flat_hash_map<TID, uint64_t> kTidToCount = {{kTid, kThreadSamplesCount},
                                                        {kOtherTid, kOtherThreadSamplesCount}};
constexpr size_t kThreadCount = 2;

static std::string MakeThreadListItemString(std::string_view name, TID tid) {
  return absl::StrFormat("[%u] %s", *tid, name);
}

const std::vector<std::string> kThreadNamesSorted = {
    MakeThreadListItemString(kThreadName, kTid),
    MakeThreadListItemString(kOtherThreadName, kOtherTid)};
const QString kInputName = QStringLiteral("InputName");

constexpr size_t kFrameTracksCount = 3;
constexpr std::array<uint64_t, kFrameTracksCount> kScopeIds = {1, 2, 10};
constexpr std::array<std::string_view, kFrameTracksCount> kFrameTrackNames = {"Foo", "Boo",
                                                                              "Manual"};
constexpr std::array<orbit_client_data::ScopeType, kFrameTracksCount> kScopeInfoTypes = {
    orbit_client_data::ScopeType::kDynamicallyInstrumentedFunction,
    orbit_client_data::ScopeType::kDynamicallyInstrumentedFunction,
    orbit_client_data::ScopeType::kApiScope};
const absl::flat_hash_map<orbit_client_data::ScopeType, std::string> kScopeTypeToString = {
    {orbit_client_data::ScopeType::kDynamicallyInstrumentedFunction, "[ D]"},
    {orbit_client_data::ScopeType::kApiScope, "[MS]"}};
const std::vector<std::string> kExpectedFrameTrackListContent = {"[ D] Boo", "[ D] Foo",
                                                                 "[MS] Manual"};
constexpr std::array<uint64_t, kFrameTracksCount> kScopeIdsInExpectedOrder = {2, 1, 10};
const std::vector<orbit_client_data::ScopeInfo> kScopeInfos = [] {
  std::vector<orbit_client_data::ScopeInfo> result;
  for (size_t i = 0; i < kFrameTracksCount; ++i) {
    result.emplace_back(std::string(kFrameTrackNames[i]), kScopeInfoTypes[i]);
  }
  return result;
}();

const absl::flat_hash_map<uint64_t, orbit_client_data::ScopeInfo> kFrameTracks =
    MakeMap(kScopeIds, kScopeInfos);

class SamplingWithFrameTrackInputWidgetTest : public ::testing::Test {
 public:
  SamplingWithFrameTrackInputWidgetTest()
      : widget_(std::make_unique<SamplingWithFrameTrackInputWidgetTmpl<MockPairedData>>(nullptr)) {
    EXPECT_CALL(data_, TidToNames).WillRepeatedly(ReturnRef(kTidToName));
    EXPECT_CALL(data_, TidToCallstackSampleCounts).WillRepeatedly(ReturnRef(kTidToCount));
    EXPECT_CALL(data_, GetFrameTracks).WillRepeatedly(Return(kFrameTracks));

    widget_->Init(data_, kInputName);
  }

  void SetUp() override {
    title_ = widget_->findChild<QLabel*>("title_");
    ASSERT_THAT(title_, NotNull());

    thread_list_ = widget_->findChild<QListWidget*>("thread_list_");
    ASSERT_THAT(thread_list_, NotNull());

    frame_track_list_ = widget_->findChild<QComboBox*>("frame_track_list_");
    ASSERT_THAT(thread_list_, NotNull());

    start_ms_ = widget_->findChild<QLineEdit*>("start_ms_");
    ASSERT_THAT(start_ms_, NotNull());
  }

  void SelectThreadListRow(int row) const {
    thread_list_->selectionModel()->select(thread_list_->model()->index(row, 0),
                                           QItemSelectionModel::Select);
  }

  void ClearThreadListSelection() const { thread_list_->selectionModel()->clearSelection(); }

  void ExpectSelectedTidsAre(std::initializer_list<TID> tids) const {
    EXPECT_THAT(widget_->MakeConfig().tids, UnorderedElementsAreArray(tids));
  }

  void ExpectSelectedFrameTrackIdIs(uint32_t scope_id) const {
    EXPECT_EQ(widget_->MakeConfig().frame_track_scope_id, scope_id);
  }

  void ExpectRelativeStartNsIs(uint64_t start_relative_ns_) const {
    EXPECT_EQ(widget_->MakeConfig().start_relative_ns, start_relative_ns_);
  }

  MockPairedData data_;
  std::unique_ptr<SamplingWithFrameTrackInputWidgetTmpl<MockPairedData>> widget_;
  QLabel* title_{};
  QListWidget* thread_list_{};
  QComboBox* frame_track_list_{};
  QLineEdit* start_ms_{};
};

TEST_F(SamplingWithFrameTrackInputWidgetTest, InitIsCorrect) {
  EXPECT_EQ(title_->text(), kInputName);

  EXPECT_EQ(thread_list_->count(), kThreadCount);
  for (int i = 0; i < thread_list_->count(); ++i) {
    QListWidgetItem* item = thread_list_->item(i);
    EXPECT_THAT(item, NotNull());
    EXPECT_EQ(item->text().toStdString(), kThreadNamesSorted[i]);
  }
}

TEST_F(SamplingWithFrameTrackInputWidgetTest, OnThreadSelectionChangedIsCorrect) {
  SelectThreadListRow(0);
  ExpectSelectedTidsAre({kTid});

  SelectThreadListRow(1);
  ExpectSelectedTidsAre({kTid, kOtherTid});

  ClearThreadListSelection();
  SelectThreadListRow(1);
  ExpectSelectedTidsAre({kOtherTid});
}

TEST_F(SamplingWithFrameTrackInputWidgetTest, OnFrameTrackSelectionChangedIsCorrect) {
  std::vector<std::string> frame_track_list_content;
  for (int i = 0; i < frame_track_list_->count(); ++i) {
    frame_track_list_content.push_back(frame_track_list_->itemText(i).toStdString());
  }
  EXPECT_THAT(frame_track_list_content, ElementsAreArray(frame_track_list_content));

  frame_track_list_->setCurrentIndex(0);
  ExpectSelectedFrameTrackIdIs(kScopeIdsInExpectedOrder[0]);

  frame_track_list_->setCurrentIndex(2);
  ExpectSelectedFrameTrackIdIs(kScopeIdsInExpectedOrder[2]);

  frame_track_list_->setCurrentIndex(1);
  ExpectSelectedFrameTrackIdIs(kScopeIdsInExpectedOrder[1]);
}

TEST_F(SamplingWithFrameTrackInputWidgetTest, OnStartMsChangedIsCorrect) {
  start_ms_->setText("");
  ExpectRelativeStartNsIs(0);

  start_ms_->setText("123");
  ExpectRelativeStartNsIs(123000);

  start_ms_->setText("0123");
  ExpectRelativeStartNsIs(123000);

  start_ms_->setText("99999999999999999999999999");
  ExpectRelativeStartNsIs(static_cast<uint64_t>(std::numeric_limits<uint64_t>::max()));

  start_ms_->setText("-0");
  ExpectRelativeStartNsIs(0);

  start_ms_->setText("-0");
  ExpectRelativeStartNsIs(0);
}

}  // namespace orbit_mizar_widgets<|endoftext|>


<commit_before>// This is sometimes required to support the full curses API
#define _XOPEN_SOURCE
#define _XOPEN_SOURCE_EXTENDED

#ifdef __GNUC__
	// Enable printf and scanf argument checking
	#define GCC_PRINTF
	#define	GCC_SCANF
#endif

#include <curses.h>
#include <climits>
#include <cstdio>
#include <unordered_map>

#include <QString>
#include <QTextBoundaryFinder>

#include "lirch_constants.h"
#include "plugins/lirch_plugin.h"
#include "plugins/display_messages.h"
#include "plugins/notify_messages.h"
#include "plugins/edict_messages.h"
#include "plugins/channel_messages.h"
#include "core/core_messages.h"

namespace std
{
	template <>
	struct hash<QString>
	{
		size_t operator()(const QString& v) const
		{
			return std::hash<std::string>()(v.toStdString());
		}
	};
}

inline char CTRL(char c)
{
	//Leave only the lower 5 bits, so the return value is the numeric value
	//of CTRL+key (e.g. CTRL('c') gives you 3, which is the value you get
	//when hitting ctrl-c)
	return c&0x1f;
}

using namespace std;

template <class... args>
string strprintf(const string &format, args... a)
{
	//Thankfully, the C++ standard grabbed the definition from POSIX
	//instead of Windows, so I don't have to binary-search the correct
	//string size.
	int size=snprintf(NULL, 0, format.c_str(), a...);
	//Add padding for the terminating byte
	vector<char> s(size+1);
	//We can use sprintf instead of snprintf because we know the buffer is large enough
	sprintf(s.data(), format.c_str(), a...);
	return s.data();
}

//Same as wprintf, but handles unicode characters properly
template <class... args>
void wprintu(WINDOW *w, const string &format, args... a)
{
	string s=strprintf(format, a...);
	for (unsigned char c : s)
		waddch(w, c|(c>0x7f ? A_ALTCHARSET : 0));
}

//This wraps WINDOW pointers so they're be destroyed on exit
class WindowWrapper
{
public:
	WindowWrapper(WINDOW *ww) : w(ww, delwin) {}
	WindowWrapper() {int maxx, maxy; getmaxyx(stdscr, maxy, maxx); w=shared_ptr<WINDOW>(newpad(maxy-1, maxx), delwin); scrollok(get(), TRUE);}
	WINDOW *get() const {return w.get();}
	operator WINDOW*() const {return get();}
	WINDOW& operator*() const {return *w;}
	WINDOW* operator->() const {return get();}
private:
	shared_ptr<WINDOW> w;
};

void runplugin(plugin_pipe &p, const string &name)
{
	QString input;
	QString channel="default";
	int maxx, maxy;
	getmaxyx(stdscr, maxy, maxx);
	//10000 lines of scrollback should be enough for anyone
	//WindowWrapper channel_output=newpad(10000, maxx);
	unordered_map<QString, WindowWrapper> channel_windows;
	if (channel_windows["default"]==nullptr)
		return;
	WindowWrapper input_display=newwin(1, maxx-1, maxy-1, 0);
	if (input_display==nullptr)
		return;
	//Be lazy and let the input scroll
	scrollok(input_display, TRUE);
	//p.write(registration_message::create(-30000, name, "display"));
	while (true)
	{
		wint_t key;
		int rc=get_wch(&key);
		if (rc==OK)
		{
			if (key=='\r' || key=='\n')
			{
				p.write(raw_edict_message::create(input,channel));
				input="";
			}
			else if (key==WEOF)
				break;
			else
				input.push_back(QString::fromWcharArray(&key, 1));
		}
		else if (rc==KEY_CODE_YES)
		{
			if (key==KEY_BACKSPACE)
			{
				QTextBoundaryFinder bounds(QTextBoundaryFinder::Grapheme, input);
				bounds.toEnd();
				int pos=bounds.toPreviousBoundary();
				if (pos!=-1)
				{
					input.remove(pos, INT_MAX);
				}
			}
			else if (key==KEY_ENTER)
			{
				p.write(raw_edict_message::create(input,channel));
				input="";
			}
		}
		while (p.has_message())
		{
			message m=p.read();
			if (m.type=="shutdown")
			{
				return;
			}
			else if (m.type=="registration_status")
			{
				auto s=dynamic_cast<registration_status *>(m.getdata());
				if (!s)
					continue;
				if (!s->status)
				{
					if (s->priority>-32000)
						p.write(registration_message::create(s->priority-1, name, s->type));
				}
			}
			else if (m.type=="display")
			{
				auto s=dynamic_cast<display_message *>(m.getdata());
				if (!s)
					continue;
				p.write(m.decrement_priority());

				QString message_channel=s->channel;
				string nick=s->nick.toLocal8Bit().constData();
				string contents=s->contents.toLocal8Bit().constData();

				if (s->channel=="")
					s->channel=channel;

				if (channel_windows.count(message_channel)!=0)
				{
					if(s->subtype==display_message_subtype::NORMAL)
						wprintu(channel_windows[message_channel], "<%s> %s\n", nick.c_str(), contents.c_str());
					if(s->subtype==display_message_subtype::ME)
						wprintu(channel_windows[message_channel], "* %s %s\n", nick.c_str(), contents.c_str());
					if(s->subtype==display_message_subtype::NOTIFY)
						wprintu(channel_windows[message_channel], "‼‽ %s\n", contents.c_str());
				}
			}
			else if (m.type=="set_channel")
			{
				auto i=dynamic_cast<set_channel *>(m.getdata());
				if (!i)
					continue;
				p.write(m.decrement_priority());
				if (i->channel=="")
					p.write(notify_message::create(channel, "On channel "+channel));
				else
					channel=i->channel;
			}
			else if (m.type=="leave_channel")
			{
				auto i=dynamic_cast<leave_channel *>(m.getdata());
				if (!i)
					continue;
				p.write(m.decrement_priority());
				channel_windows.erase(i->channel);
			}
			else
				p.write(m.decrement_priority());
		}
		int x,y;
		getyx(channel_windows[channel], y, x);
		pnoutrefresh(channel_windows[channel], max(y-(maxy-1),0), 0, 0,0,maxy-2,maxx-1);
		wmove(input_display, 0, 0);
		wprintu(input_display, "\n%s", input.toLocal8Bit().constData());
		wnoutrefresh(input_display);
		//This doesn't need to run all the time, but we should be able
		//to cope with the screen refreshing at 10Hz
		doupdate();
	}
	p.write(core_quit_message::create());
}

void run(plugin_pipe p, string name)
{
	p.write(registration_message::create(-30000, name, "display"));
	p.write(registration_message::create(-30000, name, "set_channel"));
	p.write(registration_message::create(-30000, name, "leave_channel"));
	//Set the delay when hitting escape to 10 milliseconds, unless it was
	//already set.  The ESCDELAY variable is not supported in all curses
	//implementations, but should not cause problems in implementations
	//that ignore it.
	setenv("ESCDELAY", "10", 0);
	//Initialize curses
	initscr();
	//Don't buffer typed characters
	cbreak();
	//Wain no more than a tenth of a second for input
	timeout(100);
	noecho();
	//Makes enter return \r instead of \n
	nonl();
	//Flush the input buffer if an interrupt key is pressed.  This ensures
	//we don't miss keystrokes in the event of a SIGSTOP
	intrflush(stdscr, FALSE);
	//Enable keycodes
	keypad(stdscr, TRUE);
	runplugin(p, name);
	//Make sure to always restore the terminal to a sane configuration
	endwin();
	return;
}
<commit_msg>Nothing to see here<commit_after>// This is sometimes required to support the full curses API
#define _XOPEN_SOURCE
#define _XOPEN_SOURCE_EXTENDED

#ifdef __GNUC__
	// Enable printf and scanf argument checking
	#define GCC_PRINTF
	#define	GCC_SCANF
#endif

#include <curses.h>
#include <climits>
#include <cstdio>
#include <unordered_map>

#include <QString>
#include <QTextBoundaryFinder>

#include "lirch_constants.h"
#include "plugins/lirch_plugin.h"
#include "plugins/display_messages.h"
#include "plugins/notify_messages.h"
#include "plugins/edict_messages.h"
#include "plugins/channel_messages.h"
#include "core/core_messages.h"

namespace std
{
	template <>
	struct hash<QString>
	{
		size_t operator()(const QString& v) const
		{
			return std::hash<std::string>()(v.toStdString());
		}
	};
}

inline char CTRL(char c)
{
	//Leave only the lower 5 bits, so the return value is the numeric value
	//of CTRL+key (e.g. CTRL('c') gives you 3, which is the value you get
	//when hitting ctrl-c)
	return c&0x1f;
}

using namespace std;

template <class... args>
string strprintf(const string &format, args... a)
{
	//Thankfully, the C++ standard grabbed the definition from POSIX
	//instead of Windows, so I don't have to binary-search the correct
	//string size.
	int size=snprintf(NULL, 0, format.c_str(), a...);
	//Add padding for the terminating byte
	vector<char> s(size+1);
	//We can use sprintf instead of snprintf because we know the buffer is large enough
	sprintf(s.data(), format.c_str(), a...);
	return s.data();
}

//Same as wprintf, but handles unicode characters properly
template <class... args>
void wprintu(WINDOW *w, const string &format, args... a)
{
	string s=strprintf(format, a...);
	for (unsigned char c : s)
		waddch(w, c|(c>0x7f ? A_ALTCHARSET : 0));
}

//This wraps WINDOW pointers so they're be destroyed on exit
class WindowWrapper
{
public:
	WindowWrapper(WINDOW *ww) : w(ww, delwin) {}
	WindowWrapper() {int maxx, maxy; getmaxyx(stdscr, maxy, maxx); w=shared_ptr<WINDOW>(newpad(maxy-1, maxx), delwin); scrollok(get(), TRUE);}
	WINDOW *get() const {return w.get();}
	operator WINDOW*() const {return get();}
	WINDOW& operator*() const {return *w;}
	WINDOW* operator->() const {return get();}
private:
	shared_ptr<WINDOW> w;
};

void runplugin(plugin_pipe &p, const string &name)
{
	QString input;
	QString channel="default";
	int maxx, maxy;
	getmaxyx(stdscr, maxy, maxx);
	//10000 lines of scrollback should be enough for anyone
	//WindowWrapper channel_output=newpad(10000, maxx);
	unordered_map<QString, WindowWrapper> channel_windows;
	if (channel_windows["default"]==nullptr)
		return;
	WindowWrapper input_display=newwin(1, maxx-1, maxy-1, 0);
	if (input_display==nullptr)
		return;
	//Be lazy and let the input scroll
	scrollok(input_display, TRUE);
	//p.write(registration_message::create(-30000, name, "display"));
	while (true)
	{
		wint_t key;
		int rc=get_wch(&key);
		if (rc==OK)
		{
			if (key=='\r' || key=='\n')
			{
				p.write(raw_edict_message::create(input,channel));
				input="";
			}
			else if (key==WEOF)
			{
				//Quit since we have no more input
				break;
			}
			else
			{
				//This conversion is always valid, since key's
				//only valid values are valid wchar_t values
				//and WEOF, and we know it's not WEOF.
				wchar_t tmp=key;
				input.push_back(QString::fromWCharArray(&tmp, 1));
			}
		}
		else if (rc==KEY_CODE_YES)
		{
			if (key==KEY_BACKSPACE)
			{
				QTextBoundaryFinder bounds(QTextBoundaryFinder::Grapheme, input);
				bounds.toEnd();
				int pos=bounds.toPreviousBoundary();
				if (pos!=-1)
				{
					input.remove(pos, INT_MAX);
				}
			}
			else if (key==KEY_ENTER)
			{
				p.write(raw_edict_message::create(input,channel));
				input="";
			}
		}
		while (p.has_message())
		{
			message m=p.read();
			if (m.type=="shutdown")
			{
				return;
			}
			else if (m.type=="registration_status")
			{
				auto s=dynamic_cast<registration_status *>(m.getdata());
				if (!s)
					continue;
				if (!s->status)
				{
					if (s->priority>-32000)
						p.write(registration_message::create(s->priority-1, name, s->type));
				}
			}
			else if (m.type=="display")
			{
				auto s=dynamic_cast<display_message *>(m.getdata());
				if (!s)
					continue;
				p.write(m.decrement_priority());

				QString message_channel=s->channel;
				string nick=s->nick.toLocal8Bit().constData();
				string contents=s->contents.toLocal8Bit().constData();

				if (s->channel=="")
					s->channel=channel;

				if (channel_windows.count(message_channel)!=0)
				{
					if(s->subtype==display_message_subtype::NORMAL)
						wprintu(channel_windows[message_channel], "<%s> %s\n", nick.c_str(), contents.c_str());
					if(s->subtype==display_message_subtype::ME)
						wprintu(channel_windows[message_channel], "* %s %s\n", nick.c_str(), contents.c_str());
					if(s->subtype==display_message_subtype::NOTIFY)
						wprintu(channel_windows[message_channel], "‼‽ %s\n", contents.c_str());
				}
			}
			else if (m.type=="set_channel")
			{
				auto i=dynamic_cast<set_channel *>(m.getdata());
				if (!i)
					continue;
				p.write(m.decrement_priority());
				if (i->channel=="")
					p.write(notify_message::create(channel, "On channel "+channel));
				else
					channel=i->channel;
			}
			else if (m.type=="leave_channel")
			{
				auto i=dynamic_cast<leave_channel *>(m.getdata());
				if (!i)
					continue;
				p.write(m.decrement_priority());
				channel_windows.erase(i->channel);
			}
			else
				p.write(m.decrement_priority());
		}
		int x,y;
		getyx(channel_windows[channel], y, x);
		pnoutrefresh(channel_windows[channel], max(y-(maxy-1),0), 0, 0,0,maxy-2,maxx-1);
		wmove(input_display, 0, 0);
		wprintu(input_display, "\n%s", input.toLocal8Bit().constData());
		wnoutrefresh(input_display);
		//This doesn't need to run all the time, but we should be able
		//to cope with the screen refreshing at 10Hz
		doupdate();
	}
	p.write(core_quit_message::create());
}

void run(plugin_pipe p, string name)
{
	p.write(registration_message::create(-30000, name, "display"));
	p.write(registration_message::create(-30000, name, "set_channel"));
	p.write(registration_message::create(-30000, name, "leave_channel"));
	//Set the delay when hitting escape to 10 milliseconds, unless it was
	//already set.  The ESCDELAY variable is not supported in all curses
	//implementations, but should not cause problems in implementations
	//that ignore it.
	setenv("ESCDELAY", "10", 0);
	//Initialize curses
	initscr();
	//Don't buffer typed characters
	cbreak();
	//Wain no more than a tenth of a second for input
	timeout(100);
	noecho();
	//Makes enter return \r instead of \n
	nonl();
	//Flush the input buffer if an interrupt key is pressed.  This ensures
	//we don't miss keystrokes in the event of a SIGSTOP
	intrflush(stdscr, FALSE);
	//Enable keycodes
	keypad(stdscr, TRUE);
	runplugin(p, name);
	//Make sure to always restore the terminal to a sane configuration
	endwin();
	return;
}
<|endoftext|>


<commit_before>/*
    mutexops.cpp:

    Copyright (C) 2007 by Steven Yi

    Mutex lock and unlocking opcodes, used for when running Csound with
    multiple threads

    This file is part of Csound.

    The Csound 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.

    Csound 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 Csound; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
    02111-1307 USA
*/
#include <csdl.h>
#include "csGblMtx.h"
#include <map>

static std::map<CSOUND *, std::map<size_t, std::map<size_t, void *> > > mutexes;

typedef struct {
        OPDS    h;
        MYFLT   *ilocknum;
        void    *mutex;
} OPCODE_MUTEX;

static void * getMutex(CSOUND *csound, size_t instrNum, size_t lockNum)
{

    csound_global_mutex_lock();
    if(mutexes.find(csound) == mutexes.end()) {
        std::map<size_t, std::map<size_t, void *> > values;
        mutexes[csound] = values;
    }

    if(mutexes[csound].find(instrNum) == mutexes[csound].end()) {
        std::map<size_t, void*> mutexMap;
        mutexes[csound][instrNum] = mutexMap;
    }

    if (mutexes[csound][instrNum].find(lockNum) ==
        mutexes[csound][instrNum].end()) {
        void * mutex = csound->Create_Mutex(0);
        mutexes[csound][instrNum][lockNum] = mutex;

        csound->Message(csound, "Created new mutex [%ld:%ld]\n",
                        (long)instrNum, (long)lockNum);
    }
    csound_global_mutex_unlock();

    return mutexes[csound][instrNum][lockNum];

}

static int mutexLock(CSOUND *csound, OPCODE_MUTEX *p)
{

    if(p->mutex == NULL) {
        size_t instrNum = static_cast<size_t>(p->h.insdshead->p1);
        size_t lockNum = static_cast<size_t>(*p->ilocknum);

        p->mutex = getMutex(csound, instrNum, lockNum);
    }

    csound->LockMutex(p->mutex);

    return OK;
}

static int mutexUnlock(CSOUND *csound, OPCODE_MUTEX *p)
{
    if(p->mutex == NULL) {
        size_t instrNum = static_cast<size_t>(p->h.insdshead->p1);
        size_t lockNum = static_cast<size_t>(*p->ilocknum);

        p->mutex = getMutex(csound, instrNum, lockNum);
    }

    csound->UnlockMutex(p->mutex);

    return OK;
}

#define S(x)    sizeof(x)

static OENTRY localops[] = {
  { "mutex_lock",   S(OPCODE_MUTEX),  2, "", "i", NULL, (SUBR)mutexLock, NULL   },
  { "mutex_unlock",  S(OPCODE_MUTEX), 2, "", "i", NULL, (SUBR)mutexUnlock, NULL },
  { "mutex_locki",  S(OPCODE_MUTEX),  1, "", "i", (SUBR)mutexLock, NULL, NULL   },
  { "mutex_unlocki", S(OPCODE_MUTEX), 1, "", "i", (SUBR)mutexUnlock, NULL, NULL }

};

LINKAGE
<commit_msg>no message<commit_after>/*
    mutexops.cpp:

    Copyright (C) 2007 by Steven Yi

    Mutex lock and unlocking opcodes, used for when running Csound with
    multiple threads

    This file is part of Csound.

    The Csound 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.

    Csound 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 Csound; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
    02111-1307 USA
*/
#include "csdl.h"
#include "csGblMtx.h"
#include <map>

static std::map<CSOUND *, std::map<size_t, std::map<size_t, void *> > > mutexes;

typedef struct {
        OPDS    h;
        MYFLT   *ilocknum;
        void    *mutex;
} OPCODE_MUTEX;

static void * getMutex(CSOUND *csound, size_t instrNum, size_t lockNum)
{

    csound_global_mutex_lock();
    if(mutexes.find(csound) == mutexes.end()) {
        std::map<size_t, std::map<size_t, void *> > values;
        mutexes[csound] = values;
    }

    if(mutexes[csound].find(instrNum) == mutexes[csound].end()) {
        std::map<size_t, void*> mutexMap;
        mutexes[csound][instrNum] = mutexMap;
    }

    if (mutexes[csound][instrNum].find(lockNum) ==
        mutexes[csound][instrNum].end()) {
        void * mutex = csound->Create_Mutex(0);
        mutexes[csound][instrNum][lockNum] = mutex;

        csound->Message(csound, "Created new mutex [%ld:%ld]\n",
                        (long)instrNum, (long)lockNum);
    }
    csound_global_mutex_unlock();

    return mutexes[csound][instrNum][lockNum];

}

static int mutexLock(CSOUND *csound, OPCODE_MUTEX *p)
{

    if(p->mutex == NULL) {
        size_t instrNum = static_cast<size_t>(p->h.insdshead->p1);
        size_t lockNum = static_cast<size_t>(*p->ilocknum);

        p->mutex = getMutex(csound, instrNum, lockNum);
    }

    csound->LockMutex(p->mutex);

    return OK;
}

static int mutexUnlock(CSOUND *csound, OPCODE_MUTEX *p)
{
    if(p->mutex == NULL) {
        size_t instrNum = static_cast<size_t>(p->h.insdshead->p1);
        size_t lockNum = static_cast<size_t>(*p->ilocknum);

        p->mutex = getMutex(csound, instrNum, lockNum);
    }

    csound->UnlockMutex(p->mutex);

    return OK;
}

#define S(x)    sizeof(x)

static OENTRY localops[] = {
  { "mutex_lock",   S(OPCODE_MUTEX),  2, "", "i", NULL, (SUBR)mutexLock, NULL   },
  { "mutex_unlock",  S(OPCODE_MUTEX), 2, "", "i", NULL, (SUBR)mutexUnlock, NULL },
  { "mutex_locki",  S(OPCODE_MUTEX),  1, "", "i", (SUBR)mutexLock, NULL, NULL   },
  { "mutex_unlocki", S(OPCODE_MUTEX), 1, "", "i", (SUBR)mutexUnlock, NULL, NULL }

};

LINKAGE
<|endoftext|>


<commit_before>#include <Adafruit_GPS.h>
#include <SoftwareSerial.h>
#include <SPI.h>
#include <SD.h>

File myFile;
uint32_t lastsave(0);
SoftwareSerial mySerial(3, 2);
Adafruit_GPS GPS(&mySerial);
#define GPSECHO  false
boolean usingInterrupt = false;
void useInterrupt(boolean); // Func prototype keeps Arduino 0023 happy

String getFileName()
{
  File counter;
  counter = SD.open(F("counter.txt"), FILE_WRITE);
  counter.seek(0);
  uint32_t num = 0;
  if(counter.size()>0) num = counter.read();
  counter.seek(0);
  counter.write(num+1);
  counter.close();

  String str = String(num);
  return "GPS"+str+".txt";
}
void setup()
{
  Serial.begin(115200);
  GPS.begin(9600);
  GPS.sendCommand(PMTK_SET_NMEA_OUTPUT_RMCGGA);
  GPS.sendCommand(PMTK_SET_NMEA_UPDATE_1HZ);   // 1 Hz update rate
  GPS.sendCommand(PGCMD_ANTENNA);
  useInterrupt(true);
  delay(1000);
  mySerial.println(PMTK_Q_RELEASE);
  if (!SD.begin(4)) {
    return;
  }
  String fileName = getFileName();
  myFile = SD.open(fileName, FILE_WRITE);
  myFile.println(F("date, time, fix, quality, latitude, longitude, altitude(metres), satellites"));
  myFile.flush();
}

SIGNAL(TIMER0_COMPA_vect) {
  char c = GPS.read();
#ifdef UDR0
  if (GPSECHO)
    if (c) UDR0 = c;
#endif
}

void useInterrupt(boolean v) {
  if (v) {
    OCR0A = 0xAF;
    TIMSK0 |= _BV(OCIE0A);
    usingInterrupt = true;
  } else {
    TIMSK0 &= ~_BV(OCIE0A);
    usingInterrupt = false;
  }
}

uint32_t timer = millis();

char* getRow(char *row, Adafruit_GPS& gpsNow)
{
  char lat[15], lng[16], alt[9], spd[6], agl[7];

  sprintf(row, "%d/%d/%d, %d:%d:%d, %d, %d, %s, %s, %s, %d",
          gpsNow.day, gpsNow.month, gpsNow.year,
          gpsNow.hour, gpsNow.minute, gpsNow.seconds,
          gpsNow.fix,
          gpsNow.fixquality,
          dtostrf(gpsNow.latitudeDegrees,  14, 10, lat),
          dtostrf(gpsNow.longitudeDegrees, 15, 10, lng),
          dtostrf(gpsNow.altitude,          8,  2, alt),
          gpsNow.satellites);
  return row;
}
void loop()
{
  if(myFile){
    if (! usingInterrupt) {
      char c = GPS.read();
      if (GPSECHO)
        if (c) Serial.print(c);
    }
    if (GPS.newNMEAreceived()) {
      if (!GPS.parse(GPS.lastNMEA()))
        return;
    }
    if (timer > millis())  timer = millis();
    if (millis() - timer > 2000) {
      timer = millis(); // reset the timer
      char row[128];
      getRow(row, GPS);
      myFile.println(row);
      Serial.println(row);
      myFile.flush();
    }
  }
  else
    Serial.print(F("File is corrupt"));
}<commit_msg>SD.open(..) is not overloaded to accept F(..)<commit_after>#include <Adafruit_GPS.h>
#include <SoftwareSerial.h>
#include <SPI.h>
#include <SD.h>

File myFile;
uint32_t lastsave(0);
SoftwareSerial mySerial(3, 2);
Adafruit_GPS GPS(&mySerial);
#define GPSECHO  false
boolean usingInterrupt = false;
void useInterrupt(boolean); // Func prototype keeps Arduino 0023 happy

String getFileName()
{
  File counter;
  counter = SD.open("last", FILE_WRITE);
  counter.seek(0);
  uint32_t num = 0;
  if(counter.size()>0) num = counter.read();
  counter.seek(0);
  counter.write(num+1);
  counter.close();

  String str = String(num);
  return "GPS"+str+".txt";
}
void setup()
{
  Serial.begin(115200);
  GPS.begin(9600);
  GPS.sendCommand(PMTK_SET_NMEA_OUTPUT_RMCGGA);
  GPS.sendCommand(PMTK_SET_NMEA_UPDATE_1HZ);   // 1 Hz update rate
  GPS.sendCommand(PGCMD_ANTENNA);
  useInterrupt(true);
  delay(1000);
  mySerial.println(PMTK_Q_RELEASE);
  if (!SD.begin(4)) {
    return;
  }
  String fileName = getFileName();
  myFile = SD.open(fileName, FILE_WRITE);
  myFile.println(F("date, time, fix, quality, latitude, longitude, altitude(metres), satellites"));
  myFile.flush();
}

SIGNAL(TIMER0_COMPA_vect) {
  char c = GPS.read();
#ifdef UDR0
  if (GPSECHO)
    if (c) UDR0 = c;
#endif
}

void useInterrupt(boolean v) {
  if (v) {
    OCR0A = 0xAF;
    TIMSK0 |= _BV(OCIE0A);
    usingInterrupt = true;
  } else {
    TIMSK0 &= ~_BV(OCIE0A);
    usingInterrupt = false;
  }
}

uint32_t timer = millis();

char* getRow(char *row, Adafruit_GPS& gpsNow)
{
  char lat[15], lng[16], alt[9], spd[6], agl[7];

  sprintf(row, "%d/%d/%d, %d:%d:%d, %d, %d, %s, %s, %s, %d",
          gpsNow.day, gpsNow.month, gpsNow.year,
          gpsNow.hour, gpsNow.minute, gpsNow.seconds,
          gpsNow.fix,
          gpsNow.fixquality,
          dtostrf(gpsNow.latitudeDegrees,  14, 10, lat),
          dtostrf(gpsNow.longitudeDegrees, 15, 10, lng),
          dtostrf(gpsNow.altitude,          8,  2, alt),
          gpsNow.satellites);
  return row;
}
void loop()
{
  if(myFile){
    if (! usingInterrupt) {
      char c = GPS.read();
      if (GPSECHO)
        if (c) Serial.print(c);
    }
    if (GPS.newNMEAreceived()) {
      if (!GPS.parse(GPS.lastNMEA()))
        return;
    }
    if (timer > millis())  timer = millis();
    if (millis() - timer > 2000) {
      timer = millis(); // reset the timer
      char row[128];
      getRow(row, GPS);
      myFile.println(row);
      Serial.println(row);
      myFile.flush();
    }
  }
  else
    Serial.print(F("File is corrupt"));
}<|endoftext|>


<commit_before>/******************************************************************************
 *                    _   _____   __________                                  *
 *                   | | / / _ | / __/_  __/     Visibility                   *
 *                   | |/ / __ |_\ \  / /          Across                     *
 *                   |___/_/ |_/___/ /_/       Space and Time                 *
 *                                                                            *
 * This file is part of VAST. It is subject to the license terms in the       *
 * LICENSE file found in the top-level directory of this distribution and at  *
 * http://vast.io/license. No part of VAST, including this file, may be       *
 * copied, modified, propagated, or distributed except according to the terms *
 * contained in the LICENSE file.                                             *
 ******************************************************************************/

#include "vast/system/application.hpp"

#include <iostream>

#include <caf/atom.hpp>
#include <caf/error.hpp>

#include "vast/detail/adjust_resource_consumption.hpp"
#include "vast/detail/assert.hpp"
#include "vast/error.hpp"

using std::string;

using namespace std::chrono_literals;
using namespace std::string_literals;
using namespace caf;

namespace vast::system {

application::application() {
  // TODO: this function has side effects...should we put it elsewhere where
  // it's explicit to the user? Or perhaps make whatever this function does
  // simply a configuration option and use it later?
  detail::adjust_resource_consumption();
}

void render_error(const application& app, const caf::error& err,
                  std::ostream& os) {
  if (err)
    // The user most likely killed the process via CTRL+C, print nothing.
    return;
  os << render(err);
  if (err.category() == caf::atom("vast")) {
    auto x = static_cast<vast::ec>(err.code());
    switch (x) {
      default:
        break;
      case ec::invalid_subcommand:
      case ec::missing_subcommand:
      case ec::unrecognized_option: {
        auto ctx = err.context();
        if (ctx.match_element<std::string>(1)) {
          auto name = ctx.get_as<std::string>(1);
          if (auto cmd = resolve(app.root, name))
            helptext(*cmd, os);
        }
        else {
          VAST_ASSERT("User visible error contexts must consist of strings!");
        }
        break;
      }
    }
  }
}

} // namespace vast::system
<commit_msg>Fix segfault in error reporting<commit_after>/******************************************************************************
 *                    _   _____   __________                                  *
 *                   | | / / _ | / __/_  __/     Visibility                   *
 *                   | |/ / __ |_\ \  / /          Across                     *
 *                   |___/_/ |_/___/ /_/       Space and Time                 *
 *                                                                            *
 * This file is part of VAST. It is subject to the license terms in the       *
 * LICENSE file found in the top-level directory of this distribution and at  *
 * http://vast.io/license. No part of VAST, including this file, may be       *
 * copied, modified, propagated, or distributed except according to the terms *
 * contained in the LICENSE file.                                             *
 ******************************************************************************/

#include "vast/system/application.hpp"

#include <iostream>

#include <caf/atom.hpp>
#include <caf/error.hpp>

#include "vast/detail/adjust_resource_consumption.hpp"
#include "vast/detail/assert.hpp"
#include "vast/error.hpp"

using std::string;

using namespace std::chrono_literals;
using namespace std::string_literals;
using namespace caf;

namespace vast::system {

application::application() {
  // TODO: this function has side effects...should we put it elsewhere where
  // it's explicit to the user? Or perhaps make whatever this function does
  // simply a configuration option and use it later?
  detail::adjust_resource_consumption();
}

void render_error(const application& app, const caf::error& err,
                  std::ostream& os) {
  if (!err)
    // The user most likely killed the process via CTRL+C, print nothing.
    return;
  os << render(err);
  if (err.category() == caf::atom("vast")) {
    auto x = static_cast<vast::ec>(err.code());
    switch (x) {
      default:
        break;
      case ec::invalid_subcommand:
      case ec::missing_subcommand:
      case ec::unrecognized_option: {
        auto ctx = err.context();
        if (ctx.match_element<std::string>(1)) {
          auto name = ctx.get_as<std::string>(1);
          if (auto cmd = resolve(app.root, name))
            helptext(*cmd, os);
        }
        else {
          VAST_ASSERT("User visible error contexts must consist of strings!");
        }
        break;
      }
    }
  }
}

} // namespace vast::system
<|endoftext|>