<commit_before>#ifndef DYNAMIC_FUSION_DUAL_QUATERNION_HPP
#define DYNAMIC_FUSION_DUAL_QUATERNION_HPP
#include<iostream>
#include<quaternion.hpp>

//Adapted from https://github.com/Poofjunior/QPose
/**
 * \brief a dual quaternion class for encoding transformations.
 * \details transformations are stored as first a translation; then a
 *          rotation. It is possible to switch the order. See this paper:
 *  https://www.thinkmind.org/download.php?articleid=intsys_v6_n12_2013_5
 */
namespace kfusion {
    namespace utils {
        static float epsilon()
        {
            return 1e-6;
        }
        template<typename T>
        class DualQuaternion {
        public:
            /**
             * \brief default constructor.
             */
            DualQuaternion()
            {
                rotation_ = Quaternion<float>();
                translation_ = Quaternion<float>();
            };
            ~DualQuaternion(){};

            /**
             * \brief constructor that takes cartesian coordinates and Euler angles as
             *        arguments.
             */
//            FIXME: always use Rodrigues angles, not Euler
            DualQuaternion(T x, T y, T z, T roll, T pitch, T yaw)
            {
                // convert here.
                rotation_.w_ = cos(roll / 2) * cos(pitch / 2) * cos(yaw / 2) +
                               sin(roll / 2) * sin(pitch / 2) * sin(yaw / 2);
                rotation_.x_ = sin(roll / 2) * cos(pitch / 2) * cos(yaw / 2) -
                               cos(roll / 2) * sin(pitch / 2) * sin(yaw / 2);
                rotation_.y_ = cos(roll / 2) * sin(pitch / 2) * cos(yaw / 2) +
                               sin(roll / 2) * cos(pitch / 2) * sin(yaw / 2);
                rotation_.z_ = cos(roll / 2) * cos(pitch / 2) * sin(yaw / 2) -
                               sin(roll / 2) * cos(pitch / 2) * cos(yaw / 2);

                translation_ = 0.5 * Quaternion<T>(0, x, y, z) * rotation_;
            }

            /**
             * \brief constructor that takes two quaternions as arguments.
             * \details The rotation
             *          quaternion has the conventional encoding for a rotation as a
             *          quaternion. The translation quaternion is a quaternion with
             *          cartesian coordinates encoded as (0, x, y, z)
             */
            DualQuaternion(Quaternion<T> translation, Quaternion<T> rotation)
            {
                rotation_ = rotation;
                translation_ = 0.5 * translation * rotation;
            }

            /**
             * \brief store a rotation
             * \param angle is in radians
             */
            void encodeRotation(T angle, T x, T y, T z)
            {
                rotation_.encodeRotation(angle, x, y, z);
            }
            /**
             * \brief store a rotation
             * \param angle is in radians
             */
            void encodeRotation(T x, T y, T z)
            {
                rotation_.encodeRotation(sqrt(x*x+y*y+z*z), x, y, z);
            }

            void encodeTranslation(T x, T y, T z)
            {
                translation_ = 0.5 * Quaternion<T>(0, x, y, z) * rotation_;
            }

            /// handle accumulating error.
            void normalize()
            {
                T x, y, z;
                getTranslation(x, y, z);

                rotation_.normalize();

                encodeTranslation(x, y, z);
            }

            /**
             * \brief a reference-based method for acquiring the latest
             *        translation data.
             */
            void getTranslation(T &x, T &y, T &z) const
            {
                Quaternion<T> result = getTranslation();
                /// note: inverse of a quaternion is the same as the conjugate.
                x = result.x_;
                y = result.y_;
                z = result.z_;
            }

            /**
             * \brief a reference-based method for acquiring the latest
             *        translation data.
             */
            void getTranslation(Vec3f& vec3f) const
            {
                getTranslation(vec3f[0], vec3f[1], vec3f[2]);
            }

            Quaternion<T> getTranslation() const
            {
                auto rot = rotation_;
                rot.normalize();
                return 2 * translation_ * rot.conjugate();
            }

            /**
             * \brief a reference-based method for acquiring the latest rotation data.
             */
            void getEuler(T &roll, T &pitch, T &yaw)
            {
                // FIXME: breaks for some value around PI.
                roll = getRoll();
                pitch = getPitch();
                yaw = getYaw();
            }

            Quaternion<T> getRotation() const
            {
                return rotation_;
            }

            DualQuaternion operator+(const DualQuaternion &other)
            {
                DualQuaternion result;
                result.rotation_ = rotation_ + other.rotation_;
                result.translation_ = translation_ + other.translation_;
                return result;
            }

            DualQuaternion operator-(const DualQuaternion &other)
            {
                DualQuaternion result;
                result.rotation_ = rotation_ - other.rotation_;
                result.translation_ = translation_ - other.translation_;
                return result;
            }

            DualQuaternion operator*(const DualQuaternion &other)
            {
                DualQuaternion<T> result;
                result.rotation_ = rotation_ * other.rotation_;
//                result.translation_ = (rotation_ * other.translation_) + (translation_ * other.rotation_);
                result.translation_ = translation_ + other.translation_;
                return result;
            }

            DualQuaternion operator/(const std::pair<T,T> divisor)
            {
                DualQuaternion<T> result;
                result.rotation_ = 1 / divisor.first * rotation_;
                result.translation_ = 1 / divisor.second * translation_;
                return result;
            }

            /// (left) Scalar Multiplication
            /**
             * \fn template <typename U> friend Quaternion operator*(const U scalar,
             * \brief implements scalar multiplication for arbitrary scalar types
             */
            template<typename U>
            friend DualQuaternion operator*(const U scalar, const DualQuaternion &q)
            {
                DualQuaternion<T> result;
                result.rotation_ = scalar * q.rotation_;
                result.translation_ = scalar * q.translation_;
                return result;
            }

            DualQuaternion conjugate()
            {
                DualQuaternion<T> result;
                result.rotation_ = rotation_.conjugate();
                result.translation_ = translation_.conjugate();
                return result;
            }

            inline DualQuaternion identity()
            {
                return DualQuaternion(Quaternion<T>(0, 0, 0, 0),Quaternion<T>(0, 1, 0, 0));
            }

            void transform(Vec3f& point) // TODO: this should be a lot more generic
            {
                Vec3f translation;
                getTranslation(translation);
                rotation_.rotate(point);
                point += translation;
            }

            void from_twist(const float &r0, const float &r1, const float &r2,
                            const float &x, const float &y, const float &z)
            {
                float norm = sqrt(r0*r0 + r1 * r1 + r2 * r2);
                Quaternion<T> rotation;
                if (norm > epsilon())
                {
                    float cosNorm = cos(norm);
                    float sign = (cosNorm > 0.f) - (cosNorm < 0.f);
                    cosNorm *= sign;
                    float sinNorm_norm = sign * sin(norm) / norm;
                    rotation = Quaternion<T>(cosNorm, r0 * sinNorm_norm, r1 * sinNorm_norm, r2 * sinNorm_norm);
                }
                else
                    rotation = Quaternion<T>();

                *this = DualQuaternion<T>(Quaternion<T>(0, x, y, z), rotation);
            }

            std::pair<T,T> magnitude()
            {
                DualQuaternion result = (*this) * (*this).conjugate();
                return std::make_pair(result.rotation_.w_, result.translation_.w_);
            }

        private:
            Quaternion<T> rotation_;
            Quaternion<T> translation_;

            T position_[3] = {};    /// default initialize vector to zeros.

            T rotAxis_[3] = {};     /// default initialize vector to zeros.
            T rotAngle_;

            T getRoll()
            {
                // TODO: test this!
                return atan2(2*((rotation_.w_ * rotation_.x_) + (rotation_.y_ * rotation_.z_)),
                             (1 - 2*((rotation_.x_*rotation_.x_) + (rotation_.y_*rotation_.y_))));
            }

            T getPitch()
            {
                // TODO: test this!
                return asin(2*(rotation_.w_ * rotation_.y_ - rotation_.z_ * rotation_.x_));
            }

            T getYaw()
            {
                // TODO: test this!
                return atan2(2*((rotation_.w_ * rotation_.z_) + (rotation_.x_ * rotation_.y_)),
                             (1 - 2*((rotation_.y_*rotation_.y_) + (rotation_.z_*rotation_.z_))));
            }
        };

        template <typename T>
        std::ostream &operator<<(std::ostream &os, const DualQuaternion<T> &q)
        {
            os << "[" << q.getRotation() << ", " << q.getTranslation()<< ", " << "]" << std::endl;
            return os;
        }
    }
}
#endif //DYNAMIC_FUSION_DUAL_QUATERNION_HPP<commit_msg>Fix conversion between Euler angles to quaternions<commit_after>#ifndef DYNAMIC_FUSION_DUAL_QUATERNION_HPP
#define DYNAMIC_FUSION_DUAL_QUATERNION_HPP
#include<iostream>
#include<quaternion.hpp>

//Adapted from https://github.com/Poofjunior/QPose
/**
 * \brief a dual quaternion class for encoding transformations.
 * \details transformations are stored as first a translation; then a
 *          rotation. It is possible to switch the order. See this paper:
 *  https://www.thinkmind.org/download.php?articleid=intsys_v6_n12_2013_5
 */
namespace kfusion {
    namespace utils {
        static float epsilon()
        {
            return 1e-6;
        }
        template<typename T>
        class DualQuaternion {
        public:
            /**
             * \brief default constructor.
             */
            DualQuaternion()
            {
                rotation_ = Quaternion<float>();
                translation_ = Quaternion<float>();
            };
            ~DualQuaternion(){};

            /**
             * \brief constructor that takes cartesian coordinates and Euler angles as
             *        arguments.
             */
//            FIXME: always use Rodrigues angles, not Euler
            DualQuaternion(T x, T y, T z, T roll, T pitch, T yaw)
            {
                // convert here.
                rotation_.w_ = cos(roll / 2) * cos(pitch / 2) * cos(yaw / 2) +
                               sin(roll / 2) * sin(pitch / 2) * sin(yaw / 2);
                rotation_.x_ = sin(roll / 2) * cos(pitch / 2) * cos(yaw / 2) -
                               cos(roll / 2) * sin(pitch / 2) * sin(yaw / 2);
                rotation_.y_ = cos(roll / 2) * sin(pitch / 2) * cos(yaw / 2) +
                               sin(roll / 2) * cos(pitch / 2) * sin(yaw / 2);
                rotation_.z_ = cos(roll / 2) * cos(pitch / 2) * sin(yaw / 2) -
                               sin(roll / 2) * sin(pitch / 2) * cos(yaw / 2);

                translation_ = 0.5 * Quaternion<T>(0, x, y, z) * rotation_;
            }

            /**
             * \brief constructor that takes two quaternions as arguments.
             * \details The rotation
             *          quaternion has the conventional encoding for a rotation as a
             *          quaternion. The translation quaternion is a quaternion with
             *          cartesian coordinates encoded as (0, x, y, z)
             */
            DualQuaternion(Quaternion<T> translation, Quaternion<T> rotation)
            {
                rotation_ = rotation;
                translation_ = 0.5 * translation * rotation;
            }

            /**
             * \brief store a rotation
             * \param angle is in radians
             */
            void encodeRotation(T angle, T x, T y, T z)
            {
                rotation_.encodeRotation(angle, x, y, z);
            }
            /**
             * \brief store a rotation
             * \param angle is in radians
             */
            void encodeRotation(T x, T y, T z)
            {
                rotation_.encodeRotation(sqrt(x*x+y*y+z*z), x, y, z);
            }

            void encodeTranslation(T x, T y, T z)
            {
                translation_ = 0.5 * Quaternion<T>(0, x, y, z) * rotation_;
            }

            /// handle accumulating error.
            void normalize()
            {
                T x, y, z;
                getTranslation(x, y, z);

                rotation_.normalize();

                encodeTranslation(x, y, z);
            }

            /**
             * \brief a reference-based method for acquiring the latest
             *        translation data.
             */
            void getTranslation(T &x, T &y, T &z) const
            {
                Quaternion<T> result = getTranslation();
                /// note: inverse of a quaternion is the same as the conjugate.
                x = result.x_;
                y = result.y_;
                z = result.z_;
            }

            /**
             * \brief a reference-based method for acquiring the latest
             *        translation data.
             */
            void getTranslation(Vec3f& vec3f) const
            {
                getTranslation(vec3f[0], vec3f[1], vec3f[2]);
            }

            Quaternion<T> getTranslation() const
            {
                auto rot = rotation_;
                rot.normalize();
                return 2 * translation_ * rot.conjugate();
            }

            /**
             * \brief a reference-based method for acquiring the latest rotation data.
             */
            void getEuler(T &roll, T &pitch, T &yaw)
            {
                // FIXME: breaks for some value around PI.
                roll = getRoll();
                pitch = getPitch();
                yaw = getYaw();
            }

            Quaternion<T> getRotation() const
            {
                return rotation_;
            }

            DualQuaternion operator+(const DualQuaternion &other)
            {
                DualQuaternion result;
                result.rotation_ = rotation_ + other.rotation_;
                result.translation_ = translation_ + other.translation_;
                return result;
            }

            DualQuaternion operator-(const DualQuaternion &other)
            {
                DualQuaternion result;
                result.rotation_ = rotation_ - other.rotation_;
                result.translation_ = translation_ - other.translation_;
                return result;
            }

            DualQuaternion operator*(const DualQuaternion &other)
            {
                DualQuaternion<T> result;
                result.rotation_ = rotation_ * other.rotation_;
//                result.translation_ = (rotation_ * other.translation_) + (translation_ * other.rotation_);
                result.translation_ = translation_ + other.translation_;
                return result;
            }

            DualQuaternion operator/(const std::pair<T,T> divisor)
            {
                DualQuaternion<T> result;
                result.rotation_ = 1 / divisor.first * rotation_;
                result.translation_ = 1 / divisor.second * translation_;
                return result;
            }

            /// (left) Scalar Multiplication
            /**
             * \fn template <typename U> friend Quaternion operator*(const U scalar,
             * \brief implements scalar multiplication for arbitrary scalar types
             */
            template<typename U>
            friend DualQuaternion operator*(const U scalar, const DualQuaternion &q)
            {
                DualQuaternion<T> result;
                result.rotation_ = scalar * q.rotation_;
                result.translation_ = scalar * q.translation_;
                return result;
            }

            DualQuaternion conjugate()
            {
                DualQuaternion<T> result;
                result.rotation_ = rotation_.conjugate();
                result.translation_ = translation_.conjugate();
                return result;
            }

            inline DualQuaternion identity()
            {
                return DualQuaternion(Quaternion<T>(0, 0, 0, 0),Quaternion<T>(0, 1, 0, 0));
            }

            void transform(Vec3f& point) // TODO: this should be a lot more generic
            {
                Vec3f translation;
                getTranslation(translation);
                rotation_.rotate(point);
                point += translation;
            }

            void from_twist(const float &r0, const float &r1, const float &r2,
                            const float &x, const float &y, const float &z)
            {
                float norm = sqrt(r0*r0 + r1 * r1 + r2 * r2);
                Quaternion<T> rotation;
                if (norm > epsilon())
                {
                    float cosNorm = cos(norm);
                    float sign = (cosNorm > 0.f) - (cosNorm < 0.f);
                    cosNorm *= sign;
                    float sinNorm_norm = sign * sin(norm) / norm;
                    rotation = Quaternion<T>(cosNorm, r0 * sinNorm_norm, r1 * sinNorm_norm, r2 * sinNorm_norm);
                }
                else
                    rotation = Quaternion<T>();

                *this = DualQuaternion<T>(Quaternion<T>(0, x, y, z), rotation);
            }

            std::pair<T,T> magnitude()
            {
                DualQuaternion result = (*this) * (*this).conjugate();
                return std::make_pair(result.rotation_.w_, result.translation_.w_);
            }

        private:
            Quaternion<T> rotation_;
            Quaternion<T> translation_;

            T position_[3] = {};    /// default initialize vector to zeros.

            T rotAxis_[3] = {};     /// default initialize vector to zeros.
            T rotAngle_;

            T getRoll()
            {
                // TODO: test this!
                return atan2(2*((rotation_.w_ * rotation_.x_) + (rotation_.y_ * rotation_.z_)),
                             (1 - 2*((rotation_.x_*rotation_.x_) + (rotation_.y_*rotation_.y_))));
            }

            T getPitch()
            {
                // TODO: test this!
                return asin(2*(rotation_.w_ * rotation_.y_ - rotation_.z_ * rotation_.x_));
            }

            T getYaw()
            {
                // TODO: test this!
                return atan2(2*((rotation_.w_ * rotation_.z_) + (rotation_.x_ * rotation_.y_)),
                             (1 - 2*((rotation_.y_*rotation_.y_) + (rotation_.z_*rotation_.z_))));
            }
        };

        template <typename T>
        std::ostream &operator<<(std::ostream &os, const DualQuaternion<T> &q)
        {
            os << "[" << q.getRotation() << ", " << q.getTranslation()<< ", " << "]" << std::endl;
            return os;
        }
    }
}
#endif //DYNAMIC_FUSION_DUAL_QUATERNION_HPP<|endoftext|>


<commit_before>#include "impl_request_posture.hpp"

#include "pattern_posture_generator/PatternPosture.h"

std::map<std::string, RequestPosture*> RequestPostureFactory::reqs;

RequestPosture* RequestPostureFactory::get(const std::string& name, ros::NodeHandle& nh) {
  std::map<std::string, RequestPosture*>::const_iterator found_it = reqs.find(name);
  if (found_it == reqs.end()) return create(name, nh);
  return found_it->second;
}

RequestPosture* RequestPostureFactory::create(const std::string& name, ros::NodeHandle& nh) {
  if (name == "pattern") {
    reqs["pattern"] = new PatternRequestPosture(nh);
    return reqs.at("pattern");
  }
  if (name == "pattern_normal") {
    reqs["pattern_normal"] = new PatternRequestPosture(nh, "normal");
    return reqs.at("pattern_normal");
  }
  if (name == "pattern_harvest") {
    reqs["pattern_harvest"] = new PatternRequestPosture(nh, "harvest");
    return reqs.at("pattern_harvest");
  }
  if (name == "torajectory") {
    reqs["torajectory"] = new TrajectoryRequestPosture(nh);
    return reqs.at("torajectory");
  }
  return NULL;
}

PatternRequestPosture::PatternRequestPosture(ros::NodeHandle& nh, std::string state) : state(state) {
  client = nh.serviceClient<pattern_posture_generator::PatternPosture>("/getPosture");
}

PatternRequestPosture::PatternRequestPosture(ros::NodeHandle& nh) : state("normal") {
  client = nh.serviceClient<pattern_posture_generator::PatternPosture>("/getPosture");
}

void PatternRequestPosture::requestPosture(std::vector<double>& posture) {
  pattern_posture_generator::PatternPosture srv;
  srv.request.name = state;
  if (client.call(srv)) {
    ROS_INFO("Error call: No response by Request [%s] PatternPosture", state.c_str());
    return;
  }
  std::copy(srv.response.posture.begin(), srv.response.posture.end(), std::back_inserter(posture));
}

TrajectoryRequestPosture::TrajectoryRequestPosture(ros::NodeHandle& nh) {

}

void TrajectoryRequestPosture::requestPosture(std::vector<double>& posture) {

}

<commit_msg>Update scope of ros service to local from grobal.<commit_after>#include "impl_request_posture.hpp"

#include "pattern_posture_generator/PatternPosture.h"

std::map<std::string, RequestPosture*> RequestPostureFactory::reqs;

RequestPosture* RequestPostureFactory::get(const std::string& name, ros::NodeHandle& nh) {
  std::map<std::string, RequestPosture*>::const_iterator found_it = reqs.find(name);
  if (found_it == reqs.end()) return create(name, nh);
  return found_it->second;
}

RequestPosture* RequestPostureFactory::create(const std::string& name, ros::NodeHandle& nh) {
  if (name == "pattern") {
    reqs["pattern"] = new PatternRequestPosture(nh);
    return reqs.at("pattern");
  }
  if (name == "pattern_normal") {
    reqs["pattern_normal"] = new PatternRequestPosture(nh, "normal");
    return reqs.at("pattern_normal");
  }
  if (name == "pattern_harvest") {
    reqs["pattern_harvest"] = new PatternRequestPosture(nh, "harvest");
    return reqs.at("pattern_harvest");
  }
  if (name == "torajectory") {
    reqs["torajectory"] = new TrajectoryRequestPosture(nh);
    return reqs.at("torajectory");
  }
  return NULL;
}

PatternRequestPosture::PatternRequestPosture(ros::NodeHandle& nh, std::string state) : state(state) {
  client = nh.serviceClient<pattern_posture_generator::PatternPosture>("getPosture");
}

PatternRequestPosture::PatternRequestPosture(ros::NodeHandle& nh) : state("normal") {
  client = nh.serviceClient<pattern_posture_generator::PatternPosture>("getPosture");
}

void PatternRequestPosture::requestPosture(std::vector<double>& posture) {
  pattern_posture_generator::PatternPosture srv;
  srv.request.name = state;
  if (client.call(srv)) {
    ROS_INFO("Error call: No response by Request [%s] PatternPosture", state.c_str());
    return;
  }
  std::copy(srv.response.posture.begin(), srv.response.posture.end(), std::back_inserter(posture));
}

TrajectoryRequestPosture::TrajectoryRequestPosture(ros::NodeHandle& nh) {

}

void TrajectoryRequestPosture::requestPosture(std::vector<double>& posture) {

}

<|endoftext|>


<commit_before>/****************************************************************************
**
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of Qt Creator.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Digia.  For licensing terms and
** conditions see http://qt.digia.com/licensing.  For further information
** use the contact form at http://qt.digia.com/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Digia gives you certain additional
** rights.  These rights are described in the Digia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
****************************************************************************/

#include "debuggerrunconfigurationaspect.h"

#include "debuggerconstants.h"

#include <coreplugin/icontext.h>
#include <coreplugin/icore.h>
#include <coreplugin/helpmanager.h>
#include <projectexplorer/kitinformation.h>
#include <projectexplorer/project.h>
#include <projectexplorer/projectexplorerconstants.h>
#include <projectexplorer/runconfiguration.h>
#include <projectexplorer/target.h>

#include <QCheckBox>
#include <QSpinBox>
#include <QDebug>
#include <QFormLayout>
#include <QLabel>

static const char USE_CPP_DEBUGGER_KEY[] = "RunConfiguration.UseCppDebugger";
static const char USE_QML_DEBUGGER_KEY[] = "RunConfiguration.UseQmlDebugger";
static const char USE_QML_DEBUGGER_AUTO_KEY[] = "RunConfiguration.UseQmlDebuggerAuto";
static const char QML_DEBUG_SERVER_PORT_KEY[] = "RunConfiguration.QmlDebugServerPort";
static const char USE_MULTIPROCESS_KEY[] = "RunConfiguration.UseMultiProcess";

namespace Debugger {
namespace Internal {

////////////////////////////////////////////////////////////////////////
//
// DebuggerRunConfigWidget
//
////////////////////////////////////////////////////////////////////////

class DebuggerRunConfigWidget : public ProjectExplorer::RunConfigWidget
{
    Q_OBJECT

public:
    explicit DebuggerRunConfigWidget(DebuggerRunConfigurationAspect *aspect);
    QString displayName() const { return tr("Debugger Settings"); }

private slots:
    void useCppDebuggerToggled(bool on);
    void useQmlDebuggerToggled(bool on);
    void qmlDebugServerPortChanged(int port);
    void useMultiProcessToggled(bool on);

public:
    DebuggerRunConfigurationAspect *m_aspect; // not owned

    QCheckBox *m_useCppDebugger;
    QCheckBox *m_useQmlDebugger;
    QSpinBox *m_debugServerPort;
    QLabel *m_debugServerPortLabel;
    QLabel *m_qmlDebuggerInfoLabel;
    QCheckBox *m_useMultiProcess;
};

DebuggerRunConfigWidget::DebuggerRunConfigWidget(DebuggerRunConfigurationAspect *aspect)
{
    m_aspect = aspect;

    m_useCppDebugger = new QCheckBox(tr("Enable C++"), this);
    m_useQmlDebugger = new QCheckBox(tr("Enable QML"), this);

    m_debugServerPort = new QSpinBox(this);
    m_debugServerPort->setMinimum(1);
    m_debugServerPort->setMaximum(65535);

    m_debugServerPortLabel = new QLabel(tr("Debug port:"), this);
    m_debugServerPortLabel->setBuddy(m_debugServerPort);

    m_qmlDebuggerInfoLabel = new QLabel(tr("What are the prerequisites?"));

    m_useCppDebugger->setChecked(m_aspect->useCppDebugger());
    m_useQmlDebugger->setChecked(m_aspect->useQmlDebugger());

    m_debugServerPort->setValue(m_aspect->qmlDebugServerPort());

    static const QByteArray env = qgetenv("QTC_DEBUGGER_MULTIPROCESS");
    m_useMultiProcess =
        new QCheckBox(tr("Enable Debugging of Subprocesses"), this);
    m_useMultiProcess->setChecked(m_aspect->useMultiProcess());
    m_useMultiProcess->setVisible(env.toInt());

    connect(m_qmlDebuggerInfoLabel, SIGNAL(linkActivated(QString)),
            Core::HelpManager::instance(), SLOT(handleHelpRequest(QString)));
    connect(m_useQmlDebugger, SIGNAL(toggled(bool)),
            SLOT(useQmlDebuggerToggled(bool)));
    connect(m_useCppDebugger, SIGNAL(toggled(bool)),
            SLOT(useCppDebuggerToggled(bool)));
    connect(m_debugServerPort, SIGNAL(valueChanged(int)),
            SLOT(qmlDebugServerPortChanged(int)));
    connect(m_useMultiProcess, SIGNAL(toggled(bool)),
            SLOT(useMultiProcessToggled(bool)));

    if (m_aspect->areQmlDebuggingOptionsSuppressed()) {
        m_debugServerPortLabel->hide();
        m_debugServerPort->hide();
        m_useQmlDebugger->hide();
    }

    if (m_aspect->areCppDebuggingOptionsSuppressed())
        m_useCppDebugger->hide();

    if (m_aspect->isQmlDebuggingSpinboxSuppressed()) {
        m_debugServerPort->hide();
        m_debugServerPortLabel->hide();
    }

    QHBoxLayout *qmlLayout = new QHBoxLayout;
    qmlLayout->setMargin(0);
    qmlLayout->addWidget(m_useQmlDebugger);
    qmlLayout->addWidget(m_debugServerPortLabel);
    qmlLayout->addWidget(m_debugServerPort);
    qmlLayout->addWidget(m_qmlDebuggerInfoLabel);
    qmlLayout->addStretch();

    QVBoxLayout *layout = new QVBoxLayout;
    layout->setMargin(0);
    layout->addWidget(m_useCppDebugger);
    layout->addLayout(qmlLayout);
    layout->addWidget(m_useMultiProcess);
    setLayout(layout);
}

void DebuggerRunConfigWidget::qmlDebugServerPortChanged(int port)
{
    m_aspect->m_qmlDebugServerPort = port;
}

void DebuggerRunConfigWidget::useCppDebuggerToggled(bool on)
{
    m_aspect->m_useCppDebugger = on;
    if (!on && !m_useQmlDebugger->isChecked())
        m_useQmlDebugger->setChecked(true);
}

void DebuggerRunConfigWidget::useQmlDebuggerToggled(bool on)
{
    m_debugServerPort->setEnabled(on);
    m_debugServerPortLabel->setEnabled(on);

    m_aspect->m_useQmlDebugger = on
            ? DebuggerRunConfigurationAspect::EnableQmlDebugger
            : DebuggerRunConfigurationAspect::DisableQmlDebugger;
    if (!on && !m_useCppDebugger->isChecked())
        m_useCppDebugger->setChecked(true);
}

void DebuggerRunConfigWidget::useMultiProcessToggled(bool on)
{
    m_aspect->m_useMultiProcess = on;
}

} // namespace Internal

/*!
    \class Debugger::DebuggerRunConfigurationAspect
*/

DebuggerRunConfigurationAspect::DebuggerRunConfigurationAspect(
        ProjectExplorer::RunConfiguration *rc) :
    m_runConfiguration(rc),
    m_useCppDebugger(true),
    m_useQmlDebugger(AutoEnableQmlDebugger),
    m_qmlDebugServerPort(Constants::QML_DEFAULT_DEBUG_SERVER_PORT),
    m_useMultiProcess(false)
{
    ctor();
}

DebuggerRunConfigurationAspect::DebuggerRunConfigurationAspect(
        ProjectExplorer::RunConfiguration *runConfiguration,
        const DebuggerRunConfigurationAspect *other)
    : m_runConfiguration(runConfiguration),
      m_useCppDebugger(other->m_useCppDebugger),
      m_useQmlDebugger(other->m_useQmlDebugger),
      m_qmlDebugServerPort(other->m_qmlDebugServerPort),
      m_useMultiProcess(other->m_useMultiProcess)
{
    ctor();
}

ProjectExplorer::RunConfiguration *DebuggerRunConfigurationAspect::runConfiguration()
{
    return m_runConfiguration;
}

void DebuggerRunConfigurationAspect::setUseQmlDebugger(bool value)
{
    m_useQmlDebugger = value ? EnableQmlDebugger : DisableQmlDebugger;
    emit debuggersChanged();
}

void DebuggerRunConfigurationAspect::setUseCppDebugger(bool value)
{
    m_useCppDebugger = value;
    emit debuggersChanged();
}

bool DebuggerRunConfigurationAspect::useCppDebugger() const
{
    return m_useCppDebugger;
}

bool DebuggerRunConfigurationAspect::useQmlDebugger() const
{
    if (m_useQmlDebugger == DebuggerRunConfigurationAspect::AutoEnableQmlDebugger)
        return m_runConfiguration->target()->project()->projectLanguages().contains(
                    ProjectExplorer::Constants::LANG_QMLJS);
    return m_useQmlDebugger == DebuggerRunConfigurationAspect::EnableQmlDebugger;
}

uint DebuggerRunConfigurationAspect::qmlDebugServerPort() const
{
    return m_qmlDebugServerPort;
}

void DebuggerRunConfigurationAspect::setQmllDebugServerPort(uint port)
{
    m_qmlDebugServerPort = port;
}

bool DebuggerRunConfigurationAspect::useMultiProcess() const
{
    return m_useMultiProcess;
}

void DebuggerRunConfigurationAspect::setUseMultiProcess(bool value)
{
    m_useMultiProcess = value;
}

bool DebuggerRunConfigurationAspect::areQmlDebuggingOptionsSuppressed() const
{
    return !m_runConfiguration->target()->project()
            ->projectLanguages().contains(ProjectExplorer::Constants::LANG_QMLJS);
}

bool DebuggerRunConfigurationAspect::areCppDebuggingOptionsSuppressed() const
{
    return !m_runConfiguration->target()->project()
            ->projectLanguages().contains(ProjectExplorer::Constants::LANG_CXX);
}

bool DebuggerRunConfigurationAspect::isQmlDebuggingSpinboxSuppressed() const
{
    ProjectExplorer::Kit *k = m_runConfiguration->target()->kit();
    ProjectExplorer::IDevice::ConstPtr dev = ProjectExplorer::DeviceKitInformation::device(k);
    if (dev.isNull())
        return false;
    return dev->portsGatheringMethod().isNull(); // We know the free ports...
}

QString DebuggerRunConfigurationAspect::displayName() const
{
    return tr("Debugger settings");
}

QVariantMap DebuggerRunConfigurationAspect::toMap() const
{
    QVariantMap map;
    map.insert(QLatin1String(USE_CPP_DEBUGGER_KEY), m_useCppDebugger);
    map.insert(QLatin1String(USE_QML_DEBUGGER_KEY), m_useQmlDebugger == EnableQmlDebugger);
    map.insert(QLatin1String(USE_QML_DEBUGGER_AUTO_KEY), m_useQmlDebugger == AutoEnableQmlDebugger);
    map.insert(QLatin1String(QML_DEBUG_SERVER_PORT_KEY), m_qmlDebugServerPort);
    map.insert(QLatin1String(USE_MULTIPROCESS_KEY), m_useMultiProcess);
    return map;
}

void DebuggerRunConfigurationAspect::fromMap(const QVariantMap &map)
{
    m_useCppDebugger = map.value(QLatin1String(USE_CPP_DEBUGGER_KEY), true).toBool();
    if (map.value(QLatin1String(USE_QML_DEBUGGER_AUTO_KEY), false).toBool()) {
        m_useQmlDebugger = AutoEnableQmlDebugger;
    } else {
        bool useQml = map.value(QLatin1String(USE_QML_DEBUGGER_KEY), false).toBool();
        m_useQmlDebugger = useQml ? EnableQmlDebugger : DisableQmlDebugger;
    }
    m_useMultiProcess = map.value(QLatin1String(USE_MULTIPROCESS_KEY), false).toBool();
}

DebuggerRunConfigurationAspect *DebuggerRunConfigurationAspect::clone(
        ProjectExplorer::RunConfiguration *parent) const
{
    return new DebuggerRunConfigurationAspect(parent, this);
}

ProjectExplorer::RunConfigWidget *DebuggerRunConfigurationAspect::createConfigurationWidget()
{
    if (areCppDebuggingOptionsSuppressed() && areQmlDebuggingOptionsSuppressed())
        return 0;
    else
        return new Internal::DebuggerRunConfigWidget(this);
}

void DebuggerRunConfigurationAspect::ctor()
{
    connect(this, SIGNAL(debuggersChanged()),
            m_runConfiguration, SIGNAL(requestRunActionsUpdate()));
    setUseCppDebugger(!areCppDebuggingOptionsSuppressed());
    setUseQmlDebugger(!areQmlDebuggingOptionsSuppressed());
}

} // namespace Debugger

#include "debuggerrunconfigurationaspect.moc"
<commit_msg>DebuggerRunConfigurationAspect: Update based on project languages<commit_after>/****************************************************************************
**
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of Qt Creator.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Digia.  For licensing terms and
** conditions see http://qt.digia.com/licensing.  For further information
** use the contact form at http://qt.digia.com/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Digia gives you certain additional
** rights.  These rights are described in the Digia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
****************************************************************************/

#include "debuggerrunconfigurationaspect.h"

#include "debuggerconstants.h"

#include <coreplugin/icontext.h>
#include <coreplugin/icore.h>
#include <coreplugin/helpmanager.h>
#include <projectexplorer/kitinformation.h>
#include <projectexplorer/project.h>
#include <projectexplorer/projectexplorerconstants.h>
#include <projectexplorer/runconfiguration.h>
#include <projectexplorer/target.h>

#include <QCheckBox>
#include <QSpinBox>
#include <QDebug>
#include <QFormLayout>
#include <QLabel>

static const char USE_CPP_DEBUGGER_KEY[] = "RunConfiguration.UseCppDebugger";
static const char USE_QML_DEBUGGER_KEY[] = "RunConfiguration.UseQmlDebugger";
static const char USE_QML_DEBUGGER_AUTO_KEY[] = "RunConfiguration.UseQmlDebuggerAuto";
static const char QML_DEBUG_SERVER_PORT_KEY[] = "RunConfiguration.QmlDebugServerPort";
static const char USE_MULTIPROCESS_KEY[] = "RunConfiguration.UseMultiProcess";

namespace Debugger {
namespace Internal {

////////////////////////////////////////////////////////////////////////
//
// DebuggerRunConfigWidget
//
////////////////////////////////////////////////////////////////////////

class DebuggerRunConfigWidget : public ProjectExplorer::RunConfigWidget
{
    Q_OBJECT

public:
    explicit DebuggerRunConfigWidget(DebuggerRunConfigurationAspect *aspect);
    QString displayName() const { return tr("Debugger Settings"); }

private slots:
    void useCppDebuggerToggled(bool on);
    void useQmlDebuggerToggled(bool on);
    void qmlDebugServerPortChanged(int port);
    void useMultiProcessToggled(bool on);
    void update();

public:
    DebuggerRunConfigurationAspect *m_aspect; // not owned

    QCheckBox *m_useCppDebugger;
    QCheckBox *m_useQmlDebugger;
    QSpinBox *m_debugServerPort;
    QLabel *m_debugServerPortLabel;
    QLabel *m_qmlDebuggerInfoLabel;
    QCheckBox *m_useMultiProcess;
};

DebuggerRunConfigWidget::DebuggerRunConfigWidget(DebuggerRunConfigurationAspect *aspect)
{
    m_aspect = aspect;

    m_useCppDebugger = new QCheckBox(tr("Enable C++"), this);
    m_useQmlDebugger = new QCheckBox(tr("Enable QML"), this);

    m_debugServerPort = new QSpinBox(this);
    m_debugServerPort->setMinimum(1);
    m_debugServerPort->setMaximum(65535);

    m_debugServerPortLabel = new QLabel(tr("Debug port:"), this);
    m_debugServerPortLabel->setBuddy(m_debugServerPort);

    m_qmlDebuggerInfoLabel = new QLabel(tr("What are the prerequisites?"));

    static const QByteArray env = qgetenv("QTC_DEBUGGER_MULTIPROCESS");
    m_useMultiProcess =
        new QCheckBox(tr("Enable Debugging of Subprocesses"), this);
    m_useMultiProcess->setVisible(env.toInt());

    connect(m_qmlDebuggerInfoLabel, SIGNAL(linkActivated(QString)),
            Core::HelpManager::instance(), SLOT(handleHelpRequest(QString)));
    connect(m_useQmlDebugger, SIGNAL(toggled(bool)),
            SLOT(useQmlDebuggerToggled(bool)));
    connect(m_useCppDebugger, SIGNAL(toggled(bool)),
            SLOT(useCppDebuggerToggled(bool)));
    connect(m_debugServerPort, SIGNAL(valueChanged(int)),
            SLOT(qmlDebugServerPortChanged(int)));
    connect(m_useMultiProcess, SIGNAL(toggled(bool)),
            SLOT(useMultiProcessToggled(bool)));

    QHBoxLayout *qmlLayout = new QHBoxLayout;
    qmlLayout->setMargin(0);
    qmlLayout->addWidget(m_useQmlDebugger);
    qmlLayout->addWidget(m_debugServerPortLabel);
    qmlLayout->addWidget(m_debugServerPort);
    qmlLayout->addWidget(m_qmlDebuggerInfoLabel);
    qmlLayout->addStretch();

    QVBoxLayout *layout = new QVBoxLayout;
    layout->setMargin(0);
    layout->addWidget(m_useCppDebugger);
    layout->addLayout(qmlLayout);
    layout->addWidget(m_useMultiProcess);
    setLayout(layout);

    connect(aspect->runConfiguration()->target()->project(), SIGNAL(projectLanguagesUpdated()),
            this, SLOT(update()));
    update();
}

void DebuggerRunConfigWidget::update()
{
    m_useCppDebugger->setChecked(m_aspect->useCppDebugger());
    m_useQmlDebugger->setChecked(m_aspect->useQmlDebugger());

    m_debugServerPort->setValue(m_aspect->qmlDebugServerPort());

    m_useMultiProcess->setChecked(m_aspect->useMultiProcess());

    m_useQmlDebugger->setVisible(!m_aspect->areQmlDebuggingOptionsSuppressed());
    m_qmlDebuggerInfoLabel->setVisible(!m_aspect->areQmlDebuggingOptionsSuppressed());
    m_debugServerPortLabel->setVisible(!m_aspect->areQmlDebuggingOptionsSuppressed()
                                       && !m_aspect->isQmlDebuggingSpinboxSuppressed());
    m_debugServerPort->setVisible(!m_aspect->areQmlDebuggingOptionsSuppressed()
                                  && !m_aspect->isQmlDebuggingSpinboxSuppressed());

    m_useCppDebugger->setVisible(!m_aspect->areCppDebuggingOptionsSuppressed());
}

void DebuggerRunConfigWidget::qmlDebugServerPortChanged(int port)
{
    m_aspect->m_qmlDebugServerPort = port;
}

void DebuggerRunConfigWidget::useCppDebuggerToggled(bool on)
{
    m_aspect->m_useCppDebugger = on;
    if (!on && !m_useQmlDebugger->isChecked())
        m_useQmlDebugger->setChecked(true);
}

void DebuggerRunConfigWidget::useQmlDebuggerToggled(bool on)
{
    m_debugServerPort->setEnabled(on);
    m_debugServerPortLabel->setEnabled(on);

    m_aspect->m_useQmlDebugger = on
            ? DebuggerRunConfigurationAspect::EnableQmlDebugger
            : DebuggerRunConfigurationAspect::DisableQmlDebugger;
    if (!on && !m_useCppDebugger->isChecked())
        m_useCppDebugger->setChecked(true);
}

void DebuggerRunConfigWidget::useMultiProcessToggled(bool on)
{
    m_aspect->m_useMultiProcess = on;
}

} // namespace Internal

/*!
    \class Debugger::DebuggerRunConfigurationAspect
*/

DebuggerRunConfigurationAspect::DebuggerRunConfigurationAspect(
        ProjectExplorer::RunConfiguration *rc) :
    m_runConfiguration(rc),
    m_useCppDebugger(true),
    m_useQmlDebugger(AutoEnableQmlDebugger),
    m_qmlDebugServerPort(Constants::QML_DEFAULT_DEBUG_SERVER_PORT),
    m_useMultiProcess(false)
{
    ctor();
}

DebuggerRunConfigurationAspect::DebuggerRunConfigurationAspect(
        ProjectExplorer::RunConfiguration *runConfiguration,
        const DebuggerRunConfigurationAspect *other)
    : m_runConfiguration(runConfiguration),
      m_useCppDebugger(other->m_useCppDebugger),
      m_useQmlDebugger(other->m_useQmlDebugger),
      m_qmlDebugServerPort(other->m_qmlDebugServerPort),
      m_useMultiProcess(other->m_useMultiProcess)
{
    ctor();
}

ProjectExplorer::RunConfiguration *DebuggerRunConfigurationAspect::runConfiguration()
{
    return m_runConfiguration;
}

void DebuggerRunConfigurationAspect::setUseQmlDebugger(bool value)
{
    m_useQmlDebugger = value ? EnableQmlDebugger : DisableQmlDebugger;
    emit debuggersChanged();
}

void DebuggerRunConfigurationAspect::setUseCppDebugger(bool value)
{
    m_useCppDebugger = value;
    emit debuggersChanged();
}

bool DebuggerRunConfigurationAspect::useCppDebugger() const
{
    return m_useCppDebugger && !areCppDebuggingOptionsSuppressed();
}

bool DebuggerRunConfigurationAspect::useQmlDebugger() const
{
    if (areQmlDebuggingOptionsSuppressed())
        return false;
    if (m_useQmlDebugger == DebuggerRunConfigurationAspect::AutoEnableQmlDebugger)
        return m_runConfiguration->target()->project()->projectLanguages().contains(
                    ProjectExplorer::Constants::LANG_QMLJS);
    return m_useQmlDebugger == DebuggerRunConfigurationAspect::EnableQmlDebugger;
}

uint DebuggerRunConfigurationAspect::qmlDebugServerPort() const
{
    return m_qmlDebugServerPort;
}

void DebuggerRunConfigurationAspect::setQmllDebugServerPort(uint port)
{
    m_qmlDebugServerPort = port;
}

bool DebuggerRunConfigurationAspect::useMultiProcess() const
{
    return m_useMultiProcess;
}

void DebuggerRunConfigurationAspect::setUseMultiProcess(bool value)
{
    m_useMultiProcess = value;
}

bool DebuggerRunConfigurationAspect::areQmlDebuggingOptionsSuppressed() const
{
    return !m_runConfiguration->target()->project()
            ->projectLanguages().contains(ProjectExplorer::Constants::LANG_QMLJS);
}

bool DebuggerRunConfigurationAspect::areCppDebuggingOptionsSuppressed() const
{
    return !m_runConfiguration->target()->project()
            ->projectLanguages().contains(ProjectExplorer::Constants::LANG_CXX);
}

bool DebuggerRunConfigurationAspect::isQmlDebuggingSpinboxSuppressed() const
{
    ProjectExplorer::Kit *k = m_runConfiguration->target()->kit();
    ProjectExplorer::IDevice::ConstPtr dev = ProjectExplorer::DeviceKitInformation::device(k);
    if (dev.isNull())
        return false;
    return dev->portsGatheringMethod().isNull(); // We know the free ports...
}

QString DebuggerRunConfigurationAspect::displayName() const
{
    return tr("Debugger settings");
}

QVariantMap DebuggerRunConfigurationAspect::toMap() const
{
    QVariantMap map;
    map.insert(QLatin1String(USE_CPP_DEBUGGER_KEY), m_useCppDebugger);
    map.insert(QLatin1String(USE_QML_DEBUGGER_KEY), m_useQmlDebugger == EnableQmlDebugger);
    map.insert(QLatin1String(USE_QML_DEBUGGER_AUTO_KEY), m_useQmlDebugger == AutoEnableQmlDebugger);
    map.insert(QLatin1String(QML_DEBUG_SERVER_PORT_KEY), m_qmlDebugServerPort);
    map.insert(QLatin1String(USE_MULTIPROCESS_KEY), m_useMultiProcess);
    return map;
}

void DebuggerRunConfigurationAspect::fromMap(const QVariantMap &map)
{
    m_useCppDebugger = map.value(QLatin1String(USE_CPP_DEBUGGER_KEY), true).toBool();
    if (map.value(QLatin1String(USE_QML_DEBUGGER_AUTO_KEY), false).toBool()) {
        m_useQmlDebugger = AutoEnableQmlDebugger;
    } else {
        bool useQml = map.value(QLatin1String(USE_QML_DEBUGGER_KEY), false).toBool();
        m_useQmlDebugger = useQml ? EnableQmlDebugger : DisableQmlDebugger;
    }
    m_useMultiProcess = map.value(QLatin1String(USE_MULTIPROCESS_KEY), false).toBool();
}

DebuggerRunConfigurationAspect *DebuggerRunConfigurationAspect::clone(
        ProjectExplorer::RunConfiguration *parent) const
{
    return new DebuggerRunConfigurationAspect(parent, this);
}

ProjectExplorer::RunConfigWidget *DebuggerRunConfigurationAspect::createConfigurationWidget()
{
    if (areCppDebuggingOptionsSuppressed() && areQmlDebuggingOptionsSuppressed())
        return 0;
    return new Internal::DebuggerRunConfigWidget(this);
}

void DebuggerRunConfigurationAspect::ctor()
{
    connect(this, SIGNAL(debuggersChanged()),
            m_runConfiguration, SIGNAL(requestRunActionsUpdate()));
    setUseCppDebugger(!areCppDebuggingOptionsSuppressed());
    setUseQmlDebugger(!areQmlDebuggingOptionsSuppressed());
}

} // namespace Debugger

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


<commit_before>/*
 * This file is part of TelepathyQt4
 *
 * Copyright (C) 2011 Collabora Ltd. <http://www.collabora.co.uk/>
 * Copyright (C) David Edmundson <kde@davidedmundson.co.uk>
 *
 * 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., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 */

#include "handler-auth.h"

#include <TelepathyQt4/PendingVariant>

#include <KDebug>

#include "password-prompt.h"

HandlerAuth::HandlerAuth(const Tp::AccountPtr &account,
    const Tp::ConnectionPtr &connection,
    const Tp::ChannelPtr &channel)
    : Tp::PendingOperation(channel),
      m_account(account),
      m_connection(connection),
      m_channel(new SaslChannel(channel))
{
    m_wallet = KWallet::Wallet::openWallet(KWallet::Wallet::NetworkWallet(),
                                  0,
                                  KWallet::Wallet::Asynchronous);

    Tp::Client::ChannelInterfaceSASLAuthenticationInterface *saslIface =
        channel->interface<Tp::Client::ChannelInterfaceSASLAuthenticationInterface>();
    connect(saslIface,
            SIGNAL(SASLStatusChanged(uint,QString,QVariantMap)),
            SLOT(onSASLStatusChanged(uint,QString,QVariantMap)));
    connect(saslIface->requestPropertyAvailableMechanisms(),
            SIGNAL(finished(Tp::PendingOperation*)),
            SLOT(gotAvailableSASLMechanisms(Tp::PendingOperation*)));
}

HandlerAuth::~HandlerAuth()
{
}

void HandlerAuth::gotAvailableSASLMechanisms(Tp::PendingOperation *op)
{
    if (op->isError()) {
        kWarning() << "Unable to retrieve available SASL mechanisms";
        setFinishedWithError(op->errorName(), op->errorMessage());
        return;
    }

    Tp::PendingVariant *pv = qobject_cast<Tp::PendingVariant*>(op);
    QStringList mechanisms = qdbus_cast<QStringList>(pv->result());
    if (!mechanisms.contains(QLatin1String("X-TELEPATHY-PASSWORD"))) {
        setFinishedWithError(TP_QT4_ERROR_NOT_IMPLEMENTED,
                QLatin1String("X-TELEPATHY-PASSWORD is the only supported SASL mechanisms"));
        return;
    }

    promptUser(true);
}

void HandlerAuth::onSASLStatusChanged(uint status, const QString &reason,
        const QVariantMap &details)
{
    if (status == Tp::SASLStatusServerSucceeded) {

        m_channel->acceptSasl();
        kDebug() << "Authentication handshake";
    } else if (status == Tp::SASLStatusSucceeded) {
        kDebug() << "Authentication succeeded";
        setFinished();
    } else if (status == Tp::SASLStatusInProgress) {
        kDebug() << "Authenticating...";
    } else if (status == Tp::SASLStatusServerFailed) {
        kDebug() << "Error authenticating - reason:" << reason << "- details:" << details;

        //FIXME add - if can retry.
        promptUser(false);
    }
}

void HandlerAuth::promptUser(bool isFirstRun)
{
    //if we have a password

    kDebug() << "trying to load from wallet";
    if (m_wallet->hasFolder("telepathy") && isFirstRun) {
        m_wallet->setFolder("telepathy");

        QString password;
        kDebug() << "has telepathy folder";

        if (m_wallet->hasEntry(m_account->uniqueIdentifier())) {
            kDebug() << "has entry";

            int returnValue = m_wallet->readPassword(m_account->uniqueIdentifier(), password);
            if (returnValue == 0) {
                kDebug() << "using saved password";
                m_channel->startMechanismWithData(QLatin1String("X-TELEPATHY-PASSWORD"),
                                                  password.toUtf8());
                return;
            }
            else {
                kDebug() << "Error reading wallet entry";
            }
        }
    }

    //otherwise prompt the user

    PasswordPrompt dialog(m_account);

    if (dialog.exec() == QDialog::Rejected) {
        kDebug() << "Authentication canceled";
        m_channel->close();
        return;
    }

    kDebug() << "Starting authentication...";

    m_channel->startMechanismWithData(QLatin1String("X-TELEPATHY-PASSWORD"),
            dialog.password().toUtf8());

    //save password in kwallet...
    if (dialog.savePassword()) {
        kDebug() << "Saving password";
        if (!m_wallet->hasFolder("telepathy")) {
            m_wallet->createFolder("telepathy");
        }
        m_wallet->setFolder("telepathy");
        m_wallet->writePassword(m_account->uniqueIdentifier(), dialog.password());
    }
}

#include "handler-auth.moc"
<commit_msg>Change KWallet folder name to telepathy-kde to get a nice icon in the wallet manager<commit_after>/*
 * This file is part of TelepathyQt4
 *
 * Copyright (C) 2011 Collabora Ltd. <http://www.collabora.co.uk/>
 * Copyright (C) David Edmundson <kde@davidedmundson.co.uk>
 *
 * 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., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 */

#include "handler-auth.h"

#include <TelepathyQt4/PendingVariant>

#include <KDebug>

#include "password-prompt.h"

HandlerAuth::HandlerAuth(const Tp::AccountPtr &account,
    const Tp::ConnectionPtr &connection,
    const Tp::ChannelPtr &channel)
    : Tp::PendingOperation(channel),
      m_account(account),
      m_connection(connection),
      m_channel(new SaslChannel(channel))
{
    m_wallet = KWallet::Wallet::openWallet(KWallet::Wallet::NetworkWallet(),
                                  0,
                                  KWallet::Wallet::Asynchronous);

    Tp::Client::ChannelInterfaceSASLAuthenticationInterface *saslIface =
        channel->interface<Tp::Client::ChannelInterfaceSASLAuthenticationInterface>();
    connect(saslIface,
            SIGNAL(SASLStatusChanged(uint,QString,QVariantMap)),
            SLOT(onSASLStatusChanged(uint,QString,QVariantMap)));
    connect(saslIface->requestPropertyAvailableMechanisms(),
            SIGNAL(finished(Tp::PendingOperation*)),
            SLOT(gotAvailableSASLMechanisms(Tp::PendingOperation*)));
}

HandlerAuth::~HandlerAuth()
{
}

void HandlerAuth::gotAvailableSASLMechanisms(Tp::PendingOperation *op)
{
    if (op->isError()) {
        kWarning() << "Unable to retrieve available SASL mechanisms";
        setFinishedWithError(op->errorName(), op->errorMessage());
        return;
    }

    Tp::PendingVariant *pv = qobject_cast<Tp::PendingVariant*>(op);
    QStringList mechanisms = qdbus_cast<QStringList>(pv->result());
    if (!mechanisms.contains(QLatin1String("X-TELEPATHY-PASSWORD"))) {
        setFinishedWithError(TP_QT4_ERROR_NOT_IMPLEMENTED,
                QLatin1String("X-TELEPATHY-PASSWORD is the only supported SASL mechanisms"));
        return;
    }

    promptUser(true);
}

void HandlerAuth::onSASLStatusChanged(uint status, const QString &reason,
        const QVariantMap &details)
{
    if (status == Tp::SASLStatusServerSucceeded) {

        m_channel->acceptSasl();
        kDebug() << "Authentication handshake";
    } else if (status == Tp::SASLStatusSucceeded) {
        kDebug() << "Authentication succeeded";
        setFinished();
    } else if (status == Tp::SASLStatusInProgress) {
        kDebug() << "Authenticating...";
    } else if (status == Tp::SASLStatusServerFailed) {
        kDebug() << "Error authenticating - reason:" << reason << "- details:" << details;

        //FIXME add - if can retry.
        promptUser(false);
    }
}

void HandlerAuth::promptUser(bool isFirstRun)
{
    //if we have a password

    kDebug() << "trying to load from wallet";
    if (m_wallet->hasFolder("telepathy") && isFirstRun) {
        m_wallet->setFolder("telepathy");

        QString password;
        kDebug() << "has telepathy folder";

        if (m_wallet->hasEntry(m_account->uniqueIdentifier())) {
            kDebug() << "has entry";

            int returnValue = m_wallet->readPassword(m_account->uniqueIdentifier(), password);
            if (returnValue == 0) {
                kDebug() << "using saved password";
                m_channel->startMechanismWithData(QLatin1String("X-TELEPATHY-PASSWORD"),
                                                  password.toUtf8());
                return;
            }
            else {
                kDebug() << "Error reading wallet entry";
            }
        }
    }

    //otherwise prompt the user

    PasswordPrompt dialog(m_account);

    if (dialog.exec() == QDialog::Rejected) {
        kDebug() << "Authentication canceled";
        m_channel->close();
        return;
    }

    kDebug() << "Starting authentication...";

    m_channel->startMechanismWithData(QLatin1String("X-TELEPATHY-PASSWORD"),
            dialog.password().toUtf8());

    //save password in kwallet...
    if (dialog.savePassword()) {
        kDebug() << "Saving password";
        if (!m_wallet->hasFolder("telepathy-kde")) {
            m_wallet->createFolder("telepathy-kde");
        }
        m_wallet->setFolder("telepathy-kde");
        m_wallet->writePassword(m_account->uniqueIdentifier(), dialog.password());
    }
}

#include "handler-auth.moc"
<|endoftext|>


<commit_before>/** \brief Implementation of writer classes for MARC files.
 *  \author Oliver Obenland (oliver.obenland@uni-tuebingen.de)
 *  \author Dr. Johannes Ruscheinski (johannes.ruscheinski@uni-tuebingen.de)
 *
 *  \copyright 2017 Universitätsbibliothek Tübingen.  All rights reserved.
 *
 *  This program is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU Affero General Public License as
 *  published by the Free Software Foundation, either version 3 of the
 *  License, or (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU Affero General Public License for more details.
 *
 *  You should have received a copy of the GNU Affero General Public License
 *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

#include "MarcRecord.h"
#include "Compiler.h"
#include "FileUtil.h"
#include "MarcWriter.h"
#include "StringUtil.h"
#include "util.h"

static const size_t MAX_MARC_21_RECORD_LENGTH(99999);
static char write_buffer[MAX_MARC_21_RECORD_LENGTH]; // Possibly too big for the stack!

// Returns true if we can add the new field to our record w/o overflowing the maximum size of a binary
// MARC-21 record, o/w we return false.
static bool inline NewFieldDoesFit(const size_t base_address, const size_t current_record_length,
                                   const size_t next_field_length)
{
    return base_address + DirectoryEntry::DIRECTORY_ENTRY_LENGTH + current_record_length + next_field_length
           + 1 /* for the field terminator byte */ <= MAX_MARC_21_RECORD_LENGTH;
}

/**
 * We determine the record dimensions by adding sizes of fields one-by-one (starting with the field represented by
 * "directory_iter") while we do not overflow the maximum
 * size of a binary MARC-21 record.
 */
static void inline DetermineRecordDimensions(const size_t control_number_field_length,
                                             std::vector<DirectoryEntry>::const_iterator directory_iter,
                                             const std::vector<DirectoryEntry>::const_iterator &end_iter,
                                             size_t * const number_of_directory_entries, size_t * const base_address,
                                             size_t * const record_length)
{
    *number_of_directory_entries = 0;
    *base_address = DirectoryEntry::DIRECTORY_ENTRY_LENGTH /* for the control number field */
                    + Leader::LEADER_LENGTH + 1 /* for directory separator byte */;
    *record_length = control_number_field_length + 1 /* for end of record byte */;

    // Now we add fields one-by-one while taking care not to overflow the maximum record size:
    for (/* empty */;
         directory_iter < end_iter
         and NewFieldDoesFit(*base_address, *record_length, directory_iter->getFieldLength());
         ++directory_iter)
    {
        *base_address += DirectoryEntry::DIRECTORY_ENTRY_LENGTH;
        *record_length += directory_iter->getFieldLength();
        ++*number_of_directory_entries;
    }

    *record_length += *base_address;
}

static void inline WriteToBuffer(char *&dest, const std::string &data) {
    std::memcpy(dest, data.data(), data.size());
    dest += data.size();
}

static void inline WriteToBuffer(char *&dest, const char * const source, size_t offset, size_t length) {
    std::memcpy(dest, source + offset, length);
    dest += length;
}

static void inline WriteDirEntryToBuffer(char *&directory_pointer, const DirectoryEntry &dir_entry) {
    const MarcTag &tag(dir_entry.getTag());
    WriteToBuffer(directory_pointer, tag.c_str(), DirectoryEntry::TAG_LENGTH, 0);
    WriteToBuffer(directory_pointer, StringUtil::PadLeading(std::to_string(dir_entry.getFieldLength()), 4, '0'));
    WriteToBuffer(directory_pointer, StringUtil::PadLeading(std::to_string(dir_entry.getFieldOffset()), 5, '0'));
}

void BinaryMarcWriter::write(const MarcRecord &record) {
    const std::string control_number(record.getControlNumber());
    const size_t control_number_field_length(control_number.size() + 1);

    auto directory_iter(record.directory_entries_.cbegin());
    if (unlikely(directory_iter == record.directory_entries_.cend()))
        Error("BinaryMarcWriter::write: can't write a record w/ an empty directory!");
    if (unlikely(directory_iter->getTag() != "001"))
        Error("BinaryMarcWriter::write: first directory entry has to be 001! Found: "
              + directory_iter->getTag().to_string() + " (Control number: " + record.getControlNumber() + ")");
    ++directory_iter;

    while (directory_iter < record.directory_entries_.cend()) {
        size_t number_of_directory_entries, record_length, base_address;
        DetermineRecordDimensions(control_number_field_length, directory_iter, record.directory_entries_.cend(),
                                  &number_of_directory_entries, &base_address, &record_length);

        // Update and write the leader:
        char *leader_pointer(write_buffer);
        record.leader_.setBaseAddressOfData(base_address);
        record.leader_.setRecordLength(record_length);
        record.leader_.setMultiPartRecord(directory_iter + number_of_directory_entries + 1
                                          < record.directory_entries_.cend());
        WriteToBuffer(leader_pointer, record.leader_.toString());

        // Write a control number directory entry for each record as the first entry in the directory section:
        char *directory_pointer(write_buffer + Leader::LEADER_LENGTH);
        WriteDirEntryToBuffer(directory_pointer, record.directory_entries_.front());

        size_t field_data_offset(0);
        size_t field_data_length(control_number_field_length);
        size_t written_data_offset(control_number_field_length);

        const std::vector<DirectoryEntry>::const_iterator end_iter(directory_iter + number_of_directory_entries);
        char *field_data_pointer(write_buffer + base_address);
        for (; directory_iter < end_iter; ++directory_iter) {
            WriteDirEntryToBuffer(directory_pointer, *directory_iter);

            if (field_data_offset + field_data_length == directory_iter->getFieldOffset()) {
                field_data_length += directory_iter->getFieldLength();
            } else {
                WriteToBuffer(field_data_pointer, record.field_data_.data(), field_data_offset, field_data_length);
                field_data_offset = directory_iter->getFieldOffset();
                field_data_length = directory_iter->getFieldLength();
            }

            written_data_offset += directory_iter->getFieldLength();
        }
        WriteToBuffer(directory_pointer, "\x1E");
        WriteToBuffer(field_data_pointer, record.field_data_.data(), field_data_offset, field_data_length);
        WriteToBuffer(field_data_pointer, "\x1D");
        output_->write(write_buffer, record_length);
    }
}

XmlMarcWriter::XmlMarcWriter(File * const output_file, const unsigned indent_amount,
                             const XmlWriter::TextConversionType text_conversion_type)
{
    xml_writer_ = new MarcXmlWriter(output_file, indent_amount, text_conversion_type);
}

void XmlMarcWriter::write(const MarcRecord &record) {
    xml_writer_->openTag("marc:record");

    record.leader_.setRecordLength(0);
    record.leader_.setBaseAddressOfData(0);
    xml_writer_->writeTagsWithData("marc:leader", record.leader_.toString(), /* suppress_newline = */ true);

    for (unsigned entry_no(0); entry_no < record.directory_entries_.size(); ++entry_no) {
        const DirectoryEntry &dir_entry(record.directory_entries_[entry_no]);
        if (dir_entry.isControlFieldEntry())
            xml_writer_->writeTagsWithData("marc:controlfield",
                                           { std::make_pair("tag", dir_entry.getTag().to_string()) },
                                           record.getFieldData(entry_no),
                    /* suppress_newline = */ true);
        else { // We have a data field.
            const std::string data(record.getFieldData(entry_no));
            xml_writer_->openTag("marc:datafield",
                                { std::make_pair("tag", dir_entry.getTag().to_string()),
                                  std::make_pair("ind1", std::string(1, data[0])),
                                  std::make_pair("ind2", std::string(1, data[1]))
                                });

            std::string::const_iterator ch(data.cbegin() + 2 /* Skip over the indicators. */);

            while (ch != data.cend()) {
                if (*ch != '\x1F')
                    std::runtime_error("in XmlMarcWriter::write: expected subfield code delimiter not found! Found "
                                       + std::string(1, *ch) + "! (Control number is " + record.getControlNumber()
                                       + ".)");

                ++ch;
                if (ch == data.cend())
                    std::runtime_error("in XmlMarcWriter::write: unexpected subfield data end while expecting a "
                                       "subfield code!");
                const std::string subfield_code(1, *ch++);

                std::string subfield_data;
                while (ch != data.cend() and *ch != '\x1F')
                    subfield_data += *ch++;
                if (subfield_data.empty())
                    continue;

                xml_writer_->writeTagsWithData("marc:subfield", { std::make_pair("code", subfield_code) },
                                              subfield_data, /* suppress_newline = */ true);
            }

            xml_writer_->closeTag(); // Close "marc:datafield".
        }
    }

    xml_writer_->closeTag(); // Close "marc:record".
}

std::unique_ptr<MarcWriter> MarcWriter::Factory(const std::string &output_filename, WriterType writer_type,
                                                const WriterMode writer_mode)
{
    std::unique_ptr<File> output(writer_mode == WriterMode::OVERWRITE ? FileUtil::OpenOutputFileOrDie(output_filename)
                                                                      : FileUtil::OpenForAppeningOrDie(output_filename));
    if (writer_type == AUTO) {
        if (StringUtil::EndsWith(output_filename, ".mrc") or StringUtil::EndsWith(output_filename, ".marc"))
            writer_type = BINARY;
        else if (StringUtil::EndsWith(output_filename, ".xml"))
            writer_type = XML;
        else
            throw std::runtime_error("in MarcWriter::Factory: WriterType is AUTO but filename \""
                                     + output_filename + "\" does not end in \".mrc\" or \".xml\"!");
    }
    return (writer_type == XML) ? std::unique_ptr<MarcWriter>(new XmlMarcWriter(output.release()))
                                : std::unique_ptr<MarcWriter>(new BinaryMarcWriter(output.release()));
}
<commit_msg>Final(?) cleanup.<commit_after>/** \brief Implementation of writer classes for MARC files.
 *  \author Oliver Obenland (oliver.obenland@uni-tuebingen.de)
 *  \author Dr. Johannes Ruscheinski (johannes.ruscheinski@uni-tuebingen.de)
 *
 *  \copyright 2017 Universitätsbibliothek Tübingen.  All rights reserved.
 *
 *  This program is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU Affero General Public License as
 *  published by the Free Software Foundation, either version 3 of the
 *  License, or (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU Affero General Public License for more details.
 *
 *  You should have received a copy of the GNU Affero General Public License
 *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

#include "MarcRecord.h"
#include "Compiler.h"
#include "FileUtil.h"
#include "MarcWriter.h"
#include "StringUtil.h"
#include "util.h"

static const size_t MAX_MARC_21_RECORD_LENGTH(99999);
static char write_buffer[MAX_MARC_21_RECORD_LENGTH]; // Possibly too big for the stack!

// Returns true if we can add the new field to our record w/o overflowing the maximum size of a binary
// MARC-21 record, o/w we return false.
static bool inline NewFieldDoesFit(const size_t base_address, const size_t current_record_length,
                                   const size_t next_field_length)
{
    return base_address + DirectoryEntry::DIRECTORY_ENTRY_LENGTH + current_record_length + next_field_length
           + 1 /* for the field terminator byte */ <= MAX_MARC_21_RECORD_LENGTH;
}

/**
 * We determine the record dimensions by adding sizes of fields one-by-one (starting with the field represented by
 * "directory_iter") while we do not overflow the maximum
 * size of a binary MARC-21 record.
 */
static void inline DetermineRecordDimensions(const size_t control_number_field_length,
                                             std::vector<DirectoryEntry>::const_iterator directory_iter,
                                             const std::vector<DirectoryEntry>::const_iterator &end_iter,
                                             size_t * const number_of_directory_entries, size_t * const base_address,
                                             size_t * const record_length)
{
    *number_of_directory_entries = 0;
    *base_address = DirectoryEntry::DIRECTORY_ENTRY_LENGTH /* for the control number field */
                    + Leader::LEADER_LENGTH + 1 /* for directory separator byte */;
    *record_length = control_number_field_length + 1 /* for end of record byte */;

    // Now we add fields one-by-one while taking care not to overflow the maximum record size:
    for (/* empty */;
         directory_iter < end_iter
         and NewFieldDoesFit(*base_address, *record_length, directory_iter->getFieldLength());
         ++directory_iter)
    {
        *base_address += DirectoryEntry::DIRECTORY_ENTRY_LENGTH;
        *record_length += directory_iter->getFieldLength();
        ++*number_of_directory_entries;
    }

    *record_length += *base_address;
}

static void inline WriteToBuffer(char *&dest, const std::string &data) {
    std::memcpy(dest, data.data(), data.size());
    dest += data.size();
}

static void inline WriteToBuffer(char *&dest, const char * const source, size_t offset, size_t length) {
    std::memcpy(dest, source + offset, length);
    dest += length;
}

static void inline WriteDirEntryToBuffer(char *&directory_pointer, const DirectoryEntry &dir_entry) {
    const MarcTag &tag(dir_entry.getTag());
    WriteToBuffer(directory_pointer, tag.c_str(), DirectoryEntry::TAG_LENGTH, 0);
    WriteToBuffer(directory_pointer, StringUtil::PadLeading(std::to_string(dir_entry.getFieldLength()), 4, '0'));
    WriteToBuffer(directory_pointer, StringUtil::PadLeading(std::to_string(dir_entry.getFieldOffset()), 5, '0'));
}

void BinaryMarcWriter::write(const MarcRecord &record) {
    const std::string control_number(record.getControlNumber());
    const size_t control_number_field_length(control_number.size() + 1);

    auto directory_iter(record.directory_entries_.cbegin());
    if (unlikely(directory_iter == record.directory_entries_.cend()))
        Error("BinaryMarcWriter::write: can't write a record w/ an empty directory!");
    if (unlikely(directory_iter->getTag() != "001"))
        Error("BinaryMarcWriter::write: first directory entry has to be 001! Found: "
              + directory_iter->getTag().to_string() + " (Control number: " + record.getControlNumber() + ")");
    ++directory_iter;

    while (directory_iter < record.directory_entries_.cend()) {
        size_t number_of_directory_entries, record_length, base_address_of_data;
        DetermineRecordDimensions(control_number_field_length, directory_iter, record.directory_entries_.cend(),
                                  &number_of_directory_entries, &base_address_of_data, &record_length);

        // Update and write the leader:
        char *leader_pointer(write_buffer);
        record.leader_.setBaseAddressOfData(base_address_of_data);
        record.leader_.setRecordLength(record_length);
        record.leader_.setMultiPartRecord(directory_iter + number_of_directory_entries + 1
                                          < record.directory_entries_.cend());
        WriteToBuffer(leader_pointer, record.leader_.toString());

        // Write a control number directory entry for each record as the first entry in the directory section:
        char *directory_pointer(write_buffer + Leader::LEADER_LENGTH);
        WriteDirEntryToBuffer(directory_pointer, record.directory_entries_.front());

        size_t field_data_offset(0);
        size_t field_data_length(control_number_field_length);

        const std::vector<DirectoryEntry>::const_iterator end_iter(directory_iter + number_of_directory_entries);
        char *field_data_pointer(write_buffer + base_address_of_data);
        for (; directory_iter < end_iter; ++directory_iter) {
            WriteDirEntryToBuffer(directory_pointer, *directory_iter);
            WriteToBuffer(field_data_pointer, record.field_data_.data(), field_data_offset, field_data_length);
            field_data_offset = directory_iter->getFieldOffset();
            field_data_length = directory_iter->getFieldLength();
        }
        WriteToBuffer(directory_pointer, "\x1E");
        WriteToBuffer(field_data_pointer, "\x1D");
        output_->write(write_buffer, record_length);
    }
}

XmlMarcWriter::XmlMarcWriter(File * const output_file, const unsigned indent_amount,
                             const XmlWriter::TextConversionType text_conversion_type)
{
    xml_writer_ = new MarcXmlWriter(output_file, indent_amount, text_conversion_type);
}

void XmlMarcWriter::write(const MarcRecord &record) {
    xml_writer_->openTag("marc:record");

    record.leader_.setRecordLength(0);
    record.leader_.setBaseAddressOfData(0);
    xml_writer_->writeTagsWithData("marc:leader", record.leader_.toString(), /* suppress_newline = */ true);

    for (unsigned entry_no(0); entry_no < record.directory_entries_.size(); ++entry_no) {
        const DirectoryEntry &dir_entry(record.directory_entries_[entry_no]);
        if (dir_entry.isControlFieldEntry())
            xml_writer_->writeTagsWithData("marc:controlfield",
                                           { std::make_pair("tag", dir_entry.getTag().to_string()) },
                                           record.getFieldData(entry_no),
                    /* suppress_newline = */ true);
        else { // We have a data field.
            const std::string data(record.getFieldData(entry_no));
            xml_writer_->openTag("marc:datafield",
                                { std::make_pair("tag", dir_entry.getTag().to_string()),
                                  std::make_pair("ind1", std::string(1, data[0])),
                                  std::make_pair("ind2", std::string(1, data[1]))
                                });

            std::string::const_iterator ch(data.cbegin() + 2 /* Skip over the indicators. */);

            while (ch != data.cend()) {
                if (*ch != '\x1F')
                    std::runtime_error("in XmlMarcWriter::write: expected subfield code delimiter not found! Found "
                                       + std::string(1, *ch) + "! (Control number is " + record.getControlNumber()
                                       + ".)");

                ++ch;
                if (ch == data.cend())
                    std::runtime_error("in XmlMarcWriter::write: unexpected subfield data end while expecting a "
                                       "subfield code!");
                const std::string subfield_code(1, *ch++);

                std::string subfield_data;
                while (ch != data.cend() and *ch != '\x1F')
                    subfield_data += *ch++;
                if (subfield_data.empty())
                    continue;

                xml_writer_->writeTagsWithData("marc:subfield", { std::make_pair("code", subfield_code) },
                                              subfield_data, /* suppress_newline = */ true);
            }

            xml_writer_->closeTag(); // Close "marc:datafield".
        }
    }

    xml_writer_->closeTag(); // Close "marc:record".
}

std::unique_ptr<MarcWriter> MarcWriter::Factory(const std::string &output_filename, WriterType writer_type,
                                                const WriterMode writer_mode)
{
    std::unique_ptr<File> output(writer_mode == WriterMode::OVERWRITE ? FileUtil::OpenOutputFileOrDie(output_filename)
                                                                      : FileUtil::OpenForAppeningOrDie(output_filename));
    if (writer_type == AUTO) {
        if (StringUtil::EndsWith(output_filename, ".mrc") or StringUtil::EndsWith(output_filename, ".marc"))
            writer_type = BINARY;
        else if (StringUtil::EndsWith(output_filename, ".xml"))
            writer_type = XML;
        else
            throw std::runtime_error("in MarcWriter::Factory: WriterType is AUTO but filename \""
                                     + output_filename + "\" does not end in \".mrc\" or \".xml\"!");
    }
    return (writer_type == XML) ? std::unique_ptr<MarcWriter>(new XmlMarcWriter(output.release()))
                                : std::unique_ptr<MarcWriter>(new BinaryMarcWriter(output.release()));
}
<|endoftext|>


<commit_before>/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/*
 * Copyright 2015 Cloudius Systems
 *
 * Modified by Cloudius Systems
 */

/*
 * This file is part of Scylla.
 *
 * Scylla is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * Scylla is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with Scylla.  If not, see <http://www.gnu.org/licenses/>.
 */

#pragma once

#include "cql3/selection/selectable.hh"

#include "schema.hh"

#include <algorithm>
#include <functional>
#include <iostream>

namespace cql3 {

/**
 * Represents an identifer for a CQL column definition.
 * TODO : should support light-weight mode without text representation for when not interned
 */
class column_identifier final : public selection::selectable /* implements IMeasurableMemory*/ {
public:
    bytes bytes_;
private:
    sstring _text;
#if 0
    private static final long EMPTY_SIZE = ObjectSizes.measure(new ColumnIdentifier("", true));
#endif
public:
    column_identifier(sstring raw_text, bool keep_case);

    column_identifier(bytes bytes_, data_type type);

    column_identifier(bytes bytes_, sstring text);

    bool operator==(const column_identifier& other) const;

    const sstring& text() const;

    const bytes& name() const;

    sstring to_string() const;

    friend std::ostream& operator<<(std::ostream& out, const column_identifier& i) {
        return out << i._text;
    }

#if 0
    public long unsharedHeapSize()
    {
        return EMPTY_SIZE
             + ObjectSizes.sizeOnHeapOf(bytes)
             + ObjectSizes.sizeOf(text);
    }

    public long unsharedHeapSizeExcludingData()
    {
        return EMPTY_SIZE
             + ObjectSizes.sizeOnHeapExcludingData(bytes)
             + ObjectSizes.sizeOf(text);
    }

    public ColumnIdentifier clone(AbstractAllocator allocator)
    {
        return new ColumnIdentifier(allocator.clone(bytes), text);
    }
#endif

    virtual ::shared_ptr<selection::selector::factory> new_selector_factory(database& db, schema_ptr schema,
        std::vector<const column_definition*>& defs) override;

    class raw;
};

/**
 * Because Thrift-created tables may have a non-text comparator, we cannot determine the proper 'key' until
 * we know the comparator. ColumnIdentifier.Raw is a placeholder that can be converted to a real ColumnIdentifier
 * once the comparator is known with prepare(). This should only be used with identifiers that are actual
 * column names. See CASSANDRA-8178 for more background.
 */
class column_identifier::raw final : public selectable::raw {
private:
    const sstring _raw_text;
    sstring _text;
public:
    raw(sstring raw_text, bool keep_case);

    virtual ::shared_ptr<selectable> prepare(schema_ptr s) override;

    ::shared_ptr<column_identifier> prepare_column_identifier(schema_ptr s);

    virtual bool processes_selection() const override;

    bool operator==(const raw& other) const;

    bool operator!=(const raw& other) const;

    virtual sstring to_string() const;

    friend std::hash<column_identifier::raw>;
    friend std::ostream& operator<<(std::ostream& out, const column_identifier::raw& id);
};

static inline
const column_definition* get_column_definition(schema_ptr schema, const column_identifier& id) {
    return schema->get_column_definition(id.bytes_);
}

static inline
::shared_ptr<column_identifier> to_identifier(const column_definition& def) {
    return def.column_specification->name;
}

static inline
std::vector<::shared_ptr<column_identifier>> to_identifiers(const std::vector<const column_definition*>& defs) {
    std::vector<::shared_ptr<column_identifier>> r;
    r.reserve(defs.size());
    for (auto&& def : defs) {
        r.push_back(to_identifier(*def));
    }
    return r;
}

}

namespace std {

template<>
struct hash<cql3::column_identifier> {
    size_t operator()(const cql3::column_identifier& i) const {
        return std::hash<bytes>()(i.bytes_);
    }
};

template<>
struct hash<cql3::column_identifier::raw> {
    size_t operator()(const cql3::column_identifier::raw& r) const {
        return std::hash<sstring>()(r._text);
    }
};

}
<commit_msg>cql3: Remove untranslated IMeasurableMemory code from column_identifier<commit_after>/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/*
 * Copyright 2015 Cloudius Systems
 *
 * Modified by Cloudius Systems
 */

/*
 * This file is part of Scylla.
 *
 * Scylla is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * Scylla is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with Scylla.  If not, see <http://www.gnu.org/licenses/>.
 */

#pragma once

#include "cql3/selection/selectable.hh"

#include "schema.hh"

#include <algorithm>
#include <functional>
#include <iostream>

namespace cql3 {

/**
 * Represents an identifer for a CQL column definition.
 * TODO : should support light-weight mode without text representation for when not interned
 */
class column_identifier final : public selection::selectable {
public:
    bytes bytes_;
private:
    sstring _text;
public:
    column_identifier(sstring raw_text, bool keep_case);

    column_identifier(bytes bytes_, data_type type);

    column_identifier(bytes bytes_, sstring text);

    bool operator==(const column_identifier& other) const;

    const sstring& text() const;

    const bytes& name() const;

    sstring to_string() const;

    friend std::ostream& operator<<(std::ostream& out, const column_identifier& i) {
        return out << i._text;
    }

#if 0
    public ColumnIdentifier clone(AbstractAllocator allocator)
    {
        return new ColumnIdentifier(allocator.clone(bytes), text);
    }
#endif

    virtual ::shared_ptr<selection::selector::factory> new_selector_factory(database& db, schema_ptr schema,
        std::vector<const column_definition*>& defs) override;

    class raw;
};

/**
 * Because Thrift-created tables may have a non-text comparator, we cannot determine the proper 'key' until
 * we know the comparator. ColumnIdentifier.Raw is a placeholder that can be converted to a real ColumnIdentifier
 * once the comparator is known with prepare(). This should only be used with identifiers that are actual
 * column names. See CASSANDRA-8178 for more background.
 */
class column_identifier::raw final : public selectable::raw {
private:
    const sstring _raw_text;
    sstring _text;
public:
    raw(sstring raw_text, bool keep_case);

    virtual ::shared_ptr<selectable> prepare(schema_ptr s) override;

    ::shared_ptr<column_identifier> prepare_column_identifier(schema_ptr s);

    virtual bool processes_selection() const override;

    bool operator==(const raw& other) const;

    bool operator!=(const raw& other) const;

    virtual sstring to_string() const;

    friend std::hash<column_identifier::raw>;
    friend std::ostream& operator<<(std::ostream& out, const column_identifier::raw& id);
};

static inline
const column_definition* get_column_definition(schema_ptr schema, const column_identifier& id) {
    return schema->get_column_definition(id.bytes_);
}

static inline
::shared_ptr<column_identifier> to_identifier(const column_definition& def) {
    return def.column_specification->name;
}

static inline
std::vector<::shared_ptr<column_identifier>> to_identifiers(const std::vector<const column_definition*>& defs) {
    std::vector<::shared_ptr<column_identifier>> r;
    r.reserve(defs.size());
    for (auto&& def : defs) {
        r.push_back(to_identifier(*def));
    }
    return r;
}

}

namespace std {

template<>
struct hash<cql3::column_identifier> {
    size_t operator()(const cql3::column_identifier& i) const {
        return std::hash<bytes>()(i.bytes_);
    }
};

template<>
struct hash<cql3::column_identifier::raw> {
    size_t operator()(const cql3::column_identifier::raw& r) const {
        return std::hash<sstring>()(r._text);
    }
};

}
<|endoftext|>