<commit_before>#include "label.h"

#include <QtGui/QTextCursor>

#include "umllib/nodeElement.h"
#include "umllib/edgeElement.h"
#include "brandManager/brandManager.h"

using namespace qReal;

Label::Label(models::GraphicalModelAssistApi &graphicalAssistApi, Id const &elementId
		, int index, qreal x, qreal y, QString const &text, qreal rotation)
	: mFocusIn(false), mReadOnly(true), mScalingX(false), mScalingY(false), mRotation(rotation)
	, mPoint(x, y), mBinding(""), mBackground(Qt::transparent), mIsStretched(false), mIsHard(false)
	, mParentIsSelected(false), mWasMoved(false), mShouldMove(false)
	, mIndex(index)
	, mId(elementId)
	, mGraphicalModelAssistApi(graphicalAssistApi)
{
	setText(text);
	init();
}

Label::Label(models::GraphicalModelAssistApi &graphicalAssistApi, Id const &elementId
		, int index, qreal x, qreal y, QString const &binding, bool readOnly, qreal rotation)
	: mFocusIn(false), mReadOnly(readOnly), mScalingX(false), mScalingY(false), mRotation(rotation)
	, mPoint(x, y), mBinding(binding), mBackground(Qt::transparent), mIsStretched(false), mIsHard(false)
	, mParentIsSelected(false), mWasMoved(false), mShouldMove(false)
	, mIndex(index)
	, mId(elementId)
	, mGraphicalModelAssistApi(graphicalAssistApi)
{
	init();
}

Label::~Label()
{
}

void Label::init()
{
	QGraphicsTextItem::setFlags(ItemIsSelectable);
	QGraphicsTextItem::setFlag(ItemIsMovable, SettingsManager::value("MoveLabels", true).toBool());

	setTitleFont();
	setRotation(mRotation);
	if (!mBinding.isEmpty()) {
		QList<QPair<QString, QString>> const values = mGraphicalModelAssistApi
				.editorManagerInterface().enumValues(mId, mBinding);
		for (QPair<QString, QString> const &pair : values) {
			mEnumValues[pair.first] = pair.second;
		}
	}
}

void Label::moveToParentCenter()
{
	if (mWasMoved) {
		// now it has user defined position, don't center automatically
		return;
	}

	if (orientation() == Qt::Horizontal) {
		qreal parentCenter = mParentContents.x() + mParentContents.width() / 2;
		qreal titleCenter = x() + mContents.width() / 2;
		qreal diff = parentCenter - titleCenter;

		setX(x() + diff);
	} else if (orientation() == Qt::Vertical) {
		qreal parentCenter = mParentContents.y() + mParentContents.height() / 2;
		qreal titleCenter = y() - mContents.width() / 2;
		qreal diff = parentCenter - titleCenter;

		setY(y() + diff);
	}
}

Qt::Orientation Label::orientation()
{
	if (abs(rotation()) == 90) {
		return Qt::Vertical;
	}

	return Qt::Horizontal;
}

void Label::setText(QString const &text)
{
	setPlainText(text);
}

void Label::setTextFromRepo(QString const &text)
{
	QString const friendlyText = mEnumValues.isEmpty() ? text : mEnumValues[text];
	if (friendlyText != toPlainText()) {
		QGraphicsTextItem::setPlainText(friendlyText); // need this to load old saves with html markup
		setText(toPlainText());
		updateData();
	}
}

void Label::setParentSelected(bool isSelected)
{
	mParentIsSelected = isSelected;
}

void Label::setParentContents(QRectF const &contents)
{
	mParentContents = contents;
	scaleCoordinates(contents);
}

void Label::setShouldCenter(bool shouldCenter)
{
	mWasMoved = !shouldCenter;
}

void Label::scaleCoordinates(QRectF const &contents)
{
	if (mWasMoved) {
		return;
	}

	qreal const x = mPoint.x() * (!mScalingX ? mContents.width() : contents.width());
	qreal const y = mPoint.y() * (!mScalingX ? mContents.height() : contents.height());

	setPos(x, y);
}

void Label::setFlags(GraphicsItemFlags flags)
{
	QGraphicsTextItem::setFlags(flags);
}

void Label::setTextInteractionFlags(Qt::TextInteractionFlags flags)
{
	QGraphicsTextItem::setTextInteractionFlags(flags);
}

void Label::setHtml(QString const &html)
{
	QGraphicsTextItem::setHtml(html);
}

void Label::setPlainText(QString const &text)
{
	QGraphicsTextItem::setPlainText(text);
}

void Label::updateData(bool withUndoRedo)
{
	QString const value = toPlainText();
	NodeElement * const parent = static_cast<NodeElement*>(parentItem());
	if (mBinding == "name") {
		parent->setName(value, withUndoRedo);
	} else if (mEnumValues.isEmpty()) {
		parent->setLogicalProperty(mBinding, value, withUndoRedo);
	} else {
		parent->setLogicalProperty(mBinding, mEnumValues.key(value), withUndoRedo);
	}

	mGraphicalModelAssistApi.setLabelPosition(mId, mIndex, pos());
	mGraphicalModelAssistApi.setLabelSize(mId, mIndex, this->boundingRect().size());
}

void Label::setTitleFont()
{
	setFont(BrandManager::fonts()->sceneLabelsFont());
}

void Label::mousePressEvent(QGraphicsSceneMouseEvent *event)
{
	if (!mShouldMove) {
		QGraphicsTextItem::mousePressEvent(event);
		event->ignore();
		return;
	}

	mIsStretched = (event->pos().x() >= boundingRect().right() - 10
			&& event->pos().y() >= boundingRect().bottom() - 10);

	QGraphicsTextItem::mousePressEvent(event);
	event->accept();
}

void Label::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
{
	if (!mShouldMove) {
		setSelected(false);
		return;
	}

	QPointF cursorPoint = mapToItem(this, event->pos());

	if (mIsStretched && SettingsManager::value("ResizeLabels", true).toBool()) {
		updateRect(cursorPoint);
		return;
	}

	if (!SettingsManager::value("MoveLabels", true).toBool()) {
		event->ignore();
		return;
	}

	mWasMoved = true;

	if (!labelMovingRect().contains(event->pos())) {
		event->ignore();
		return;
	}

	QGraphicsTextItem::mouseMoveEvent(event);
	event->accept();
}

void Label::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
{
	mShouldMove = true;

	updateData();

	QGraphicsTextItem::mouseReleaseEvent(event);
	setSelected(true);
}

void Label::init(QRectF const &contents)
{
	mContents = contents;
	mParentContents = contents;

	if (mGraphicalModelAssistApi.hasLabel(mId, mIndex)) {
		QPointF const currentPos = mGraphicalModelAssistApi.labelPosition(mId, mIndex);
		mPoint.setX(currentPos.x() / mContents.width());
		mPoint.setY(currentPos.y() / mContents.height());
		setPos(currentPos);
	} else {
		qreal const x = mPoint.x() * mContents.width();
		qreal const y = mPoint.y() * mContents.height();
		setPos(x, y);
		mGraphicalModelAssistApi.createLabel(mId, mIndex, QPointF(x, y), this->boundingRect().size());
	}
}

void Label::setScaling(bool scalingX, bool scalingY)
{
	mScalingX = scalingX;
	mScalingY = scalingY;
}

void Label::setBackground(QColor const &background)
{
	mBackground = background;
}

bool Label::isHard() const
{
	return mIsHard;
}

void Label::setHard(bool hard)
{
	mIsHard = hard;
}

bool Label::isReadOnly() const
{
	return mReadOnly;
}

void Label::focusOutEvent(QFocusEvent *event)
{
	QGraphicsTextItem::focusOutEvent(event);
	setTextInteractionFlags(Qt::NoTextInteraction);

	// Clear selection
	QTextCursor cursor = textCursor();
	cursor.clearSelection();
	setTextCursor(cursor);

	unsetCursor();

	if (mReadOnly) {
		return;
	}

	if (mOldText != toPlainText()) {
		updateData(true);
	}
}

void Label::keyPressEvent(QKeyEvent *event)
{
	int const keyEvent = event->key();
	if (keyEvent == Qt::Key_Escape) {
		// Restore previous text and loose focus
		setText(mOldText);
		clearFocus();
		return;
	}

	if ((event->modifiers() & Qt::ShiftModifier) && (event->key() == Qt::Key_Return)) {
		// Line feed
		QTextCursor cursor = textCursor();
		QString currentText = toPlainText();
		int const oldPos = cursor.position();
		currentText.insert(oldPos, "\n");
		setText(currentText);
		cursor.movePosition(QTextCursor::Start);
		cursor.movePosition(QTextCursor::NextCharacter, QTextCursor::MoveAnchor, oldPos + 1);
		setTextCursor(cursor);
		return;
	}

	if (keyEvent == Qt::Key_Enter || keyEvent == Qt::Key_Return) {
		// Loose focus: new name will be applied in focusOutEvent
		clearFocus();
		return;
	}

	QGraphicsTextItem::keyPressEvent(event);
}

void Label::startTextInteraction()
{
	// Already interacting?
	if (hasFocus()) {
		return;
	}

	mOldText = toPlainText();

	setTextInteractionFlags(mReadOnly ? Qt::TextBrowserInteraction : Qt::TextEditorInteraction);
	setFocus(Qt::OtherFocusReason);

	// Set full text selection
	QTextCursor cursor = QTextCursor(document());
	cursor.select(QTextCursor::Document);
	setTextCursor(cursor);
	setCursor(Qt::IBeamCursor);
}

void Label::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
{
	QString text = toPlainText();

	if (text.isEmpty() && !mParentIsSelected && !isSelected()) {
		return;
	}

	painter->save();
	painter->setBrush(QBrush(mBackground));

	if ((mParentIsSelected && toPlainText().isEmpty()) || isSelected()) {
		painter->setPen(QPen(Qt::DotLine));
	} else if (!toPlainText().isEmpty()) {
		painter->setPen(QPen(Qt::transparent));
	}

	painter->drawRect(boundingRect());
	painter->restore();

	QGraphicsTextItem::paint(painter, option, widget);
}

void Label::updateRect(QPointF newBottomRightPoint)
{
	mContents.setBottomRight(newBottomRightPoint);
	setTextWidth(mContents.width());
}

void Label::clearMoveFlag()
{
	mShouldMove = false;
}

QRectF Label::labelMovingRect() const
{
	int const distance = SettingsManager::value("LabelsDistance").toInt();
	return mapFromItem(parentItem(), parentItem()->boundingRect()).boundingRect()
			.adjusted(-distance, -distance, distance, distance);
}
<commit_msg>Removed non-actual comment.<commit_after>#include "label.h"

#include <QtGui/QTextCursor>

#include "umllib/nodeElement.h"
#include "umllib/edgeElement.h"
#include "brandManager/brandManager.h"

using namespace qReal;

Label::Label(models::GraphicalModelAssistApi &graphicalAssistApi, Id const &elementId
		, int index, qreal x, qreal y, QString const &text, qreal rotation)
	: mFocusIn(false), mReadOnly(true), mScalingX(false), mScalingY(false), mRotation(rotation)
	, mPoint(x, y), mBinding(""), mBackground(Qt::transparent), mIsStretched(false), mIsHard(false)
	, mParentIsSelected(false), mWasMoved(false), mShouldMove(false)
	, mIndex(index)
	, mId(elementId)
	, mGraphicalModelAssistApi(graphicalAssistApi)
{
	setText(text);
	init();
}

Label::Label(models::GraphicalModelAssistApi &graphicalAssistApi, Id const &elementId
		, int index, qreal x, qreal y, QString const &binding, bool readOnly, qreal rotation)
	: mFocusIn(false), mReadOnly(readOnly), mScalingX(false), mScalingY(false), mRotation(rotation)
	, mPoint(x, y), mBinding(binding), mBackground(Qt::transparent), mIsStretched(false), mIsHard(false)
	, mParentIsSelected(false), mWasMoved(false), mShouldMove(false)
	, mIndex(index)
	, mId(elementId)
	, mGraphicalModelAssistApi(graphicalAssistApi)
{
	init();
}

Label::~Label()
{
}

void Label::init()
{
	QGraphicsTextItem::setFlags(ItemIsSelectable);
	QGraphicsTextItem::setFlag(ItemIsMovable, SettingsManager::value("MoveLabels", true).toBool());

	setTitleFont();
	setRotation(mRotation);
	if (!mBinding.isEmpty()) {
		QList<QPair<QString, QString>> const values = mGraphicalModelAssistApi
				.editorManagerInterface().enumValues(mId, mBinding);
		for (QPair<QString, QString> const &pair : values) {
			mEnumValues[pair.first] = pair.second;
		}
	}
}

void Label::moveToParentCenter()
{
	if (mWasMoved) {
		// now it has user defined position, don't center automatically
		return;
	}

	if (orientation() == Qt::Horizontal) {
		qreal parentCenter = mParentContents.x() + mParentContents.width() / 2;
		qreal titleCenter = x() + mContents.width() / 2;
		qreal diff = parentCenter - titleCenter;

		setX(x() + diff);
	} else if (orientation() == Qt::Vertical) {
		qreal parentCenter = mParentContents.y() + mParentContents.height() / 2;
		qreal titleCenter = y() - mContents.width() / 2;
		qreal diff = parentCenter - titleCenter;

		setY(y() + diff);
	}
}

Qt::Orientation Label::orientation()
{
	if (abs(rotation()) == 90) {
		return Qt::Vertical;
	}

	return Qt::Horizontal;
}

void Label::setText(QString const &text)
{
	setPlainText(text);
}

void Label::setTextFromRepo(QString const &text)
{
	QString const friendlyText = mEnumValues.isEmpty() ? text : mEnumValues[text];
	if (friendlyText != toPlainText()) {
		QGraphicsTextItem::setPlainText(friendlyText);
		setText(toPlainText());
		updateData();
	}
}

void Label::setParentSelected(bool isSelected)
{
	mParentIsSelected = isSelected;
}

void Label::setParentContents(QRectF const &contents)
{
	mParentContents = contents;
	scaleCoordinates(contents);
}

void Label::setShouldCenter(bool shouldCenter)
{
	mWasMoved = !shouldCenter;
}

void Label::scaleCoordinates(QRectF const &contents)
{
	if (mWasMoved) {
		return;
	}

	qreal const x = mPoint.x() * (!mScalingX ? mContents.width() : contents.width());
	qreal const y = mPoint.y() * (!mScalingX ? mContents.height() : contents.height());

	setPos(x, y);
}

void Label::setFlags(GraphicsItemFlags flags)
{
	QGraphicsTextItem::setFlags(flags);
}

void Label::setTextInteractionFlags(Qt::TextInteractionFlags flags)
{
	QGraphicsTextItem::setTextInteractionFlags(flags);
}

void Label::setHtml(QString const &html)
{
	QGraphicsTextItem::setHtml(html);
}

void Label::setPlainText(QString const &text)
{
	QGraphicsTextItem::setPlainText(text);
}

void Label::updateData(bool withUndoRedo)
{
	QString const value = toPlainText();
	NodeElement * const parent = static_cast<NodeElement*>(parentItem());
	if (mBinding == "name") {
		parent->setName(value, withUndoRedo);
	} else if (mEnumValues.isEmpty()) {
		parent->setLogicalProperty(mBinding, value, withUndoRedo);
	} else {
		parent->setLogicalProperty(mBinding, mEnumValues.key(value), withUndoRedo);
	}

	mGraphicalModelAssistApi.setLabelPosition(mId, mIndex, pos());
	mGraphicalModelAssistApi.setLabelSize(mId, mIndex, this->boundingRect().size());
}

void Label::setTitleFont()
{
	setFont(BrandManager::fonts()->sceneLabelsFont());
}

void Label::mousePressEvent(QGraphicsSceneMouseEvent *event)
{
	if (!mShouldMove) {
		QGraphicsTextItem::mousePressEvent(event);
		event->ignore();
		return;
	}

	mIsStretched = (event->pos().x() >= boundingRect().right() - 10
			&& event->pos().y() >= boundingRect().bottom() - 10);

	QGraphicsTextItem::mousePressEvent(event);
	event->accept();
}

void Label::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
{
	if (!mShouldMove) {
		setSelected(false);
		return;
	}

	QPointF cursorPoint = mapToItem(this, event->pos());

	if (mIsStretched && SettingsManager::value("ResizeLabels", true).toBool()) {
		updateRect(cursorPoint);
		return;
	}

	if (!SettingsManager::value("MoveLabels", true).toBool()) {
		event->ignore();
		return;
	}

	mWasMoved = true;

	if (!labelMovingRect().contains(event->pos())) {
		event->ignore();
		return;
	}

	QGraphicsTextItem::mouseMoveEvent(event);
	event->accept();
}

void Label::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
{
	mShouldMove = true;

	updateData();

	QGraphicsTextItem::mouseReleaseEvent(event);
	setSelected(true);
}

void Label::init(QRectF const &contents)
{
	mContents = contents;
	mParentContents = contents;

	if (mGraphicalModelAssistApi.hasLabel(mId, mIndex)) {
		QPointF const currentPos = mGraphicalModelAssistApi.labelPosition(mId, mIndex);
		mPoint.setX(currentPos.x() / mContents.width());
		mPoint.setY(currentPos.y() / mContents.height());
		setPos(currentPos);
	} else {
		qreal const x = mPoint.x() * mContents.width();
		qreal const y = mPoint.y() * mContents.height();
		setPos(x, y);
		mGraphicalModelAssistApi.createLabel(mId, mIndex, QPointF(x, y), this->boundingRect().size());
	}
}

void Label::setScaling(bool scalingX, bool scalingY)
{
	mScalingX = scalingX;
	mScalingY = scalingY;
}

void Label::setBackground(QColor const &background)
{
	mBackground = background;
}

bool Label::isHard() const
{
	return mIsHard;
}

void Label::setHard(bool hard)
{
	mIsHard = hard;
}

bool Label::isReadOnly() const
{
	return mReadOnly;
}

void Label::focusOutEvent(QFocusEvent *event)
{
	QGraphicsTextItem::focusOutEvent(event);
	setTextInteractionFlags(Qt::NoTextInteraction);

	// Clear selection
	QTextCursor cursor = textCursor();
	cursor.clearSelection();
	setTextCursor(cursor);

	unsetCursor();

	if (mReadOnly) {
		return;
	}

	if (mOldText != toPlainText()) {
		updateData(true);
	}
}

void Label::keyPressEvent(QKeyEvent *event)
{
	int const keyEvent = event->key();
	if (keyEvent == Qt::Key_Escape) {
		// Restore previous text and loose focus
		setText(mOldText);
		clearFocus();
		return;
	}

	if ((event->modifiers() & Qt::ShiftModifier) && (event->key() == Qt::Key_Return)) {
		// Line feed
		QTextCursor cursor = textCursor();
		QString currentText = toPlainText();
		int const oldPos = cursor.position();
		currentText.insert(oldPos, "\n");
		setText(currentText);
		cursor.movePosition(QTextCursor::Start);
		cursor.movePosition(QTextCursor::NextCharacter, QTextCursor::MoveAnchor, oldPos + 1);
		setTextCursor(cursor);
		return;
	}

	if (keyEvent == Qt::Key_Enter || keyEvent == Qt::Key_Return) {
		// Loose focus: new name will be applied in focusOutEvent
		clearFocus();
		return;
	}

	QGraphicsTextItem::keyPressEvent(event);
}

void Label::startTextInteraction()
{
	// Already interacting?
	if (hasFocus()) {
		return;
	}

	mOldText = toPlainText();

	setTextInteractionFlags(mReadOnly ? Qt::TextBrowserInteraction : Qt::TextEditorInteraction);
	setFocus(Qt::OtherFocusReason);

	// Set full text selection
	QTextCursor cursor = QTextCursor(document());
	cursor.select(QTextCursor::Document);
	setTextCursor(cursor);
	setCursor(Qt::IBeamCursor);
}

void Label::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
{
	QString text = toPlainText();

	if (text.isEmpty() && !mParentIsSelected && !isSelected()) {
		return;
	}

	painter->save();
	painter->setBrush(QBrush(mBackground));

	if ((mParentIsSelected && toPlainText().isEmpty()) || isSelected()) {
		painter->setPen(QPen(Qt::DotLine));
	} else if (!toPlainText().isEmpty()) {
		painter->setPen(QPen(Qt::transparent));
	}

	painter->drawRect(boundingRect());
	painter->restore();

	QGraphicsTextItem::paint(painter, option, widget);
}

void Label::updateRect(QPointF newBottomRightPoint)
{
	mContents.setBottomRight(newBottomRightPoint);
	setTextWidth(mContents.width());
}

void Label::clearMoveFlag()
{
	mShouldMove = false;
}

QRectF Label::labelMovingRect() const
{
	int const distance = SettingsManager::value("LabelsDistance").toInt();
	return mapFromItem(parentItem(), parentItem()->boundingRect()).boundingRect()
			.adjusted(-distance, -distance, distance, distance);
}
<|endoftext|>


<commit_before>#include <ros/ros.h>
#include <ros/forwards.h>
#include <ros/single_subscriber_publisher.h>
#include <sensor_msgs/Image.h>
#include <image_transport/image_transport.h>
#include <visualization_msgs/Marker.h>
#include <opencv/cv.h>
#include <opencv/highgui.h>
#include <cv_bridge/cv_bridge.h>

#include <src/TagDetector.h>
#include <src/TagDetection.h>
#include <src/TagFamily.h>

#include <Eigen/Core>
#include <Eigen/Geometry>

#include <visualization_msgs/MarkerArray.h>
#include "yaml-cpp/yaml.h"
#include <sstream>
#include <fstream>

#include <boost/unordered_set.hpp>
#include <boost/unordered_map.hpp>
#include <boost/make_shared.hpp>

#include "apriltags.h"

using namespace std;

// Functions

double GetTagSize(int tag_id)
{
    boost::unordered_map<size_t, double>::iterator tag_sizes_it =
        tag_sizes_.find(tag_id);
    if(tag_sizes_it != tag_sizes_.end()) {
        return tag_sizes_it->second;
    } else {
        return default_tag_size_;
    }
}

Eigen::Matrix4d GetDetectionTransform(TagDetection detection)
{
    double tag_size = GetTagSize(detection.id);

    std::vector<cv::Point3f> object_pts;
    std::vector<cv::Point2f> image_pts;
    double tag_radius = tag_size/2.;

    object_pts.push_back(cv::Point3f(-tag_radius, -tag_radius, 0));
    object_pts.push_back(cv::Point3f( tag_radius, -tag_radius, 0));
    object_pts.push_back(cv::Point3f( tag_radius,  tag_radius, 0));
    object_pts.push_back(cv::Point3f(-tag_radius,  tag_radius, 0));

    image_pts.push_back(detection.p[0]);
    cout << detection.p[0] << endl;
    image_pts.push_back(detection.p[1]);
    cout << detection.p[1] << endl;
    image_pts.push_back(detection.p[2]);
    cout << detection.p[2] << endl;
    image_pts.push_back(detection.p[3]);
    cout << detection.p[3] << endl;

    cv::Matx33f intrinsics(camera_info_.K[0], 0, camera_info_.K[2],
                           0, camera_info_.K[4], camera_info_.K[5],
                           0, 0, 1);

    cv::Mat rvec, tvec;
    cv::Vec4f dist_param(0,0,0,0);
    cv::solvePnP(object_pts, image_pts, intrinsics, dist_param,
            rvec, tvec);
    cv::Matx33d r;
    cv::Rodrigues(rvec, r);
    Eigen::Matrix3d rot;
    rot << r(0,0), r(0,1), r(0,2),
           r(1,0), r(1,1), r(1,2),
           r(2,0), r(2,1), r(2,2);

    Eigen::Matrix4d T;
    T.topLeftCorner(3,3) = rot;
    T.col(3).head(3) <<
            tvec.at<double>(0), tvec.at<double>(1), tvec.at<double>(2);
    T.row(3) << 0,0,0,1;

    return T;
}

// Callback for camera info
void InfoCallback(const sensor_msgs::CameraInfoConstPtr& camera_info)
{
    camera_info_ = (*camera_info);
    has_camera_info_ = true;
}

// Callback for image data
void ImageCallback(const sensor_msgs::ImageConstPtr& msg )
{
    if(!has_camera_info_){
        ROS_WARN("No Camera Info Received Yet");
        return;
    }

    // Get the image
    cv_bridge::CvImagePtr subscribed_ptr;
    try
    {
        subscribed_ptr = cv_bridge::toCvCopy(msg, "mono8");
    }
    catch(cv_bridge::Exception& e)
    {
        ROS_ERROR("cv_bridge exception: %s", e.what());
        return;
    }

    cv::Mat subscribed_gray = subscribed_ptr->image;
    cv::Mat tmp;
    cv::Point2d opticalCenter(0.5*subscribed_gray.rows,
                              0.5*subscribed_gray.cols);
    TagDetectionArray detections;
    detector_->process(subscribed_gray, opticalCenter, detections);
    visualization_msgs::MarkerArray marker_transforms;

    if(viewer_)
    {
        subscribed_gray = family_->superimposeDetections(subscribed_gray,
                                                         detections);
    }
    for(unsigned int i = 0; i < detections.size(); ++i)
    {
        Eigen::Matrix4d pose = GetDetectionTransform(detections[i]);

        // Get this info from earlier code, don't extract it again
        Eigen::Matrix3d R = pose.block<3,3>(0,0);
        Eigen::Quaternion<double> q(R);

        visualization_msgs::Marker marker_transform;
        marker_transform.header.frame_id = frame_;
        marker_transform.header.stamp = ros::Time::now();
        stringstream convert;
        convert << "tag" << detections[i].id;
        marker_transform.ns = convert.str().c_str();
        marker_transform.id = detections[i].id;
        marker_transform.type = visualization_msgs::Marker::ARROW;
        //marker_transform.type = visualization_msgs::Marker::CUBE;
        marker_transform.action = visualization_msgs::Marker::ADD;
        marker_transform.pose.position.x = pose(0,3);
        marker_transform.pose.position.y = pose(1,3);
        marker_transform.pose.position.z = pose(2,3);
        marker_transform.pose.orientation.x = q.x();
        marker_transform.pose.orientation.y = q.y();
        marker_transform.pose.orientation.z = q.z();
        marker_transform.pose.orientation.w = q.w();

    	double tag_size = GetTagSize(detections[i].id);
        /*
        marker_transform.scale.x = tag_size;
        marker_transform.scale.y = tag_size;
        marker_transform.scale.z = 0.01 * tag_size;
        */
        marker_transform.scale.x = tag_size;
        marker_transform.scale.y = tag_size*10;
        marker_transform.scale.z = tag_size*0.5;

        marker_transform.color.r = 1.0;
        marker_transform.color.g = 0.0;
        marker_transform.color.b = 1.0;
        marker_transform.color.a = 1.0;
        marker_transforms.markers.push_back(marker_transform);
    }
    marker_publisher_.publish(marker_transforms);

    if(viewer_)
    {
        cv::imshow("AprilTags", subscribed_gray);
    }
}

void ConnectCallback(const ros::SingleSubscriberPublisher& info)
{
    // Check for subscribers.
    uint32_t subscribers = marker_publisher_.getNumSubscribers();
    ROS_DEBUG("Subscription detected! (%d subscribers)", subscribers);

    if(subscribers && !running_)
    {
        ROS_DEBUG("New Subscribers, Connecting to Input Image Topic.");
        ros::TransportHints ros_transport_hints(ros::TransportHints().tcpNoDelay());
        image_transport::TransportHints image_transport_hint(image_transport::TransportHints(
                                "raw", ros_transport_hints, (*node_),
                                "image_transport"));

        image_subscriber = (*image_).subscribe(
                DEFAULT_IMAGE_TOPIC, 1, &ImageCallback,
                image_transport_hint);
        info_subscriber = (*node_).subscribe(
                DEFAULT_CAMERA_INFO_TOPIC, 10, &InfoCallback);
        running_ = true;
    }
}

void DisconnectHandler()
{
}

void DisconnectCallback(const ros::SingleSubscriberPublisher& info)
{
    // Check for subscribers.
    uint32_t subscribers = marker_publisher_.getNumSubscribers();
    ROS_DEBUG("Unsubscription detected! (%d subscribers)", subscribers);

    if(!subscribers && running_)
    {
        ROS_DEBUG("No Subscribers, Disconnecting from Input Image Topic.");
		image_subscriber.shutdown();
		info_subscriber.shutdown();
		running_ = false;
    }
}

void GetParameterValues()
{
    // Load node-wide configuration values.
    node_->param("viewer", viewer_, 0);
    node_->param("tag_family", tag_family_name_, DEFAULT_TAG_FAMILY);
    node_->param("default_tag_size", default_tag_size_, DEFAULT_TAG_SIZE);
    node_->param("tf_frame", frame_, DEFAULT_TF_FRAME);

    // Load tag specific configuration values.
    XmlRpc::XmlRpcValue tag_data;
    node_->param("tag_data", tag_data, tag_data);

    // Iterate through each tag in the configuration.
    XmlRpc::XmlRpcValue::ValueStruct::iterator it;
    for (it = tag_data.begin(); it != tag_data.end(); ++it)
    {
        // Retrieve the settings for the next tag.
        int tag_id = boost::lexical_cast<int>(it->first);
        XmlRpc::XmlRpcValue tag_values = it->second;

        // Load all the settings for this tag.
        if (tag_values.hasMember("size"))
        {
            tag_sizes_[tag_id] = static_cast<double>(tag_values["size"]);
            ROS_DEBUG("Setting tag%d to size %f m.", tag_id, tag_sizes_[tag_id]);
        }
    }
}

void SetupPublisher()
{
    ros::SubscriberStatusCallback connect_callback = &ConnectCallback;
    ros::SubscriberStatusCallback disconnect_callback = &DisconnectCallback;

    // Publisher
    marker_publisher_ = node_->advertise<visualization_msgs::MarkerArray>(
            DEFAULT_MARKER_TOPIC, 1, connect_callback,
            disconnect_callback);
}

void InitializeTags()
{
    tag_params.newQuadAlgorithm = 1;
    family_ = new TagFamily(tag_family_name_);
    detector_ = new TagDetector(*family_, tag_params);
}

void InitializeROSNode(int argc, char **argv)
{
    ros::init(argc, argv, "apriltags");
    node_ =  boost::make_shared<ros::NodeHandle>("~");
    image_ = boost::make_shared<image_transport::ImageTransport>(*node_);
}

int main(int argc, char **argv)
{
    InitializeROSNode(argc,argv);
    GetParameterValues();
    SetupPublisher();
    InitializeTags();

    if(viewer_){
        cvNamedWindow("AprilTags");
        cvStartWindowThread();
    }

    ROS_INFO("AprilTags node started.");
    running_ = false;
    has_camera_info_ = false;
    ros::spin();
    ROS_INFO("AprilTags node stopped.");

    //Destroying Stuff
    cvDestroyWindow("AprilTags");
    delete detector_;
    delete family_;

    return EXIT_SUCCESS;
}
<commit_msg>testing sizes<commit_after>#include <ros/ros.h>
#include <ros/forwards.h>
#include <ros/single_subscriber_publisher.h>
#include <sensor_msgs/Image.h>
#include <image_transport/image_transport.h>
#include <visualization_msgs/Marker.h>
#include <opencv/cv.h>
#include <opencv/highgui.h>
#include <cv_bridge/cv_bridge.h>

#include <src/TagDetector.h>
#include <src/TagDetection.h>
#include <src/TagFamily.h>

#include <Eigen/Core>
#include <Eigen/Geometry>

#include <visualization_msgs/MarkerArray.h>
#include "yaml-cpp/yaml.h"
#include <sstream>
#include <fstream>

#include <boost/unordered_set.hpp>
#include <boost/unordered_map.hpp>
#include <boost/make_shared.hpp>

#include "apriltags.h"

using namespace std;

// Functions

double GetTagSize(int tag_id)
{
    boost::unordered_map<size_t, double>::iterator tag_sizes_it =
        tag_sizes_.find(tag_id);
    if(tag_sizes_it != tag_sizes_.end()) {
        return tag_sizes_it->second;
    } else {
        return default_tag_size_;
    }
}

Eigen::Matrix4d GetDetectionTransform(TagDetection detection)
{
    double tag_size = GetTagSize(detection.id);

    std::vector<cv::Point3f> object_pts;
    std::vector<cv::Point2f> image_pts;
    double tag_radius = tag_size/2.;

    object_pts.push_back(cv::Point3f(-tag_radius, -tag_radius, 0));
    object_pts.push_back(cv::Point3f( tag_radius, -tag_radius, 0));
    object_pts.push_back(cv::Point3f( tag_radius,  tag_radius, 0));
    object_pts.push_back(cv::Point3f(-tag_radius,  tag_radius, 0));

    image_pts.push_back(detection.p[0]);
    image_pts.push_back(detection.p[1]);
    image_pts.push_back(detection.p[2]);
    image_pts.push_back(detection.p[3]);

    cv::Matx33f intrinsics(camera_info_.K[0], 0, camera_info_.K[2],
                           0, camera_info_.K[4], camera_info_.K[5],
                           0, 0, 1);

    cv::Mat rvec, tvec;
    cv::Vec4f dist_param(0,0,0,0);
    cv::solvePnP(object_pts, image_pts, intrinsics, dist_param,
            rvec, tvec);
    cv::Matx33d r;
    cv::Rodrigues(rvec, r);
    Eigen::Matrix3d rot;
    rot << r(0,0), r(0,1), r(0,2),
           r(1,0), r(1,1), r(1,2),
           r(2,0), r(2,1), r(2,2);

    Eigen::Matrix4d T;
    T.topLeftCorner(3,3) = rot;
    T.col(3).head(3) <<
            tvec.at<double>(0), tvec.at<double>(1), tvec.at<double>(2);
    T.row(3) << 0,0,0,1;

    return T;
}

// Callback for camera info
void InfoCallback(const sensor_msgs::CameraInfoConstPtr& camera_info)
{
    camera_info_ = (*camera_info);
    has_camera_info_ = true;
}

// Callback for image data
void ImageCallback(const sensor_msgs::ImageConstPtr& msg )
{
    if(!has_camera_info_){
        ROS_WARN("No Camera Info Received Yet");
        return;
    }

    // Get the image
    cv_bridge::CvImagePtr subscribed_ptr;
    try
    {
        subscribed_ptr = cv_bridge::toCvCopy(msg, "mono8");
    }
    catch(cv_bridge::Exception& e)
    {
        ROS_ERROR("cv_bridge exception: %s", e.what());
        return;
    }

    cv::Mat subscribed_gray = subscribed_ptr->image;
    cv::Mat tmp;
    cv::Point2d opticalCenter(0.5*subscribed_gray.rows,
                              0.5*subscribed_gray.cols);
    TagDetectionArray detections;
    detector_->process(subscribed_gray, opticalCenter, detections);
    visualization_msgs::MarkerArray marker_transforms;

    if(viewer_)
    {
        subscribed_gray = family_->superimposeDetections(subscribed_gray,
                                                         detections);
    }
    for(unsigned int i = 0; i < detections.size(); ++i)
    {
        Eigen::Matrix4d pose = GetDetectionTransform(detections[i]);

        // Get this info from earlier code, don't extract it again
        Eigen::Matrix3d R = pose.block<3,3>(0,0);
        Eigen::Quaternion<double> q(R);

        visualization_msgs::Marker marker_transform;
        marker_transform.header.frame_id = frame_;
        marker_transform.header.stamp = ros::Time::now();
        stringstream convert;
        convert << "tag" << detections[i].id;
        marker_transform.ns = convert.str().c_str();
        marker_transform.id = detections[i].id;
        marker_transform.type = visualization_msgs::Marker::ARROW;
        //marker_transform.type = visualization_msgs::Marker::CUBE;
        marker_transform.action = visualization_msgs::Marker::ADD;
        marker_transform.pose.position.x = pose(0,3);
        marker_transform.pose.position.y = pose(1,3);
        marker_transform.pose.position.z = pose(2,3);
        marker_transform.pose.orientation.x = q.x();
        marker_transform.pose.orientation.y = q.y();
        marker_transform.pose.orientation.z = q.z();
        marker_transform.pose.orientation.w = q.w();

    	double tag_size = GetTagSize(detections[i].id);
        /*
        marker_transform.scale.x = tag_size;
        marker_transform.scale.y = tag_size;
        marker_transform.scale.z = 0.01 * tag_size;
        */
        marker_transform.scale.x = tag_size;
        marker_transform.scale.y = tag_size*10;
        marker_transform.scale.z = tag_size*0.5;

        marker_transform.color.r = 1.0;
        marker_transform.color.g = 0.0;
        marker_transform.color.b = 1.0;
        marker_transform.color.a = 1.0;
        marker_transforms.markers.push_back(marker_transform);
    }
    marker_publisher_.publish(marker_transforms);

    if(viewer_)
    {
        cv::imshow("AprilTags", subscribed_gray);
    }
}

void ConnectCallback(const ros::SingleSubscriberPublisher& info)
{
    // Check for subscribers.
    uint32_t subscribers = marker_publisher_.getNumSubscribers();
    ROS_DEBUG("Subscription detected! (%d subscribers)", subscribers);

    if(subscribers && !running_)
    {
        ROS_DEBUG("New Subscribers, Connecting to Input Image Topic.");
        ros::TransportHints ros_transport_hints(ros::TransportHints().tcpNoDelay());
        image_transport::TransportHints image_transport_hint(image_transport::TransportHints(
                                "raw", ros_transport_hints, (*node_),
                                "image_transport"));

        image_subscriber = (*image_).subscribe(
                DEFAULT_IMAGE_TOPIC, 1, &ImageCallback,
                image_transport_hint);
        info_subscriber = (*node_).subscribe(
                DEFAULT_CAMERA_INFO_TOPIC, 10, &InfoCallback);
        running_ = true;
    }
}

void DisconnectHandler()
{
}

void DisconnectCallback(const ros::SingleSubscriberPublisher& info)
{
    // Check for subscribers.
    uint32_t subscribers = marker_publisher_.getNumSubscribers();
    ROS_DEBUG("Unsubscription detected! (%d subscribers)", subscribers);

    if(!subscribers && running_)
    {
        ROS_DEBUG("No Subscribers, Disconnecting from Input Image Topic.");
		image_subscriber.shutdown();
		info_subscriber.shutdown();
		running_ = false;
    }
}

void GetParameterValues()
{
    // Load node-wide configuration values.
    node_->param("viewer", viewer_, 0);
    node_->param("tag_family", tag_family_name_, DEFAULT_TAG_FAMILY);
    node_->param("default_tag_size", default_tag_size_, DEFAULT_TAG_SIZE);
    node_->param("tf_frame", frame_, DEFAULT_TF_FRAME);

    // Load tag specific configuration values.
    XmlRpc::XmlRpcValue tag_data;
    node_->param("tag_data", tag_data, tag_data);

    // Iterate through each tag in the configuration.
    XmlRpc::XmlRpcValue::ValueStruct::iterator it;
    for (it = tag_data.begin(); it != tag_data.end(); ++it)
    {
        // Retrieve the settings for the next tag.
        int tag_id = boost::lexical_cast<int>(it->first);
        XmlRpc::XmlRpcValue tag_values = it->second;

        // Load all the settings for this tag.
        if (tag_values.hasMember("size"))
        {
            tag_sizes_[tag_id] = static_cast<double>(tag_values["size"]);
            ROS_DEBUG("Setting tag%d to size %f m.", tag_id, tag_sizes_[tag_id]);
        }
    }
}

void SetupPublisher()
{
    ros::SubscriberStatusCallback connect_callback = &ConnectCallback;
    ros::SubscriberStatusCallback disconnect_callback = &DisconnectCallback;

    // Publisher
    marker_publisher_ = node_->advertise<visualization_msgs::MarkerArray>(
            DEFAULT_MARKER_TOPIC, 1, connect_callback,
            disconnect_callback);
}

void InitializeTags()
{
    tag_params.newQuadAlgorithm = 1;
    family_ = new TagFamily(tag_family_name_);
    detector_ = new TagDetector(*family_, tag_params);
}

void InitializeROSNode(int argc, char **argv)
{
    ros::init(argc, argv, "apriltags");
    node_ =  boost::make_shared<ros::NodeHandle>("~");
    image_ = boost::make_shared<image_transport::ImageTransport>(*node_);
}

int main(int argc, char **argv)
{
    InitializeROSNode(argc,argv);
    GetParameterValues();
    SetupPublisher();
    InitializeTags();

    if(viewer_){
        cvNamedWindow("AprilTags");
        cvStartWindowThread();
    }

    ROS_INFO("AprilTags node started.");
    running_ = false;
    has_camera_info_ = false;
    ros::spin();
    ROS_INFO("AprilTags node stopped.");

    //Destroying Stuff
    cvDestroyWindow("AprilTags");
    delete detector_;
    delete family_;

    return EXIT_SUCCESS;
}
<|endoftext|>


<commit_before>#include <Script/NativeScriptApi.h>
#include <Actor/Player.h>
#include "Event/EventHelper.h"
#include <ScriptObject.h>

// Quest Script: SubSea001_00111
// Quest Name: Making a Name
// Quest ID: 65647
// Start NPC: 1002698
// End NPC: 1003604

class SubSea001 : public EventScript
{
private:
   // Basic quest information
   // Quest vars / flags used
   // GetQuestBitFlag8
   // GetQuestUI8AL
   // GetQuestUI8BH

   enum Sequence : uint8_t
   {
      Seq0 = 0,
      Seq1 = 1,
      Seq2 = 2,
      SeqFinish = 255,
   };

   // Quest rewards
   static constexpr auto RewardExpFactor = 50;
   static constexpr auto RewardItem = 4551;
   static constexpr auto RewardItemCount = 2;

   // Entities found in the script data of the quest
   static constexpr auto Actor0 = 1002698;
   static constexpr auto Actor1 = 1000969;
   static constexpr auto Actor2 = 1003604;
   static constexpr auto Eobject0 = 2001563;
   static constexpr auto Eobject1 = 2001564;
   static constexpr auto Eobject2 = 2001565;
   static constexpr auto Eobject3 = 2001566;
   static constexpr auto Eobject4 = 2001567;
   static constexpr auto Eobject5 = 2001568;
   static constexpr auto EventActionProcess = 14;
   static constexpr auto Item0 = 2000447;
   static constexpr auto Poprange0 = 4161445;
   static constexpr auto Quest0 = 65644;
   static constexpr auto Quest1 = 65645;
   static constexpr auto Territorytype0 = 129;

public:
   SubSea001() : EventScript(65647)
   {};
   ~SubSea001()
   {};

   void onTalk(uint32_t eventId, Entity::Player& player, uint64_t actorId ) override
   {
      auto actor = Event::mapEventActorToRealActor( static_cast< uint32_t >( actorId ) );
      auto currentCC = player.getQuestUI8AL( getId() );

      if( actor == Actor0 )
      {
         Scene00000( player );
      }
      else if( actor == Actor1 )
      {
         Scene00002( player );
      }
      else if( actor == Actor2 )
      {
         Scene00016( player );
      }
      //EOBJECTS CHECK
      else if( actor == Eobject0 )
      {
         player.eventActionStart( getId(), 0x0E,
            [&]( Entity::Player& player, uint32_t eventId, uint64_t additional )
            {
               Scene00003( player );
            },
               nullptr, eventId );
      }
      else if(actor == Eobject1 )
      {
         player.eventActionStart( getId(), 0x0E,
            [&]( Entity::Player& player, uint32_t eventId, uint64_t additional )
            {
               Scene00005( player );
            },
               nullptr, eventId );
      }
      else if( actor == Eobject2 )
      {
         player.eventActionStart( getId(), 0x0E,
            [&]( Entity::Player& player, uint32_t eventId, uint64_t additional )
            {
               Scene00007( player );
            },
               nullptr, eventId );
      }
      else if( actor == Eobject3 )
      {
         player.eventActionStart( getId(), 0x0E,
            [&]( Entity::Player& player, uint32_t eventId, uint64_t additional )
            {
               Scene00009( player );
            },
               nullptr, eventId );
      }
      else if( actor == Eobject4 )
      {
         player.eventActionStart( getId(), 0x0E,
            [&]( Entity::Player& player, uint32_t eventId, uint64_t additional )
            {
               Scene00011( player );
            },
               nullptr, eventId );
      }
      else if( actor == Eobject5 )
      {
         player.eventActionStart( getId(), 0x0E,
            [&]( Entity::Player& player, uint32_t eventId, uint64_t additional )
            {
               Scene00013( player );
            },
               nullptr, eventId );
      }
   };

private:

   void checkQuestcompletion( Entity::Player& player )
   {
      auto currentCC = player.getQuestUI8BH( getId() );

      player.sendQuestMessage( getId(), 1, 3, currentCC + 1, 6 );

      if( currentCC + 1 >= 6 )
      {
         player.updateQuest( getId(), SeqFinish );
         player.setQuestUI8BH(getId(), currentCC + 1);
         player.setQuestUI8AL(getId(), currentCC + 1);
      }
      else
      {
         player.setQuestUI8BH( getId(), currentCC + 1 );
         player.setQuestUI8AL( getId(), currentCC + 1 );
      }
   }

   void Scene00000( Entity::Player& player )
   {
      player.playScene( getId(), 0, HIDE_HOTBAR,
         [&]( Entity::Player& player, const Event::SceneResult& result )
         {
            if( result.param2 == 1 )
               player.updateQuest( getId(), 1 );
         } );
   }

   void Scene00001( Entity::Player& player )
   {
      player.playScene( getId(), 1, HIDE_HOTBAR,
         [&]( Entity::Player& player, const Event::SceneResult& result )
         {
         } );
   }

   void Scene00002( Entity::Player& player )
   {
      player.playScene( getId(), 2, HIDE_HOTBAR,
         [&]( Entity::Player& player, const Event::SceneResult& result )
         {
            if( player.hasQuest( 65644 ) || player.hasQuest( 65645 ) )
            {
               if( result.param2 == 1 )
               {
                  player.updateQuest( getId(), 2 );
                  player.changePosition( 10, 21, 13, -2 );
                  player.forceZoneing( Territorytype0 ); // teleport to real limsa
               }
            }
            else return;
         } );
   }

   void Scene00003( Entity::Player& player )
   {
      player.playScene( getId(), 3, HIDE_HOTBAR,
         [&]( Entity::Player& player, const Event::SceneResult& result )
         {
            Scene00004( player );
         } );
   }

   void Scene00004( Entity::Player& player )
   {
      player.playScene( getId(), 4, HIDE_HOTBAR,
         [&]( Entity::Player& player, const Event::SceneResult& result )
         {
            checkQuestcompletion( player );
            player.setQuestBitFlag8( getId(), 7, true );
         } );
   }

   void Scene00005( Entity::Player& player )
   {
      player.playScene( getId(), 5, HIDE_HOTBAR,
         [&]( Entity::Player& player, const Event::SceneResult& result )
         {
            Scene00006( player );
         } );
   }

   void Scene00006( Entity::Player& player )
   {
      player.playScene( getId(), 6, HIDE_HOTBAR,
         [&]( Entity::Player& player, const Event::SceneResult& result )
         {
            checkQuestcompletion( player );
            player.setQuestBitFlag8( getId(), 6, true );
         } );
   }

   void Scene00007( Entity::Player& player )
   {
      player.playScene( getId(), 7, HIDE_HOTBAR,
         [&]( Entity::Player& player, const Event::SceneResult& result )
         {
            Scene00008( player );
         } );
   }

   void Scene00008( Entity::Player& player )
   {
      player.playScene( getId(), 8, HIDE_HOTBAR,
         [&]( Entity::Player& player, const Event::SceneResult& result )
         {
            checkQuestcompletion( player );
            player.setQuestBitFlag8( getId(), 5, true );
         } );
   }

   void Scene00009( Entity::Player& player )
   {
      player.playScene( getId(), 9, HIDE_HOTBAR,
         [&]( Entity::Player& player, const Event::SceneResult& result )
         {
            Scene00010( player );
         } );
   }

   void Scene00010( Entity::Player& player )
   {
      player.playScene( getId(), 10, HIDE_HOTBAR,
         [&]( Entity::Player& player, const Event::SceneResult& result )
         {
            checkQuestcompletion( player );
            player.setQuestBitFlag8( getId(), 4, true );
         } );
   }

   void Scene00011( Entity::Player& player )
   {
      player.playScene( getId(), 11, HIDE_HOTBAR,
         [&]( Entity::Player& player, const Event::SceneResult& result )
         {
            Scene00012( player );
         } );
   }

   void Scene00012( Entity::Player& player )
   {
      player.playScene( getId(), 12, HIDE_HOTBAR,
         [&]( Entity::Player& player, const Event::SceneResult& result )
         {
            checkQuestcompletion( player );
            player.setQuestBitFlag8( getId(), 3, true );
         } );
   }

   void Scene00013( Entity::Player& player )
   {
      player.playScene( getId(), 13, HIDE_HOTBAR,
         [&]( Entity::Player& player, const Event::SceneResult& result )
         {
            Scene00014( player );
         } );
   }

   void Scene00014( Entity::Player& player )
   {
      player.playScene( getId(), 14, HIDE_HOTBAR,
         [&]( Entity::Player& player, const Event::SceneResult& result )
         {
            checkQuestcompletion( player );
            player.setQuestBitFlag8( getId(), 2, true );
         } );
   }

   void Scene00015( Entity::Player& player )
   {
      player.playScene( getId(), 15, HIDE_HOTBAR,
         [&]( Entity::Player& player, const Event::SceneResult& result )
         {
            player.playScene( getId(), 15, 0, 0, 0 );
         } );
   }

   void Scene00016( Entity::Player& player )
   {
      player.playScene( getId(), 16, HIDE_HOTBAR,
         [&]( Entity::Player& player, const Event::SceneResult& result )
         {
            if( result.param2 == 1 )
            {
               Scene00017( player );
            }
         } );
   }

   void Scene00017( Entity::Player& player )
   {
      player.playScene( getId(), 17, HIDE_HOTBAR,
         [&]( Entity::Player& player, const Event::SceneResult& result )
      {
         if( result.param2 == 1 )
         {
            if( player.giveQuestRewards( getId(), 0 ) )
               player.finishQuest( getId() );
         }
       } );
   }
};

<commit_msg>fix formatting<commit_after>#include <Script/NativeScriptApi.h>
#include <Actor/Player.h>
#include "Event/EventHelper.h"
#include <ScriptObject.h>

// Quest Script: SubSea001_00111
// Quest Name: Making a Name
// Quest ID: 65647
// Start NPC: 1002698
// End NPC: 1003604

class SubSea001 : public EventScript
{
private:
   // Basic quest information
   // Quest vars / flags used
   // GetQuestBitFlag8
   // GetQuestUI8AL
   // GetQuestUI8BH

   enum Sequence : uint8_t
   {
      Seq0 = 0,
      Seq1 = 1,
      Seq2 = 2,
      SeqFinish = 255,
   };

   // Quest rewards
   static constexpr auto RewardExpFactor = 50;
   static constexpr auto RewardItem = 4551;
   static constexpr auto RewardItemCount = 2;

   // Entities found in the script data of the quest
   static constexpr auto Actor0 = 1002698;
   static constexpr auto Actor1 = 1000969;
   static constexpr auto Actor2 = 1003604;
   static constexpr auto Eobject0 = 2001563;
   static constexpr auto Eobject1 = 2001564;
   static constexpr auto Eobject2 = 2001565;
   static constexpr auto Eobject3 = 2001566;
   static constexpr auto Eobject4 = 2001567;
   static constexpr auto Eobject5 = 2001568;
   static constexpr auto EventActionProcess = 14;
   static constexpr auto Item0 = 2000447;
   static constexpr auto Poprange0 = 4161445;
   static constexpr auto Quest0 = 65644;
   static constexpr auto Quest1 = 65645;
   static constexpr auto Territorytype0 = 129;

public:
   SubSea001() : EventScript(65647)
   {};
   ~SubSea001()
   {};

   void onTalk(uint32_t eventId, Entity::Player& player, uint64_t actorId ) override
   {
      auto actor = Event::mapEventActorToRealActor( static_cast< uint32_t >( actorId ) );
      auto currentCC = player.getQuestUI8AL( getId() );

      if( actor == Actor0 )
      {
         Scene00000( player );
      }
      else if( actor == Actor1 )
      {
         Scene00002( player );
      }
      else if( actor == Actor2 )
      {
         Scene00016( player );
      }
      //EOBJECTS CHECK
      else if( actor == Eobject0 )
      {
         player.eventActionStart( getId(), 0x0E,
            [&]( Entity::Player& player, uint32_t eventId, uint64_t additional )
            {
               Scene00003( player );
            },
            nullptr, eventId );
      }
      else if( actor == Eobject1 )
      {
         player.eventActionStart( getId(), 0x0E,
            [&]( Entity::Player& player, uint32_t eventId, uint64_t additional )
            {
               Scene00005( player );
            },
            nullptr, eventId );
      }
      else if( actor == Eobject2 )
      {
         player.eventActionStart( getId(), 0x0E,
            [&]( Entity::Player& player, uint32_t eventId, uint64_t additional )
            {
               Scene00007( player );
            },
            nullptr, eventId );
      }
      else if( actor == Eobject3 )
      {
         player.eventActionStart( getId(), 0x0E,
            [&]( Entity::Player& player, uint32_t eventId, uint64_t additional )
            {
               Scene00009( player );
            },
            nullptr, eventId );
      }
      else if( actor == Eobject4 )
      {
         player.eventActionStart( getId(), 0x0E,
            [&]( Entity::Player& player, uint32_t eventId, uint64_t additional )
            {
               Scene00011( player );
            },
               nullptr, eventId );
      }
      else if( actor == Eobject5 )
      {
         player.eventActionStart( getId(), 0x0E,
            [&]( Entity::Player& player, uint32_t eventId, uint64_t additional )
            {
               Scene00013( player );
            },
            nullptr, eventId );
      }
   };

private:

   void checkQuestCompletion( Entity::Player& player )
   {
      auto currentCC = player.getQuestUI8BH( getId() );

      player.sendQuestMessage( getId(), 1, 3, currentCC + 1, 6 );

      if( currentCC + 1 >= 6 )
      {
         player.updateQuest( getId(), SeqFinish );
         player.setQuestUI8BH(getId(), currentCC + 1);
         player.setQuestUI8AL(getId(), currentCC + 1);
      }
      else
      {
         player.setQuestUI8BH( getId(), currentCC + 1 );
         player.setQuestUI8AL( getId(), currentCC + 1 );
      }
   }

   void Scene00000( Entity::Player& player )
   {
      player.playScene( getId(), 0, HIDE_HOTBAR,
         [&]( Entity::Player& player, const Event::SceneResult& result )
         {
            if( result.param2 == 1 )
               player.updateQuest( getId(), 1 );
         } );
   }

   void Scene00001( Entity::Player& player )
   {
      player.playScene( getId(), 1, HIDE_HOTBAR,
         [&]( Entity::Player& player, const Event::SceneResult& result )
         {
         } );
   }

   void Scene00002( Entity::Player& player )
   {
      player.playScene( getId(), 2, HIDE_HOTBAR,
         [&]( Entity::Player& player, const Event::SceneResult& result )
         {
            if( player.hasQuest( Quest0 ) || player.hasQuest( Quest1 ) )
            {
               if( result.param2 == 1 )
               {
                  player.updateQuest( getId(), 2 );
                  player.changePosition( 10, 21, 13, -2 );
                  player.forceZoneing( Territorytype0 ); // teleport to real limsa
               }
            }
            else return;
         } );
   }

   void Scene00003( Entity::Player& player )
   {
      player.playScene( getId(), 3, HIDE_HOTBAR,
         [&]( Entity::Player& player, const Event::SceneResult& result )
         {
            Scene00004( player );
         } );
   }

   void Scene00004( Entity::Player& player )
   {
      player.playScene( getId(), 4, HIDE_HOTBAR,
         [&]( Entity::Player& player, const Event::SceneResult& result )
         {
            checkQuestCompletion( player );
            player.setQuestBitFlag8( getId(), 7, true );
         } );
   }

   void Scene00005( Entity::Player& player )
   {
      player.playScene( getId(), 5, HIDE_HOTBAR,
         [&]( Entity::Player& player, const Event::SceneResult& result )
         {
            Scene00006( player );
         } );
   }

   void Scene00006( Entity::Player& player )
   {
      player.playScene( getId(), 6, HIDE_HOTBAR,
         [&]( Entity::Player& player, const Event::SceneResult& result )
         {
            checkQuestCompletion( player );
            player.setQuestBitFlag8( getId(), 6, true );
         } );
   }

   void Scene00007( Entity::Player& player )
   {
      player.playScene( getId(), 7, HIDE_HOTBAR,
         [&]( Entity::Player& player, const Event::SceneResult& result )
         {
            Scene00008( player );
         } );
   }

   void Scene00008( Entity::Player& player )
   {
      player.playScene( getId(), 8, HIDE_HOTBAR,
         [&]( Entity::Player& player, const Event::SceneResult& result )
         {
            checkQuestCompletion( player );
            player.setQuestBitFlag8( getId(), 5, true );
         } );
   }

   void Scene00009( Entity::Player& player )
   {
      player.playScene( getId(), 9, HIDE_HOTBAR,
         [&]( Entity::Player& player, const Event::SceneResult& result )
         {
            Scene00010( player );
         } );
   }

   void Scene00010( Entity::Player& player )
   {
      player.playScene( getId(), 10, HIDE_HOTBAR,
         [&]( Entity::Player& player, const Event::SceneResult& result )
         {
            checkQuestCompletion( player );
            player.setQuestBitFlag8( getId(), 4, true );
         } );
   }

   void Scene00011( Entity::Player& player )
   {
      player.playScene( getId(), 11, HIDE_HOTBAR,
         [&]( Entity::Player& player, const Event::SceneResult& result )
         {
            Scene00012( player );
         } );
   }

   void Scene00012( Entity::Player& player )
   {
      player.playScene( getId(), 12, HIDE_HOTBAR,
         [&]( Entity::Player& player, const Event::SceneResult& result )
         {
            checkQuestCompletion( player );
            player.setQuestBitFlag8( getId(), 3, true );
         } );
   }

   void Scene00013( Entity::Player& player )
   {
      player.playScene( getId(), 13, HIDE_HOTBAR,
         [&]( Entity::Player& player, const Event::SceneResult& result )
         {
            Scene00014( player );
         } );
   }

   void Scene00014( Entity::Player& player )
   {
      player.playScene( getId(), 14, HIDE_HOTBAR,
         [&]( Entity::Player& player, const Event::SceneResult& result )
         {
            checkQuestCompletion( player );
            player.setQuestBitFlag8( getId(), 2, true );
         } );
   }

   void Scene00015( Entity::Player& player )
   {
      player.playScene( getId(), 15, HIDE_HOTBAR,
         [&]( Entity::Player& player, const Event::SceneResult& result )
         {
            player.playScene( getId(), 15, 0, 0, 0 );
         } );
   }

   void Scene00016( Entity::Player& player )
   {
      player.playScene( getId(), 16, HIDE_HOTBAR,
         [&]( Entity::Player& player, const Event::SceneResult& result )
         {
            if( result.param2 == 1 )
            {
               Scene00017( player );
            }
         } );
   }

   void Scene00017( Entity::Player& player )
   {
      player.playScene( getId(), 17, HIDE_HOTBAR,
         [&]( Entity::Player& player, const Event::SceneResult& result )
      {
         if( result.param2 == 1 )
         {
            if( player.giveQuestRewards( getId(), 0 ) )
               player.finishQuest( getId() );
         }
       } );
   }
};

<|endoftext|>


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

#include <policy/feerate.h>

#include <tinyformat.h>

CFeeRate::CFeeRate(const CAmount& nFeePaid, size_t nBytes_)
{
    if(nBytes_ < 0 || nFeePaid < 0 || nFeePaid > int64_t(std::numeric_limits<int64_t>::max()/1000))
        return;
    int64_t nSize = int64_t(nBytes_);

    if (nSize > 0)
        nSatoshisPerK = nFeePaid * 1000 / nSize;
    else
        nSatoshisPerK = 0;
}

CAmount CFeeRate::GetFee(size_t nBytes_) const
{
    if(nBytes_ > uint64_t(std::numeric_limits<int64_t>::max()/1000))
        return 0;
    if(nSatoshisPerK > std::numeric_limits<int64_t>::max()/1000)
        return 0;

    int64_t nSize = int64_t(nBytes_);

    CAmount nFee = nSatoshisPerK * nSize / 1000;

    if (nFee == 0 && nSize != 0) {
        if (nSatoshisPerK > 0)
            nFee = CAmount(1);
        if (nSatoshisPerK < 0)
            nFee = CAmount(-1);
    }

    return nFee;
}

std::string CFeeRate::ToString(const FeeEstimateMode& fee_estimate_mode) const
{
    switch (fee_estimate_mode) {
    case FeeEstimateMode::SAT_B:  return strprintf("%d.%03d %s/B", nSatoshisPerK / 1000, nSatoshisPerK % 1000, CURRENCY_ATOM);
    default:                      return strprintf("%d.%08d %s/kB", nSatoshisPerK / COIN, nSatoshisPerK % COIN, CURRENCY_UNIT);
    }
}
<commit_msg>Update feerate.cpp<commit_after>// Copyright (c) 2009-2010 Satoshi Nakamoto
// Copyright (c) 2009-2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#include <policy/feerate.h>

#include <tinyformat.h>

CFeeRate::CFeeRate(const CAmount& nFeePaid, size_t nBytes_)
{
    if(nFeePaid < 0 || nFeePaid > int64_t(std::numeric_limits<int64_t>::max()/1000))
        return;
    int64_t nSize = int64_t(nBytes_);

    if (nSize > 0)
        nSatoshisPerK = nFeePaid * 1000 / nSize;
    else
        nSatoshisPerK = 0;
}

CAmount CFeeRate::GetFee(size_t nBytes_) const
{
    if(nBytes_ > uint64_t(std::numeric_limits<int64_t>::max()/1000))
        return 0;
    if(nSatoshisPerK > std::numeric_limits<int64_t>::max()/1000)
        return 0;

    int64_t nSize = int64_t(nBytes_);

    CAmount nFee = nSatoshisPerK * nSize / 1000;

    if (nFee == 0 && nSize != 0) {
        if (nSatoshisPerK > 0)
            nFee = CAmount(1);
        if (nSatoshisPerK < 0)
            nFee = CAmount(-1);
    }

    return nFee;
}

std::string CFeeRate::ToString(const FeeEstimateMode& fee_estimate_mode) const
{
    switch (fee_estimate_mode) {
    case FeeEstimateMode::SAT_B:  return strprintf("%d.%03d %s/B", nSatoshisPerK / 1000, nSatoshisPerK % 1000, CURRENCY_ATOM);
    default:                      return strprintf("%d.%08d %s/kB", nSatoshisPerK / COIN, nSatoshisPerK % COIN, CURRENCY_UNIT);
    }
}
<|endoftext|>


<commit_before>/*
    This file is part of Android File Transfer For Linux.
    Copyright (C) 2015-2018  Vladimir Menshakov

    This library is free software; you can redistribute it and/or modify it
    under the terms of the GNU Lesser General Public License as published by
    the Free Software Foundation; either version 2.1 of the License,
    or (at your option) any later version.

    This library is distributed in the hope that it will be useful, but
    WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
    Lesser General Public License for more details.

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

#include "mtpobjectsmodel.h"
#include "qtobjectstream.h"
#include "utils.h"
#include <QDebug>
#include <QBrush>
#include <QColor>
#include <QIcon>
#include <QFile>
#include <QFont>
#include <QFileInfo>
#include <QMimeData>
#include <QUrl>

#include <mtp/ptp/MemoryObjectStream.h>
#include <cli/PosixStreams.h> //for mtime

MtpObjectsModel::MtpObjectsModel(QObject *parent):
	QAbstractListModel(parent),
	_storageId(mtp::Session::AllStorages),
	_parentObjectId(mtp::Session::Root),
	_enableThumbnails(false)
{ }

MtpObjectsModel::~MtpObjectsModel()
{ }

void MtpObjectsModel::setStorageId(mtp::StorageId storageId)
{
	_storageId = storageId;
	setParent(mtp::Session::Root);
}

void MtpObjectsModel::setParent(mtp::ObjectId parentObjectId)
{
	beginResetModel();

	_parentObjectId = parentObjectId;
	mtp::msg::ObjectHandles handles;
	try
	{
		handles = _session->GetObjectHandles(_storageId, mtp::ObjectFormat::Any, parentObjectId);
	}
	catch(const std::exception & ex)
	{ qDebug() << "setParent failed:" << fromUtf8(ex.what()); }
	_rows.clear();
	_rows.reserve(handles.ObjectHandles.size());
	for(size_t i = 0; i < handles.ObjectHandles.size(); ++i)
	{
		mtp::ObjectId oid = handles.ObjectHandles[i];
		_rows.append(Row(oid));
	}

	endResetModel();
}

bool MtpObjectsModel::enter(int idx)
{
	if (idx < 0 || idx >= _rows.size())
		return false;

	Row &row = _rows[idx];
	if (row.IsAssociation(_session))
	{
		setParent(row.ObjectId);
		return true;
	}
	else
		return false;
}

QModelIndex MtpObjectsModel::findObject(mtp::ObjectId objectId) const
{
	auto idx = std::find_if(_rows.begin(), _rows.end(), [objectId](const Row & row) { return row.ObjectId == objectId; } );
	return idx != _rows.end()? createIndex(std::distance(_rows.begin(), idx), 0): QModelIndex();
}

QModelIndex MtpObjectsModel::findObject(const QString &filename) const
{
	auto idx = std::find_if(_rows.begin(), _rows.end(), [filename, this](Row & row) { return fromUtf8(row.GetInfo(_session)->Filename) == filename; } );
	return idx != _rows.end()? createIndex(std::distance(_rows.begin(), idx), 0): QModelIndex();
}

void MtpObjectsModel::setSession(mtp::SessionPtr session)
{
	beginResetModel();
	_session = session;
	setParent(mtp::Session::Root);
	endResetModel();
}

int MtpObjectsModel::rowCount(const QModelIndex &) const
{ return _rows.size(); }

mtp::msg::ObjectInfoPtr MtpObjectsModel::Row::GetInfo(mtp::SessionPtr session)
{
	if (!_info)
	{
		_info = std::make_shared<mtp::msg::ObjectInfo>();
		try
		{
			*_info = session->GetObjectInfo(ObjectId);
			//qDebug() << fromUtf8(row.Info->Filename);
		}
		catch(const std::exception &ex)
		{ qDebug() << "failed to get object info " << fromUtf8(ex.what()); }
	}
	return _info;
}

MtpObjectsModel::ThumbnailPtr MtpObjectsModel::Row::GetThumbnail(mtp::SessionPtr session, QSize maxSize)
{
	if (!_thumbnail)
	{
		auto stream = std::make_shared<mtp::MemoryObjectOutputStream>();
		_thumbnail = std::make_shared<QPixmap>();
		try
		{
			qDebug() << "requesting thumbnail for " << ObjectId.Id;
			session->GetThumb(ObjectId, stream);

			auto data = stream->GetData();
			QPixmap pixmap;
			if (!pixmap.loadFromData(data->data(), data->size()))
				throw std::runtime_error("couldn't load pixmap");

			*_thumbnail = pixmap.scaled(maxSize, Qt::KeepAspectRatio, Qt::SmoothTransformation);

			qDebug() << "loaded " << data->size() << " bytes of thumbnail data";
		}
		catch(const std::exception &ex)
		{
			qDebug() << "failed to get thumbnail" << fromUtf8(ex.what());
			*_thumbnail = QIcon::fromTheme("image-missing").pixmap(maxSize);
		}
	}
	return _thumbnail;
}

bool MtpObjectsModel::Row::IsAssociation(mtp::SessionPtr session)
{
	mtp::ObjectFormat format = GetInfo(session)->ObjectFormat;
	return format == mtp::ObjectFormat::Association || format == mtp::ObjectFormat::AudioAlbum;
}

void MtpObjectsModel::rename(int idx, const QString &fileName)
{
	qDebug() << "renaming row " << idx << " to " << fileName;
	_session->SetObjectProperty(objectIdAt(idx), mtp::ObjectProperty::ObjectFilename, toUtf8(fileName));
	_rows[idx].ResetInfo();
	emit dataChanged(createIndex(idx, 0), createIndex(idx, 0));
}

void MtpObjectsModel::deleteObjects(const MtpObjectList &objects)
{
	for(mtp::ObjectId objectId: objects)
	{
		try
		{
			qDebug() << "deleting object " << objectId;
			_session->DeleteObject(objectId);
		}
		catch(const std::exception &ex)
		{ qDebug() << "failed to delete object " << fromUtf8(ex.what()); }
	}
	refresh();
}

mtp::ObjectId MtpObjectsModel::objectIdAt(int idx)
{
	return (idx >= 0 && idx < _rows.size())? _rows[idx].ObjectId: mtp::ObjectId();
}

QVariant MtpObjectsModel::data(const QModelIndex &index, int role) const
{
	int row_idx = index.row();
	if (row_idx < 0 || row_idx > _rows.size())
		return QVariant();

	Row &row = _rows[row_idx];

	switch(role)
	{
	case Qt::ToolTipRole:
	case Qt::DisplayRole:
		return fromUtf8(row.GetInfo(_session)->Filename);

	case Qt::FontRole:
		{
			QFont font;
			if (row.IsAssociation(_session))
				font.setBold(true);
			return font;
		}

	case Qt::DecorationRole:
		if (_enableThumbnails)
			return *row.GetThumbnail(_session, QSize(_maxThumbnailSize.width(), _maxThumbnailSize.height() / 1.5f));
		else
			return QVariant();

	case Qt::SizeHintRole:
		if (_enableThumbnails)
			return _maxThumbnailSize;
		else
			return QVariant();

	default:
		return QVariant();
	}
}

mtp::ObjectId MtpObjectsModel::createDirectory(mtp::ObjectId parentObjectId, const QString &name, mtp::AssociationType type)
{
	QModelIndex existingDir = findObject(name);
	if (existingDir.isValid())
		return _rows.at(existingDir.row()).ObjectId;

	mtp::StorageId storageId = _storageId != mtp::Session::AllStorages? _storageId: mtp::Session::AnyStorage;
	mtp::Session::NewObjectInfo noi = _session->CreateDirectory(toUtf8(name), parentObjectId, storageId, type);
	if (parentObjectId == _parentObjectId)
	{
		beginInsertRows(QModelIndex(), _rows.size(), _rows.size());
		_rows.push_back(Row(noi.ObjectId));
		endInsertRows();
	}
	return noi.ObjectId;
}

bool MtpObjectsModel::uploadFile(mtp::ObjectId parentObjectId, const QString &filePath, QString filename)
{
	QFileInfo fileInfo(filePath);
	mtp::ObjectFormat objectFormat = mtp::ObjectFormatFromFilename(toUtf8(filePath));

	if (filename.isEmpty())
		filename = fileInfo.fileName();

	qDebug() << "uploadFile " << fileInfo.fileName() << " as " << filename;

	bool needReset = false;
	QModelIndex existingObject = findObject(filename);
	if (existingObject.isValid())
	{
		if (!emit existingFileOverwrite(filename))
		{
			qDebug() << "skipping, overwrite not confirmed";
			return false;
		}
		_session->DeleteObject(_rows.at(existingObject.row()).ObjectId);
		needReset = parentObjectId == _parentObjectId;
	}

	std::shared_ptr<QtObjectInputStream> object(new QtObjectInputStream(filePath));
	if (!object->Valid())
	{
		qWarning() << "file " << filePath << " could not be opened";
		return false;
	}
	qDebug() << "sending " << fileInfo.size() << " bytes";
	connect(object.get(), SIGNAL(positionChanged(qint64,qint64)), this, SIGNAL(filePositionChanged(qint64,qint64)));

	mtp::msg::ObjectInfo oi;
	oi.Filename = toUtf8(filename);
	oi.ObjectFormat = objectFormat;
	oi.SetSize(fileInfo.size());
	mtp::Session::NewObjectInfo noi = _session->SendObjectInfo(oi, _storageId != mtp::Session::AllStorages? _storageId: mtp::Session::AnyStorage, parentObjectId);
	qDebug() << "new object id: " << noi.ObjectId << ", sending...";
	_session->SendObject(object);
	qDebug() << "ok";
	if (parentObjectId == _parentObjectId)
	{
		beginInsertRows(QModelIndex(), _rows.size(), _rows.size());
		_rows.push_back(Row(noi.ObjectId));
		endInsertRows();
	}
	if (needReset)
		refresh();
	return true;
}

bool MtpObjectsModel::downloadFile(const QString &filePath, mtp::ObjectId objectId)
{
	auto object = std::make_shared<QtObjectOutputStream>(filePath);
	if (!object->Valid())
	{
		qWarning() << "cannot open file " << filePath;
		return false;
	}
	connect(object.get(), SIGNAL(positionChanged(qint64,qint64)), this, SIGNAL(filePositionChanged(qint64,qint64)));
	_session->GetObject(objectId, object);
	object.reset();
	cli::ObjectOutputStream::SetModificationTime(filePath.toStdString(), _session->GetObjectModificationTime(objectId));
	return true;
}

MtpObjectsModel::ObjectInfo MtpObjectsModel::getInfoById(mtp::ObjectId objectId) const
{
	mtp::msg::ObjectInfo oi(_session->GetObjectInfo(objectId));
	qint64 size = oi.ObjectCompressedSize;
	if (size == mtp::MaxObjectSize)
		size = _session->GetObjectIntegerProperty(objectId, mtp::ObjectProperty::ObjectSize);
	return ObjectInfo(fromUtf8(oi.Filename), oi.ObjectFormat, size);
}

QStringList MtpObjectsModel::extractMimeData(const QMimeData *data)
{
	QStringList files;
	QList<QUrl> urls = data->urls();
	for (auto url : urls)
	{
		//qDebug() << "url " << url;
		if (url.isLocalFile())
			files.push_back(url.toLocalFile());
		else
			qWarning() << "skipping non-local url" << url;
	}
	return files;
}

bool MtpObjectsModel::dropMimeData(const QMimeData *data,
	 Qt::DropAction action, int row, int column, const QModelIndex &parent)
{
	qDebug() << "data: " << data << action << row << column;
	if (action != Qt::CopyAction || !data)
		return false;

	QStringList files = extractMimeData(data);
	qDebug() << "files dropped: " << files;
	emit onFilesDropped(files);
	return true;
}

QStringList MtpObjectsModel::mimeTypes () const
{ return QStringList("text/uri-list"); }

Qt::ItemFlags MtpObjectsModel::flags(const QModelIndex &index) const
{
	Qt::ItemFlags defaultFlags = QAbstractListModel::flags(index);
	return defaultFlags | Qt::ItemIsDropEnabled;
}

void MtpObjectsModel::enableThumbnail(bool enable, QSize maxSize)
{
	beginResetModel();

	_enableThumbnails = enable;
	_maxThumbnailSize = maxSize;

	endResetModel();
}
<commit_msg>added try/catch around most of the session method calls<commit_after>/*
    This file is part of Android File Transfer For Linux.
    Copyright (C) 2015-2018  Vladimir Menshakov

    This library is free software; you can redistribute it and/or modify it
    under the terms of the GNU Lesser General Public License as published by
    the Free Software Foundation; either version 2.1 of the License,
    or (at your option) any later version.

    This library is distributed in the hope that it will be useful, but
    WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
    Lesser General Public License for more details.

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

#include "mtpobjectsmodel.h"
#include "qtobjectstream.h"
#include "utils.h"
#include <QDebug>
#include <QBrush>
#include <QColor>
#include <QIcon>
#include <QFile>
#include <QFont>
#include <QFileInfo>
#include <QMimeData>
#include <QUrl>

#include <mtp/ptp/MemoryObjectStream.h>
#include <cli/PosixStreams.h> //for mtime

MtpObjectsModel::MtpObjectsModel(QObject *parent):
	QAbstractListModel(parent),
	_storageId(mtp::Session::AllStorages),
	_parentObjectId(mtp::Session::Root),
	_enableThumbnails(false)
{ }

MtpObjectsModel::~MtpObjectsModel()
{ }

void MtpObjectsModel::setStorageId(mtp::StorageId storageId)
{
	_storageId = storageId;
	setParent(mtp::Session::Root);
}

void MtpObjectsModel::setParent(mtp::ObjectId parentObjectId)
{
	beginResetModel();

	_parentObjectId = parentObjectId;
	mtp::msg::ObjectHandles handles;
	try
	{
		handles = _session->GetObjectHandles(_storageId, mtp::ObjectFormat::Any, parentObjectId);
	}
	catch(const std::exception & ex)
	{ qDebug() << "setParent failed:" << fromUtf8(ex.what()); }
	_rows.clear();
	_rows.reserve(handles.ObjectHandles.size());
	for(size_t i = 0; i < handles.ObjectHandles.size(); ++i)
	{
		mtp::ObjectId oid = handles.ObjectHandles[i];
		_rows.append(Row(oid));
	}

	endResetModel();
}

bool MtpObjectsModel::enter(int idx)
{
	if (idx < 0 || idx >= _rows.size())
		return false;

	Row &row = _rows[idx];
	if (row.IsAssociation(_session))
	{
		setParent(row.ObjectId);
		return true;
	}
	else
		return false;
}

QModelIndex MtpObjectsModel::findObject(mtp::ObjectId objectId) const
{
	auto idx = std::find_if(_rows.begin(), _rows.end(), [objectId](const Row & row) { return row.ObjectId == objectId; } );
	return idx != _rows.end()? createIndex(std::distance(_rows.begin(), idx), 0): QModelIndex();
}

QModelIndex MtpObjectsModel::findObject(const QString &filename) const
{
	auto idx = std::find_if(_rows.begin(), _rows.end(), [filename, this](Row & row) { return fromUtf8(row.GetInfo(_session)->Filename) == filename; } );
	return idx != _rows.end()? createIndex(std::distance(_rows.begin(), idx), 0): QModelIndex();
}

void MtpObjectsModel::setSession(mtp::SessionPtr session)
{
	beginResetModel();
	_session = session;
	setParent(mtp::Session::Root);
	endResetModel();
}

int MtpObjectsModel::rowCount(const QModelIndex &) const
{ return _rows.size(); }

mtp::msg::ObjectInfoPtr MtpObjectsModel::Row::GetInfo(mtp::SessionPtr session)
{
	if (!_info)
	{
		_info = std::make_shared<mtp::msg::ObjectInfo>();
		try
		{
			*_info = session->GetObjectInfo(ObjectId);
			//qDebug() << fromUtf8(row.Info->Filename);
		}
		catch(const std::exception &ex)
		{ qDebug() << "failed to get object info " << fromUtf8(ex.what()); }
	}
	return _info;
}

MtpObjectsModel::ThumbnailPtr MtpObjectsModel::Row::GetThumbnail(mtp::SessionPtr session, QSize maxSize)
{
	if (!_thumbnail)
	{
		auto stream = std::make_shared<mtp::MemoryObjectOutputStream>();
		_thumbnail = std::make_shared<QPixmap>();
		try
		{
			qDebug() << "requesting thumbnail for " << ObjectId.Id;
			session->GetThumb(ObjectId, stream);

			auto data = stream->GetData();
			QPixmap pixmap;
			if (!pixmap.loadFromData(data->data(), data->size()))
				throw std::runtime_error("couldn't load pixmap");

			*_thumbnail = pixmap.scaled(maxSize, Qt::KeepAspectRatio, Qt::SmoothTransformation);

			qDebug() << "loaded " << data->size() << " bytes of thumbnail data";
		}
		catch(const std::exception &ex)
		{
			qDebug() << "failed to get thumbnail" << fromUtf8(ex.what());
			*_thumbnail = QIcon::fromTheme("image-missing").pixmap(maxSize);
		}
	}
	return _thumbnail;
}

bool MtpObjectsModel::Row::IsAssociation(mtp::SessionPtr session)
{
	mtp::ObjectFormat format = GetInfo(session)->ObjectFormat;
	return format == mtp::ObjectFormat::Association || format == mtp::ObjectFormat::AudioAlbum;
}

void MtpObjectsModel::rename(int idx, const QString &fileName)
{
	qDebug() << "renaming row " << idx << " to " << fileName;
	try
	{
		_session->SetObjectProperty(objectIdAt(idx), mtp::ObjectProperty::ObjectFilename, toUtf8(fileName));
	}
	catch(const std::exception &ex)
	{ qDebug() << "failed to rename object" << fromUtf8(ex.what()); }

	_rows[idx].ResetInfo();
	emit dataChanged(createIndex(idx, 0), createIndex(idx, 0));
}

void MtpObjectsModel::deleteObjects(const MtpObjectList &objects)
{
	for(mtp::ObjectId objectId: objects)
	{
		try
		{
			qDebug() << "deleting object " << objectId;
			_session->DeleteObject(objectId);
		}
		catch(const std::exception &ex)
		{ qDebug() << "failed to delete object " << fromUtf8(ex.what()); }
	}
	refresh();
}

mtp::ObjectId MtpObjectsModel::objectIdAt(int idx)
{
	return (idx >= 0 && idx < _rows.size())? _rows[idx].ObjectId: mtp::ObjectId();
}

QVariant MtpObjectsModel::data(const QModelIndex &index, int role) const
{
	int row_idx = index.row();
	if (row_idx < 0 || row_idx > _rows.size())
		return QVariant();

	Row &row = _rows[row_idx];

	switch(role)
	{
	case Qt::ToolTipRole:
	case Qt::DisplayRole:
		return fromUtf8(row.GetInfo(_session)->Filename);

	case Qt::FontRole:
		{
			QFont font;
			if (row.IsAssociation(_session))
				font.setBold(true);
			return font;
		}

	case Qt::DecorationRole:
		if (_enableThumbnails)
			return *row.GetThumbnail(_session, QSize(_maxThumbnailSize.width(), _maxThumbnailSize.height() / 1.5f));
		else
			return QVariant();

	case Qt::SizeHintRole:
		if (_enableThumbnails)
			return _maxThumbnailSize;
		else
			return QVariant();

	default:
		return QVariant();
	}
}

mtp::ObjectId MtpObjectsModel::createDirectory(mtp::ObjectId parentObjectId, const QString &name, mtp::AssociationType type)
{
	QModelIndex existingDir = findObject(name);
	if (existingDir.isValid())
		return _rows.at(existingDir.row()).ObjectId;

	mtp::StorageId storageId = _storageId != mtp::Session::AllStorages? _storageId: mtp::Session::AnyStorage;
	mtp::Session::NewObjectInfo noi = _session->CreateDirectory(toUtf8(name), parentObjectId, storageId, type);
	if (parentObjectId == _parentObjectId)
	{
		beginInsertRows(QModelIndex(), _rows.size(), _rows.size());
		_rows.push_back(Row(noi.ObjectId));
		endInsertRows();
	}
	return noi.ObjectId;
}

bool MtpObjectsModel::uploadFile(mtp::ObjectId parentObjectId, const QString &filePath, QString filename)
{
	QFileInfo fileInfo(filePath);
	mtp::ObjectFormat objectFormat = mtp::ObjectFormatFromFilename(toUtf8(filePath));

	if (filename.isEmpty())
		filename = fileInfo.fileName();

	qDebug() << "uploadFile " << fileInfo.fileName() << " as " << filename;

	bool needReset = false;
	QModelIndex existingObject = findObject(filename);
	if (existingObject.isValid())
	{
		if (!emit existingFileOverwrite(filename))
		{
			qDebug() << "skipping, overwrite not confirmed";
			return false;
		}
		try
		{
			_session->DeleteObject(_rows.at(existingObject.row()).ObjectId);
		}
		catch(const std::exception &ex)
		{ qDebug() << "failed to delete object" << fromUtf8(ex.what()); return false; }

		needReset = parentObjectId == _parentObjectId;
	}

	std::shared_ptr<QtObjectInputStream> object(new QtObjectInputStream(filePath));
	if (!object->Valid())
	{
		qWarning() << "file " << filePath << " could not be opened";
		return false;
	}
	qDebug() << "sending " << fileInfo.size() << " bytes";
	connect(object.get(), SIGNAL(positionChanged(qint64,qint64)), this, SIGNAL(filePositionChanged(qint64,qint64)));

	mtp::msg::ObjectInfo oi;
	oi.Filename = toUtf8(filename);
	oi.ObjectFormat = objectFormat;
	oi.SetSize(fileInfo.size());
	mtp::Session::NewObjectInfo noi;
	try
	{
		noi = _session->SendObjectInfo(oi, _storageId != mtp::Session::AllStorages? _storageId: mtp::Session::AnyStorage, parentObjectId);
		qDebug() << "new object id: " << noi.ObjectId << ", sending...";
		_session->SendObject(object);
		qDebug() << "ok";
	}
	catch(const std::exception &ex)
	{ qDebug() << "failed to send new object info " << fromUtf8(ex.what()); return false; }

	if (parentObjectId == _parentObjectId)
	{
		beginInsertRows(QModelIndex(), _rows.size(), _rows.size());
		_rows.push_back(Row(noi.ObjectId));
		endInsertRows();
	}
	if (needReset)
		refresh();
	return true;
}

bool MtpObjectsModel::downloadFile(const QString &filePath, mtp::ObjectId objectId)
{
	auto object = std::make_shared<QtObjectOutputStream>(filePath);
	if (!object->Valid())
	{
		qWarning() << "cannot open file " << filePath;
		return false;
	}
	connect(object.get(), SIGNAL(positionChanged(qint64,qint64)), this, SIGNAL(filePositionChanged(qint64,qint64)));
	_session->GetObject(objectId, object);
	object.reset();
	cli::ObjectOutputStream::SetModificationTime(filePath.toStdString(), _session->GetObjectModificationTime(objectId));
	return true;
}

MtpObjectsModel::ObjectInfo MtpObjectsModel::getInfoById(mtp::ObjectId objectId) const
{
	mtp::msg::ObjectInfo oi(_session->GetObjectInfo(objectId));
	qint64 size = oi.ObjectCompressedSize;
	if (size == mtp::MaxObjectSize)
		size = _session->GetObjectIntegerProperty(objectId, mtp::ObjectProperty::ObjectSize);
	return ObjectInfo(fromUtf8(oi.Filename), oi.ObjectFormat, size);
}

QStringList MtpObjectsModel::extractMimeData(const QMimeData *data)
{
	QStringList files;
	QList<QUrl> urls = data->urls();
	for (auto url : urls)
	{
		//qDebug() << "url " << url;
		if (url.isLocalFile())
			files.push_back(url.toLocalFile());
		else
			qWarning() << "skipping non-local url" << url;
	}
	return files;
}

bool MtpObjectsModel::dropMimeData(const QMimeData *data,
	 Qt::DropAction action, int row, int column, const QModelIndex &parent)
{
	qDebug() << "data: " << data << action << row << column;
	if (action != Qt::CopyAction || !data)
		return false;

	QStringList files = extractMimeData(data);
	qDebug() << "files dropped: " << files;
	emit onFilesDropped(files);
	return true;
}

QStringList MtpObjectsModel::mimeTypes () const
{ return QStringList("text/uri-list"); }

Qt::ItemFlags MtpObjectsModel::flags(const QModelIndex &index) const
{
	Qt::ItemFlags defaultFlags = QAbstractListModel::flags(index);
	return defaultFlags | Qt::ItemIsDropEnabled;
}

void MtpObjectsModel::enableThumbnail(bool enable, QSize maxSize)
{
	beginResetModel();

	_enableThumbnails = enable;
	_maxThumbnailSize = maxSize;

	endResetModel();
}
<|endoftext|>


<commit_before>#include <fcntl.h>
#include <string.h>
#include <unistd.h>
#include "arch/linux/event_queue.hpp"
#include "arch/timer.hpp"
#include "logger.hpp"
#include "arch/arch.hpp"
#include "concurrency/cond_var.hpp"

/* Timer token */
struct timer_token_t :
    public intrusive_list_node_t<timer_token_t>
{
    friend class timer_handler_t;

private:
    bool once;   // If 'false', the timer is repeating
    long interval_ms;   // If a repeating timer, this is the time between 'rings'
    long next_time_in_ms;   // This is the time (in ms since the server started) of the next 'ring'

    // It's unsafe to remove arbitrary timers from the list as we iterate over
    // it, so instead we set the 'deleted' flag and then remove them in a
    // controlled fashion.
    bool deleted;

    void (*callback)(void *ctx);
    void *context;
};

/* Timer implementation */
timer_handler_t::timer_handler_t(linux_event_queue_t *queue)
    : timer_provider(queue, this, TIMER_TICKS_IN_MS / 1000, (TIMER_TICKS_IN_MS % 1000) * 1000000L),
      timer_ticks_since_server_startup(0)
{
    // Nothing to do here, timer_provider handles the OS
}

timer_handler_t::~timer_handler_t() {
    // Delete the registered timers
    while (timer_token_t *t = timers.head()) {
        rassert(t->deleted);
        timers.remove(t);
        delete t;
    }
}

void timer_handler_t::on_timer(int nexpirations) {
    timer_ticks_since_server_startup += nexpirations;
    long time_in_ms = timer_ticks_since_server_startup * TIMER_TICKS_IN_MS;

    intrusive_list_t<timer_token_t>::iterator t;
    for (t = timers.begin(); t != timers.end(); ) {
        timer_token_t *timer = &*t;

        // Increment now instead of in the header of the 'for' loop because we may
        // delete the timer we are on
        t++;

        if (!timer->deleted && time_in_ms > timer->next_time_in_ms) {
            // Note that a repeating timer may have "expired" multiple times since the last time
            // process_timer_notify() was called. However, everything that uses the timer mechanism
            // right now works better if the timer's callback only happens once. Perhaps there
            // should be a flag on the timer that determines whether to call the timer's callback
            // more than once or not.

            timer->callback(timer->context);

            if (timer->once) {
                cancel_timer(timer);
            } else {
                timer->next_time_in_ms = time_in_ms + timer->interval_ms;
            }
        }

        if (timer->deleted) {
            timers.remove(timer);
            delete timer;
        }
    }
}

timer_token_t *timer_handler_t::add_timer_internal(long ms, void (*callback)(void *ctx), void *ctx, bool once) {
    rassert(ms >= 0);

    timer_token_t *t = new timer_token_t();
    t->next_time_in_ms = timer_ticks_since_server_startup * TIMER_TICKS_IN_MS + ms;
    t->once = once;
    t->interval_ms = ms;
    t->deleted = false;
    t->callback = callback;
    t->context = ctx;

    timers.push_front(t);

    return t;
}

void timer_handler_t::cancel_timer(timer_token_t *timer) {
    timer->deleted = true;
}
<commit_msg>When a timer token is leaked, display an error message rather than crashing so that we can use Valgrind to figure out what created the leaked timer.<commit_after>#include <fcntl.h>
#include <string.h>
#include <unistd.h>
#include "arch/linux/event_queue.hpp"
#include "arch/timer.hpp"
#include "logger.hpp"
#include "arch/arch.hpp"
#include "concurrency/cond_var.hpp"

/* Timer token */
struct timer_token_t :
    public intrusive_list_node_t<timer_token_t>
{
    friend class timer_handler_t;

private:
    bool once;   // If 'false', the timer is repeating
    long interval_ms;   // If a repeating timer, this is the time between 'rings'
    long next_time_in_ms;   // This is the time (in ms since the server started) of the next 'ring'

    // It's unsafe to remove arbitrary timers from the list as we iterate over
    // it, so instead we set the 'deleted' flag and then remove them in a
    // controlled fashion.
    bool deleted;

    void (*callback)(void *ctx);
    void *context;
};

/* Timer implementation */
timer_handler_t::timer_handler_t(linux_event_queue_t *queue)
    : timer_provider(queue, this, TIMER_TICKS_IN_MS / 1000, (TIMER_TICKS_IN_MS % 1000) * 1000000L),
      timer_ticks_since_server_startup(0)
{
    // Nothing to do here, timer_provider handles the OS
}

timer_handler_t::~timer_handler_t() {
    // Delete the registered timers
    while (timer_token_t *t = timers.head()) {
        timers.remove(t);
        if (t->deleted) {
	    delete t;
        } else {
            /* This is an error. However, the best way to debug this error is to have
            the timer token leak and have Valgrind tell us where the leaked block originated
            from. So we just write a warning message. */
            logERR("Internal error: leaked timer.\n");
        }
    }
}

void timer_handler_t::on_timer(int nexpirations) {
    timer_ticks_since_server_startup += nexpirations;
    long time_in_ms = timer_ticks_since_server_startup * TIMER_TICKS_IN_MS;

    intrusive_list_t<timer_token_t>::iterator t;
    for (t = timers.begin(); t != timers.end(); ) {
        timer_token_t *timer = &*t;

        // Increment now instead of in the header of the 'for' loop because we may
        // delete the timer we are on
        t++;

        if (!timer->deleted && time_in_ms > timer->next_time_in_ms) {
            // Note that a repeating timer may have "expired" multiple times since the last time
            // process_timer_notify() was called. However, everything that uses the timer mechanism
            // right now works better if the timer's callback only happens once. Perhaps there
            // should be a flag on the timer that determines whether to call the timer's callback
            // more than once or not.

            timer->callback(timer->context);

            if (timer->once) {
                cancel_timer(timer);
            } else {
                timer->next_time_in_ms = time_in_ms + timer->interval_ms;
            }
        }

        if (timer->deleted) {
            timers.remove(timer);
            delete timer;
        }
    }
}

timer_token_t *timer_handler_t::add_timer_internal(long ms, void (*callback)(void *ctx), void *ctx, bool once) {
    rassert(ms >= 0);

    timer_token_t *t = new timer_token_t();
    t->next_time_in_ms = timer_ticks_since_server_startup * TIMER_TICKS_IN_MS + ms;
    t->once = once;
    t->interval_ms = ms;
    t->deleted = false;
    t->callback = callback;
    t->context = ctx;

    timers.push_front(t);

    return t;
}

void timer_handler_t::cancel_timer(timer_token_t *timer) {
    timer->deleted = true;
}
<|endoftext|>