<commit_before>/** @date 2015

    @author
    Sensics, Inc.
    <http://sensics.com/osvr>
*/

// Copyright 2015 Vuzix Corporation.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

// Internal Includes
#include "DriverWrapper.h"
#include "InterfaceTraits.h"
#include "OSVRViveTracker.h"
#include "PropertyHelper.h"
#include <osvr/PluginKit/PluginKit.h>
#include <osvr/Util/PlatformConfig.h>

// Library/third-party includes
#include <math.h>
#include <openvr_driver.h>

// Standard includes
#include <chrono>
#include <deque>
#include <iostream>
#include <memory>
#include <mutex>
#include <thread>
#include <vector>

// Anonymous namespace to avoid symbol collision
namespace {

static const auto PREFIX = "[OSVR-Vive] ";

class HardwareDetection {

  public:
    HardwareDetection() {}
    OSVR_ReturnCode operator()(OSVR_PluginRegContext ctx) {
        if (m_driverHost) {
            // Already found a Vive.
            /// @todo what are the semantics of the return value from a hardware
            /// detect?
            return OSVR_RETURN_SUCCESS;
        }

        {
            osvr::vive::DriverHostPtr host(new osvr::vive::ViveDriverHost);

            auto vive = osvr::vive::DriverWrapper(host.get());

            if (vive.foundDriver()) {
                std::cout << PREFIX << "Found the Vive driver at "
                          << vive.getDriverFileLocation() << std::endl;
            }

            if (!vive.haveDriverLoaded()) {
                std::cout << PREFIX << "Could not open driver." << std::endl;
                return OSVR_RETURN_FAILURE;
            }

            if (vive.foundConfigDirs()) {
                std::cout << PREFIX << "Driver config dir is: "
                          << vive.getDriverConfigDir() << std::endl;
            }

            if (!vive) {
                std::cerr << PREFIX
                          << "Error in first-stage Vive driver startup. Exiting"
                          << std::endl;
                return OSVR_RETURN_FAILURE;
            }

            if (!vive.isHMDPresent()) {
                std::cerr << PREFIX
                          << "Driver loaded, but no Vive is connected. Exiting"
                          << std::endl;
                return OSVR_RETURN_FAILURE;
            }

            std::cout << PREFIX << "Vive is connected." << std::endl;

            /// Hand the Vive object off to the OSVR driver.
            auto startResult = host->start(ctx, std::move(vive));
            if (startResult) {
                /// and it started up the rest of the way just fine!
                /// We'll keep the driver around!
                m_driverHost = std::move(host);
                std::cout << PREFIX
                          << "Vive driver finished startup successfully!"
                          << std::endl;
                return OSVR_RETURN_SUCCESS;
            }
        }

        std::cout << PREFIX << "Vive driver startup failed somewhere, "
                               "unloading to perhaps try again later."
                  << std::endl;
        return OSVR_RETURN_FAILURE;
    }

  private:
    std::vector<std::string> m_deviceTypes;
    /// This is the OSVR driver object, which also serves as the "SteamVR"
    /// driver host. We can only run one Vive at a time.
    osvr::vive::DriverHostPtr m_driverHost;
};
} // namespace

OSVR_PLUGIN(com_osvr_Vive) {
    osvr::pluginkit::PluginContext context(ctx);

    /// Register a detection callback function object.
    context.registerHardwareDetectCallback(new HardwareDetection());

    return OSVR_RETURN_SUCCESS;
}
<commit_msg>Adjust hardware detection so we don't unload the DLL so much, for faster detection callbacks.<commit_after>/** @date 2015

    @author
    Sensics, Inc.
    <http://sensics.com/osvr>
*/

// Copyright 2015 Vuzix Corporation.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

// Internal Includes
#include "DriverWrapper.h"
#include "InterfaceTraits.h"
#include "OSVRViveTracker.h"
#include "PropertyHelper.h"
#include <osvr/PluginKit/PluginKit.h>
#include <osvr/Util/PlatformConfig.h>

// Library/third-party includes
#include <math.h>
#include <openvr_driver.h>

// Standard includes
#include <chrono>
#include <deque>
#include <iostream>
#include <memory>
#include <mutex>
#include <thread>
#include <vector>

// Anonymous namespace to avoid symbol collision
namespace {

static const auto PREFIX = "[OSVR-Vive] ";

class HardwareDetection {

  public:
    HardwareDetection()
        : m_inactiveDriverHost(new osvr::vive::ViveDriverHost) {}
    OSVR_ReturnCode operator()(OSVR_PluginRegContext ctx) {
        if (m_driverHost) {
            // Already found a Vive.
            /// @todo what are the semantics of the return value from a hardware
            /// detect?
            return OSVR_RETURN_SUCCESS;
        }
        if (!m_shouldAttemptDetection) {
            /// We said we shouldn't and wouldn't try again.
            return OSVR_RETURN_FAILURE;
        }

        auto vivePtr = startupAndGetVive();
        if (!vivePtr) {
            /// There was trouble in early startup
            return OSVR_RETURN_FAILURE;
        }

        if (!vivePtr->isHMDPresent()) {
            /// Didn't detect anything - leave the driver DLL loaded,
            /// though, to make things faster next time around.
            /// Silent failure, to avoid annoying users.
            return OSVR_RETURN_FAILURE;
        }

        std::cout << PREFIX << "Vive is connected." << std::endl;

        /// Hand the Vive object off to the OSVR driver.
        auto startResult = finishViveStartup(ctx);
        if (startResult) {
            /// and it started up the rest of the way just fine!
            /// We'll keep the driver around!
            std::cout << PREFIX << "Vive driver finished startup successfully!"
                      << std::endl;
            return OSVR_RETURN_SUCCESS;
        }

        std::cout << PREFIX << "Vive driver startup failed somewhere, "
                               "unloading to perhaps try again later."
                  << std::endl;

        unloadTemporaries();
        return OSVR_RETURN_FAILURE;
    }

    bool finishViveStartup(OSVR_PluginRegContext ctx) {
        auto startResult =
            m_inactiveDriverHost->start(ctx, std::move(*m_viveWrapper));
        m_viveWrapper.reset();
        if (startResult) {
            m_driverHost = std::move(m_inactiveDriverHost);
        }
        return startResult;
    }

    /// Attempts the first part of startup, if required.
    osvr::vive::DriverWrapper *startupAndGetVive() {
        if (!m_viveWrapper) {
            m_viveWrapper.reset(
                new osvr::vive::DriverWrapper(&getInactiveHost()));

            if (m_viveWrapper->foundDriver()) {
                std::cout << PREFIX << "Found the Vive driver at "
                          << m_viveWrapper->getDriverFileLocation()
                          << std::endl;
            }

            if (!m_viveWrapper->haveDriverLoaded()) {
                std::cout << PREFIX << "Could not open driver." << std::endl;
                stopAttemptingDetection();
                return nullptr;
            }

            if (m_viveWrapper->foundConfigDirs()) {
                std::cout << PREFIX << "Driver config dir is: "
                          << m_viveWrapper->getDriverConfigDir() << std::endl;
            }

            if (!(*m_viveWrapper)) {
                std::cerr << PREFIX
                          << "Error in first-stage Vive driver startup."
                          << std::endl;
                m_viveWrapper.reset();
                return nullptr;
            }
        }
        return m_viveWrapper.get();
    }

    /// returns a reference because it will never be null.
    /// Creates one if needed.
    osvr::vive::ViveDriverHost &getInactiveHost() {
        if (m_driverHost) {
            throw std::logic_error("Can't get an inactive host - we already "
                                   "have a live device driver!");
        }
        if (!m_inactiveDriverHost) {
            m_inactiveDriverHost.reset(new osvr::vive::ViveDriverHost);
        }
        return *m_inactiveDriverHost.get();
    }

    void stopAttemptingDetection() {
        std::cerr << PREFIX << "Will not re-attempt detecting Vive."
                  << std::endl;
        m_shouldAttemptDetection = false;
        unloadTemporaries();
        m_driverHost.reset();
    }

    void unloadTemporaries() {
        m_viveWrapper.reset();
        m_inactiveDriverHost.reset();
    }

  private:
    /// This is the OSVR driver object, which also serves as the "SteamVR"
    /// driver host. We can only run one Vive at a time.
    osvr::vive::DriverHostPtr m_driverHost;

    /// A Vive object that we hang on to if we don't have a fully-started-up
    /// device, to save time in hardware detection.
    std::unique_ptr<osvr::vive::DriverWrapper> m_viveWrapper;
    /// Populated only when we don't have an active driver - we keep it around
    /// so we don't have to re-load the full driver every time we get hit with a
    /// hardware detect request.
    osvr::vive::DriverHostPtr m_inactiveDriverHost;

    bool m_shouldAttemptDetection = true;
};
} // namespace

OSVR_PLUGIN(com_osvr_Vive) {
    osvr::pluginkit::PluginContext context(ctx);

    /// Register a detection callback function object.
    context.registerHardwareDetectCallback(new HardwareDetection());

    return OSVR_RETURN_SUCCESS;
}
<|endoftext|>


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

#include "shellgenerator.h"
#include "reporthandler.h"

#include "metaqtscript.h"

bool ShellGenerator::shouldGenerate(const AbstractMetaClass *meta_class) const
{
    uint cg = meta_class->typeEntry()->codeGeneration();
    if (meta_class->name().startsWith("QtScript")) return false;
    if (meta_class->name().startsWith("QFuture")) return false;
    if (meta_class->name().startsWith("Global")) return false;
    if (meta_class->name().startsWith("QStyleOptionComplex")) return false;
    if (meta_class->name().startsWith("QTextLayout")) return false;
    //if (meta_class->name().startsWith("QTextStream")) return false; // because of >> operators
    //if (meta_class->name().startsWith("QDataStream")) return false; // "
    return ((cg & TypeEntry::GenerateCode) != 0);
}

void ShellGenerator::writeTypeInfo(QTextStream &s, const AbstractMetaType *type, Option options)
{
    if ((options & OriginalTypeDescription) && !type->originalTypeDescription().isEmpty()) {
        s << type->originalTypeDescription();
        return;
    }

    if (type->isArray()) {
        writeTypeInfo(s, type->arrayElementType(), options);
        if (options & ArrayAsPointer) {
            s << "*";
        } else {
            s << "[" << type->arrayElementCount() << "]";
        }
        return;
    }

    const TypeEntry *te = type->typeEntry();

    if (type->isConstant() && !(options & ExcludeConst))
        s << "const ";

    if ((options & EnumAsInts) && (te->isEnum() || te->isFlags())) {
        s << "int";
    } else if (te->isFlags()) {
        s << ((FlagsTypeEntry *) te)->originalName();
    } else {
        s << fixCppTypeName(te->qualifiedCppName());
    }

    if (type->instantiations().size() > 0
        && (!type->isContainer()
            || (static_cast<const ContainerTypeEntry *>(te))->type() != ContainerTypeEntry::StringListContainer)) {
        s << '<';
        QList<AbstractMetaType *> args = type->instantiations();
        bool nested_template = false;
        for (int i=0; i<args.size(); ++i) {
            if (i != 0)
                s << ", ";
            nested_template |= args.at(i)->isContainer();
            writeTypeInfo(s, args.at(i));
        }
        if (nested_template)
            s << ' ';
        s << '>';
    }

    s << QString(type->indirections(), '*');

    if (type->isReference() && !(options & ExcludeReference) && !(options & ConvertReferenceToPtr))
        s << "&";

    if (type->isReference() && (options & ConvertReferenceToPtr)) {
      s << "*";
    }

    if (!(options & SkipName))
        s << ' ';
}

void ShellGenerator::writeFunctionArguments(QTextStream &s, const AbstractMetaClass* owner,
                                          const AbstractMetaArgumentList &arguments,
                                          Option option,
                                          int numArguments)
{
    if (numArguments < 0) numArguments = arguments.size();

    for (int i=0; i<numArguments; ++i) {
        if (i != 0)
            s << ", ";
        AbstractMetaArgument *arg = arguments.at(i);
        writeTypeInfo(s, arg->type(), option);
        if (!(option & SkipName))
            s << " " << arg->argumentName();
        if ((option & IncludeDefaultExpression) && !arg->originalDefaultValueExpression().isEmpty()) {
            s << " = ";

          QString expr = arg->originalDefaultValueExpression();
          if (expr != "0") {
            QString qualifier;
            if (arg->type()->typeEntry()->isEnum() && expr.indexOf("::") < 0) {
              qualifier =  ((EnumTypeEntry *)arg->type()->typeEntry())->qualifier();
            } else if (arg->type()->typeEntry()->isFlags() && expr.indexOf("::") < 0) {
              qualifier = ((FlagsTypeEntry *)arg->type()->typeEntry())->originator()->qualifier();
            }
            if (!qualifier.isEmpty()) {
              s << qualifier << "::";
            }
          }
          if (expr.contains("defaultConnection")) {
            expr.replace("defaultConnection","QSqlDatabase::defaultConnection");
          }
          if (expr == "MediaSource()") {
            expr = "Phonon::MediaSource()";
          }
          s << expr;
        }
    }
}

/*!
 * Writes the function \a meta_function signature to the textstream \a s.
 *
 * The \a name_prefix can be used to give the function name a prefix,
 * like "__public_" or "__override_" and \a classname_prefix can
 * be used to give the class name a prefix.
 *
 * The \a option flags can be used to tweak various parameters, such as
 * showing static, original vs renamed name, underscores for space etc.
 *
 * The \a extra_arguments list is a list of extra arguments on the
 * form "bool static_call".
 */

void ShellGenerator::writeFunctionSignature(QTextStream &s,
                                          const AbstractMetaFunction *meta_function,
                                          const AbstractMetaClass *implementor,
                                          const QString &name_prefix,
                                          Option option,
                                          const QString &classname_prefix,
                                          const QStringList &extra_arguments,
                                          int numArguments)
{
// ### remove the implementor
    AbstractMetaType *function_type = meta_function->type();

    if ((option & SkipReturnType) == 0) {
        if (function_type) {
            writeTypeInfo(s, function_type, option);
            s << " ";
        } else if (!meta_function->isConstructor()) {
            s << "void ";
        }
    }

    if (implementor) {
        if (classname_prefix.isEmpty())
            s << wrapperClassName(implementor) << "::";
        else
            s << classname_prefix << implementor->name() << "::";
    }

    QString function_name;
    if (option & OriginalName)
        function_name = meta_function->originalName();
    else
        function_name = meta_function->name();

    if (option & UnderscoreSpaces)
        function_name = function_name.replace(' ', '_');

    if (meta_function->isConstructor())
        function_name = meta_function->ownerClass()->name();

    if (meta_function->isStatic() && (option & ShowStatic)) {
      function_name = "static_" + meta_function->ownerClass()->name() + "_" + function_name;
    }

    if (function_name.startsWith("operator")) {
      function_name = meta_function->name();
    }

    s << name_prefix << function_name;

    if (meta_function->attributes() & AbstractMetaAttributes::SetterFunction)
        s << "_setter";
    else if (meta_function->attributes() & AbstractMetaAttributes::GetterFunction)
        s << "_getter";

    s << "(";

  if ((option & FirstArgIsWrappedObject) && meta_function->ownerClass() && !meta_function->isConstructor() && !meta_function->isStatic()) {
    s << meta_function->ownerClass()->qualifiedCppName() << "* theWrappedObject";
    if (meta_function->arguments().size() != 0) {
      s << ", ";
    }
  }

   writeFunctionArguments(s, meta_function->ownerClass(), meta_function->arguments(), Option(option & Option(~ConvertReferenceToPtr)), numArguments);

    // The extra arguments...
    for (int i=0; i<extra_arguments.size(); ++i) {
        if (i > 0 || meta_function->arguments().size() != 0)
            s << ", ";
        s << extra_arguments.at(i);
    }

    s << ")";
    if (meta_function->isConstant())
        s << " const";
}

AbstractMetaFunctionList ShellGenerator::getFunctionsToWrap(const AbstractMetaClass* meta_class)
{
  AbstractMetaFunctionList functions = meta_class->queryFunctions(
    AbstractMetaClass::NormalFunctions | AbstractMetaClass::WasPublic
    | AbstractMetaClass::NotRemovedFromTargetLang | AbstractMetaClass::ClassImplements
    );
  AbstractMetaFunctionList functions2 = meta_class->queryFunctions(
    AbstractMetaClass::VirtualFunctions | AbstractMetaClass::WasVisible
    | AbstractMetaClass::NotRemovedFromTargetLang | AbstractMetaClass::ClassImplements
    );
  QSet<AbstractMetaFunction*> set1 = QSet<AbstractMetaFunction*>::fromList(functions);
  foreach(AbstractMetaFunction* func, functions2) {
    set1.insert(func);
  }

  AbstractMetaFunctionList resultFunctions;

  foreach(AbstractMetaFunction* func, set1.toList()) {
    if (!func->isAbstract() && func->implementingClass()==meta_class) {
      resultFunctions << func;
    }
  }
  return resultFunctions;
}

AbstractMetaFunctionList ShellGenerator::getVirtualFunctionsForShell(const AbstractMetaClass* meta_class)
{
  AbstractMetaFunctionList functions = meta_class->queryFunctions(
    AbstractMetaClass::VirtualFunctions | AbstractMetaClass::WasVisible
//    | AbstractMetaClass::NotRemovedFromTargetLang
    );
  return functions;
}

AbstractMetaFunctionList ShellGenerator::getProtectedFunctionsThatNeedPromotion(const AbstractMetaClass* meta_class)
{
  AbstractMetaFunctionList functions;
  AbstractMetaFunctionList functions1 = getFunctionsToWrap(meta_class);
  foreach(AbstractMetaFunction* func, functions1) {
    if (!func->isPublic() || func->isVirtual()) {
      functions << func;
    }
  }
  return functions;
}

/*!
Writes the include defined by \a inc to \a stream.
*/
void ShellGenerator::writeInclude(QTextStream &stream, const Include &inc)
{
  if (inc.name.isEmpty())
    return;
  if (inc.type == Include::TargetLangImport)
    return;
  stream << "#include ";
  if (inc.type == Include::IncludePath)
    stream << "<";
  else
    stream << "\"";
  stream << inc.name;
  if (inc.type == Include::IncludePath)
    stream << ">";
  else
    stream << "\"";
  stream << endl;
}

/*!
Returns true if the given function \a fun is operator>>() or
operator<<() that streams from/to a Q{Data,Text}Stream, false
otherwise.
*/
bool ShellGenerator::isSpecialStreamingOperator(const AbstractMetaFunction *fun)
{
  return ((fun->functionType() == AbstractMetaFunction::GlobalScopeFunction)
    && (fun->arguments().size() == 1)
    && (((fun->originalName() == "operator>>") && (fun->modifiedName() == "readFrom"))
    || ((fun->originalName() == "operator<<") && (fun->modifiedName() == "writeTo"))));
}

bool ShellGenerator::isBuiltIn(const QString& name) {

  static QSet<QString> builtIn;
  if (builtIn.isEmpty()) {
    builtIn.insert("Qt");
    builtIn.insert("QFont");
    builtIn.insert("QPixmap");
    builtIn.insert("QBrush");
    builtIn.insert("QBitArray");
    builtIn.insert("QPalette");
    builtIn.insert("QPen");
    builtIn.insert("QIcon");
    builtIn.insert("QImage");
    builtIn.insert("QPolygon");
    builtIn.insert("QRegion");
    builtIn.insert("QBitmap");
    builtIn.insert("QCursor");
    builtIn.insert("QColor");
    builtIn.insert("QSizePolicy");
    builtIn.insert("QKeySequence");
    builtIn.insert("QTextLength");
    builtIn.insert("QTextFormat");
    builtIn.insert("QMatrix");
    builtIn.insert("QDate");
    builtIn.insert("QTime");
    builtIn.insert("QDateTime");
    builtIn.insert("QUrl");
    builtIn.insert("QLocale");
    builtIn.insert("QRect");
    builtIn.insert("QRectF");
    builtIn.insert("QSize");
    builtIn.insert("QSizeF");
    builtIn.insert("QLine");
    builtIn.insert("QLineF");
    builtIn.insert("QPoint");
    builtIn.insert("QPointF");
    builtIn.insert("QRegExp");
  }
  return builtIn.contains(name);
}

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

#include "shellgenerator.h"
#include "reporthandler.h"

#include "metaqtscript.h"

bool ShellGenerator::shouldGenerate(const AbstractMetaClass *meta_class) const
{
    uint cg = meta_class->typeEntry()->codeGeneration();
    if (meta_class->name().startsWith("QtScript")) return false;
    if (meta_class->name().startsWith("QFuture")) return false;
    if (meta_class->name().startsWith("Global")) return false;
    if (meta_class->name().startsWith("QStyleOptionComplex")) return false;
    if (meta_class->name().startsWith("QTextLayout")) return false;
    //if (meta_class->name().startsWith("QTextStream")) return false; // because of >> operators
    //if (meta_class->name().startsWith("QDataStream")) return false; // "
    return ((cg & TypeEntry::GenerateCode) != 0);
}

void ShellGenerator::writeTypeInfo(QTextStream &s, const AbstractMetaType *type, Option options)
{
    if ((options & OriginalTypeDescription) && !type->originalTypeDescription().isEmpty()) {
        s << type->originalTypeDescription();
        return;
    }

    if (type->isArray()) {
        writeTypeInfo(s, type->arrayElementType(), options);
        if (options & ArrayAsPointer) {
            s << "*";
        } else {
            s << "[" << type->arrayElementCount() << "]";
        }
        return;
    }

    const TypeEntry *te = type->typeEntry();

    if (type->isConstant() && !(options & ExcludeConst))
        s << "const ";

    if ((options & EnumAsInts) && (te->isEnum() || te->isFlags())) {
        s << "int";
    } else if (te->isFlags()) {
        s << ((FlagsTypeEntry *) te)->originalName();
    } else {
        s << fixCppTypeName(te->qualifiedCppName());
    }

    if (type->instantiations().size() > 0
        && (!type->isContainer()
            || (static_cast<const ContainerTypeEntry *>(te))->type() != ContainerTypeEntry::StringListContainer)) {
        s << '<';
        QList<AbstractMetaType *> args = type->instantiations();
        bool nested_template = false;
        for (int i=0; i<args.size(); ++i) {
            if (i != 0)
                s << ", ";
            nested_template |= args.at(i)->isContainer();
            writeTypeInfo(s, args.at(i));
        }
        if (nested_template)
            s << ' ';
        s << '>';
    }

    s << QString(type->indirections(), '*');

    if (type->isReference() && !(options & ExcludeReference) && !(options & ConvertReferenceToPtr))
        s << "&";

    if (type->isReference() && (options & ConvertReferenceToPtr)) {
      s << "*";
    }

    if (!(options & SkipName))
        s << ' ';
}

void ShellGenerator::writeFunctionArguments(QTextStream &s, const AbstractMetaClass* owner,
                                          const AbstractMetaArgumentList &arguments,
                                          Option option,
                                          int numArguments)
{
    if (numArguments < 0) numArguments = arguments.size();

    for (int i=0; i<numArguments; ++i) {
        if (i != 0)
            s << ", ";
        AbstractMetaArgument *arg = arguments.at(i);
        writeTypeInfo(s, arg->type(), option);
        if (!(option & SkipName))
            s << " " << arg->argumentName();
        if ((option & IncludeDefaultExpression) && !arg->originalDefaultValueExpression().isEmpty()) {
            s << " = ";

          QString expr = arg->originalDefaultValueExpression();
          if (expr != "0") {
            QString qualifier;
            if (arg->type()->typeEntry()->isEnum() && expr.indexOf("::") < 0) {
              qualifier =  ((EnumTypeEntry *)arg->type()->typeEntry())->qualifier();
            } else if (arg->type()->typeEntry()->isFlags() && expr.indexOf("::") < 0) {
              qualifier = ((FlagsTypeEntry *)arg->type()->typeEntry())->originator()->qualifier();
            }
            if (!qualifier.isEmpty()) {
              s << qualifier << "::";
            }
          }
          if (expr.contains("defaultConnection")) {
            expr.replace("defaultConnection","QSqlDatabase::defaultConnection");
          }
          if (expr == "MediaSource()") {
            expr = "Phonon::MediaSource()";
          }
          s << expr;
        }
    }
}

/*!
 * Writes the function \a meta_function signature to the textstream \a s.
 *
 * The \a name_prefix can be used to give the function name a prefix,
 * like "__public_" or "__override_" and \a classname_prefix can
 * be used to give the class name a prefix.
 *
 * The \a option flags can be used to tweak various parameters, such as
 * showing static, original vs renamed name, underscores for space etc.
 *
 * The \a extra_arguments list is a list of extra arguments on the
 * form "bool static_call".
 */

void ShellGenerator::writeFunctionSignature(QTextStream &s,
                                          const AbstractMetaFunction *meta_function,
                                          const AbstractMetaClass *implementor,
                                          const QString &name_prefix,
                                          Option option,
                                          const QString &classname_prefix,
                                          const QStringList &extra_arguments,
                                          int numArguments)
{
// ### remove the implementor
    AbstractMetaType *function_type = meta_function->type();

    if ((option & SkipReturnType) == 0) {
        if (function_type) {
            writeTypeInfo(s, function_type, option);
            s << " ";
        } else if (!meta_function->isConstructor()) {
            s << "void ";
        }
    }

    if (implementor) {
        if (classname_prefix.isEmpty())
            s << wrapperClassName(implementor) << "::";
        else
            s << classname_prefix << implementor->name() << "::";
    }

    QString function_name;
    if (option & OriginalName)
        function_name = meta_function->originalName();
    else
        function_name = meta_function->name();

    if (option & UnderscoreSpaces)
        function_name = function_name.replace(' ', '_');

    if (meta_function->isConstructor())
        function_name = meta_function->ownerClass()->name();

    if (meta_function->isStatic() && (option & ShowStatic)) {
      function_name = "static_" + meta_function->ownerClass()->name() + "_" + function_name;
    }

    if (function_name.startsWith("operator")) {
      function_name = meta_function->name();
    }

    s << name_prefix << function_name;

    if (meta_function->attributes() & AbstractMetaAttributes::SetterFunction)
        s << "_setter";
    else if (meta_function->attributes() & AbstractMetaAttributes::GetterFunction)
        s << "_getter";

    s << "(";

  if ((option & FirstArgIsWrappedObject) && meta_function->ownerClass() && !meta_function->isConstructor() && !meta_function->isStatic()) {
    s << meta_function->ownerClass()->qualifiedCppName() << "* theWrappedObject";
    if (meta_function->arguments().size() != 0) {
      s << ", ";
    }
  }

   writeFunctionArguments(s, meta_function->ownerClass(), meta_function->arguments(), Option(option & Option(~ConvertReferenceToPtr)), numArguments);

    // The extra arguments...
    for (int i=0; i<extra_arguments.size(); ++i) {
        if (i > 0 || meta_function->arguments().size() != 0)
            s << ", ";
        s << extra_arguments.at(i);
    }

    s << ")";
    if (meta_function->isConstant())
        s << " const";
}

AbstractMetaFunctionList ShellGenerator::getFunctionsToWrap(const AbstractMetaClass* meta_class)
{
  AbstractMetaFunctionList functions = meta_class->queryFunctions(
    AbstractMetaClass::NormalFunctions | AbstractMetaClass::WasPublic
    | AbstractMetaClass::NotRemovedFromTargetLang | AbstractMetaClass::ClassImplements
    );
  AbstractMetaFunctionList functions2 = meta_class->queryFunctions(
    AbstractMetaClass::VirtualFunctions | AbstractMetaClass::WasVisible
    | AbstractMetaClass::NotRemovedFromTargetLang | AbstractMetaClass::ClassImplements
    );
  QSet<AbstractMetaFunction*> set1 = QSet<AbstractMetaFunction*>::fromList(functions);
  foreach(AbstractMetaFunction* func, functions2) {
    set1.insert(func);
  }

  AbstractMetaFunctionList resultFunctions;

  foreach(AbstractMetaFunction* func, set1.toList()) {
    if (!func->isAbstract() && func->implementingClass()==meta_class) {
      resultFunctions << func;
    }
  }
  qStableSort(resultFunctions);
  return resultFunctions;
}

AbstractMetaFunctionList ShellGenerator::getVirtualFunctionsForShell(const AbstractMetaClass* meta_class)
{
  AbstractMetaFunctionList functions = meta_class->queryFunctions(
    AbstractMetaClass::VirtualFunctions | AbstractMetaClass::WasVisible
//    | AbstractMetaClass::NotRemovedFromTargetLang
    );
  qStableSort(functions);
  return functions;
}

AbstractMetaFunctionList ShellGenerator::getProtectedFunctionsThatNeedPromotion(const AbstractMetaClass* meta_class)
{
  AbstractMetaFunctionList functions;
  AbstractMetaFunctionList functions1 = getFunctionsToWrap(meta_class);
  foreach(AbstractMetaFunction* func, functions1) {
    if (!func->isPublic() || func->isVirtual()) {
      functions << func;
    }
  }
  qStableSort(functions);
  return functions;
}

/*!
Writes the include defined by \a inc to \a stream.
*/
void ShellGenerator::writeInclude(QTextStream &stream, const Include &inc)
{
  if (inc.name.isEmpty())
    return;
  if (inc.type == Include::TargetLangImport)
    return;
  stream << "#include ";
  if (inc.type == Include::IncludePath)
    stream << "<";
  else
    stream << "\"";
  stream << inc.name;
  if (inc.type == Include::IncludePath)
    stream << ">";
  else
    stream << "\"";
  stream << endl;
}

/*!
Returns true if the given function \a fun is operator>>() or
operator<<() that streams from/to a Q{Data,Text}Stream, false
otherwise.
*/
bool ShellGenerator::isSpecialStreamingOperator(const AbstractMetaFunction *fun)
{
  return ((fun->functionType() == AbstractMetaFunction::GlobalScopeFunction)
    && (fun->arguments().size() == 1)
    && (((fun->originalName() == "operator>>") && (fun->modifiedName() == "readFrom"))
    || ((fun->originalName() == "operator<<") && (fun->modifiedName() == "writeTo"))));
}

bool ShellGenerator::isBuiltIn(const QString& name) {

  static QSet<QString> builtIn;
  if (builtIn.isEmpty()) {
    builtIn.insert("Qt");
    builtIn.insert("QFont");
    builtIn.insert("QPixmap");
    builtIn.insert("QBrush");
    builtIn.insert("QBitArray");
    builtIn.insert("QPalette");
    builtIn.insert("QPen");
    builtIn.insert("QIcon");
    builtIn.insert("QImage");
    builtIn.insert("QPolygon");
    builtIn.insert("QRegion");
    builtIn.insert("QBitmap");
    builtIn.insert("QCursor");
    builtIn.insert("QColor");
    builtIn.insert("QSizePolicy");
    builtIn.insert("QKeySequence");
    builtIn.insert("QTextLength");
    builtIn.insert("QTextFormat");
    builtIn.insert("QMatrix");
    builtIn.insert("QDate");
    builtIn.insert("QTime");
    builtIn.insert("QDateTime");
    builtIn.insert("QUrl");
    builtIn.insert("QLocale");
    builtIn.insert("QRect");
    builtIn.insert("QRectF");
    builtIn.insert("QSize");
    builtIn.insert("QSizeF");
    builtIn.insert("QLine");
    builtIn.insert("QLineF");
    builtIn.insert("QPoint");
    builtIn.insert("QPointF");
    builtIn.insert("QRegExp");
  }
  return builtIn.contains(name);
}

<|endoftext|>


<commit_before><commit_msg>Add the initial template of the first part of question 3.7<commit_after><|endoftext|>


<commit_before>#include "Logging.h"
#include "WebInterface.h"
#include <string.h>
#include <stdio.h>
#include <list>
#include <sstream>
#include "JSON.h"
#include <stdlib.h>

using namespace Dumais::WebServer;

WebInterface::WebInterface(int port,RESTInterface *pRESTInterface, WebNotificationEngine *pWebNotificationEngine)
{
    mpRESTInterface = pRESTInterface;
//    mpWebNotificationEngine = pWebNotificationEngine;
    mPort = port;
    mpWebServer = 0;
    mpThread = 0;
}

WebInterface::~WebInterface()
{
    if (mpWebServer) delete mpWebServer;
    mpWebServer = 0;
}

void WebInterface::configure(Dumais::JSON::JSON& config)
{
    this->mPasswdFile = config["passwd"].str();
}

void WebInterface::stop()
{
    if (mpWebServer)
    {
        Logging::log("Attempting to shutdown Web server");
        mpWebServer->stop();
    }
    if (mpThread) mpThread->join();
}

void WebInterface::onConnectionOpen()
{
//    Logging::log("WebInterface::onConnectionOpen(%i)",sock);
    if (mpWebServer->getConnectionCount()>10) Logging::log("WARNING: There are %i connections opened on web server",mpWebServer->getConnectionCount());
}

void WebInterface::onConnectionClosed()
{
  //  Logging::log("WebInterface::onConnectionClosed(%i)",sock);
//    mpWebNotificationEngine->unsubscribe(sock);
}

void WebInterface::onResponseSent()
{
//    mpWebNotificationEngine->activateSubscription(sock);
}

HTTPResponse* WebInterface::processHTTPRequest(HTTPRequest* request)
{
    HTTPResponse *resp;

    Dumais::JSON::JSON json;
    std::string method = request->getMethod();
    if (method != "GET")
    {
        resp = HTTPProtocol::buildBufferedResponse(NotImplemented,"","");
    }
    else
    {
        std::string url = request->getURL();
        // We will not support SSE anymore because we don't use it. I removed
        // the code from dumaislib to support persistant connections. There is a backup
        // in a "backup-server-sent-events" folder with that code
        /*if (request->accepts("text/event-stream") && url=="/subscribe")
        {
            mpWebNotificationEngine->subscribe(id);
            resp = HTTPProtocol::buildBufferedResponse(OK,"","text/event-stream","keep-alive","chunked");
        }
        else
        {*/
            std::string responseType = "application/json";
            bool queryProcessed = mpRESTInterface->processQuery(json,url);
            if (queryProcessed)
            {
                resp = HTTPProtocol::buildBufferedResponse(OK,json.stringify(false),responseType);
            }
            else
            {
                resp = HTTPProtocol::buildBufferedResponse(NotFound,"","");
            }
        //}
    }
    return resp;
}

// This server accepts one connection at a time only. So sockets are blocking
void WebInterface::start()
{
    mpWebServer = new WebServer(mPort, "0.0.0.0",100);
    mpWebServer->requireAuth(this->mPasswdFile.c_str(), 10);
    mpWebServer->setListener(this);
    this->mpWebServer->start();
}

<commit_msg>added logging for web server<commit_after>#include "Logging.h"
#include "WebInterface.h"
#include <string.h>
#include <stdio.h>
#include <list>
#include <sstream>
#include "JSON.h"
#include <stdlib.h>
#include "WebServerLogging.h"

using namespace Dumais::WebServer;

class WebServerInterfaceLogger: public Dumais::WebServer::IWebServerLogger
{
    virtual void log(const std::string& ss)
    {
        Logging::log("%s",ss.c_str());
    }
};

WebInterface::WebInterface(int port,RESTInterface *pRESTInterface, WebNotificationEngine *pWebNotificationEngine)
{
    mpRESTInterface = pRESTInterface;
    Dumais::WebServer::WebServerLogging::logger = new WebServerInterfaceLogger();
//    mpWebNotificationEngine = pWebNotificationEngine;
    mPort = port;
    mpWebServer = 0;
    mpThread = 0;
}

WebInterface::~WebInterface()
{
    if (mpWebServer) delete mpWebServer;
    mpWebServer = 0;
}

void WebInterface::configure(Dumais::JSON::JSON& config)
{
    this->mPasswdFile = config["passwd"].str();
}

void WebInterface::stop()
{
    if (mpWebServer)
    {
        Logging::log("Attempting to shutdown Web server");
        mpWebServer->stop();
    }
    if (mpThread) mpThread->join();
}

void WebInterface::onConnectionOpen()
{
//    Logging::log("WebInterface::onConnectionOpen(%i)",sock);
    if (mpWebServer->getConnectionCount()>10) Logging::log("WARNING: There are %i connections opened on web server",mpWebServer->getConnectionCount());
}

void WebInterface::onConnectionClosed()
{
  //  Logging::log("WebInterface::onConnectionClosed(%i)",sock);
//    mpWebNotificationEngine->unsubscribe(sock);
}

void WebInterface::onResponseSent()
{
//    mpWebNotificationEngine->activateSubscription(sock);
}

HTTPResponse* WebInterface::processHTTPRequest(HTTPRequest* request)
{
    HTTPResponse *resp;

    Dumais::JSON::JSON json;
    std::string method = request->getMethod();
    if (method != "GET")
    {
        resp = HTTPProtocol::buildBufferedResponse(NotImplemented,"","");
    }
    else
    {
        std::string url = request->getURL();
        // We will not support SSE anymore because we don't use it. I removed
        // the code from dumaislib to support persistant connections. There is a backup
        // in a "backup-server-sent-events" folder with that code
        /*if (request->accepts("text/event-stream") && url=="/subscribe")
        {
            mpWebNotificationEngine->subscribe(id);
            resp = HTTPProtocol::buildBufferedResponse(OK,"","text/event-stream","keep-alive","chunked");
        }
        else
        {*/
            std::string responseType = "application/json";
            bool queryProcessed = mpRESTInterface->processQuery(json,url);
            if (queryProcessed)
            {
                resp = HTTPProtocol::buildBufferedResponse(OK,json.stringify(false),responseType);
            }
            else
            {
                resp = HTTPProtocol::buildBufferedResponse(NotFound,"","");
            }
        //}
    }
    return resp;
}

// This server accepts one connection at a time only. So sockets are blocking
void WebInterface::start()
{
    mpWebServer = new WebServer(mPort, "0.0.0.0",100);
    mpWebServer->requireAuth(this->mPasswdFile.c_str(), 10);
    mpWebServer->setListener(this);
    this->mpWebServer->start();
}

<|endoftext|>


<commit_before>/* Copyright (c) 2016, the Cap authors.
 *
 * This file is subject to the Modified BSD License and may not be distributed
 * without copyright and license information. Please refer to the file LICENSE
 * for the text and further information on this license.
 */

#define BOOST_TEST_MODULE EnergyStorageDevice

#include "main.cc"

#include <cap/energy_storage_device.h>
#include <cap/resistor_capacitor.h>
#include <boost/test/unit_test.hpp>
#include <boost/property_tree/ptree.hpp>
#include <boost/property_tree/info_parser.hpp>
#include <boost/archive/text_iarchive.hpp>
#include <boost/archive/text_oarchive.hpp>
#include <boost/serialization/shared_ptr.hpp>
#include <boost/serialization/export.hpp>
#include <boost/mpi/communicator.hpp>
#include <sstream>

// list of valid inputs to build an EnergyStorageDevice
// These are meant as example
std::list<std::string> const valid_device_input = {
    "series_rc.info", "parallel_rc.info",
#ifdef WITH_DEAL_II
    "super_capacitor.info",
#endif
};

BOOST_AUTO_TEST_CASE(test_energy_storage_device_builders)
{
  boost::mpi::communicator world;
  int const size = world.size();
  int const rank = world.rank();
  std::cout << "hello world from rank " << rank << " of size " << size << "\n";
  for (auto const &filename : valid_device_input)
  {
    boost::property_tree::ptree ptree;
    boost::property_tree::info_parser::read_info(filename, ptree);
    BOOST_CHECK_NO_THROW(cap::EnergyStorageDevice::build(world, ptree));
  }

  // invalid type must throw an exception
  boost::property_tree::ptree ptree;
  ptree.put("type", "InvalidDeviceType");
  BOOST_CHECK_THROW(cap::EnergyStorageDevice::build(world, ptree),
                    std::runtime_error);
}

class ExampleInspector : public cap::EnergyStorageDeviceInspector
{
public:
  // get the device type and set the voltage to 1.4 volt
  void inspect(cap::EnergyStorageDevice *device)
  {
    // use dynamic_cast to find out the actual type
    if (dynamic_cast<cap::SeriesRC *>(device) != nullptr)
      _type = "SeriesRC";
    else if (dynamic_cast<cap::ParallelRC *>(device) != nullptr)
      _type = "ParallelRC";
    else
      throw std::runtime_error("not an equivalent circuit model");
    // if we make ExampleInspector friend of the derived
    // class for the EnergyStorageDevice we could virtually
    // do anything
    device->evolve_one_time_step_constant_voltage(1.0, 1.4);
  }
  // the type of the device last inspected
  std::string _type;
};

BOOST_AUTO_TEST_CASE(test_energy_storage_device_inspectors)
{
  std::string const filename = "series_rc.info";
  boost::mpi::communicator world;
  boost::property_tree::ptree ptree;
  boost::property_tree::info_parser::read_info(filename, ptree);
  auto device = cap::EnergyStorageDevice::build(world, ptree);
  double voltage;
  device->get_voltage(voltage);
  BOOST_TEST(voltage != 1.4);
  ExampleInspector inspector;
  device->inspect(&inspector);
  BOOST_TEST((inspector._type).compare("SeriesRC") == 0);
  device->get_voltage(voltage);
  BOOST_TEST(voltage == 1.4);
}

// TODO: won't work for SuperCapacitor
#ifdef WITH_DEAL_II
BOOST_AUTO_TEST_CASE_EXPECTED_FAILURES(test_serialization, 1)
#endif

BOOST_AUTO_TEST_CASE(test_serialization)
{
  for (auto const &filename : valid_device_input)
  {
    boost::property_tree::ptree ptree;
    boost::property_tree::info_parser::read_info(filename, ptree);
    std::shared_ptr<cap::EnergyStorageDevice> original_device =
        cap::EnergyStorageDevice::build(boost::mpi::communicator(), ptree);

    original_device->evolve_one_time_step_constant_voltage(0.1, 2.1);
    double original_voltage;
    double original_current;
    original_device->get_voltage(original_voltage);
    original_device->get_current(original_current);

    try
    {
      std::stringstream ss;
      // save device
      boost::archive::text_oarchive oa(ss);
      oa.register_type<cap::SeriesRC>();
      oa.register_type<cap::ParallelRC>();
      oa << original_device;
      // print the content of the stream to the screen
      std::cout << ss.str() << "\n";
      BOOST_CHECK(!ss.str().empty());

      // restore device
      boost::archive::text_iarchive ia(ss);
      ia.register_type<cap::SeriesRC>();
      ia.register_type<cap::ParallelRC>();
      std::shared_ptr<cap::EnergyStorageDevice> restored_device;
      ia >> restored_device;
      double restored_voltage;
      double restored_current;
      restored_device->get_voltage(restored_voltage);
      restored_device->get_current(restored_current);
      BOOST_CHECK_EQUAL(original_voltage, restored_voltage);
      BOOST_CHECK_EQUAL(original_current, restored_current);
    }
    catch (boost::archive::archive_exception e)
    {
      BOOST_TEST_MESSAGE("unable to serialize the device");
      BOOST_TEST(false);
    }
    catch (...)
    {
      throw std::runtime_error("unexpected exception occured");
    }
  }
}
<commit_msg>Improve test_energy_storage_device.<commit_after>/* Copyright (c) 2016, the Cap authors.
 *
 * This file is subject to the Modified BSD License and may not be distributed
 * without copyright and license information. Please refer to the file LICENSE
 * for the text and further information on this license.
 */

#define BOOST_TEST_MODULE EnergyStorageDevice

#include "main.cc"

#include <cap/energy_storage_device.h>
#include <cap/resistor_capacitor.h>
#include <boost/test/unit_test.hpp>
#include <boost/property_tree/ptree.hpp>
#include <boost/property_tree/info_parser.hpp>
#include <boost/archive/text_iarchive.hpp>
#include <boost/archive/text_oarchive.hpp>
#include <boost/serialization/shared_ptr.hpp>
#include <boost/serialization/export.hpp>
#include <boost/mpi/communicator.hpp>
#include <sstream>

// list of valid inputs to build an EnergyStorageDevice
// These are meant as example
std::list<std::string> const valid_device_input = {
    "series_rc.info", "parallel_rc.info",
#ifdef WITH_DEAL_II
    "super_capacitor.info",
#endif
};

BOOST_AUTO_TEST_CASE(test_energy_storage_device_builders)
{
  boost::mpi::communicator world;
  int const size = world.size();
  int const rank = world.rank();
  std::cout << "hello world from rank " << rank << " of size " << size << "\n";
  for (auto const &filename : valid_device_input)
  {
    boost::property_tree::ptree ptree;
    boost::property_tree::info_parser::read_info(filename, ptree);
    BOOST_CHECK_NO_THROW(cap::EnergyStorageDevice::build(world, ptree));
  }

  // invalid type must throw an exception
  boost::property_tree::ptree ptree;
  ptree.put("type", "InvalidDeviceType");
  BOOST_CHECK_THROW(cap::EnergyStorageDevice::build(world, ptree),
                    std::runtime_error);
}

class ExampleInspector : public cap::EnergyStorageDeviceInspector
{
public:
  // get the device type and set the voltage to 1.4 volt
  void inspect(cap::EnergyStorageDevice *device)
  {
    // use dynamic_cast to find out the actual type
    if (dynamic_cast<cap::SeriesRC *>(device) != nullptr)
      _type = "SeriesRC";
    else if (dynamic_cast<cap::ParallelRC *>(device) != nullptr)
      _type = "ParallelRC";
    else
      throw std::runtime_error("not an equivalent circuit model");
    // if we make ExampleInspector friend of the derived
    // class for the EnergyStorageDevice we could virtually
    // do anything
    device->evolve_one_time_step_constant_voltage(1.0, 1.4);
  }
  // the type of the device last inspected
  std::string _type;
};

BOOST_AUTO_TEST_CASE(test_energy_storage_device_inspectors)
{
  std::vector<std::string> filename(2);
  filename[0] = "series_rc.info";
  filename[1] = "parallel_rc.info";
  std::vector<std::string> RC_type(2);
  RC_type[0] = "SeriesRC";
  RC_type[1] = "ParallelRC";
  for (unsigned int i = 0; i < 2; ++i)
  {
    boost::mpi::communicator world;
    boost::property_tree::ptree ptree;
    boost::property_tree::info_parser::read_info(filename[i], ptree);
    auto device = cap::EnergyStorageDevice::build(world, ptree);
    double voltage;
    device->get_voltage(voltage);
    BOOST_TEST(voltage != 1.4);
    ExampleInspector inspector;
    device->inspect(&inspector);
    BOOST_TEST((inspector._type).compare(RC_type[i]) == 0);
    device->get_voltage(voltage);
    BOOST_TEST(voltage == 1.4);
  }
}

// TODO: won't work for SuperCapacitor
#ifdef WITH_DEAL_II
BOOST_AUTO_TEST_CASE_EXPECTED_FAILURES(test_serialization, 1)
#endif

BOOST_AUTO_TEST_CASE(test_serialization)
{
  for (auto const &filename : valid_device_input)
  {
    boost::property_tree::ptree ptree;
    boost::property_tree::info_parser::read_info(filename, ptree);
    std::shared_ptr<cap::EnergyStorageDevice> original_device =
        cap::EnergyStorageDevice::build(boost::mpi::communicator(), ptree);

    original_device->evolve_one_time_step_constant_voltage(0.1, 2.1);
    double original_voltage;
    double original_current;
    original_device->get_voltage(original_voltage);
    original_device->get_current(original_current);

    try
    {
      std::stringstream ss;
      // save device
      boost::archive::text_oarchive oa(ss);
      oa.register_type<cap::SeriesRC>();
      oa.register_type<cap::ParallelRC>();
      oa << original_device;
      // print the content of the stream to the screen
      std::cout << ss.str() << "\n";
      BOOST_CHECK(!ss.str().empty());

      // restore device
      boost::archive::text_iarchive ia(ss);
      ia.register_type<cap::SeriesRC>();
      ia.register_type<cap::ParallelRC>();
      std::shared_ptr<cap::EnergyStorageDevice> restored_device;
      ia >> restored_device;
      double restored_voltage;
      double restored_current;
      restored_device->get_voltage(restored_voltage);
      restored_device->get_current(restored_current);
      BOOST_CHECK_EQUAL(original_voltage, restored_voltage);
      BOOST_CHECK_EQUAL(original_current, restored_current);
    }
    catch (boost::archive::archive_exception e)
    {
      BOOST_TEST_MESSAGE("unable to serialize the device");
      BOOST_TEST(false);
    }
    catch (...)
    {
      throw std::runtime_error("unexpected exception occured");
    }
  }
}
<|endoftext|>


<commit_before>/*
*   Copyright (c) 2010-2016, MIT Probabilistic Computing Project
*
*   Lead Developers: Dan Lovell and Jay Baxter
*   Authors: Dan Lovell, Baxter Eaves, Jay Baxter, Vikash Mansinghka
*   Research Leads: Vikash Mansinghka, Patrick Shafto
*
*   Licensed under the Apache License, Version 2.0 (the "License");
*   you may not use this file except in compliance with the License.
*   You may obtain a copy of the License at
*
*       http://www.apache.org/licenses/LICENSE-2.0
*
*   Unless required by applicable law or agreed to in writing, software
*   distributed under the License is distributed on an "AS IS" BASIS,
*   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*   See the License for the specific language governing permissions and
*   limitations under the License.
*/

#define __STDC_CONSTANT_MACROS  // Make <stdint.h> define UINT64_C &c.

#include <algorithm>
#include <cassert>
#include <cmath>
#include <stdint.h>

#include "RandomNumberGenerator.h"

static inline unsigned bitcount64(uint64_t x) {
    // Count two-bit groups.
    x -= ((x >> 1) & UINT64_C(0x5555555555555555));

    // Add to four-bit groups, carefully masking carries and garbage.
    x = ((x >> 2) & UINT64_C(0x3333333333333333)) +
        (x & UINT64_C(0x3333333333333333));

    // Add to eight-bit groups.
    x = (((x >> 4) + x) & UINT64_C(0x0f0f0f0f0f0f0f0f));

    // Add all eight-bit groups in the leftmost column of a multiply.
    // Bit counts are small enough no other columns will carry.
    return (x * UINT64_C(0x0101010101010101)) >> 56;
}

static inline unsigned clz64(uint64_t x) {
    // Round up to a power of two minus one.
    x |= x >> 1;
    x |= x >> 2;
    x |= x >> 4;
    x |= x >> 8;
    x |= x >> 16;
    x |= x >> 32;

    // Count the bits thus set, and subtract from 64 to count leading
    // zeros.
    return 64 - bitcount64(x);
}

//////////////////////////////////
// return a random real between
// 0 and 1 with uniform dist
double RandomNumberGenerator::next() {
    int e = -64;
    uint64_t s;
    unsigned d;

    // Draw a significand from an infinite stream of bits.
    while ((s = crypto_weakprng_64(&_weakprng)) == 0) {
        e -= 64;
        // Just return zero if the exponent is so small there are no
        // floating-point numbers that tiny.
        if (e < -1074)
            return 0;
    }

    // Shift leading zeros into the exponent and fill trailing bits of
    // significand uniformly at random.
    if ((d = clz64(s)) != 0) {
        e -= d;
        s <<= d;
        s |= crypto_weakprng_64(&_weakprng) >> (64 - d);
    }

    // Set sticky bit, since there is (almost surely) another 1 in the
    // bit stream, to avoid a bias toward `even'.
    s |= 1;

    // Return s * 2^e.
    return ldexp(static_cast<double>(s), e);
}

//////////////////////////////
// return a random int bewteen
// zero and max - 1 with uniform
// dist if called with same max
int RandomNumberGenerator::nexti(int bound) {
    assert(0 < bound);
    return crypto_weakprng_below(&_weakprng, bound);
}

/////////////////////////////
// standard normal samples
// via Box-Muller transform
double RandomNumberGenerator::stdnormal() {
    double u, v;

    u = next();
    v = next();

    return sqrt(-2*log(u)) * sin(2*M_PI*v);
}

/////////////////////////////
// standard Gamma samples
//
//       George Marsaglia & Wai Wan Tsang, `A simple method for
//       generating gamma variables', ACM Transactions on Mathematical
//       Software 26(3), September 2000.  DOI: 10.1145/358407.358414
//       URI: https://dl.acm.org/citation.cfm?doid=358407.358414
double RandomNumberGenerator::stdgamma(double alpha) {
    const double d = alpha - (double)1/3;
    const double c = 1/sqrt(9*d);
    double x, u, v;

    assert(1 <= alpha);

    for (;;) {
        x = stdnormal();
        v = 1 + x*c;
        if (v <= 0)
            continue;
        v = v*v*v;

        u = next();
        if (u < 1 - 0.0331*((x*x)*(x*x)) ||
            log(u) < x*x/2 + d - d*v + d*log(v))
            return d*v;
    }
}

/////////////////////////////
// chi^2 samples
double RandomNumberGenerator::chisquare(double nu) {
    double shape = nu/2;
    double scale = 2;

    return scale*stdgamma(shape);
}

/////////////////////////////
// Student's t-distribution samples
double RandomNumberGenerator::student_t(double nu) {
    return stdnormal() * sqrt(nu/chisquare(nu));
}

/////////////////////////////
// control the seed
void RandomNumberGenerator::set_seed(std::time_t seed) {
    uint8_t seedbuf[crypto_weakprng_SEEDBYTES] = {0};
    size_t i;

    for (i = 0; i < std::min(sizeof seedbuf, sizeof seed); i++)
        seedbuf[i] = seed >> (8*i);
    crypto_weakprng_seed(&_weakprng, seedbuf);
}
<commit_msg>Prophylactically grab the alpha boosting note from Marsaglia and Tsang.<commit_after>/*
*   Copyright (c) 2010-2016, MIT Probabilistic Computing Project
*
*   Lead Developers: Dan Lovell and Jay Baxter
*   Authors: Dan Lovell, Baxter Eaves, Jay Baxter, Vikash Mansinghka
*   Research Leads: Vikash Mansinghka, Patrick Shafto
*
*   Licensed under the Apache License, Version 2.0 (the "License");
*   you may not use this file except in compliance with the License.
*   You may obtain a copy of the License at
*
*       http://www.apache.org/licenses/LICENSE-2.0
*
*   Unless required by applicable law or agreed to in writing, software
*   distributed under the License is distributed on an "AS IS" BASIS,
*   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*   See the License for the specific language governing permissions and
*   limitations under the License.
*/

#define __STDC_CONSTANT_MACROS  // Make <stdint.h> define UINT64_C &c.

#include <algorithm>
#include <cassert>
#include <cmath>
#include <stdint.h>

#include "RandomNumberGenerator.h"

static inline unsigned bitcount64(uint64_t x) {
    // Count two-bit groups.
    x -= ((x >> 1) & UINT64_C(0x5555555555555555));

    // Add to four-bit groups, carefully masking carries and garbage.
    x = ((x >> 2) & UINT64_C(0x3333333333333333)) +
        (x & UINT64_C(0x3333333333333333));

    // Add to eight-bit groups.
    x = (((x >> 4) + x) & UINT64_C(0x0f0f0f0f0f0f0f0f));

    // Add all eight-bit groups in the leftmost column of a multiply.
    // Bit counts are small enough no other columns will carry.
    return (x * UINT64_C(0x0101010101010101)) >> 56;
}

static inline unsigned clz64(uint64_t x) {
    // Round up to a power of two minus one.
    x |= x >> 1;
    x |= x >> 2;
    x |= x >> 4;
    x |= x >> 8;
    x |= x >> 16;
    x |= x >> 32;

    // Count the bits thus set, and subtract from 64 to count leading
    // zeros.
    return 64 - bitcount64(x);
}

//////////////////////////////////
// return a random real between
// 0 and 1 with uniform dist
double RandomNumberGenerator::next() {
    int e = -64;
    uint64_t s;
    unsigned d;

    // Draw a significand from an infinite stream of bits.
    while ((s = crypto_weakprng_64(&_weakprng)) == 0) {
        e -= 64;
        // Just return zero if the exponent is so small there are no
        // floating-point numbers that tiny.
        if (e < -1074)
            return 0;
    }

    // Shift leading zeros into the exponent and fill trailing bits of
    // significand uniformly at random.
    if ((d = clz64(s)) != 0) {
        e -= d;
        s <<= d;
        s |= crypto_weakprng_64(&_weakprng) >> (64 - d);
    }

    // Set sticky bit, since there is (almost surely) another 1 in the
    // bit stream, to avoid a bias toward `even'.
    s |= 1;

    // Return s * 2^e.
    return ldexp(static_cast<double>(s), e);
}

//////////////////////////////
// return a random int bewteen
// zero and max - 1 with uniform
// dist if called with same max
int RandomNumberGenerator::nexti(int bound) {
    assert(0 < bound);
    return crypto_weakprng_below(&_weakprng, bound);
}

/////////////////////////////
// standard normal samples
// via Box-Muller transform
double RandomNumberGenerator::stdnormal() {
    double u, v;

    u = next();
    v = next();

    return sqrt(-2*log(u)) * sin(2*M_PI*v);
}

/////////////////////////////
// standard Gamma samples
//
//       George Marsaglia & Wai Wan Tsang, `A simple method for
//       generating gamma variables', ACM Transactions on Mathematical
//       Software 26(3), September 2000.  DOI: 10.1145/358407.358414
//       URI: https://dl.acm.org/citation.cfm?doid=358407.358414
double RandomNumberGenerator::stdgamma(double alpha) {
    const double d = alpha - (double)1/3;
    const double c = 1/sqrt(9*d);
    double x, u, v;

    // The clients currently do not need alpha < 1.  Should they, the
    // reference contains a note (at the end of Section 6) on how to
    // boost the alpha parameter:
    //   stdgamma(alpha) = stdgamma(alpha+1) * (uniform() ** (1/alpha))
    assert(1 <= alpha);

    for (;;) {
        x = stdnormal();
        v = 1 + x*c;
        if (v <= 0)
            continue;
        v = v*v*v;

        u = next();
        if (u < 1 - 0.0331*((x*x)*(x*x)) ||
            log(u) < x*x/2 + d - d*v + d*log(v))
            return d*v;
    }
}

/////////////////////////////
// chi^2 samples
double RandomNumberGenerator::chisquare(double nu) {
    double shape = nu/2;
    double scale = 2;

    return scale*stdgamma(shape);
}

/////////////////////////////
// Student's t-distribution samples
double RandomNumberGenerator::student_t(double nu) {
    return stdnormal() * sqrt(nu/chisquare(nu));
}

/////////////////////////////
// control the seed
void RandomNumberGenerator::set_seed(std::time_t seed) {
    uint8_t seedbuf[crypto_weakprng_SEEDBYTES] = {0};
    size_t i;

    for (i = 0; i < std::min(sizeof seedbuf, sizeof seed); i++)
        seedbuf[i] = seed >> (8*i);
    crypto_weakprng_seed(&_weakprng, seedbuf);
}
<|endoftext|>


<commit_before>/******************************************************************************
 * This file is part of the Gluon Development Platform
 * Copyright (c) 2009 Dan Leinir Turthra Jensen <admin@leinir.dk>
 * Copyright (c) 2010 Arjen Hiemstra <>
 *
 * 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 Street, Fifth Floor, Boston, MA  02110-1301  USA
 */

#include "propertywidget.h"

using namespace GluonCreator;

#include "propertywidget.h"
#include "propertywidgetitem.h"
#include "propertywidgetitemfactory.h"

#include <core/gluonobject.h>
#include <core/debughelper.h>

#include <QtCore/QVariant>
#include <QtCore/QMetaClassInfo>

#include <QtGui/QBoxLayout>
#include <QtGui/QGridLayout>
#include <QtGui/QGroupBox>
#include <QtGui/QLabel>

class PropertyWidget::PropertyWidgetPrivate
{
    public:
        PropertyWidgetPrivate()
        {
            object = 0;
            layout = 0;
        }
        GluonCore::GluonObject *object;
        QVBoxLayout *layout;

        void appendMetaObject(QWidget* parent, QObject* object, QGridLayout* layout);
};

PropertyWidget::PropertyWidget(QWidget* parent): QScrollArea(parent), d(new PropertyWidgetPrivate)
{
}

PropertyWidget::~PropertyWidget()
{
    delete d;
}

GluonCore::GluonObject *PropertyWidget::object() const
{
    return d->object;
}

void PropertyWidget::setObject(GluonCore::GluonObject * object)
{
    if (object)
    {
        d->object = object;
        d->layout = new QVBoxLayout(this);
        d->layout->setSpacing(0);
        d->layout->setContentsMargins(0, 0, 0, 0);
        d->layout->setAlignment(Qt::AlignTop);

        appendObject(object, true);
        for (int i = 0; i < object->children().count(); i++)
        {
            appendObject(object->child(i));
        }
        d->layout->addStretch();

        QWidget * containerWidget = new QWidget(this);
        containerWidget->setLayout(d->layout);

        setWidget(containerWidget);
        setWidgetResizable(true);
    }
}

void PropertyWidget::clear()
{
    delete widget();
}

void PropertyWidget::appendObject(GluonCore::GluonObject *obj, bool first)
{
    if (!first && obj->metaObject()->className() == QString("GluonEngine::GameObject"))
    {
        return;
    }

    QString classname = obj->metaObject()->className();
    classname = classname.right(classname.length() - classname.lastIndexOf(':') - 1);
    #ifdef __GNUC__
    #warning We will need to replace the group box with a custom widget of some type, as we cannot collapse it. Unfortunate, but such is life ;)
    #endif
    QGroupBox* objectBox = new QGroupBox(classname, this);

    objectBox->setFlat(true);
    objectBox->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);

    if (first)
    {
        long addr = reinterpret_cast<long>(obj);
        QColor color;
        color.setHsv(addr % 255, 255, 192);
        objectBox->setPalette(QPalette(color));
    }

    d->layout->addWidget(objectBox);

    QGridLayout* boxLayout = new QGridLayout(objectBox);
    boxLayout->setSpacing(0);
    boxLayout->setContentsMargins(0, 0, 0, 0);
    objectBox->setLayout(boxLayout);

    d->appendMetaObject(this, obj, boxLayout);
}

void PropertyWidget::PropertyWidgetPrivate::appendMetaObject(QWidget *parent, QObject *object, QGridLayout* layout)
{
    QString propertyName;
    QString propertyDescription;
    QVariant propertyValue;

    const QMetaObject *metaObject = object->metaObject();
    QMetaProperty metaProperty;

    int row;
    int count = metaObject->propertyCount();
    for (int i = 0; i < count; ++i)
    {
        row = layout->rowCount();
        metaProperty = metaObject->property(i);

        if (metaProperty.name() == QString("objectName"))
            continue;

        QLabel * nameLabel = new QLabel(parent);
        nameLabel->setText(metaProperty.name());
        nameLabel->setAlignment(Qt::AlignRight | Qt::AlignVCenter);
        layout->addWidget(nameLabel, row, 0);

        PropertyWidgetItem *editWidget = PropertyWidgetItemFactory::instance()->create(object, metaProperty.typeName(), parent);
        editWidget->setEditObject(object);
        editWidget->setEditProperty(metaProperty.name());
        connect(editWidget, SIGNAL(propertyChanged(QObject*, QString, QVariant, QVariant)), parent, SIGNAL(propertyChanged(QObject*, QString, QVariant, QVariant)));
        editWidget->setMinimumWidth(250);
        editWidget->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Fixed);
        layout->addWidget(editWidget, row, 1);
    }

    foreach(const QByteArray &propName, object->dynamicPropertyNames())
    {
        QString thePropName(propName);
        row = layout->rowCount();
        QLabel * nameLabel = new QLabel(parent);
        nameLabel->setText(thePropName);
        nameLabel->setAlignment(Qt::AlignRight | Qt::AlignVCenter);
        layout->addWidget(nameLabel, row, 0);

        PropertyWidgetItem *editWidget = PropertyWidgetItemFactory::instance()->create(object, object->property(propName).typeName(), parent);
        editWidget->setEditObject(object);
        editWidget->setEditProperty(thePropName);
        connect(editWidget, SIGNAL(propertyChanged(QObject*, QString, QVariant, QVariant)), parent, SIGNAL(propertyChanged(QObject*, QString, QVariant, QVariant)));
        editWidget->setMinimumWidth(250);
        editWidget->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Fixed);
        layout->addWidget(editWidget);
    }
}

#include "propertywidget.moc"
<commit_msg>Remove the obsolete colouring code<commit_after>/******************************************************************************
 * This file is part of the Gluon Development Platform
 * Copyright (c) 2009 Dan Leinir Turthra Jensen <admin@leinir.dk>
 * Copyright (c) 2010 Arjen Hiemstra <>
 *
 * 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 Street, Fifth Floor, Boston, MA  02110-1301  USA
 */

#include "propertywidget.h"

using namespace GluonCreator;

#include "propertywidget.h"
#include "propertywidgetitem.h"
#include "propertywidgetitemfactory.h"

#include <core/gluonobject.h>
#include <core/debughelper.h>

#include <QtCore/QVariant>
#include <QtCore/QMetaClassInfo>

#include <QtGui/QBoxLayout>
#include <QtGui/QGridLayout>
#include <QtGui/QGroupBox>
#include <QtGui/QLabel>
#include <QtGui/QToolButton>

#include <KIcon>
#include <klocalizedstring.h>

class PropertyWidget::PropertyWidgetPrivate
{
    public:
        PropertyWidgetPrivate()
        {
            object = 0;
            layout = 0;
        }
        GluonCore::GluonObject *object;
        QVBoxLayout *layout;

        void appendMetaObject(QWidget* parent, QObject* object, QGridLayout* layout);
};

PropertyWidget::PropertyWidget(QWidget* parent): QScrollArea(parent), d(new PropertyWidgetPrivate)
{
}

PropertyWidget::~PropertyWidget()
{
    delete d;
}

GluonCore::GluonObject *PropertyWidget::object() const
{
    return d->object;
}

void PropertyWidget::setObject(GluonCore::GluonObject * object)
{
    if (object)
    {
        d->object = object;
        d->layout = new QVBoxLayout(this);
        d->layout->setSpacing(0);
        d->layout->setContentsMargins(0, 0, 0, 0);
        d->layout->setAlignment(Qt::AlignTop);

        appendObject(object, true);
        for (int i = 0; i < object->children().count(); i++)
        {
            appendObject(object->child(i));
        }
        d->layout->addStretch();

        QWidget * containerWidget = new QWidget(this);
        containerWidget->setLayout(d->layout);

        setWidget(containerWidget);
        setWidgetResizable(true);
    }
}

void PropertyWidget::clear()
{
    delete widget();
}

void PropertyWidget::appendObject(GluonCore::GluonObject *obj, bool first)
{
    if (!first && obj->metaObject()->className() == QString("GluonEngine::GameObject"))
    {
        return;
    }

    QString classname = obj->metaObject()->className();
    classname = classname.right(classname.length() - classname.lastIndexOf(':') - 1);
    #ifdef __GNUC__
    #warning We will need to replace the group box with a custom widget of some type, as we cannot collapse it. Unfortunate, but such is life ;)
    #endif
    QGroupBox* objectBox = new QGroupBox(classname, this);

    objectBox->setFlat(true);
    objectBox->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);

    d->layout->addWidget(objectBox);

    QGridLayout* boxLayout = new QGridLayout(objectBox);
    boxLayout->setSpacing(0);
    boxLayout->setContentsMargins(0, 0, 0, 0);
    objectBox->setLayout(boxLayout);

    d->appendMetaObject(this, obj, boxLayout);
}

void PropertyWidget::PropertyWidgetPrivate::appendMetaObject(QWidget *parent, QObject *object, QGridLayout* layout)
{
    QString propertyName;
    QString propertyDescription;
    QVariant propertyValue;

    const QMetaObject *metaObject = object->metaObject();
    QMetaProperty metaProperty;

    int row;
    int count = metaObject->propertyCount();
    for (int i = 0; i < count; ++i)
    {
        row = layout->rowCount();
        metaProperty = metaObject->property(i);

        if (metaProperty.name() == QString("objectName"))
            continue;

        QLabel * nameLabel = new QLabel(parent);
        nameLabel->setText(metaProperty.name());
        nameLabel->setAlignment(Qt::AlignRight | Qt::AlignVCenter);
        layout->addWidget(nameLabel, row, 0);

        PropertyWidgetItem *editWidget = PropertyWidgetItemFactory::instance()->create(object, metaProperty.typeName(), parent);
        editWidget->setEditObject(object);
        editWidget->setEditProperty(metaProperty.name());
        connect(editWidget, SIGNAL(propertyChanged(QObject*, QString, QVariant, QVariant)), parent, SIGNAL(propertyChanged(QObject*, QString, QVariant, QVariant)));
        editWidget->setMinimumWidth(250);
        editWidget->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Fixed);
        layout->addWidget(editWidget, row, 1);
    }

    foreach(const QByteArray &propName, object->dynamicPropertyNames())
    {
        QString thePropName(propName);
        row = layout->rowCount();
        QLabel * nameLabel = new QLabel(parent);
        nameLabel->setText(thePropName);
        nameLabel->setAlignment(Qt::AlignRight | Qt::AlignVCenter);
        layout->addWidget(nameLabel, row, 0);

        PropertyWidgetItem *editWidget = PropertyWidgetItemFactory::instance()->create(object, object->property(propName).typeName(), parent);
        editWidget->setEditObject(object);
        editWidget->setEditProperty(thePropName);
        connect(editWidget, SIGNAL(propertyChanged(QObject*, QString, QVariant, QVariant)), parent, SIGNAL(propertyChanged(QObject*, QString, QVariant, QVariant)));
        editWidget->setMinimumWidth(250);
        editWidget->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Fixed);
        layout->addWidget(editWidget, row, 1);
    }
}

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


<commit_before>/* This file is part of Zanshin

   Copyright 2014 Kevin Ottens <ervin@kde.org>

   This program is free software; you can redistribute it and/or
   modify it under the terms of the GNU General Public License as
   published by the Free Software Foundation; either version 2 of
   the License or (at your option) version 3 or any later version
   accepted by the membership of KDE e.V. (or its successor approved
   by the membership of KDE e.V.), which shall act as a proxy
   defined in Section 14 of version 3 of the license.

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

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

#include "akonaditagqueries.h"

#include "akonadicollectionfetchjobinterface.h"
#include "akonadiitemfetchjobinterface.h"
#include "akonaditagfetchjobinterface.h"

#include "akonadimonitorimpl.h"
#include "akonadiserializer.h"
#include "akonadistorage.h"

#include "utils/jobhandler.h"

using namespace Akonadi;

TagQueries::TagQueries(QObject *parent)
    : QObject(parent),
      m_storage(new Storage),
      m_serializer(new Serializer),
      m_monitor(new MonitorImpl),
      m_fetchContentTypeFilter(StorageInterface::Tasks|StorageInterface::Notes),
      m_ownInterfaces(true)
{
    connect(m_monitor, SIGNAL(tagAdded(Akonadi::Tag)), this, SLOT(onTagAdded(Akonadi::Tag)));
    connect(m_monitor, SIGNAL(tagRemoved(Akonadi::Tag)), this, SLOT(onTagRemoved(Akonadi::Tag)));
    connect(m_monitor, SIGNAL(tagChanged(Akonadi::Tag)), this, SLOT(onTagChanged(Akonadi::Tag)));

    connect(m_monitor, SIGNAL(itemAdded(Akonadi::Item)), this, SLOT(onItemAdded(Akonadi::Item)));
    connect(m_monitor, SIGNAL(itemRemoved(Akonadi::Item)), this, SLOT(onItemRemoved(Akonadi::Item)));
    connect(m_monitor, SIGNAL(itemChanged(Akonadi::Item)), this, SLOT(onItemChanged(Akonadi::Item)));
}

TagQueries::TagQueries(StorageInterface *storage, SerializerInterface *serializer, MonitorInterface *monitor)
    : m_storage(storage),
      m_serializer(serializer),
      m_monitor(monitor),
      m_fetchContentTypeFilter(StorageInterface::Tasks|StorageInterface::Notes),
      m_ownInterfaces(false)
{
    connect(m_monitor, SIGNAL(tagAdded(Akonadi::Tag)), this, SLOT(onTagAdded(Akonadi::Tag)));
    connect(m_monitor, SIGNAL(tagRemoved(Akonadi::Tag)), this, SLOT(onTagRemoved(Akonadi::Tag)));
    connect(m_monitor, SIGNAL(tagChanged(Akonadi::Tag)), this, SLOT(onTagChanged(Akonadi::Tag)));

    connect(monitor, SIGNAL(itemAdded(Akonadi::Item)), this, SLOT(onItemAdded(Akonadi::Item)));
    connect(monitor, SIGNAL(itemRemoved(Akonadi::Item)), this, SLOT(onItemRemoved(Akonadi::Item)));
    connect(monitor, SIGNAL(itemChanged(Akonadi::Item)), this, SLOT(onItemChanged(Akonadi::Item)));
}

TagQueries::~TagQueries()
{
    if (m_ownInterfaces) {
        delete m_storage;
        delete m_serializer;
        delete m_monitor;
    }
}

void TagQueries::setApplicationMode(TagQueries::ApplicationMode mode)
{
    if (mode == TasksOnly) {
        m_fetchContentTypeFilter = StorageInterface::Tasks;
    } else if (mode == NotesOnly) {
        m_fetchContentTypeFilter = StorageInterface::Notes;
    }
}

TagQueries::TagResult::Ptr TagQueries::findAll() const
{
    if (!m_findAll) {
        {
            TagQueries *self = const_cast<TagQueries*>(this);
            self->m_findAll = self->createTagQuery();
        }

        m_findAll->setFetchFunction([this] (const TagQuery::AddFunction &add) {
            TagFetchJobInterface *job = m_storage->fetchTags();
            Utils::JobHandler::install(job->kjob(), [this, job, add] {
                for (Akonadi::Tag tag : job->tags())
                    add(tag);
            });
        });

        m_findAll->setConvertFunction([this] (const Akonadi::Tag &tag) {
            return m_serializer->createTagFromAkonadiTag(tag);
        });

        m_findAll->setUpdateFunction([this] (const Akonadi::Tag &akonadiTag, Domain::Tag::Ptr &tag) {
            m_serializer->updateTagFromAkonadiTag(tag, akonadiTag);
        });
        m_findAll->setPredicateFunction([this] (const Akonadi::Tag &akonadiTag) {
            return akonadiTag.type() == Akonadi::Tag::PLAIN;
        });
        m_findAll->setRepresentsFunction([this] (const Akonadi::Tag &akonadiTag, const Domain::Tag::Ptr &tag) {
            return m_serializer->representsAkonadiTag(tag, akonadiTag);
        });
    }

    return m_findAll->result();
}

TagQueries::ArtifactResult::Ptr TagQueries::findTopLevelArtifacts(Domain::Tag::Ptr tag) const
{
    Akonadi::Tag akonadiTag = m_serializer->createAkonadiTagFromTag(tag);
    if (!m_findTopLevel.contains(akonadiTag.id())) {
        ArtifactQuery::Ptr query;
        {
            TagQueries *self = const_cast<TagQueries*>(this);
            query = self->createArtifactQuery();
            self->m_findTopLevel.insert(akonadiTag.id(), query);
        }

        query->setFetchFunction([this, akonadiTag] (const ArtifactQuery::AddFunction &add) {
            CollectionFetchJobInterface *job = m_storage->fetchCollections(Akonadi::Collection::root(),
                                                                           StorageInterface::Recursive,
                                                                           m_fetchContentTypeFilter);
            Utils::JobHandler::install(job->kjob(), [this, job, add] {
                if (job->kjob()->error() != KJob::NoError)
                    return;

                for (auto collection : job->collections()) {
                    ItemFetchJobInterface *job = m_storage->fetchItems(collection);
                    Utils::JobHandler::install(job->kjob(), [this, job, add] {
                        if (job->kjob()->error() != KJob::NoError)
                            return;

                        for (auto item : job->items())
                            add(item);
                    });
                }
            });
        });
        query->setConvertFunction([this] (const Akonadi::Item &item) {
            if (m_serializer->isTaskItem(item)) {
                auto task = m_serializer->createTaskFromItem(item);
                return Domain::Artifact::Ptr(task);

            } else if (m_serializer->isNoteItem(item)) {
                auto note = m_serializer->createNoteFromItem(item);
                return Domain::Artifact::Ptr(note);

            } else {
                return Domain::Artifact::Ptr();
            }
        });
        query->setUpdateFunction([this] (const Akonadi::Item &item, Domain::Artifact::Ptr &artifact) {
            if (auto task = artifact.dynamicCast<Domain::Task>()) {
                m_serializer->updateTaskFromItem(task, item);
            } else if (auto note = artifact.dynamicCast<Domain::Note>()) {
                m_serializer->updateNoteFromItem(note, item);
            }
        });
        query->setPredicateFunction([this, tag] (const Akonadi::Item &item) {
            return m_serializer->isTagChild(tag, item);
        });
        query->setRepresentsFunction([this] (const Akonadi::Item &item, const Domain::Artifact::Ptr &artifact) {
            return m_serializer->representsItem(artifact, item);
        });
    }

    return m_findTopLevel.value(akonadiTag.id())->result();
}

void TagQueries::onTagAdded(const Tag &tag)
{
    foreach (const TagQuery::Ptr &query, m_tagQueries)
        query->onAdded(tag);
}

void TagQueries::onTagRemoved(const Tag &tag)
{
    foreach (const TagQuery::Ptr &query, m_tagQueries)
        query->onRemoved(tag);
}

void TagQueries::onTagChanged(const Tag &tag)
{
    foreach (const TagQuery::Ptr &query, m_tagQueries)
        query->onChanged(tag);
}

void TagQueries::onItemAdded(const Item &item)
{
    foreach (const ArtifactQuery::Ptr &query, m_artifactQueries)
        query->onAdded(item);
}

void TagQueries::onItemRemoved(const Item &item)
{
    Q_UNUSED(item);
}

void TagQueries::onItemChanged(const Item &item)
{
    foreach (const ArtifactQuery::Ptr &query, m_artifactQueries)
        query->onChanged(item);
}

TagQueries::TagQuery::Ptr TagQueries::createTagQuery()
{
    auto query = TagQueries::TagQuery::Ptr::create();
    m_tagQueries << query;
    return query;
}

TagQueries::ArtifactQuery::Ptr TagQueries::createArtifactQuery()
{
    auto query = TagQueries::ArtifactQuery::Ptr::create();
    m_artifactQueries << query;
    return query;
}
<commit_msg>Avoid an endless loop in tagqueries.<commit_after>/* This file is part of Zanshin

   Copyright 2014 Kevin Ottens <ervin@kde.org>

   This program is free software; you can redistribute it and/or
   modify it under the terms of the GNU General Public License as
   published by the Free Software Foundation; either version 2 of
   the License or (at your option) version 3 or any later version
   accepted by the membership of KDE e.V. (or its successor approved
   by the membership of KDE e.V.), which shall act as a proxy
   defined in Section 14 of version 3 of the license.

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

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

#include "akonaditagqueries.h"

#include "akonadicollectionfetchjobinterface.h"
#include "akonadiitemfetchjobinterface.h"
#include "akonaditagfetchjobinterface.h"

#include "akonadimonitorimpl.h"
#include "akonadiserializer.h"
#include "akonadistorage.h"

#include "utils/jobhandler.h"

using namespace Akonadi;

TagQueries::TagQueries(QObject *parent)
    : QObject(parent),
      m_storage(new Storage),
      m_serializer(new Serializer),
      m_monitor(new MonitorImpl),
      m_fetchContentTypeFilter(StorageInterface::Tasks|StorageInterface::Notes),
      m_ownInterfaces(true)
{
    connect(m_monitor, SIGNAL(tagAdded(Akonadi::Tag)), this, SLOT(onTagAdded(Akonadi::Tag)));
    connect(m_monitor, SIGNAL(tagRemoved(Akonadi::Tag)), this, SLOT(onTagRemoved(Akonadi::Tag)));
    connect(m_monitor, SIGNAL(tagChanged(Akonadi::Tag)), this, SLOT(onTagChanged(Akonadi::Tag)));

    connect(m_monitor, SIGNAL(itemAdded(Akonadi::Item)), this, SLOT(onItemAdded(Akonadi::Item)));
    connect(m_monitor, SIGNAL(itemRemoved(Akonadi::Item)), this, SLOT(onItemRemoved(Akonadi::Item)));
    connect(m_monitor, SIGNAL(itemChanged(Akonadi::Item)), this, SLOT(onItemChanged(Akonadi::Item)));
}

TagQueries::TagQueries(StorageInterface *storage, SerializerInterface *serializer, MonitorInterface *monitor)
    : m_storage(storage),
      m_serializer(serializer),
      m_monitor(monitor),
      m_fetchContentTypeFilter(StorageInterface::Tasks|StorageInterface::Notes),
      m_ownInterfaces(false)
{
    connect(m_monitor, SIGNAL(tagAdded(Akonadi::Tag)), this, SLOT(onTagAdded(Akonadi::Tag)));
    connect(m_monitor, SIGNAL(tagRemoved(Akonadi::Tag)), this, SLOT(onTagRemoved(Akonadi::Tag)));
    connect(m_monitor, SIGNAL(tagChanged(Akonadi::Tag)), this, SLOT(onTagChanged(Akonadi::Tag)));

    connect(monitor, SIGNAL(itemAdded(Akonadi::Item)), this, SLOT(onItemAdded(Akonadi::Item)));
    connect(monitor, SIGNAL(itemRemoved(Akonadi::Item)), this, SLOT(onItemRemoved(Akonadi::Item)));
    connect(monitor, SIGNAL(itemChanged(Akonadi::Item)), this, SLOT(onItemChanged(Akonadi::Item)));
}

TagQueries::~TagQueries()
{
    if (m_ownInterfaces) {
        delete m_storage;
        delete m_serializer;
        delete m_monitor;
    }
}

void TagQueries::setApplicationMode(TagQueries::ApplicationMode mode)
{
    if (mode == TasksOnly) {
        m_fetchContentTypeFilter = StorageInterface::Tasks;
    } else if (mode == NotesOnly) {
        m_fetchContentTypeFilter = StorageInterface::Notes;
    }
}

TagQueries::TagResult::Ptr TagQueries::findAll() const
{
    if (!m_findAll) {
        {
            TagQueries *self = const_cast<TagQueries*>(this);
            self->m_findAll = self->createTagQuery();
        }

        m_findAll->setFetchFunction([this] (const TagQuery::AddFunction &add) {
            TagFetchJobInterface *job = m_storage->fetchTags();
            Utils::JobHandler::install(job->kjob(), [this, job, add] {
                for (Akonadi::Tag tag : job->tags())
                    add(tag);
            });
        });

        m_findAll->setConvertFunction([this] (const Akonadi::Tag &tag) {
            return m_serializer->createTagFromAkonadiTag(tag);
        });

        m_findAll->setUpdateFunction([this] (const Akonadi::Tag &akonadiTag, Domain::Tag::Ptr &tag) {
            m_serializer->updateTagFromAkonadiTag(tag, akonadiTag);
        });
        m_findAll->setPredicateFunction([this] (const Akonadi::Tag &akonadiTag) {
            return akonadiTag.type() == Akonadi::Tag::PLAIN;
        });
        m_findAll->setRepresentsFunction([this] (const Akonadi::Tag &akonadiTag, const Domain::Tag::Ptr &tag) {
            return m_serializer->representsAkonadiTag(tag, akonadiTag);
        });
    }

    return m_findAll->result();
}

TagQueries::ArtifactResult::Ptr TagQueries::findTopLevelArtifacts(Domain::Tag::Ptr tag) const
{
    Akonadi::Tag akonadiTag = m_serializer->createAkonadiTagFromTag(tag);
    if (!m_findTopLevel.contains(akonadiTag.id())) {
        ArtifactQuery::Ptr query;
        {
            TagQueries *self = const_cast<TagQueries*>(this);
            query = self->createArtifactQuery();
            self->m_findTopLevel.insert(akonadiTag.id(), query);
        }

        query->setFetchFunction([this, akonadiTag] (const ArtifactQuery::AddFunction &add) {
            CollectionFetchJobInterface *job = m_storage->fetchCollections(Akonadi::Collection::root(),
                                                                           StorageInterface::Recursive,
                                                                           m_fetchContentTypeFilter);
            Utils::JobHandler::install(job->kjob(), [this, job, add] {
                if (job->kjob()->error() != KJob::NoError)
                    return;

                for (auto collection : job->collections()) {
                    ItemFetchJobInterface *job = m_storage->fetchItems(collection);
                    Utils::JobHandler::install(job->kjob(), [this, job, add] {
                        if (job->kjob()->error() != KJob::NoError)
                            return;

                        for (auto item : job->items())
                            add(item);
                    });
                }
            });
        });
        query->setConvertFunction([this] (const Akonadi::Item &item) {
            if (m_serializer->isTaskItem(item)) {
                auto task = m_serializer->createTaskFromItem(item);
                return Domain::Artifact::Ptr(task);

            } else if (m_serializer->isNoteItem(item)) {
                auto note = m_serializer->createNoteFromItem(item);
                return Domain::Artifact::Ptr(note);

            }
            //The conversion must never fail, otherwise we create an endless loop (child of invalid node is invalid).
            //We therefore catch this case in the predicate.
            Q_ASSERT(false);
            return Domain::Artifact::Ptr();
        });
        query->setUpdateFunction([this] (const Akonadi::Item &item, Domain::Artifact::Ptr &artifact) {
            if (auto task = artifact.dynamicCast<Domain::Task>()) {
                m_serializer->updateTaskFromItem(task, item);
            } else if (auto note = artifact.dynamicCast<Domain::Note>()) {
                m_serializer->updateNoteFromItem(note, item);
            }
        });
        query->setPredicateFunction([this, tag] (const Akonadi::Item &item) {
            if (m_serializer->isTaskItem(item)) {
                return false;
            }
            if (!m_serializer->isNoteItem(item)) {
                return false;
            }
            return m_serializer->isTagChild(tag, item);
        });
        query->setRepresentsFunction([this] (const Akonadi::Item &item, const Domain::Artifact::Ptr &artifact) {
            return m_serializer->representsItem(artifact, item);
        });
    }

    return m_findTopLevel.value(akonadiTag.id())->result();
}

void TagQueries::onTagAdded(const Tag &tag)
{
    foreach (const TagQuery::Ptr &query, m_tagQueries)
        query->onAdded(tag);
}

void TagQueries::onTagRemoved(const Tag &tag)
{
    foreach (const TagQuery::Ptr &query, m_tagQueries)
        query->onRemoved(tag);
}

void TagQueries::onTagChanged(const Tag &tag)
{
    foreach (const TagQuery::Ptr &query, m_tagQueries)
        query->onChanged(tag);
}

void TagQueries::onItemAdded(const Item &item)
{
    foreach (const ArtifactQuery::Ptr &query, m_artifactQueries)
        query->onAdded(item);
}

void TagQueries::onItemRemoved(const Item &item)
{
    Q_UNUSED(item);
}

void TagQueries::onItemChanged(const Item &item)
{
    foreach (const ArtifactQuery::Ptr &query, m_artifactQueries)
        query->onChanged(item);
}

TagQueries::TagQuery::Ptr TagQueries::createTagQuery()
{
    auto query = TagQueries::TagQuery::Ptr::create();
    m_tagQueries << query;
    return query;
}

TagQueries::ArtifactQuery::Ptr TagQueries::createArtifactQuery()
{
    auto query = TagQueries::ArtifactQuery::Ptr::create();
    m_artifactQueries << query;
    return query;
}
<|endoftext|>