<commit_before>/*=========================================================================
 *
 *  Copyright David Doria 2012 daviddoria@gmail.com
 *
 *  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.txt
 *
 *  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.
 *
 *=========================================================================*/

#ifndef LinearSearchBestHistogramNewColors_HPP
#define LinearSearchBestHistogramNewColors_HPP

#include "HistogramParent.hpp"

#include <Utilities/Histogram/HistogramHelpers.hpp>
#include <Utilities/Histogram/HistogramDifferences.hpp>

#include <Utilities/PatchHelpers.h>

/**
   * This function template is similar to std::min_element but can be used when the comparison
   * involves computing a derived quantity (a.k.a. distance). This algorithm will search for the
   * the element in the range [first,last) which has the "smallest" distance (of course, both the
   * distance metric and comparison can be overriden to perform something other than the canonical
   * Euclidean distance and less-than comparison, which would yield the element with minimum distance).
   * \tparam DistanceValueType The value-type for the distance measures.
   * \tparam DistanceFunctionType The functor type to compute the distance measure.
   * \tparam CompareFunctionType The functor type that can compare two distance measures (strict weak-ordering).
   */
template <typename PropertyMapType, typename TImage, typename TIterator, typename TImageToWrite = TImage>
class LinearSearchBestHistogramNewColors : public LinearSearchBestHistogramParent<PropertyMapType, TImage, TIterator, TImageToWrite>
{

public:
  /** Constructor. This class requires the property map, an image, and a mask. */
  LinearSearchBestHistogramNewColors(PropertyMapType propertyMap, TImage* const image, Mask* const mask) :
    LinearSearchBestHistogramParent<PropertyMapType, TImage, TIterator, TImageToWrite>(propertyMap, image, mask)
  {}

  /**
    * \param first Start of the range in which to search.
    * \param last One element past the last element in the range in which to search.
    * \param query The element to compare to.
    * \return The iterator to the best element in the range (best is defined as the one which would compare favorably to all
    *         the elements in the range with respect to the distance metric).
    */
  typename TIterator::value_type operator()(const TIterator first, const TIterator last, typename TIterator::value_type query)
  {
    // If the input element range is empty, there is nothing to do.
    if(first == last)
    {
      std::cerr << "LinearSearchBestHistogram: Nothing to do..." << std::endl;
      return *last;
    }

    // If the input element range is empty, there is nothing to do.
    for(unsigned int channel = 0; channel < this->Image->GetNumberOfComponentsPerPixel(); ++channel)
    {
      if(!(this->RangeMax[channel] > this->RangeMin[channel]))
      {
        std::stringstream ss;
        ss << "LinearSearchBestHistogramDifference: Channel " << channel
           << " has RangeMax (" << this->RangeMax[channel] << ") must be > RangeMin ("
           << this->RangeMin[channel] << ")";
        throw std::runtime_error(ss.str());
      }
    }

    typedef int BinValueType;
    typedef MaskedHistogramGenerator<BinValueType> MaskedHistogramGeneratorType;
    typedef HistogramGenerator<BinValueType>::HistogramType HistogramType;

    itk::ImageRegion<2> queryRegion = get(this->PropertyMap, query).GetRegion();

    bool allowOutside = true;

    HistogramType targetHistogram =
      MaskedHistogramGeneratorType::ComputeMaskedImage1DHistogram(
          this->Image, queryRegion, this->MaskImage, queryRegion, this->NumberOfBinsPerDimension,
          this->RangeMin, this->RangeMax, allowOutside, this->MaskImage->GetValidValue());

    if(this->WriteDebugPatches)
    {
      std::cout << "LinearSearchBestHistogram: Iteration " << this->Iteration << std::endl;
      ITKHelpers::WriteRegionAsRGBImage(this->ImageToWrite, queryRegion, Helpers::GetSequentialFileName("QueryRegion",this->Iteration,"png",3));
//      ITKHelpers::WriteScalarImageRegion(this->MaskImage, queryRegion, Helpers::GetSequentialFileName("QueryMask",this->Iteration,"png",3));
      ITKHelpers::WriteRegion(this->MaskImage, queryRegion, Helpers::GetSequentialFileName("QueryMask",this->Iteration,"png",3));
      ITKHelpers::WriteImage(this->MaskImage, Helpers::GetSequentialFileName("Mask",this->Iteration,"png",3));
      ITKHelpers::WriteRegionAsRGBImage(this->ImageToWrite, get(this->PropertyMap, *first).GetRegion(),
                                        Helpers::GetSequentialFileName("SSDRegion",this->Iteration,"png",3));
      typename TImage::PixelType holeColor;
      holeColor[0] = 0;
      holeColor[1] = 255;
      holeColor[2] = 0;
      MaskOperations::WriteMaskedRegionPNG(this->ImageToWrite, this->MaskImage, queryRegion,
                                           Helpers::GetSequentialFileName("MaskedQueryRegion",this->Iteration,"png",3), holeColor);

      PatchHelpers::WriteTopPatches(this->ImageToWrite, this->PropertyMap, first, last, "HistogramNewColors", this->Iteration);

      // Compute the histogram of the best SSD region using the queryRegion mask
      HistogramType bestSSDHistogram =
       MaskedHistogramGeneratorType::ComputeMaskedImage1DHistogram(
                      this->Image, get(this->PropertyMap, *first).GetRegion(), this->MaskImage, queryRegion, this->NumberOfBinsPerDimension,
                      this->RangeMin, this->RangeMax, allowOutside, this->MaskImage->GetValidValue());

      float ssdMatchHistogramScore = HistogramDifferences::HistogramDifference(targetHistogram, bestSSDHistogram);
//      float ssdMatchHistogramScore = HistogramDifferences::WeightedHistogramDifference(targetHistogram, bestSSDHistogram);
//      float ssdMatchHistogramScore = HistogramDifferences::HistogramCoherence(targetHistogram, bestSSDHistogram);

      std::cout << "Best SSDHistogramDifference: " << ssdMatchHistogramScore << std::endl;
      HistogramHelpers::WriteHistogram(bestSSDHistogram, Helpers::GetSequentialFileName("BestSSDHistogram",this->Iteration,"txt",3));
      HistogramHelpers::WriteHistogram(targetHistogram, Helpers::GetSequentialFileName("TargetHistogram",this->Iteration,"txt",3));
    }

    // Initialize
    unsigned int fewestNewColors = std::numeric_limits<unsigned int>::infinity();
    TIterator bestPatch = last;

    unsigned int bestId = 0; // Keep track of which of the top SSD patches is the best by histogram score (just for information sake)
    HistogramType bestHistogram;

    // Iterate through all of the input elements
    for(TIterator currentPatch = first; currentPatch != last; ++currentPatch)
    {
      itk::ImageRegion<2> currentRegion = get(this->PropertyMap, *currentPatch).GetRegion();

      // Compute the histogram of the source region using the queryRegion mask
      HistogramType testHistogram =
          MaskedHistogramGeneratorType::ComputeMaskedImage1DHistogram(
                      this->Image, currentRegion, this->MaskImage, queryRegion, this->NumberOfBinsPerDimension,
                      this->RangeMin, this->RangeMax, allowOutside, this->MaskImage->GetValidValue());

       unsigned int numberOfNewColors = HistogramDifferences::CountNewColors(targetHistogram, testHistogram);

      if(numberOfNewColors < fewestNewColors)
      {
        fewestNewColors = numberOfNewColors;
        bestPatch = currentPatch;

        // These are not needed - just for debugging
        bestId = currentPatch - first;
        bestHistogram = testHistogram;
      }
    }

    if(this->WriteDebugPatches)
    {
      itk::ImageRegion<2> bestRegion = get(this->PropertyMap, *bestPatch).GetRegion();
      ITKHelpers::WriteRegionAsRGBImage(this->ImageToWrite, bestRegion, Helpers::GetSequentialFileName("HistogramRegion",this->Iteration,"png",3));
      HistogramHelpers::WriteHistogram(bestHistogram, Helpers::GetSequentialFileName("BestHistogram",this->Iteration,"txt",3));
      std::cout << "Best histogram id: " << bestId << std::endl;
      std::cout << "Fewest new colors: " << fewestNewColors << std::endl;
    }

    this->Iteration++;

    return *bestPatch;
  }

}; // end class LinearSearchBestHistogramNewColors

#endif
<commit_msg>Fix cropping bug.<commit_after>/*=========================================================================
 *
 *  Copyright David Doria 2012 daviddoria@gmail.com
 *
 *  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.txt
 *
 *  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.
 *
 *=========================================================================*/

#ifndef LinearSearchBestHistogramNewColors_HPP
#define LinearSearchBestHistogramNewColors_HPP

#include "HistogramParent.hpp"

#include <Utilities/Histogram/HistogramHelpers.hpp>
#include <Utilities/Histogram/HistogramDifferences.hpp>

#include <Utilities/PatchHelpers.h>

/**
   * This function template is similar to std::min_element but can be used when the comparison
   * involves computing a derived quantity (a.k.a. distance). This algorithm will search for the
   * the element in the range [first,last) which has the "smallest" distance (of course, both the
   * distance metric and comparison can be overriden to perform something other than the canonical
   * Euclidean distance and less-than comparison, which would yield the element with minimum distance).
   * \tparam DistanceValueType The value-type for the distance measures.
   * \tparam DistanceFunctionType The functor type to compute the distance measure.
   * \tparam CompareFunctionType The functor type that can compare two distance measures (strict weak-ordering).
   */
template <typename PropertyMapType, typename TImage, typename TIterator, typename TImageToWrite = TImage>
class LinearSearchBestHistogramNewColors : public LinearSearchBestHistogramParent<PropertyMapType, TImage, TIterator, TImageToWrite>
{

public:
  /** Constructor. This class requires the property map, an image, and a mask. */
  LinearSearchBestHistogramNewColors(PropertyMapType propertyMap, TImage* const image, Mask* const mask) :
    LinearSearchBestHistogramParent<PropertyMapType, TImage, TIterator, TImageToWrite>(propertyMap, image, mask)
  {}

  /**
    * \param first Start of the range in which to search.
    * \param last One element past the last element in the range in which to search.
    * \param query The element to compare to.
    * \return The iterator to the best element in the range (best is defined as the one which would compare favorably to all
    *         the elements in the range with respect to the distance metric).
    */
  typename TIterator::value_type operator()(const TIterator first, const TIterator last, typename TIterator::value_type query)
  {
    // If the input element range is empty, there is nothing to do.
    if(first == last)
    {
      std::cerr << "LinearSearchBestHistogram: Nothing to do..." << std::endl;
      return *last;
    }

    // If the input element range is empty, there is nothing to do.
    for(unsigned int channel = 0; channel < this->Image->GetNumberOfComponentsPerPixel(); ++channel)
    {
      if(!(this->RangeMax[channel] > this->RangeMin[channel]))
      {
        std::stringstream ss;
        ss << "LinearSearchBestHistogramDifference: Channel " << channel
           << " has RangeMax (" << this->RangeMax[channel] << ") must be > RangeMin ("
           << this->RangeMin[channel] << ")";
        throw std::runtime_error(ss.str());
      }
    }

    typedef int BinValueType;
    typedef MaskedHistogramGenerator<BinValueType> MaskedHistogramGeneratorType;
    typedef HistogramGenerator<BinValueType>::HistogramType HistogramType;

    itk::ImageRegion<2> originalQueryRegion = get(this->PropertyMap, query).GetRegion();

    itk::ImageRegion<2> croppedQueryRegion = originalQueryRegion;

    bool allowOutside = true;

    HistogramType targetHistogram =
      MaskedHistogramGeneratorType::ComputeMaskedImage1DHistogram(
          this->Image, croppedQueryRegion, this->MaskImage, croppedQueryRegion, this->NumberOfBinsPerDimension,
          this->RangeMin, this->RangeMax, allowOutside, this->MaskImage->GetValidValue());

    if(this->WriteDebugPatches)
    {
      // Compute the histogram of the best SSD region using the queryRegion mask
      itk::ImageRegion<2> bestSSDRegion = get(this->PropertyMap, *first).GetRegion();
      bestSSDRegion = ITKHelpers::CropRegionAtPosition(bestSSDRegion, this->MaskImage->GetLargestPossibleRegion(), originalQueryRegion);

      std::cout << "LinearSearchBestHistogram: Iteration " << this->Iteration << std::endl;
      ITKHelpers::WriteRegionAsRGBImage(this->ImageToWrite, croppedQueryRegion, Helpers::GetSequentialFileName("QueryRegion",this->Iteration,"png",3));
//      ITKHelpers::WriteScalarImageRegion(this->MaskImage, queryRegion, Helpers::GetSequentialFileName("QueryMask",this->Iteration,"png",3));
      ITKHelpers::WriteRegion(this->MaskImage, croppedQueryRegion, Helpers::GetSequentialFileName("QueryMask",this->Iteration,"png",3));
      ITKHelpers::WriteImage(this->MaskImage, Helpers::GetSequentialFileName("Mask",this->Iteration,"png",3));
      ITKHelpers::WriteRegionAsRGBImage(this->ImageToWrite, bestSSDRegion,
                                        Helpers::GetSequentialFileName("SSDRegion",this->Iteration,"png",3));
      typename TImage::PixelType holeColor;
      holeColor[0] = 0;
      holeColor[1] = 255;
      holeColor[2] = 0;
      MaskOperations::WriteMaskedRegionPNG(this->ImageToWrite, this->MaskImage, croppedQueryRegion,
                                           Helpers::GetSequentialFileName("MaskedQueryRegion",this->Iteration,"png",3), holeColor);

      PatchHelpers::WriteTopPatches(this->ImageToWrite, this->PropertyMap, first, last, "HistogramNewColors", this->Iteration);

      HistogramType bestSSDHistogram =
       MaskedHistogramGeneratorType::ComputeMaskedImage1DHistogram(
                      this->Image, bestSSDRegion, this->MaskImage, croppedQueryRegion, this->NumberOfBinsPerDimension,
                      this->RangeMin, this->RangeMax, allowOutside, this->MaskImage->GetValidValue());

      float ssdMatchHistogramScore = HistogramDifferences::HistogramDifference(targetHistogram, bestSSDHistogram);
//      float ssdMatchHistogramScore = HistogramDifferences::WeightedHistogramDifference(targetHistogram, bestSSDHistogram);
//      float ssdMatchHistogramScore = HistogramDifferences::HistogramCoherence(targetHistogram, bestSSDHistogram);

      std::cout << "Best SSDHistogramDifference: " << ssdMatchHistogramScore << std::endl;
      HistogramHelpers::WriteHistogram(bestSSDHistogram, Helpers::GetSequentialFileName("BestSSDHistogram",this->Iteration,"txt",3));
      HistogramHelpers::WriteHistogram(targetHistogram, Helpers::GetSequentialFileName("TargetHistogram",this->Iteration,"txt",3));
    }

    // Initialize
    unsigned int fewestNewColors = std::numeric_limits<unsigned int>::infinity();
    TIterator bestPatch = last;

    unsigned int bestId = 0; // Keep track of which of the top SSD patches is the best by histogram score (just for information sake)
    HistogramType bestHistogram;

    // Iterate through all of the input elements
    for(TIterator currentPatch = first; currentPatch != last; ++currentPatch)
    {
      itk::ImageRegion<2> currentRegion = get(this->PropertyMap, *currentPatch).GetRegion();
      currentRegion = ITKHelpers::CropRegionAtPosition(currentRegion, this->MaskImage->GetLargestPossibleRegion(), originalQueryRegion);

      // Compute the histogram of the source region using the queryRegion mask
      HistogramType testHistogram =
          MaskedHistogramGeneratorType::ComputeMaskedImage1DHistogram(
                      this->Image, currentRegion, this->MaskImage, croppedQueryRegion, this->NumberOfBinsPerDimension,
                      this->RangeMin, this->RangeMax, allowOutside, this->MaskImage->GetValidValue());

       unsigned int numberOfNewColors = HistogramDifferences::CountNewColors(targetHistogram, testHistogram);

      if(numberOfNewColors < fewestNewColors)
      {
        fewestNewColors = numberOfNewColors;
        bestPatch = currentPatch;

        // These are not needed - just for debugging
        bestId = currentPatch - first;
        bestHistogram = testHistogram;
      }
    }

    if(this->WriteDebugPatches)
    {
      itk::ImageRegion<2> bestRegion = get(this->PropertyMap, *bestPatch).GetRegion();
      bestRegion = ITKHelpers::CropRegionAtPosition(bestRegion, this->MaskImage->GetLargestPossibleRegion(), originalQueryRegion);

      ITKHelpers::WriteRegionAsRGBImage(this->ImageToWrite, bestRegion, Helpers::GetSequentialFileName("HistogramRegion",this->Iteration,"png",3));
      HistogramHelpers::WriteHistogram(bestHistogram, Helpers::GetSequentialFileName("BestHistogram",this->Iteration,"txt",3));
      std::cout << "Best histogram id: " << bestId << std::endl;
      std::cout << "Fewest new colors: " << fewestNewColors << std::endl;
    }

    this->Iteration++;

    return *bestPatch;
  }

}; // end class LinearSearchBestHistogramNewColors

#endif
<|endoftext|>


<commit_before>/**
 * This file is part of TelepathyQt4
 *
 * @copyright Copyright (C) 2010-2011 Collabora Ltd. <http://www.collabora.co.uk/>
 * @license LGPL 2.1
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 */

#include <TelepathyQt4/TubeChannel>

#include "TelepathyQt4/_gen/tube-channel.moc.hpp"

#include "TelepathyQt4/debug-internal.h"

#include <TelepathyQt4/PendingVariantMap>

namespace Tp
{

struct TELEPATHY_QT4_NO_EXPORT TubeChannel::Private
{
    Private(TubeChannel *parent);

    static void introspectTube(TubeChannel::Private *self);

    void extractTubeProperties(const QVariantMap &props);

    // Public object
    TubeChannel *parent;

    ReadinessHelper *readinessHelper;

    // Introspection
    TubeChannelState state;
    QVariantMap parameters;
};

TubeChannel::Private::Private(TubeChannel *parent)
    : parent(parent),
      readinessHelper(parent->readinessHelper()),
      state((TubeChannelState) -1)
{
    ReadinessHelper::Introspectables introspectables;

    ReadinessHelper::Introspectable introspectableTube(
            QSet<uint>() << 0,                                                          // makesSenseForStatuses
            Features() << Channel::FeatureCore,                                         // dependsOnFeatures (core)
            QStringList() << QLatin1String(TELEPATHY_INTERFACE_CHANNEL_INTERFACE_TUBE), // dependsOnInterfaces
            (ReadinessHelper::IntrospectFunc) &TubeChannel::Private::introspectTube,
            this);
    introspectables[TubeChannel::FeatureCore] = introspectableTube;

    readinessHelper->addIntrospectables(introspectables);
}

void TubeChannel::Private::introspectTube(TubeChannel::Private *self)
{
    TubeChannel *parent = self->parent;

    debug() << "Introspecting tube properties";
    Client::ChannelInterfaceTubeInterface *tubeInterface =
            parent->interface<Client::ChannelInterfaceTubeInterface>();

    parent->connect(tubeInterface,
            SIGNAL(TubeChannelStateChanged(uint)),
            SLOT(onTubeChannelStateChanged(uint)));

    PendingVariantMap *pvm = tubeInterface->requestAllProperties();
    parent->connect(pvm,
            SIGNAL(finished(Tp::PendingOperation *)),
            SLOT(gotTubeProperties(Tp::PendingOperation *)));
}

void TubeChannel::Private::extractTubeProperties(const QVariantMap &props)
{
    state = (Tp::TubeChannelState) qdbus_cast<uint>(props[QLatin1String("State")]);
    parameters = qdbus_cast<QVariantMap>(props[QLatin1String("Parameters")]);
}

/**
 * \class TubeChannel
 * \ingroup clientchannel
 * \headerfile TelepathyQt4/tube-channel.h <TelepathyQt4/TubeChannel>
 *
 * \brief The TubeChannel class is a base class for all tube types.
 *
 * A tube is a mechanism for arbitrary data transfer between two or more IM users,
 * used to allow applications on the users' systems to communicate without having
 * to establish network connections themselves.
 *
 * Note that TubeChannel should never be instantiated directly, instead one of its
 * subclasses (e.g. IncomingStreamTubeChannel or OutgoingStreamTubeChannel) should be used.
 *
 * For more details, please refer to \telepathy_spec.
 *
 * See \ref async_model, \ref shared_ptr
 */

/**
 * Feature representing the core that needs to become ready to make the
 * TubeChannel object usable.
 *
 * Note that this feature must be enabled in order to use most
 * TubeChannel methods.
 * See specific methods documentation for more details.
 */
const Feature TubeChannel::FeatureCore = Feature(QLatin1String(TubeChannel::staticMetaObject.className()), 0);

/**
 * \deprecated Use TubeChannel::FeatureCore instead.
 */
const Feature TubeChannel::FeatureTube = TubeChannel::FeatureCore;

/**
 * Create a new TubeChannel channel.
 *
 * \param connection Connection owning this channel, and specifying the
 *                   service.
 * \param objectPath The channel object path.
 * \param immutableProperties The channel immutable properties.
 * \return A TubeChannelPtr object pointing to the newly created
 *         TubeChannel object.
 */
TubeChannelPtr TubeChannel::create(const ConnectionPtr &connection,
        const QString &objectPath, const QVariantMap &immutableProperties)
{
    return TubeChannelPtr(new TubeChannel(connection, objectPath,
            immutableProperties));
}

/**
 * Construct a new TubeChannel object.
 *
 * \param connection Connection owning this channel, and specifying the
 *                   service.
 * \param objectPath The channel object path.
 * \param immutableProperties The channel immutable properties.
 * \param coreFeature The core feature of the channel type, if any. The corresponding introspectable should
 *                    depend on TubeChannel::FeatureCore.
 */
TubeChannel::TubeChannel(const ConnectionPtr &connection,
        const QString &objectPath,
        const QVariantMap &immutableProperties,
        const Feature &coreFeature)
    : Channel(connection, objectPath, immutableProperties, coreFeature),
      mPriv(new Private(this))
{
}

/**
 * Class destructor.
 */
TubeChannel::~TubeChannel()
{
    delete mPriv;
}

/**
 * Return the parameters associated with this tube, if any.
 *
 * Note that for outgoing tubes, this function will only return a valid value after the tube has
 * been offered successfully.
 *
 * This method requires TubeChannel::FeatureCore to be ready.
 *
 * \return The parameters as QVariantMap.
 *         For more details, please refer to \telepathy_spec.
 */
QVariantMap TubeChannel::parameters() const
{
    if (!isReady(FeatureCore)) {
        warning() << "TubeChannel::parameters() used with FeatureCore not ready";
        return QVariantMap();
    }

    return mPriv->parameters;
}

/**
 * Return the state of this tube.
 *
 * Change notification is via the stateChanged() signal.
 *
 * This method requires TubeChannel::FeatureCore to be ready.
 *
 * \return The state as #TubeChannelState.
 * \sa stateChanged()
 */
TubeChannelState TubeChannel::state() const
{
    if (!isReady(FeatureCore)) {
        warning() << "TubeChannel::state() used with FeatureCore not ready";
        return TubeChannelStateNotOffered;
    }

    return mPriv->state;
}

/**
 * \deprecated Use state() instead.
 */
TubeChannelState TubeChannel::tubeState() const
{
    return state();
}

void TubeChannel::setParameters(const QVariantMap &parameters)
{
    mPriv->parameters = parameters;
}

void TubeChannel::onTubeChannelStateChanged(uint newState)
{
    if (newState == mPriv->state) {
        return;
    }

    uint oldState = mPriv->state;

    debug() << "Tube state changed to" << newState;
    mPriv->state = (Tp::TubeChannelState) newState;

    /* only emit stateChanged if we already received the state from initial introspection */
    if (oldState != (uint) -1) {
        emit stateChanged((Tp::TubeChannelState) newState);
        // FIXME (API/ABI break) Remove tubeStateChanged call
        emit tubeStateChanged((Tp::TubeChannelState) newState);
    }
}

void TubeChannel::gotTubeProperties(PendingOperation *op)
{
    if (!op->isError()) {
        PendingVariantMap *pvm = qobject_cast<PendingVariantMap *>(op);

        mPriv->extractTubeProperties(pvm->result());

        debug() << "Got reply to Properties::GetAll(TubeChannel)";
        mPriv->readinessHelper->setIntrospectCompleted(TubeChannel::FeatureCore, true);
    } else {
        warning().nospace() << "Properties::GetAll(TubeChannel) failed "
            "with " << op->errorName() << ": " << op->errorMessage();
        mPriv->readinessHelper->setIntrospectCompleted(TubeChannel::FeatureCore, false,
                op->errorName(), op->errorMessage());
    }
}

/**
 * \fn void TubeChannel::stateChanged(Tp::TubeChannelState state)
 *
 * Emitted when the value of state() changes.
 *
 * \sa state The new state of this tube.
 * \sa state()
 */

/**
 * \fn void TubeChannel::tubeStateChanged(Tp::TubeChannelState state)
 *
 * \deprecated Use stateChanged() instead.
 */

void TubeChannel::connectNotify(const char *signalName)
{
    if (qstrcmp(signalName, SIGNAL(tubeStateChanged(Tp::TubeChannelState))) == 0) {
        warning() << "Connecting to deprecated signal tubeStateChanged(Tp::TubeChannelState)";
    }
}

} // Tp
<commit_msg>TubeChannel: clean up docs<commit_after>/**
 * This file is part of TelepathyQt4
 *
 * @copyright Copyright (C) 2010-2011 Collabora Ltd. <http://www.collabora.co.uk/>
 * @license LGPL 2.1
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 */

#include <TelepathyQt4/TubeChannel>

#include "TelepathyQt4/_gen/tube-channel.moc.hpp"

#include "TelepathyQt4/debug-internal.h"

#include <TelepathyQt4/PendingVariantMap>

namespace Tp
{

struct TELEPATHY_QT4_NO_EXPORT TubeChannel::Private
{
    Private(TubeChannel *parent);

    static void introspectTube(TubeChannel::Private *self);

    void extractTubeProperties(const QVariantMap &props);

    // Public object
    TubeChannel *parent;

    ReadinessHelper *readinessHelper;

    // Introspection
    TubeChannelState state;
    QVariantMap parameters;
};

TubeChannel::Private::Private(TubeChannel *parent)
    : parent(parent),
      readinessHelper(parent->readinessHelper()),
      state((TubeChannelState) -1)
{
    ReadinessHelper::Introspectables introspectables;

    ReadinessHelper::Introspectable introspectableTube(
            QSet<uint>() << 0,                                                          // makesSenseForStatuses
            Features() << Channel::FeatureCore,                                         // dependsOnFeatures (core)
            QStringList() << QLatin1String(TELEPATHY_INTERFACE_CHANNEL_INTERFACE_TUBE), // dependsOnInterfaces
            (ReadinessHelper::IntrospectFunc) &TubeChannel::Private::introspectTube,
            this);
    introspectables[TubeChannel::FeatureCore] = introspectableTube;

    readinessHelper->addIntrospectables(introspectables);
}

void TubeChannel::Private::introspectTube(TubeChannel::Private *self)
{
    TubeChannel *parent = self->parent;

    debug() << "Introspecting tube properties";
    Client::ChannelInterfaceTubeInterface *tubeInterface =
            parent->interface<Client::ChannelInterfaceTubeInterface>();

    parent->connect(tubeInterface,
            SIGNAL(TubeChannelStateChanged(uint)),
            SLOT(onTubeChannelStateChanged(uint)));

    PendingVariantMap *pvm = tubeInterface->requestAllProperties();
    parent->connect(pvm,
            SIGNAL(finished(Tp::PendingOperation *)),
            SLOT(gotTubeProperties(Tp::PendingOperation *)));
}

void TubeChannel::Private::extractTubeProperties(const QVariantMap &props)
{
    state = (Tp::TubeChannelState) qdbus_cast<uint>(props[QLatin1String("State")]);
    parameters = qdbus_cast<QVariantMap>(props[QLatin1String("Parameters")]);
}

/**
 * \class TubeChannel
 * \ingroup clientchannel
 * \headerfile TelepathyQt4/tube-channel.h <TelepathyQt4/TubeChannel>
 *
 * \brief The TubeChannel class is a base class for all tube types.
 *
 * A tube is a mechanism for arbitrary data transfer between two or more IM users,
 * used to allow applications on the users' systems to communicate without having
 * to establish network connections themselves.
 *
 * Note that TubeChannel should never be instantiated directly, instead one of its
 * subclasses (e.g. IncomingStreamTubeChannel or OutgoingStreamTubeChannel) should be used.
 *
 * See \ref async_model, \ref shared_ptr
 */

/**
 * Feature representing the core that needs to become ready to make the
 * TubeChannel object usable.
 *
 * Note that this feature must be enabled in order to use most
 * TubeChannel methods.
 * See specific methods documentation for more details.
 */
const Feature TubeChannel::FeatureCore = Feature(QLatin1String(TubeChannel::staticMetaObject.className()), 0);

/**
 * \deprecated Use TubeChannel::FeatureCore instead.
 */
const Feature TubeChannel::FeatureTube = TubeChannel::FeatureCore;

/**
 * Create a new TubeChannel channel.
 *
 * \param connection Connection owning this channel, and specifying the
 *                   service.
 * \param objectPath The channel object path.
 * \param immutableProperties The channel immutable properties.
 * \return A TubeChannelPtr object pointing to the newly created
 *         TubeChannel object.
 */
TubeChannelPtr TubeChannel::create(const ConnectionPtr &connection,
        const QString &objectPath, const QVariantMap &immutableProperties)
{
    return TubeChannelPtr(new TubeChannel(connection, objectPath,
            immutableProperties));
}

/**
 * Construct a new TubeChannel object.
 *
 * \param connection Connection owning this channel, and specifying the
 *                   service.
 * \param objectPath The channel object path.
 * \param immutableProperties The channel immutable properties.
 * \param coreFeature The core feature of the channel type, if any. The corresponding introspectable should
 *                    depend on TubeChannel::FeatureCore.
 */
TubeChannel::TubeChannel(const ConnectionPtr &connection,
        const QString &objectPath,
        const QVariantMap &immutableProperties,
        const Feature &coreFeature)
    : Channel(connection, objectPath, immutableProperties, coreFeature),
      mPriv(new Private(this))
{
}

/**
 * Class destructor.
 */
TubeChannel::~TubeChannel()
{
    delete mPriv;
}

/**
 * Return the parameters associated with this tube, if any.
 *
 * The parameters are populated when an outgoing tube is offered, but they are most useful in the
 * receiving end, where the parameters passed to the offer can be extracted for the tube's entire
 * lifetime to bootstrap legacy protocols. All parameters are passed unchanged.
 *
 * This method requires TubeChannel::FeatureCore to be ready.
 *
 * \return The parameters as QVariantMap.
 */
QVariantMap TubeChannel::parameters() const
{
    if (!isReady(FeatureCore)) {
        warning() << "TubeChannel::parameters() used with FeatureCore not ready";
        return QVariantMap();
    }

    return mPriv->parameters;
}

/**
 * Return the state of this tube.
 *
 * Change notification is via the stateChanged() signal.
 *
 * This method requires TubeChannel::FeatureCore to be ready.
 *
 * \return The state as #TubeChannelState.
 * \sa stateChanged()
 */
TubeChannelState TubeChannel::state() const
{
    if (!isReady(FeatureCore)) {
        warning() << "TubeChannel::state() used with FeatureCore not ready";
        return TubeChannelStateNotOffered;
    }

    return mPriv->state;
}

/**
 * \deprecated Use state() instead.
 */
TubeChannelState TubeChannel::tubeState() const
{
    return state();
}

void TubeChannel::setParameters(const QVariantMap &parameters)
{
    mPriv->parameters = parameters;
}

void TubeChannel::onTubeChannelStateChanged(uint newState)
{
    if (newState == mPriv->state) {
        return;
    }

    uint oldState = mPriv->state;

    debug() << "Tube state changed to" << newState;
    mPriv->state = (Tp::TubeChannelState) newState;

    /* only emit stateChanged if we already received the state from initial introspection */
    if (oldState != (uint) -1) {
        emit stateChanged((Tp::TubeChannelState) newState);
        // FIXME (API/ABI break) Remove tubeStateChanged call
        emit tubeStateChanged((Tp::TubeChannelState) newState);
    }
}

void TubeChannel::gotTubeProperties(PendingOperation *op)
{
    if (!op->isError()) {
        PendingVariantMap *pvm = qobject_cast<PendingVariantMap *>(op);

        mPriv->extractTubeProperties(pvm->result());

        debug() << "Got reply to Properties::GetAll(TubeChannel)";
        mPriv->readinessHelper->setIntrospectCompleted(TubeChannel::FeatureCore, true);
    } else {
        warning().nospace() << "Properties::GetAll(TubeChannel) failed "
            "with " << op->errorName() << ": " << op->errorMessage();
        mPriv->readinessHelper->setIntrospectCompleted(TubeChannel::FeatureCore, false,
                op->errorName(), op->errorMessage());
    }
}

/**
 * \fn void TubeChannel::stateChanged(Tp::TubeChannelState state)
 *
 * Emitted when the value of state() changes.
 *
 * \sa state The new state of this tube.
 */

/**
 * \fn void TubeChannel::tubeStateChanged(Tp::TubeChannelState state)
 *
 * \deprecated Use stateChanged() instead.
 */

void TubeChannel::connectNotify(const char *signalName)
{
    if (qstrcmp(signalName, SIGNAL(tubeStateChanged(Tp::TubeChannelState))) == 0) {
        warning() << "Connecting to deprecated signal tubeStateChanged(Tp::TubeChannelState)";
    }
}

} // Tp
<|endoftext|>


<commit_before>/*
 * Copyright (c) 2007-2008 Digital Bazaar, Inc.  All rights reserved.
 */
#include "db/test/Test.h"

#include <assert.h>
#include <iostream>
#include <sstream>

#include "db/sql/SqlException.h"
#include "db/data/json/JsonWriter.h"
#include "db/io/OStreamOutputStream.h"

using namespace std;
using namespace db::data::json;
using namespace db::io;
using namespace db::rt;
using namespace db::test;

void db::test::dumpException(ExceptionRef& e)
{
   db::sql::SqlException* sqlEx = NULL;
   if(!e.isNull())
   {
      sqlEx = dynamic_cast<db::sql::SqlException*>(&(*e));
   }

   if(sqlEx != NULL)
   {
      cout << "SqlException occurred!" << endl;
      cout << "message: " << sqlEx->getMessage() << endl;
      cout << "type: " << sqlEx->getType() << endl;
      cout << "code: " << sqlEx->getCode() << endl;
      cout << "sqlstate: " << sqlEx->getSqlState() << endl;
   }
   else
   {
      cout << "Exception occurred!" << endl;
      cout << "message: " << e->getMessage() << endl;
      cout << "type: " << e->getType() << endl;
      cout << "code: " << e->getCode() << endl;
      if(!e->getCause().isNull())

   {
      cout << "CAUSE:" << endl;
      dumpException(e->getCause());
   }
}

void db::test::dumpDynamicObjectText_(
   DynamicObject& dyno, DynamicObjectIterator doi, int indent)
{
   for(int i = 0; i < indent; i++)
   {
      cout << ' ';
   }

   if(doi == NULL)
   {
      doi = dyno.getIterator();
   }

   switch(dyno->getType())
   {
      case String:
         cout << "Name=" << doi->getName() << ",Value=" << dyno->getString();
         cout << endl;
         break;
      case Boolean:
         cout << "Name=" << doi->getName() << ",Value=" << dyno->getBoolean();
         cout << endl;
         break;
      case Int32:
         cout << "Name=" << doi->getName() << ",Value=" << dyno->getInt32();
         cout << endl;
         break;
      case UInt32:
         cout << "Name=" << doi->getName() << ",Value=" << dyno->getUInt32();
         cout << endl;
         break;
      case Int64:
         cout << "Name=" << doi->getName() << ",Value=" << dyno->getInt64();
         cout << endl;
         break;
      case UInt64:
         cout << "Name=" << doi->getName() << ",Value=" << dyno->getUInt64();
         cout << endl;
         break;
      case Double:
         cout << "Name=" << doi->getName() << ",Value=" << dyno->getDouble();
         cout << endl;
         break;
      case Map:
      case Array:
         cout << "Name=" << doi->getName() << endl;
         DynamicObjectIterator i = dyno.getIterator();
         while(i->hasNext())
         {
            dumpDynamicObjectText_(i->next(), i, indent + 1);
         }
         break;
   }
}

void db::test::dumpDynamicObjectText(DynamicObject& dyno)
{
   dumpDynamicObjectText_(dyno, NULL, 0);
}

void db::test::dynamicObjectToStream(
   DynamicObject& dyno, ostream& stream, bool compact)
{
   OStreamOutputStream os(&stream);
   JsonWriter jw;
   jw.setCompact(compact);
   if(!compact)
   {
      jw.setIndentation(0, 3);
   }
   jw.write(dyno, &os);
}

void db::test::dynamicObjectToString(
   DynamicObject& dyno, string& str, bool compact)
{
   ostringstream oss;
   dynamicObjectToStream(dyno, oss, compact);
   str = oss.str();
}

void db::test::dumpDynamicObject(DynamicObject& dyno, bool compact)
{
   string str;
   dynamicObjectToString(dyno, str, compact);
   cout << str << endl;
   cout.flush();
}
<commit_msg>Added recursive cause printout for exceptions in Test.<commit_after>/*
 * Copyright (c) 2007-2008 Digital Bazaar, Inc.  All rights reserved.
 */
#include "db/test/Test.h"

#include <assert.h>
#include <iostream>
#include <sstream>

#include "db/sql/SqlException.h"
#include "db/data/json/JsonWriter.h"
#include "db/io/OStreamOutputStream.h"

using namespace std;
using namespace db::data::json;
using namespace db::io;
using namespace db::rt;
using namespace db::test;

void db::test::dumpException(ExceptionRef& e)
{
   db::sql::SqlException* sqlEx = NULL;
   if(!e.isNull())
   {
      sqlEx = dynamic_cast<db::sql::SqlException*>(&(*e));
   }

   if(sqlEx != NULL)
   {
      cout << "SqlException occurred!" << endl;
      cout << "message: " << sqlEx->getMessage() << endl;
      cout << "type: " << sqlEx->getType() << endl;
      cout << "code: " << sqlEx->getCode() << endl;
      cout << "sqlstate: " << sqlEx->getSqlState() << endl;
   }
   else
   {
      cout << "Exception occurred!" << endl;
      cout << "message: " << e->getMessage() << endl;
      cout << "type: " << e->getType() << endl;
      cout << "code: " << e->getCode() << endl;
   }

   if(!e.isNull() && !e->getCause().isNull())
   {
      cout << "CAUSE:" << endl;
      dumpException(e->getCause());
   }
}

void db::test::dumpDynamicObjectText_(
   DynamicObject& dyno, DynamicObjectIterator doi, int indent)
{
   for(int i = 0; i < indent; i++)
   {
      cout << ' ';
   }

   if(doi == NULL)
   {
      doi = dyno.getIterator();
   }

   switch(dyno->getType())
   {
      case String:
         cout << "Name=" << doi->getName() << ",Value=" << dyno->getString();
         cout << endl;
         break;
      case Boolean:
         cout << "Name=" << doi->getName() << ",Value=" << dyno->getBoolean();
         cout << endl;
         break;
      case Int32:
         cout << "Name=" << doi->getName() << ",Value=" << dyno->getInt32();
         cout << endl;
         break;
      case UInt32:
         cout << "Name=" << doi->getName() << ",Value=" << dyno->getUInt32();
         cout << endl;
         break;
      case Int64:
         cout << "Name=" << doi->getName() << ",Value=" << dyno->getInt64();
         cout << endl;
         break;
      case UInt64:
         cout << "Name=" << doi->getName() << ",Value=" << dyno->getUInt64();
         cout << endl;
         break;
      case Double:
         cout << "Name=" << doi->getName() << ",Value=" << dyno->getDouble();
         cout << endl;
         break;
      case Map:
      case Array:
         cout << "Name=" << doi->getName() << endl;
         DynamicObjectIterator i = dyno.getIterator();
         while(i->hasNext())
         {
            dumpDynamicObjectText_(i->next(), i, indent + 1);
         }
         break;
   }
}

void db::test::dumpDynamicObjectText(DynamicObject& dyno)
{
   dumpDynamicObjectText_(dyno, NULL, 0);
}

void db::test::dynamicObjectToStream(
   DynamicObject& dyno, ostream& stream, bool compact)
{
   OStreamOutputStream os(&stream);
   JsonWriter jw;
   jw.setCompact(compact);
   if(!compact)
   {
      jw.setIndentation(0, 3);
   }
   jw.write(dyno, &os);
}

void db::test::dynamicObjectToString(
   DynamicObject& dyno, string& str, bool compact)
{
   ostringstream oss;
   dynamicObjectToStream(dyno, oss, compact);
   str = oss.str();
}

void db::test::dumpDynamicObject(DynamicObject& dyno, bool compact)
{
   string str;
   dynamicObjectToString(dyno, str, compact);
   cout << str << endl;
   cout.flush();
}
<|endoftext|>


<commit_before>#include <TestSupport.h>
#include <Utils/Template.h>
#include <cstdarg>

using namespace Passenger;

namespace tut {
	struct TemplateTest {
		string apply(const StaticString &templateContent, ...) {
			va_list ap;
			const char *arg;
			StringMap<StaticString> params;

			va_start(ap, templateContent);
			while ((arg = va_arg(ap, const char *)) != NULL) {
				params.set(arg, va_arg(ap, const char *));
			}
			string result = Template::apply(templateContent, params);
			va_end(ap);
			return result;
		}
	};

	DEFINE_TEST_GROUP(TemplateTest);

	TEST_METHOD(1) {
		// Test 1 substitution.
		string result = apply("hello {{name}}",
			"name", "world",
			NULL);
		ensure_equals(result, "hello world");
	}

	TEST_METHOD(2) {
		// Test multiple substitutions.
		string result = apply("hello {{name}} and {{name2}}",
			"name", "joe",
			"name2", "jane",
			NULL);
		ensure_equals(result, "hello joe and jane");
	}

	TEST_METHOD(3) {
		// Test unspecified substitutions.
		string result = apply("hello {{name}} and {{name2}}!",
			"name", "joe",
			NULL);
		ensure_equals(result, "hello joe and !");
	}

	TEST_METHOD(4) {
		// Test default values.
		string result = apply("hello {{name|default=joe}} and {{name2|default=jane}}",
			NULL);
		ensure_equals(result, "hello joe and jane");
	}

	TEST_METHOD(5) {
		// Substitutions are HTML-escaped by default.
		string result = apply("hello {{name}}",
			"name", "<joe>",
			NULL);
		ensure_equals(result, "hello <joe>");
		result = apply("hello {{name|default=<joe>}}",
			NULL);
		ensure_equals(result, "hello <joe>");
	}

	TEST_METHOD(6) {
		// HTML escaping can be disabled with the 'raw' option.
		string result = apply("hello {{name|raw}}",
			"name", "<joe>",
			NULL);
		ensure_equals(result, "hello <joe>");
	}

	TEST_METHOD(7) {
		// Test combining default values and the 'raw' option.
		string result = apply("hello {{name|raw,default=<joe>}}",
			NULL);
		ensure_equals(result, "hello <joe>");
	}

	TEST_METHOD(8) {
		// Test 'if' statements.
		string result = apply("hello. {{if morning}}good morning. {{/if}}{{if evening}}good evening. {{/if}}",
			"morning", "true",
			NULL);
		ensure_equals(result, "hello. good morning. ");
	}

	TEST_METHOD(9) {
		// An 'if' condition is considered true when it is neither the empty string nor "false".
		string result = apply("hello. {{if morning}}good morning. {{/if}}"
			"{{if afternoon}}good afternoon. {{/if}"
			"{{if evening}}good evening. {{/if}}",
			"morning", "of course",
			"afternoon", "false",
			NULL);
		ensure_equals(result, "hello. good morning. ");
	}

	TEST_METHOD(10) {
		// Test nesting substitutions within 'if's.
		string result = apply("hello. {{if name}}good morning {{name}}.{{/if}}",
			"name", "joe",
			NULL);
		ensure_equals(result, "hello. good morning joe.");
	}

	TEST_METHOD(11) {
		// Test auto-breaking on certain characters.
		string result = apply("{{content}}",
			"content", "Hello, world: a=b;c=d",
			NULL);
		ensure_equals(result, "Hello,<wbr> world:<wbr> a=<wbr>b;<wbr>c=<wbr>d");
	}
}
<commit_msg>Fix incorrect usage of va_args in TemplateTest.<commit_after>#include <TestSupport.h>
#include <Utils/Template.h>
#include <cstdarg>

using namespace Passenger;

namespace tut {
	struct TemplateTest {
		string apply(const char *templateContent, ...) {
			va_list ap;
			const char *arg;
			StringMap<StaticString> params;

			va_start(ap, templateContent);
			while ((arg = va_arg(ap, const char *)) != NULL) {
				params.set(arg, va_arg(ap, const char *));
			}
			string result = Template::apply(templateContent, params);
			va_end(ap);
			return result;
		}
	};

	DEFINE_TEST_GROUP(TemplateTest);

	TEST_METHOD(1) {
		// Test 1 substitution.
		string result = apply("hello {{name}}",
			"name", "world",
			NULL);
		ensure_equals(result, "hello world");
	}

	TEST_METHOD(2) {
		// Test multiple substitutions.
		string result = apply("hello {{name}} and {{name2}}",
			"name", "joe",
			"name2", "jane",
			NULL);
		ensure_equals(result, "hello joe and jane");
	}

	TEST_METHOD(3) {
		// Test unspecified substitutions.
		string result = apply("hello {{name}} and {{name2}}!",
			"name", "joe",
			NULL);
		ensure_equals(result, "hello joe and !");
	}

	TEST_METHOD(4) {
		// Test default values.
		string result = apply("hello {{name|default=joe}} and {{name2|default=jane}}",
			NULL);
		ensure_equals(result, "hello joe and jane");
	}

	TEST_METHOD(5) {
		// Substitutions are HTML-escaped by default.
		string result = apply("hello {{name}}",
			"name", "<joe>",
			NULL);
		ensure_equals(result, "hello <joe>");
		result = apply("hello {{name|default=<joe>}}",
			NULL);
		ensure_equals(result, "hello <joe>");
	}

	TEST_METHOD(6) {
		// HTML escaping can be disabled with the 'raw' option.
		string result = apply("hello {{name|raw}}",
			"name", "<joe>",
			NULL);
		ensure_equals(result, "hello <joe>");
	}

	TEST_METHOD(7) {
		// Test combining default values and the 'raw' option.
		string result = apply("hello {{name|raw,default=<joe>}}",
			NULL);
		ensure_equals(result, "hello <joe>");
	}

	TEST_METHOD(8) {
		// Test 'if' statements.
		string result = apply("hello. {{if morning}}good morning. {{/if}}{{if evening}}good evening. {{/if}}",
			"morning", "true",
			NULL);
		ensure_equals(result, "hello. good morning. ");
	}

	TEST_METHOD(9) {
		// An 'if' condition is considered true when it is neither the empty string nor "false".
		string result = apply("hello. {{if morning}}good morning. {{/if}}"
			"{{if afternoon}}good afternoon. {{/if}"
			"{{if evening}}good evening. {{/if}}",
			"morning", "of course",
			"afternoon", "false",
			NULL);
		ensure_equals(result, "hello. good morning. ");
	}

	TEST_METHOD(10) {
		// Test nesting substitutions within 'if's.
		string result = apply("hello. {{if name}}good morning {{name}}.{{/if}}",
			"name", "joe",
			NULL);
		ensure_equals(result, "hello. good morning joe.");
	}

	TEST_METHOD(11) {
		// Test auto-breaking on certain characters.
		string result = apply("{{content}}",
			"content", "Hello, world: a=b;c=d",
			NULL);
		ensure_equals(result, "Hello,<wbr> world:<wbr> a=<wbr>b;<wbr>c=<wbr>d");
	}
}
<|endoftext|>


<commit_before>/**
 * @file Cosa/TWI/Driver/HMC5883L.cpp
 * @version 1.0
 *
 * @section License
 * Copyright (C) 2013, Mikael Patel
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General
 * Public License along with this library; if not, write to the
 * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
 * Boston, MA  02111-1307  USA
 *
 * @section Description
 * Driver for the HMC5883L 3-Axis Digital Compass IC.
 *
 * See Honeywell product description (Rev. E, February 2013).
 *
 * This file is part of the Arduino Che Cosa project.
 */

#include "Cosa/TWI/Driver/HMC5883L.hh"

bool
HMC5883L::begin()
{
  if (!twi.begin()) return (false);
  twi.write(ADDR, (uint8_t) 0);
  int count = twi.read(ADDR, &m_reg, sizeof(m_reg));
  twi.end();
  return (count == sizeof(m_reg));
}

bool
HMC5883L::end()
{
  return (set_mode(IDLE_MEASUREMENT_MODE));
}

void
HMC5883L::set_bias(Bias bias)
{
  m_reg.config[0] = (m_reg.config[0] & ~BIAS_MASK) | bias;
}

void
HMC5883L::set_output_rate(Rate rate)
{
  m_reg.config[0] = (m_reg.config[0] & ~OUTPUT_RATE_MASK) | rate;
}

void
HMC5883L::set_sample_avg(Avg avg)
{
  m_reg.config[0] = (m_reg.config[0] & ~SAMPLES_AVG_MASK) | avg;
}

void
HMC5883L::set_range(Range range)
{
  m_reg.config[1] = (m_reg.config[1] & ~RANGE_MASK) | range;
}

bool
HMC5883L::write_config()
{
  if (!twi.begin()) return (false);
  int count = twi.write(ADDR, (uint8_t) offsetof(reg_t, config),
			&m_reg.config, sizeof(m_reg.config));
  twi.end();
  return (count == (sizeof(m_reg.config) + 1));
}

bool
HMC5883L::set_mode(Mode mode)
{
  m_reg.mode = (m_reg.mode & ~MEASUREMENT_MODE_MASK) | mode;
  if (!twi.begin()) return (false);
  int count = twi.write(ADDR, (uint8_t) offsetof(reg_t, mode),
			&m_reg.mode, sizeof(m_reg.mode));
  twi.end();
  return (count == (sizeof(m_reg.mode) + 1));
}

bool
HMC5883L::read_status(Status& status)
{
  if (!twi.begin()) return (false);
  twi.write(ADDR, (uint8_t) offsetof(reg_t, status));
  int count = twi.read(ADDR, &m_reg.status, sizeof(m_reg.status));
  twi.end();
  status = (Status) m_reg.status;
  return (count == sizeof(m_reg.status));
}

bool
HMC5883L::read_data(data_t& data)
{
  if (!twi.begin()) return (false);
  twi.write(ADDR, (uint8_t) offsetof(reg_t, output));
  int count = twi.read(ADDR, &m_reg.output, sizeof(m_reg.output));
  twi.end();
  data.x = swap(m_reg.output.x);
  data.y = swap(m_reg.output.y);
  data.z = swap(m_reg.output.z);
  return (count == sizeof(m_reg.output));
}

<commit_msg>Fixed HMC5883L driver; did not compile for ATtinyX5, should be ignored.<commit_after>/**
 * @file Cosa/TWI/Driver/HMC5883L.cpp
 * @version 1.0
 *
 * @section License
 * Copyright (C) 2013, Mikael Patel
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General
 * Public License along with this library; if not, write to the
 * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
 * Boston, MA  02111-1307  USA
 *
 * @section Description
 * Driver for the HMC5883L 3-Axis Digital Compass IC.
 *
 * See Honeywell product description (Rev. E, February 2013).
 *
 * This file is part of the Arduino Che Cosa project.
 */

#include "Cosa/Board.hh"
#if !defined(__ARDUINO_TINYX5__)
#include "Cosa/TWI/Driver/HMC5883L.hh"

bool
HMC5883L::begin()
{
  if (!twi.begin()) return (false);
  twi.write(ADDR, (uint8_t) 0);
  int count = twi.read(ADDR, &m_reg, sizeof(m_reg));
  twi.end();
  return (count == sizeof(m_reg));
}

bool
HMC5883L::end()
{
  return (set_mode(IDLE_MEASUREMENT_MODE));
}

void
HMC5883L::set_bias(Bias bias)
{
  m_reg.config[0] = (m_reg.config[0] & ~BIAS_MASK) | bias;
}

void
HMC5883L::set_output_rate(Rate rate)
{
  m_reg.config[0] = (m_reg.config[0] & ~OUTPUT_RATE_MASK) | rate;
}

void
HMC5883L::set_sample_avg(Avg avg)
{
  m_reg.config[0] = (m_reg.config[0] & ~SAMPLES_AVG_MASK) | avg;
}

void
HMC5883L::set_range(Range range)
{
  m_reg.config[1] = (m_reg.config[1] & ~RANGE_MASK) | range;
}

bool
HMC5883L::write_config()
{
  if (!twi.begin()) return (false);
  int count = twi.write(ADDR, (uint8_t) offsetof(reg_t, config),
			&m_reg.config, sizeof(m_reg.config));
  twi.end();
  return (count == (sizeof(m_reg.config) + 1));
}

bool
HMC5883L::set_mode(Mode mode)
{
  m_reg.mode = (m_reg.mode & ~MEASUREMENT_MODE_MASK) | mode;
  if (!twi.begin()) return (false);
  int count = twi.write(ADDR, (uint8_t) offsetof(reg_t, mode),
			&m_reg.mode, sizeof(m_reg.mode));
  twi.end();
  return (count == (sizeof(m_reg.mode) + 1));
}

bool
HMC5883L::read_status(Status& status)
{
  if (!twi.begin()) return (false);
  twi.write(ADDR, (uint8_t) offsetof(reg_t, status));
  int count = twi.read(ADDR, &m_reg.status, sizeof(m_reg.status));
  twi.end();
  status = (Status) m_reg.status;
  return (count == sizeof(m_reg.status));
}

bool
HMC5883L::read_data(data_t& data)
{
  if (!twi.begin()) return (false);
  twi.write(ADDR, (uint8_t) offsetof(reg_t, output));
  int count = twi.read(ADDR, &m_reg.output, sizeof(m_reg.output));
  twi.end();
  data.x = swap(m_reg.output.x);
  data.y = swap(m_reg.output.y);
  data.z = swap(m_reg.output.z);
  return (count == sizeof(m_reg.output));
}
#endif
<|endoftext|>


<commit_before>#include <cmath>
#include <cstddef>
#include <limits>
#include <memory>
#include <type_traits>
#include <utility>
#include <gtest/gtest.h>
#include <entt/core/memory.hpp>
#include "../common/basic_test_allocator.hpp"
#include "../common/throwing_allocator.hpp"
#include "../common/throwing_type.hpp"
#include "../common/tracked_memory_resource.hpp"

TEST(Memory, ToAddress) {
    std::shared_ptr<int> shared = std::make_shared<int>();
    auto *plain = std::addressof(*shared);

    ASSERT_EQ(entt::to_address(shared), plain);
    ASSERT_EQ(entt::to_address(plain), plain);
}

TEST(Memory, PoccaPocmaAndPocs) {
    test::basic_test_allocator<int> lhs, rhs;
    // honestly, I don't even know how one is supposed to test such a thing :)
    entt::propagate_on_container_copy_assignment(lhs, rhs);
    entt::propagate_on_container_move_assignment(lhs, rhs);
    entt::propagate_on_container_swap(lhs, rhs);
}

TEST(Memory, IsPowerOfTwo) {
    // constexpr-ness guaranteed
    constexpr auto zero_is_power_of_two = entt::is_power_of_two(0u);

    ASSERT_FALSE(zero_is_power_of_two);
    ASSERT_TRUE(entt::is_power_of_two(1u));
    ASSERT_TRUE(entt::is_power_of_two(2u));
    ASSERT_TRUE(entt::is_power_of_two(4u));
    ASSERT_FALSE(entt::is_power_of_two(7u));
    ASSERT_TRUE(entt::is_power_of_two(128u));
    ASSERT_FALSE(entt::is_power_of_two(200u));
}

TEST(Memory, NextPowerOfTwo) {
    // constexpr-ness guaranteed
    constexpr auto next_power_of_two_of_zero = entt::next_power_of_two(0u);

    ASSERT_EQ(next_power_of_two_of_zero, 1u);
    ASSERT_EQ(entt::next_power_of_two(1u), 1u);
    ASSERT_EQ(entt::next_power_of_two(2u), 2u);
    ASSERT_EQ(entt::next_power_of_two(3u), 4u);
    ASSERT_EQ(entt::next_power_of_two(17u), 32u);
    ASSERT_EQ(entt::next_power_of_two(32u), 32u);
    ASSERT_EQ(entt::next_power_of_two(33u), 64u);
    ASSERT_EQ(entt::next_power_of_two(std::pow(2, 16)), std::pow(2, 16));
    ASSERT_EQ(entt::next_power_of_two(std::pow(2, 16) + 1u), std::pow(2, 17));
}

TEST(MemoryDeathTest, NextPowerOfTwo) {
    ASSERT_DEATH(static_cast<void>(entt::next_power_of_two((std::size_t{1u} << (std::numeric_limits<std::size_t>::digits - 1)) + 1)), "");
}

TEST(Memory, FastMod) {
    // constexpr-ness guaranteed
    constexpr auto fast_mod_of_zero = entt::fast_mod(0u, 8u);

    ASSERT_EQ(fast_mod_of_zero, 0u);
    ASSERT_EQ(entt::fast_mod(7u, 8u), 7u);
    ASSERT_EQ(entt::fast_mod(8u, 8u), 0u);
}

TEST(Memory, AllocateUnique) {
    test::throwing_allocator<int> allocator{};
    test::throwing_allocator<int>::trigger_on_allocate = true;

    ASSERT_THROW((entt::allocate_unique<int>(allocator, 0)), test::throwing_allocator<int>::exception_type);

    std::unique_ptr<int, entt::allocation_deleter<test::throwing_allocator<int>>> ptr = entt::allocate_unique<int>(allocator, 42);

    ASSERT_TRUE(ptr);
    ASSERT_EQ(*ptr, 42);

    ptr.reset();

    ASSERT_FALSE(ptr);
}

#if defined(ENTT_HAS_TRACKED_MEMORY_RESOURCE)

TEST(Memory, NoUsesAllocatorConstruction) {
    test::tracked_memory_resource memory_resource{};
    std::pmr::polymorphic_allocator<int> allocator{&memory_resource};

    using type = std::unique_ptr<int, entt::allocation_deleter<std::pmr::polymorphic_allocator<int>>>;
    type ptr = entt::allocate_unique<int>(allocator, 0);

    ASSERT_TRUE(memory_resource.is_equal(memory_resource));
    ASSERT_EQ(memory_resource.do_allocate_counter(), 1u);
    ASSERT_EQ(memory_resource.do_deallocate_counter(), 0u);
}

TEST(Memory, UsesAllocatorConstruction) {
    using string_type = typename test::tracked_memory_resource::string_type;

    test::tracked_memory_resource memory_resource{};
    std::pmr::polymorphic_allocator<string_type> allocator{&memory_resource};

    using type = std::unique_ptr<string_type, entt::allocation_deleter<std::pmr::polymorphic_allocator<string_type>>>;
    type ptr = entt::allocate_unique<string_type>(allocator, test::tracked_memory_resource::default_value);

    ASSERT_TRUE(memory_resource.is_equal(memory_resource));
    ASSERT_GT(memory_resource.do_allocate_counter(), 1u);
    ASSERT_EQ(memory_resource.do_deallocate_counter(), 0u);
}

#endif
<commit_msg>test: increase code coverage<commit_after>#include <cmath>
#include <cstddef>
#include <limits>
#include <memory>
#include <type_traits>
#include <utility>
#include <gtest/gtest.h>
#include <entt/core/memory.hpp>
#include "../common/basic_test_allocator.hpp"
#include "../common/throwing_allocator.hpp"
#include "../common/throwing_type.hpp"
#include "../common/tracked_memory_resource.hpp"

TEST(Memory, ToAddress) {
    std::shared_ptr<int> shared = std::make_shared<int>();
    auto *plain = std::addressof(*shared);

    ASSERT_EQ(entt::to_address(shared), plain);
    ASSERT_EQ(entt::to_address(plain), plain);
}

TEST(Memory, PoccaPocmaAndPocs) {
    test::basic_test_allocator<int> lhs, rhs;
    // honestly, I don't even know how one is supposed to test such a thing :)
    entt::propagate_on_container_copy_assignment(lhs, rhs);
    entt::propagate_on_container_move_assignment(lhs, rhs);
    entt::propagate_on_container_swap(lhs, rhs);
}

TEST(Memory, IsPowerOfTwo) {
    // constexpr-ness guaranteed
    constexpr auto zero_is_power_of_two = entt::is_power_of_two(0u);

    ASSERT_FALSE(zero_is_power_of_two);
    ASSERT_TRUE(entt::is_power_of_two(1u));
    ASSERT_TRUE(entt::is_power_of_two(2u));
    ASSERT_TRUE(entt::is_power_of_two(4u));
    ASSERT_FALSE(entt::is_power_of_two(7u));
    ASSERT_TRUE(entt::is_power_of_two(128u));
    ASSERT_FALSE(entt::is_power_of_two(200u));
}

TEST(Memory, NextPowerOfTwo) {
    // constexpr-ness guaranteed
    constexpr auto next_power_of_two_of_zero = entt::next_power_of_two(0u);

    ASSERT_EQ(next_power_of_two_of_zero, 1u);
    ASSERT_EQ(entt::next_power_of_two(1u), 1u);
    ASSERT_EQ(entt::next_power_of_two(2u), 2u);
    ASSERT_EQ(entt::next_power_of_two(3u), 4u);
    ASSERT_EQ(entt::next_power_of_two(17u), 32u);
    ASSERT_EQ(entt::next_power_of_two(32u), 32u);
    ASSERT_EQ(entt::next_power_of_two(33u), 64u);
    ASSERT_EQ(entt::next_power_of_two(std::pow(2, 16)), std::pow(2, 16));
    ASSERT_EQ(entt::next_power_of_two(std::pow(2, 16) + 1u), std::pow(2, 17));
}

TEST(MemoryDeathTest, NextPowerOfTwo) {
    ASSERT_DEATH(static_cast<void>(entt::next_power_of_two((std::size_t{1u} << (std::numeric_limits<std::size_t>::digits - 1)) + 1)), "");
}

TEST(Memory, FastMod) {
    // constexpr-ness guaranteed
    constexpr auto fast_mod_of_zero = entt::fast_mod(0u, 8u);

    ASSERT_EQ(fast_mod_of_zero, 0u);
    ASSERT_EQ(entt::fast_mod(7u, 8u), 7u);
    ASSERT_EQ(entt::fast_mod(8u, 8u), 0u);
}

TEST(Memory, AllocateUnique) {
    test::throwing_allocator<test::throwing_type> allocator{};
    test::throwing_allocator<test::throwing_type>::trigger_on_allocate = true;
    test::throwing_type::trigger_on_value = 0;

    ASSERT_THROW((entt::allocate_unique<test::throwing_type>(allocator, 0)), test::throwing_allocator<test::throwing_type>::exception_type);
    ASSERT_THROW((entt::allocate_unique<test::throwing_type>(allocator, test::throwing_type{0})), test::throwing_type::exception_type);

    std::unique_ptr<test::throwing_type, entt::allocation_deleter<test::throwing_allocator<test::throwing_type>>> ptr = entt::allocate_unique<test::throwing_type>(allocator, 42);

    ASSERT_TRUE(ptr);
    ASSERT_EQ(*ptr, 42);

    ptr.reset();

    ASSERT_FALSE(ptr);
}

#if defined(ENTT_HAS_TRACKED_MEMORY_RESOURCE)

TEST(Memory, NoUsesAllocatorConstruction) {
    test::tracked_memory_resource memory_resource{};
    std::pmr::polymorphic_allocator<int> allocator{&memory_resource};

    using type = std::unique_ptr<int, entt::allocation_deleter<std::pmr::polymorphic_allocator<int>>>;
    type ptr = entt::allocate_unique<int>(allocator, 0);

    ASSERT_TRUE(memory_resource.is_equal(memory_resource));
    ASSERT_EQ(memory_resource.do_allocate_counter(), 1u);
    ASSERT_EQ(memory_resource.do_deallocate_counter(), 0u);
}

TEST(Memory, UsesAllocatorConstruction) {
    using string_type = typename test::tracked_memory_resource::string_type;

    test::tracked_memory_resource memory_resource{};
    std::pmr::polymorphic_allocator<string_type> allocator{&memory_resource};

    using type = std::unique_ptr<string_type, entt::allocation_deleter<std::pmr::polymorphic_allocator<string_type>>>;
    type ptr = entt::allocate_unique<string_type>(allocator, test::tracked_memory_resource::default_value);

    ASSERT_TRUE(memory_resource.is_equal(memory_resource));
    ASSERT_GT(memory_resource.do_allocate_counter(), 1u);
    ASSERT_EQ(memory_resource.do_deallocate_counter(), 0u);
}

#endif
<|endoftext|>


<commit_before>#include "musicvideoplaywidget.h"
#include "musicvideoview.h"
#include "musicvideotablewidget.h"
#include "musiclocalsongsearchedit.h"
#include "musicobject.h"

#include <QVBoxLayout>
#include <QHBoxLayout>
#include <QLabel>
#include <QPushButton>
#include <QStackedWidget>

MusicVideoPlayWidget::MusicVideoPlayWidget(bool popup, QWidget *parent)
    : MusicAbstractMoveWidget(parent)
{
    if(popup)
    {
        resize(525, 455);
    }

    QVBoxLayout *layout = new QVBoxLayout(this);
    layout->setMargin(0);
    layout->setSpacing(0);
    m_topWidget = new QWidget(this);
    m_topWidget->setObjectName("#topWidget");
    m_topWidget->setStyleSheet(MusicUIObject::MCustomStyle19 + \
                               MusicUIObject::MCustomStyle20);
    QHBoxLayout *topLayout = new QHBoxLayout(m_topWidget);
    topLayout->setSpacing(0);
    m_backButton = new QPushButton(this);
    m_backButton->setIcon(QIcon(":/video/back"));
    m_backButton->setCursor(QCursor(Qt::PointingHandCursor));
    m_backButton->setIconSize(QSize(18, 18));
    m_afterButton = new QPushButton(this);
    m_afterButton->setIcon(QIcon(":/video/after"));
    m_afterButton->setCursor(QCursor(Qt::PointingHandCursor));
    m_afterButton->setIconSize(QSize(18, 18));

    m_textLabel = new QLabel(m_topWidget);
    m_textLabel->setStyleSheet(MusicUIObject::MCustomStyle11);
    m_searchEdit = new MusicLocalSongSearchEdit(m_topWidget);
    m_searchEdit->setFixedHeight(18);
    m_searchButton = new QPushButton(m_topWidget);
    m_searchButton->setIcon(QIcon(":/share/searchlineleft"));
    m_searchButton->setCursor(QCursor(Qt::PointingHandCursor));
    m_searchButton->setIconSize(QSize(18, 18));
    topLayout->addWidget(m_backButton);
    topLayout->addWidget(m_afterButton);
    topLayout->addStretch();
    topLayout->addWidget(m_textLabel);
    topLayout->addStretch();
    topLayout->addWidget(m_searchEdit);
    topLayout->addWidget(m_searchButton);
    m_topWidget->setLayout(topLayout);
    m_topWidget->setFixedHeight(40);

    m_stackedWidget = new QStackedWidget(this);
    m_stackedWidget->setStyleSheet(MusicUIObject::MCustomStyle20);
    layout->addWidget(m_topWidget);
    layout->addWidget(m_stackedWidget);
    setLayout(layout);

    m_videoTable = new MusicVideoTableWidget(this);
    m_videoView = new MusicVideoView(popup, this);
    m_stackedWidget->addWidget(m_videoView);
    m_stackedWidget->addWidget(m_videoTable);
    m_stackedWidget->setCurrentIndex(0);

    connect(m_afterButton, SIGNAL(clicked(bool)), SLOT(afterButtonClicked()));
    connect(m_backButton, SIGNAL(clicked(bool)), SLOT(backButtonClicked()));
    connect(m_searchButton,SIGNAL(clicked(bool)), SLOT(searchButtonClicked()));
    connect(m_videoTable, SIGNAL(mvURLNameChanged(QString,QString)),
                          SLOT(mvURLNameChanged(QString,QString)));
    connect(m_videoTable, SIGNAL(restartSearchQuery(QString)),
                          SLOT(musicResearchButtonSearched(QString)));

}

MusicVideoPlayWidget::~MusicVideoPlayWidget()
{
    delete m_backButton;
    delete m_textLabel;
    delete m_searchEdit;
    delete m_searchButton;
    delete m_topWidget;
    delete m_videoView;
    delete m_stackedWidget;
}

void MusicVideoPlayWidget::resizeWindow(bool resize)
{
    if(resize)
    {
        showFullScreen();
    }
    else
    {
        setGeometry(250, 150, 525, 455);
    }
    m_videoView->resizeWindow(resize, size());
    m_videoTable->resizeWindow(size().width() / 525.0);
}

void MusicVideoPlayWidget::backButtonClicked()
{
    m_stackedWidget->setCurrentIndex(0);
}

void MusicVideoPlayWidget::afterButtonClicked()
{
    m_stackedWidget->setCurrentIndex(1);
}

void MusicVideoPlayWidget::searchButtonClicked()
{
    musicResearchButtonSearched(m_searchEdit->text().trimmed());
}

void MusicVideoPlayWidget::musicResearchButtonSearched(const QString &name)
{
    m_searchEdit->setText(name);
    m_stackedWidget->setCurrentIndex(1);
    m_videoTable->startSearchQuery(name);
}

void MusicVideoPlayWidget::mvURLChanged(const QString &data)
{
    m_videoView->setMedia(data);
    m_videoView->play();
    m_stackedWidget->setCurrentIndex(0);
}

void MusicVideoPlayWidget::mvURLNameChanged(const QString &name, const QString &data)
{
    m_textLabel->setText(QFontMetrics(font()).elidedText(name, Qt::ElideRight, 275));
    mvURLChanged(data);
}
<commit_msg>add close button on video play widget[025620]<commit_after>#include "musicvideoplaywidget.h"
#include "musicvideoview.h"
#include "musicvideotablewidget.h"
#include "musiclocalsongsearchedit.h"
#include "musicobject.h"

#include <QVBoxLayout>
#include <QHBoxLayout>
#include <QLabel>
#include <QPushButton>
#include <QStackedWidget>

MusicVideoPlayWidget::MusicVideoPlayWidget(bool popup, QWidget *parent)
    : MusicAbstractMoveWidget(parent)
{
    if(popup)
    {
        resize(525, 455);
    }

    QVBoxLayout *layout = new QVBoxLayout(this);
    layout->setMargin(0);
    layout->setSpacing(0);
    m_topWidget = new QWidget(this);
    m_topWidget->setObjectName("#topWidget");
    m_topWidget->setStyleSheet(MusicUIObject::MCustomStyle19 + \
                               MusicUIObject::MCustomStyle20);
    QHBoxLayout *topLayout = new QHBoxLayout(m_topWidget);
    topLayout->setSpacing(0);
    m_backButton = new QPushButton(this);
    m_backButton->setIcon(QIcon(":/video/back"));
    m_backButton->setCursor(QCursor(Qt::PointingHandCursor));
    m_backButton->setIconSize(QSize(18, 18));
    m_afterButton = new QPushButton(this);
    m_afterButton->setIcon(QIcon(":/video/after"));
    m_afterButton->setCursor(QCursor(Qt::PointingHandCursor));
    m_afterButton->setIconSize(QSize(18, 18));

    m_textLabel = new QLabel(m_topWidget);
    m_textLabel->setStyleSheet(MusicUIObject::MCustomStyle11);
    m_searchEdit = new MusicLocalSongSearchEdit(m_topWidget);
    m_searchEdit->setFixedHeight(18);
    m_searchButton = new QPushButton(m_topWidget);
    m_searchButton->setIcon(QIcon(":/share/searchlineleft"));
    m_searchButton->setCursor(QCursor(Qt::PointingHandCursor));
    m_searchButton->setIconSize(QSize(18, 18));
    topLayout->addWidget(m_backButton);
    topLayout->addWidget(m_afterButton);
    topLayout->addStretch();
    topLayout->addWidget(m_textLabel);
    topLayout->addStretch();
    topLayout->addWidget(m_searchEdit);
    topLayout->addWidget(m_searchButton);

    if(popup)
    {
        QPushButton *closeButton = new QPushButton(this);
        closeButton->setToolTip(tr("Close"));
        closeButton->setIcon(QIcon(":/image/close"));
        closeButton->setCursor(QCursor(Qt::PointingHandCursor));
        closeButton->setIconSize(QSize(18, 18));
        topLayout->addWidget(closeButton);
    }
    m_topWidget->setLayout(topLayout);
    m_topWidget->setFixedHeight(40);

    m_stackedWidget = new QStackedWidget(this);
    m_stackedWidget->setStyleSheet(MusicUIObject::MCustomStyle20);
    layout->addWidget(m_topWidget);
    layout->addWidget(m_stackedWidget);
    setLayout(layout);

    m_videoTable = new MusicVideoTableWidget(this);
    m_videoView = new MusicVideoView(popup, this);
    m_stackedWidget->addWidget(m_videoView);
    m_stackedWidget->addWidget(m_videoTable);
    m_stackedWidget->setCurrentIndex(0);

    connect(m_afterButton, SIGNAL(clicked(bool)), SLOT(afterButtonClicked()));
    connect(m_backButton, SIGNAL(clicked(bool)), SLOT(backButtonClicked()));
    connect(m_searchButton,SIGNAL(clicked(bool)), SLOT(searchButtonClicked()));
    connect(m_videoTable, SIGNAL(mvURLNameChanged(QString,QString)),
                          SLOT(mvURLNameChanged(QString,QString)));
    connect(m_videoTable, SIGNAL(restartSearchQuery(QString)),
                          SLOT(musicResearchButtonSearched(QString)));

}

MusicVideoPlayWidget::~MusicVideoPlayWidget()
{
    delete m_backButton;
    delete m_textLabel;
    delete m_searchEdit;
    delete m_searchButton;
    delete m_topWidget;
    delete m_videoView;
    delete m_stackedWidget;
}

void MusicVideoPlayWidget::resizeWindow(bool resize)
{
    if(resize)
    {
        showFullScreen();
    }
    else
    {
        setGeometry(250, 150, 525, 455);
    }
    m_videoView->resizeWindow(resize, size());
    m_videoTable->resizeWindow(size().width() / 525.0);
}

void MusicVideoPlayWidget::backButtonClicked()
{
    m_stackedWidget->setCurrentIndex(0);
}

void MusicVideoPlayWidget::afterButtonClicked()
{
    m_stackedWidget->setCurrentIndex(1);
}

void MusicVideoPlayWidget::searchButtonClicked()
{
    musicResearchButtonSearched(m_searchEdit->text().trimmed());
}

void MusicVideoPlayWidget::musicResearchButtonSearched(const QString &name)
{
    m_searchEdit->setText(name);
    m_stackedWidget->setCurrentIndex(1);
    m_videoTable->startSearchQuery(name);
}

void MusicVideoPlayWidget::mvURLChanged(const QString &data)
{
    m_videoView->setMedia(data);
    m_videoView->play();
    m_stackedWidget->setCurrentIndex(0);
}

void MusicVideoPlayWidget::mvURLNameChanged(const QString &name, const QString &data)
{
    m_textLabel->setText(QFontMetrics(font()).elidedText(name, Qt::ElideRight, 275));
    mvURLChanged(data);
}
<|endoftext|>


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

#include "chrome/browser/chromeos/status/power_menu_button.h"

#include "chrome/browser/browser.h"
#include "chrome/browser/browser_window.h"
#include "chrome/browser/chromeos/cros/cros_in_process_browser_test.h"
#include "chrome/browser/chromeos/cros/mock_power_library.h"
#include "chrome/browser/chromeos/frame/browser_view.h"
#include "chrome/browser/chromeos/status/browser_status_area_view.h"
#include "chrome/browser/chromeos/view_ids.h"
#include "grit/theme_resources.h"

namespace chromeos {
using ::testing::AnyNumber;
using ::testing::InvokeWithoutArgs;
using ::testing::Return;
using ::testing::ReturnRef;
using ::testing::_;

class PowerMenuButtonTest : public CrosInProcessBrowserTest {
 protected:
  PowerMenuButtonTest() : CrosInProcessBrowserTest() {}

  virtual void SetUpInProcessBrowserTestFixture() {
    InitStatusAreaMocks();
    SetStatusAreaMocksExpectations();
  }

  PowerMenuButton* GetPowerMenuButton() {
    BrowserView* view = static_cast<BrowserView*>(browser()->window());
    PowerMenuButton* power = static_cast<BrowserStatusAreaView*>(view->
        GetViewByID(VIEW_ID_STATUS_AREA))->power_view();
    return power;
  }

  int CallPowerChangedAndGetIconId() {
    PowerMenuButton* power = GetPowerMenuButton();
    power->PowerChanged(mock_power_library_);
    return power->icon_id();
  }
};

IN_PROC_BROWSER_TEST_F(PowerMenuButtonTest, BatteryMissingTest) {
  EXPECT_CALL(*mock_power_library_, battery_is_present())
      .WillRepeatedly((Return(false)));
  EXPECT_EQ(IDR_STATUSBAR_BATTERY_MISSING, CallPowerChangedAndGetIconId());
}

IN_PROC_BROWSER_TEST_F(PowerMenuButtonTest, BatteryChargedTest) {
  EXPECT_CALL(*mock_power_library_, battery_is_present())
      .WillRepeatedly((Return(true)));
  EXPECT_CALL(*mock_power_library_, battery_fully_charged())
      .WillRepeatedly((Return(true)));
  EXPECT_CALL(*mock_power_library_, line_power_on())
      .WillRepeatedly((Return(true)));
  EXPECT_EQ(IDR_STATUSBAR_BATTERY_CHARGED, CallPowerChangedAndGetIconId());
}

// http://crbug.com/48912
IN_PROC_BROWSER_TEST_F(PowerMenuButtonTest, FAILS_BatteryChargingTest) {
  EXPECT_CALL(*mock_power_library_, battery_is_present())
      .WillRepeatedly((Return(true)));
  EXPECT_CALL(*mock_power_library_, battery_fully_charged())
      .WillRepeatedly((Return(false)));
  EXPECT_CALL(*mock_power_library_, line_power_on())
      .WillRepeatedly((Return(true)));

  // Test the 12 battery charging states.
  int id = IDR_STATUSBAR_BATTERY_CHARGING_1;
  for (float precent = 6.0; precent < 100.0; precent += 8.0) {
    EXPECT_CALL(*mock_power_library_, battery_percentage())
        .WillRepeatedly((Return(precent)));
    EXPECT_EQ(id, CallPowerChangedAndGetIconId());
    id++;
  }
}

// http://crbug.com/48912
IN_PROC_BROWSER_TEST_F(PowerMenuButtonTest, FAILS_BatteryDischargingTest) {
  EXPECT_CALL(*mock_power_library_, battery_is_present())
      .WillRepeatedly((Return(true)));
  EXPECT_CALL(*mock_power_library_, battery_fully_charged())
      .WillRepeatedly((Return(false)));
  EXPECT_CALL(*mock_power_library_, line_power_on())
      .WillRepeatedly((Return(false)));

  // Test the 12 battery discharing states.
  int id = IDR_STATUSBAR_BATTERY_DISCHARGING_1;
  for (float precent = 6.0; precent < 100.0; precent += 8.0) {
    EXPECT_CALL(*mock_power_library_, battery_percentage())
        .WillRepeatedly((Return(precent)));
    EXPECT_EQ(id, CallPowerChangedAndGetIconId());
    id++;
  }
}

}  // namespace chromeos
<commit_msg>Fix browser test broken by resource ID ordering change.<commit_after>// Copyright (c) 2010 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/browser/chromeos/status/power_menu_button.h"

#include "chrome/browser/browser.h"
#include "chrome/browser/browser_window.h"
#include "chrome/browser/chromeos/cros/cros_in_process_browser_test.h"
#include "chrome/browser/chromeos/cros/mock_power_library.h"
#include "chrome/browser/chromeos/frame/browser_view.h"
#include "chrome/browser/chromeos/status/browser_status_area_view.h"
#include "chrome/browser/chromeos/view_ids.h"
#include "grit/theme_resources.h"

namespace chromeos {
using ::testing::AnyNumber;
using ::testing::InvokeWithoutArgs;
using ::testing::Return;
using ::testing::ReturnRef;
using ::testing::_;

class PowerMenuButtonTest : public CrosInProcessBrowserTest {
 protected:
  PowerMenuButtonTest() : CrosInProcessBrowserTest() {}

  virtual void SetUpInProcessBrowserTestFixture() {
    InitStatusAreaMocks();
    SetStatusAreaMocksExpectations();
  }

  PowerMenuButton* GetPowerMenuButton() {
    BrowserView* view = static_cast<BrowserView*>(browser()->window());
    PowerMenuButton* power = static_cast<BrowserStatusAreaView*>(view->
        GetViewByID(VIEW_ID_STATUS_AREA))->power_view();
    return power;
  }

  int CallPowerChangedAndGetIconId() {
    PowerMenuButton* power = GetPowerMenuButton();
    power->PowerChanged(mock_power_library_);
    return power->icon_id();
  }
};

IN_PROC_BROWSER_TEST_F(PowerMenuButtonTest, BatteryMissingTest) {
  EXPECT_CALL(*mock_power_library_, battery_is_present())
      .WillRepeatedly((Return(false)));
  EXPECT_EQ(IDR_STATUSBAR_BATTERY_MISSING, CallPowerChangedAndGetIconId());
}

IN_PROC_BROWSER_TEST_F(PowerMenuButtonTest, BatteryChargedTest) {
  EXPECT_CALL(*mock_power_library_, battery_is_present())
      .WillRepeatedly((Return(true)));
  EXPECT_CALL(*mock_power_library_, battery_fully_charged())
      .WillRepeatedly((Return(true)));
  EXPECT_CALL(*mock_power_library_, line_power_on())
      .WillRepeatedly((Return(true)));
  EXPECT_EQ(IDR_STATUSBAR_BATTERY_CHARGED, CallPowerChangedAndGetIconId());
}

IN_PROC_BROWSER_TEST_F(PowerMenuButtonTest, BatteryChargingTest) {
  EXPECT_CALL(*mock_power_library_, battery_is_present())
      .WillRepeatedly((Return(true)));
  EXPECT_CALL(*mock_power_library_, battery_fully_charged())
      .WillRepeatedly((Return(false)));
  EXPECT_CALL(*mock_power_library_, line_power_on())
      .WillRepeatedly((Return(true)));

  // Test the 12 battery charging states.
  // NOTE: Use an array rather than just calculating a resource number to avoid
  // creating implicit ordering dependencies on the resource values.
  static const int kChargingImages[] = {
    IDR_STATUSBAR_BATTERY_CHARGING_1,
    IDR_STATUSBAR_BATTERY_CHARGING_2,
    IDR_STATUSBAR_BATTERY_CHARGING_3,
    IDR_STATUSBAR_BATTERY_CHARGING_4,
    IDR_STATUSBAR_BATTERY_CHARGING_5,
    IDR_STATUSBAR_BATTERY_CHARGING_6,
    IDR_STATUSBAR_BATTERY_CHARGING_7,
    IDR_STATUSBAR_BATTERY_CHARGING_8,
    IDR_STATUSBAR_BATTERY_CHARGING_9,
    IDR_STATUSBAR_BATTERY_CHARGING_10,
    IDR_STATUSBAR_BATTERY_CHARGING_11,
    IDR_STATUSBAR_BATTERY_CHARGING_12,
  };
  size_t id = 0;
  for (float percent = 6.0; percent < 100.0; percent += 8.0) {
    EXPECT_CALL(*mock_power_library_, battery_percentage())
        .WillRepeatedly((Return(percent)));
    ASSERT_LT(id, arraysize(kChargingImages));
    EXPECT_EQ(kChargingImages[id], CallPowerChangedAndGetIconId());
    id++;
  }
}

IN_PROC_BROWSER_TEST_F(PowerMenuButtonTest, BatteryDischargingTest) {
  EXPECT_CALL(*mock_power_library_, battery_is_present())
      .WillRepeatedly((Return(true)));
  EXPECT_CALL(*mock_power_library_, battery_fully_charged())
      .WillRepeatedly((Return(false)));
  EXPECT_CALL(*mock_power_library_, line_power_on())
      .WillRepeatedly((Return(false)));

  // Test the 12 battery discharing states.
  // NOTE: Use an array rather than just calculating a resource number to avoid
  // creating implicit ordering dependencies on the resource values.
  static const int kDischargingImages[] = {
    IDR_STATUSBAR_BATTERY_DISCHARGING_1,
    IDR_STATUSBAR_BATTERY_DISCHARGING_2,
    IDR_STATUSBAR_BATTERY_DISCHARGING_3,
    IDR_STATUSBAR_BATTERY_DISCHARGING_4,
    IDR_STATUSBAR_BATTERY_DISCHARGING_5,
    IDR_STATUSBAR_BATTERY_DISCHARGING_6,
    IDR_STATUSBAR_BATTERY_DISCHARGING_7,
    IDR_STATUSBAR_BATTERY_DISCHARGING_8,
    IDR_STATUSBAR_BATTERY_DISCHARGING_9,
    IDR_STATUSBAR_BATTERY_DISCHARGING_10,
    IDR_STATUSBAR_BATTERY_DISCHARGING_11,
    IDR_STATUSBAR_BATTERY_DISCHARGING_12,
  };
  size_t id = 0;
  for (float percent = 6.0; percent < 100.0; percent += 8.0) {
    EXPECT_CALL(*mock_power_library_, battery_percentage())
        .WillRepeatedly((Return(percent)));
    ASSERT_LT(id, arraysize(kDischargingImages));
    EXPECT_EQ(kDischargingImages[id], CallPowerChangedAndGetIconId());
    id++;
  }
}

}  // namespace chromeos
<|endoftext|>


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

#include "base/bind.h"
#include "base/file_util.h"
#include "base/files/file_enumerator.h"
#include "base/files/file_path.h"
#include "base/values.h"
#include "base/version.h"
#include "chrome/browser/component_updater/default_component_installer.h"
#include "content/public/browser/browser_thread.h"

namespace {
// Version "0" corresponds to no installed version. By the server's conventions,
// we represent it as a dotted quad.
const char kNullVersion[] = "0.0.0.0";
}  // namespace

DefaultComponentInstaller::DefaultComponentInstaller(
    scoped_ptr<ComponentInstallerTraits> installer_traits)
    : current_version_(kNullVersion) {
  installer_traits_ = installer_traits.Pass();
}

DefaultComponentInstaller::~DefaultComponentInstaller() {
}

void DefaultComponentInstaller::Register(ComponentUpdateService* cus) {
  if (!installer_traits_) {
    NOTREACHED() << "A DefaultComponentInstaller has been created but "
                 << "has no installer traits.";
    return;
  }
  content::BrowserThread::PostTask(
      content::BrowserThread::FILE, FROM_HERE,
      base::Bind(&DefaultComponentInstaller::StartRegistration,
                 base::Unretained(this),
                 cus));
}

void DefaultComponentInstaller::OnUpdateError(int error) {
  NOTREACHED() << "Component update error: " << error;
}

bool DefaultComponentInstaller::Install(const base::DictionaryValue& manifest,
                                        const base::FilePath& unpack_path) {
  std::string manifest_version;
  manifest.GetStringASCII("version", &manifest_version);
  base::Version version(manifest_version.c_str());
  if (!version.IsValid())
    return false;
  if (current_version_.CompareTo(version) > 0)
    return false;
  base::FilePath install_path =
      installer_traits_->GetBaseDirectory().AppendASCII(version.GetString());
  if (base::PathExists(install_path))
    return false;
  if (!base::Move(unpack_path, install_path))
    return false;
  if (!installer_traits_->OnCustomInstall(manifest, install_path))
    return false;
  if (!installer_traits_->VerifyInstallation(install_path)) {
    return false;
  }
  current_version_ = version;
  installer_traits_->ComponentReady(current_version_, GetInstallDirectory());
  return true;
}

bool DefaultComponentInstaller::GetInstalledFile(
    const std::string& file,
    base::FilePath* installed_file) {
  if (current_version_.Equals(base::Version(kNullVersion)))
    return false;  // No component has been installed yet.

  *installed_file =
      installer_traits_->GetBaseDirectory()
          .AppendASCII(current_version_.GetString()).AppendASCII(file);
  return true;
}

void DefaultComponentInstaller::StartRegistration(
    ComponentUpdateService* cus) {
  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::FILE));
  base::FilePath base_dir = installer_traits_->GetBaseDirectory();
  if (!base::PathExists(base_dir) &&
      !file_util::CreateDirectory(base_dir)) {
    NOTREACHED() << "Could not create the base directory for "
                 << installer_traits_->GetName() << " ("
                 << base_dir.MaybeAsASCII() << ").";
    return;
  }

  base::FilePath latest_dir;
  base::Version latest_version(kNullVersion);
  std::vector<base::FilePath> older_dirs;
  bool found = false;
  base::FileEnumerator file_enumerator(
      base_dir, false, base::FileEnumerator::DIRECTORIES);
  for (base::FilePath path = file_enumerator.Next();
       !path.value().empty();
       path = file_enumerator.Next()) {
    base::Version version(path.BaseName().MaybeAsASCII());
    if (!version.IsValid())
      continue;
    if (found) {
      if (version.CompareTo(latest_version) > 0) {
        older_dirs.push_back(latest_dir);
        latest_dir = path;
        latest_version = version;
      } else {
        older_dirs.push_back(path);
      }
    } else {
      latest_dir = path;
      latest_version = version;
      found = true;
    }
  }

  if (found) {
    current_version_ = latest_version;
    base::ReadFileToString(latest_dir.AppendASCII("manifest.fingerprint"),
                           &current_fingerprint_);
  }

  // Remove older versions of the component. None should be in use during
  // browser startup.
  for (std::vector<base::FilePath>::iterator iter = older_dirs.begin();
       iter != older_dirs.end(); ++iter) {
   base::DeleteFile(*iter, true);
  }

  content::BrowserThread::PostTask(
      content::BrowserThread::UI, FROM_HERE,
      base::Bind(&DefaultComponentInstaller::FinishRegistration,
                 base::Unretained(this),
                 cus));
}

base::FilePath DefaultComponentInstaller::GetInstallDirectory() {
  return installer_traits_->GetBaseDirectory()
      .AppendASCII(current_version_.GetString());
}

void DefaultComponentInstaller::FinishRegistration(
    ComponentUpdateService* cus) {
  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
  CrxComponent crx;
  crx.name = installer_traits_->GetName();
  crx.installer = this;
  crx.version = current_version_;
  crx.fingerprint = current_fingerprint_;
  installer_traits_->GetHash(&crx.pk_hash);
  ComponentUpdateService::Status status = cus->RegisterComponent(crx);
  if (status != ComponentUpdateService::kOk &&
      status != ComponentUpdateService::kReplaced) {
    NOTREACHED() << "Component registration failed for "
                 << installer_traits_->GetName();
    return;
  }

  base::Version installed_version;
  if (current_version_.CompareTo(base::Version(kNullVersion)) <= 0) {
    content::BrowserThread::PostTask(
        content::BrowserThread::FILE, FROM_HERE,
        base::Bind(&ComponentInstallerTraits::ComponentReady,
                   base::Unretained(installer_traits_.get()),
                   installed_version,
                   GetInstallDirectory()));
  }
}
<commit_msg>Component Installer provides proper version to traits on registration.<commit_after>// Copyright 2013 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "base/bind.h"
#include "base/file_util.h"
#include "base/files/file_enumerator.h"
#include "base/files/file_path.h"
#include "base/values.h"
#include "base/version.h"
#include "chrome/browser/component_updater/default_component_installer.h"
#include "content/public/browser/browser_thread.h"

namespace {
// Version "0" corresponds to no installed version. By the server's conventions,
// we represent it as a dotted quad.
const char kNullVersion[] = "0.0.0.0";
}  // namespace

DefaultComponentInstaller::DefaultComponentInstaller(
    scoped_ptr<ComponentInstallerTraits> installer_traits)
    : current_version_(kNullVersion) {
  installer_traits_ = installer_traits.Pass();
}

DefaultComponentInstaller::~DefaultComponentInstaller() {
}

void DefaultComponentInstaller::Register(ComponentUpdateService* cus) {
  if (!installer_traits_) {
    NOTREACHED() << "A DefaultComponentInstaller has been created but "
                 << "has no installer traits.";
    return;
  }
  content::BrowserThread::PostTask(
      content::BrowserThread::FILE, FROM_HERE,
      base::Bind(&DefaultComponentInstaller::StartRegistration,
                 base::Unretained(this),
                 cus));
}

void DefaultComponentInstaller::OnUpdateError(int error) {
  NOTREACHED() << "Component update error: " << error;
}

bool DefaultComponentInstaller::Install(const base::DictionaryValue& manifest,
                                        const base::FilePath& unpack_path) {
  std::string manifest_version;
  manifest.GetStringASCII("version", &manifest_version);
  base::Version version(manifest_version.c_str());
  if (!version.IsValid())
    return false;
  if (current_version_.CompareTo(version) > 0)
    return false;
  base::FilePath install_path =
      installer_traits_->GetBaseDirectory().AppendASCII(version.GetString());
  if (base::PathExists(install_path))
    return false;
  if (!base::Move(unpack_path, install_path))
    return false;
  if (!installer_traits_->OnCustomInstall(manifest, install_path))
    return false;
  if (!installer_traits_->VerifyInstallation(install_path)) {
    return false;
  }
  current_version_ = version;
  installer_traits_->ComponentReady(current_version_, GetInstallDirectory());
  return true;
}

bool DefaultComponentInstaller::GetInstalledFile(
    const std::string& file,
    base::FilePath* installed_file) {
  if (current_version_.Equals(base::Version(kNullVersion)))
    return false;  // No component has been installed yet.

  *installed_file =
      installer_traits_->GetBaseDirectory()
          .AppendASCII(current_version_.GetString()).AppendASCII(file);
  return true;
}

void DefaultComponentInstaller::StartRegistration(
    ComponentUpdateService* cus) {
  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::FILE));
  base::FilePath base_dir = installer_traits_->GetBaseDirectory();
  if (!base::PathExists(base_dir) &&
      !file_util::CreateDirectory(base_dir)) {
    NOTREACHED() << "Could not create the base directory for "
                 << installer_traits_->GetName() << " ("
                 << base_dir.MaybeAsASCII() << ").";
    return;
  }

  base::FilePath latest_dir;
  base::Version latest_version(kNullVersion);
  std::vector<base::FilePath> older_dirs;
  bool found = false;
  base::FileEnumerator file_enumerator(
      base_dir, false, base::FileEnumerator::DIRECTORIES);
  for (base::FilePath path = file_enumerator.Next();
       !path.value().empty();
       path = file_enumerator.Next()) {
    base::Version version(path.BaseName().MaybeAsASCII());
    if (!version.IsValid())
      continue;
    if (found) {
      if (version.CompareTo(latest_version) > 0) {
        older_dirs.push_back(latest_dir);
        latest_dir = path;
        latest_version = version;
      } else {
        older_dirs.push_back(path);
      }
    } else {
      latest_dir = path;
      latest_version = version;
      found = true;
    }
  }

  if (found) {
    current_version_ = latest_version;
    base::ReadFileToString(latest_dir.AppendASCII("manifest.fingerprint"),
                           &current_fingerprint_);
  }

  // Remove older versions of the component. None should be in use during
  // browser startup.
  for (std::vector<base::FilePath>::iterator iter = older_dirs.begin();
       iter != older_dirs.end(); ++iter) {
   base::DeleteFile(*iter, true);
  }

  content::BrowserThread::PostTask(
      content::BrowserThread::UI, FROM_HERE,
      base::Bind(&DefaultComponentInstaller::FinishRegistration,
                 base::Unretained(this),
                 cus));
}

base::FilePath DefaultComponentInstaller::GetInstallDirectory() {
  return installer_traits_->GetBaseDirectory()
      .AppendASCII(current_version_.GetString());
}

void DefaultComponentInstaller::FinishRegistration(
    ComponentUpdateService* cus) {
  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
  CrxComponent crx;
  crx.name = installer_traits_->GetName();
  crx.installer = this;
  crx.version = current_version_;
  crx.fingerprint = current_fingerprint_;
  installer_traits_->GetHash(&crx.pk_hash);
  ComponentUpdateService::Status status = cus->RegisterComponent(crx);
  if (status != ComponentUpdateService::kOk &&
      status != ComponentUpdateService::kReplaced) {
    NOTREACHED() << "Component registration failed for "
                 << installer_traits_->GetName();
    return;
  }

  if (current_version_.CompareTo(base::Version(kNullVersion)) > 0) {
    content::BrowserThread::PostTask(
        content::BrowserThread::FILE, FROM_HERE,
        base::Bind(&ComponentInstallerTraits::ComponentReady,
                   base::Unretained(installer_traits_.get()),
                   current_version_,
                   GetInstallDirectory()));
  }
}
<|endoftext|>