<commit_before>/*  This file is part of the Vc library.

    Copyright (C) 2009 Matthias Kretz <kretz@kde.org>

    Vc 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 3 of
    the License, or (at your option) any later version.

    Vc 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 Vc.  If not, see <http://www.gnu.org/licenses/>.

*/

#include <Vc/Vc>
#include "benchmark.h"
#include "random.h"
#include "cpuid.h"
#include <cstdio>
#include <cstdlib>

using namespace Vc;

bool blackHoleBool = false;

template<typename Vector> class DoCompares
{
    public:
        static void run(const int Repetitions)
        {
            const int Factor = CpuId::L1Data() / sizeof(Vector);
            Vector *a = new Vector[Factor + 1];
            for (int i = 0; i < Factor + 1; ++i) {
                a[i] = PseudoRandom<Vector>::next();
            }

            {
                Benchmark timer("operator==", Vector::Size * Factor, "Op");
                for (int repetitions = 0; repetitions < Repetitions; ++repetitions) {
                    timer.Start();
                    for (int i = 0; i < Factor; ++i) {
                        typename Vector::Mask tmp = a[i] == a[i + 1];
#if VC_IMPL_SSE
                        asm(""::"x"(reinterpret_cast<const __m128 &>(tmp)));
#else
                        asm(""::"r"(tmp));
#endif
                    }
                    timer.Stop();
                }
                timer.Print(Benchmark::PrintAverage);
            }
            {
                Benchmark timer("operator<", Vector::Size * Factor, "Op");
                for (int repetitions = 0; repetitions < Repetitions; ++repetitions) {
                    timer.Start();
                    for (int i = 0; i < Factor; ++i) {
                        typename Vector::Mask tmp = a[i] < a[i + 1];
#if VC_IMPL_SSE
                        asm(""::"x"(reinterpret_cast<const __m128 &>(tmp)));
#else
                        asm(""::"r"(tmp));
#endif
                    }
                    timer.Stop();
                }
                timer.Print(Benchmark::PrintAverage);
            }
            {
                Benchmark timer("(operator<).isFull()", Vector::Size * Factor, "Op");
                for (int repetitions = 0; repetitions < Repetitions; ++repetitions) {
                    timer.Start();
                    const Vector one(One);
                    for (int i = 0; i < Factor; ++i) {
                        bool tmp = (a[i] < a[i + 1]).isFull();
                        asm(""::"r"(tmp));
                    }
                    timer.Stop();
                }
                timer.Print(Benchmark::PrintAverage);
            }
            {
                Benchmark timer("!(operator<).isEmpty()", Vector::Size * Factor, "Op");
                for (int repetitions = 0; repetitions < Repetitions; ++repetitions) {
                    timer.Start();
                    const Vector one(One);
                    for (int i = 0; i < Factor; ++i) {
                        bool tmp = !(a[i] < a[i + 1]).isEmpty();
                        asm(""::"r"(tmp));
                    }
                    timer.Stop();
                }
                timer.Print(Benchmark::PrintAverage);
            }
            delete[] a;
        }

    private:
        static typename Vector::Mask blackHoleMask;
        static Vector blackHoleVector;
};

template<> double_m DoCompares<double_v>::blackHoleMask = double_m();
template<> double_v DoCompares<double_v>::blackHoleVector = double_v();
template<> float_m DoCompares<float_v>::blackHoleMask = float_m();
template<> float_v DoCompares<float_v>::blackHoleVector = float_v();
template<> short_m DoCompares<short_v>::blackHoleMask = short_m();
template<> short_v DoCompares<short_v>::blackHoleVector = short_v();
template<> ushort_m DoCompares<ushort_v>::blackHoleMask = ushort_m();
template<> ushort_v DoCompares<ushort_v>::blackHoleVector = ushort_v();
#if !VC_IMPL_LRBni
template<> int_m DoCompares<int_v>::blackHoleMask = int_m();
template<> int_v DoCompares<int_v>::blackHoleVector = int_v();
template<> uint_m DoCompares<uint_v>::blackHoleMask = uint_m();
template<> uint_v DoCompares<uint_v>::blackHoleVector = uint_v();
#endif
#if VC_IMPL_SSE
template<> sfloat_m DoCompares<sfloat_v>::blackHoleMask = sfloat_m();
template<> sfloat_v DoCompares<sfloat_v>::blackHoleVector = sfloat_v();
#endif

int bmain(Benchmark::OutputMode out)
{
    const int Repetitions = out == Benchmark::Stdout ? 10 : g_Repetitions > 0 ? g_Repetitions : 100;

    Benchmark::addColumn("datatype");

    Benchmark::setColumnData("datatype", "double_v");
    DoCompares<double_v>::run(Repetitions);
    Benchmark::setColumnData("datatype", "float_v");
    DoCompares<float_v>::run(Repetitions);
    Benchmark::setColumnData("datatype", "int_v");
    DoCompares<int_v>::run(Repetitions);
    Benchmark::setColumnData("datatype", "uint_v");
    DoCompares<uint_v>::run(Repetitions);
    Benchmark::setColumnData("datatype", "short_v");
    DoCompares<short_v>::run(Repetitions);
    Benchmark::setColumnData("datatype", "ushort_v");
    DoCompares<ushort_v>::run(Repetitions);
    Benchmark::setColumnData("datatype", "sfloat_v");
    DoCompares<sfloat_v>::run(Repetitions);

    return 0;
}
<commit_msg>GCC emits an unnecessary mov. Hack around it to get more correct results<commit_after>/*  This file is part of the Vc library.

    Copyright (C) 2009 Matthias Kretz <kretz@kde.org>

    Vc 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 3 of
    the License, or (at your option) any later version.

    Vc 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 Vc.  If not, see <http://www.gnu.org/licenses/>.

*/

#include <Vc/Vc>
#include "benchmark.h"
#include "random.h"
#include "cpuid.h"
#include <cstdio>
#include <cstdlib>

using namespace Vc;

bool blackHoleBool = false;

template<typename Vector> class DoCompares
{
    public:
        static void run(const int Repetitions)
        {
            const int Factor = CpuId::L1Data() / sizeof(Vector);
            Vector *a = new Vector[Factor + 1];
            for (int i = 0; i < Factor + 1; ++i) {
                a[i] = PseudoRandom<Vector>::next();
            }

#ifdef VC_IMPL_Scalar
            typedef bool M;
#else
            typedef typename Vector::Mask M;
#endif

            {
                Benchmark timer("operator==", Vector::Size * Factor, "Op");
                for (int repetitions = 0; repetitions < Repetitions; ++repetitions) {
                    timer.Start();
                    for (int i = 0; i < Factor; ++i) {
                        const M tmp = a[i] == a[i + 1];
#if VC_IMPL_SSE
                        asm(""::"x"(reinterpret_cast<const __m128 &>(tmp)));
#else
                        asm(""::"r"(tmp));
#endif
                    }
                    timer.Stop();
                }
                timer.Print(Benchmark::PrintAverage);
            }
            {
                Benchmark timer("operator<", Vector::Size * Factor, "Op");
                for (int repetitions = 0; repetitions < Repetitions; ++repetitions) {
                    timer.Start();
                    for (int i = 0; i < Factor; ++i) {
                        const M tmp = a[i] < a[i + 1];
#if VC_IMPL_SSE
                        asm(""::"x"(reinterpret_cast<const __m128 &>(tmp)));
#else
                        asm(""::"r"(tmp));
#endif
                    }
                    timer.Stop();
                }
                timer.Print(Benchmark::PrintAverage);
            }
            {
                Benchmark timer("(operator<).isFull()", Vector::Size * Factor, "Op");
                for (int repetitions = 0; repetitions < Repetitions; ++repetitions) {
                    timer.Start();
                    const Vector one(One);
                    for (int i = 0; i < Factor; ++i) {
                        const bool tmp = (a[i] < a[i + 1]).isFull();
                        asm(""::"r"(tmp));
                    }
                    timer.Stop();
                }
                timer.Print(Benchmark::PrintAverage);
            }
            {
                Benchmark timer("!(operator<).isEmpty()", Vector::Size * Factor, "Op");
                for (int repetitions = 0; repetitions < Repetitions; ++repetitions) {
                    timer.Start();
                    const Vector one(One);
                    for (int i = 0; i < Factor; ++i) {
                        const bool tmp = !(a[i] < a[i + 1]).isEmpty();
                        asm(""::"r"(tmp));
                    }
                    timer.Stop();
                }
                timer.Print(Benchmark::PrintAverage);
            }
            delete[] a;
        }

    private:
        static typename Vector::Mask blackHoleMask;
        static Vector blackHoleVector;
};

template<> double_m DoCompares<double_v>::blackHoleMask = double_m();
template<> double_v DoCompares<double_v>::blackHoleVector = double_v();
template<> float_m DoCompares<float_v>::blackHoleMask = float_m();
template<> float_v DoCompares<float_v>::blackHoleVector = float_v();
template<> short_m DoCompares<short_v>::blackHoleMask = short_m();
template<> short_v DoCompares<short_v>::blackHoleVector = short_v();
template<> ushort_m DoCompares<ushort_v>::blackHoleMask = ushort_m();
template<> ushort_v DoCompares<ushort_v>::blackHoleVector = ushort_v();
#if !VC_IMPL_LRBni
template<> int_m DoCompares<int_v>::blackHoleMask = int_m();
template<> int_v DoCompares<int_v>::blackHoleVector = int_v();
template<> uint_m DoCompares<uint_v>::blackHoleMask = uint_m();
template<> uint_v DoCompares<uint_v>::blackHoleVector = uint_v();
#endif
#if VC_IMPL_SSE
template<> sfloat_m DoCompares<sfloat_v>::blackHoleMask = sfloat_m();
template<> sfloat_v DoCompares<sfloat_v>::blackHoleVector = sfloat_v();
#endif

int bmain(Benchmark::OutputMode out)
{
    const int Repetitions = out == Benchmark::Stdout ? 10 : g_Repetitions > 0 ? g_Repetitions : 100;

    Benchmark::addColumn("datatype");

    Benchmark::setColumnData("datatype", "double_v");
    DoCompares<double_v>::run(Repetitions);
    Benchmark::setColumnData("datatype", "float_v");
    DoCompares<float_v>::run(Repetitions);
    Benchmark::setColumnData("datatype", "int_v");
    DoCompares<int_v>::run(Repetitions);
    Benchmark::setColumnData("datatype", "uint_v");
    DoCompares<uint_v>::run(Repetitions);
    Benchmark::setColumnData("datatype", "short_v");
    DoCompares<short_v>::run(Repetitions);
    Benchmark::setColumnData("datatype", "ushort_v");
    DoCompares<ushort_v>::run(Repetitions);
    Benchmark::setColumnData("datatype", "sfloat_v");
    DoCompares<sfloat_v>::run(Repetitions);

    return 0;
}
<|endoftext|>


<commit_before>#include "calc.h"
#include <cstdlib>
#include <iostream>
#include <algorithm>

Calculator::Calculator(std::string string): expression_(clean_expression(string)) {}

const char Calculator::OPEN_BRACKET = '(';
const char Calculator::CLOSE_BRACKET = ')';
const std::regex Calculator::DIGITS_RE("\\d+");
const std::regex Calculator::EXPRESSION_RE("^[\\d\\(\\)\\+\\*\\/\\-]*$");

void Calculator::register_operator(const Operator* op) {
    if(op_mapping_.count(op->get_operator()) > 0) {
        return;
    }
    op_mapping_[op->get_operator()] = op;
}

double Calculator::calculate() {
    std::smatch match;
    for(size_t i = 0; i < expression_.length(); i++) {
        char c = expression_[i];
        if(isdigit(c)) {
            std::regex_search(expression_.substr(i, expression_.length() - i), match, DIGITS_RE);
            const char* digits_ptr = match.str().c_str();
            operand_stack_.push(std::strtod(digits_ptr, nullptr)); // There is probably a better way...
            i += match.length() - 1;
            continue;
        } else {
           if(c == OPEN_BRACKET) {
               operator_stack_.push(c);
               continue;
           } else if(c == CLOSE_BRACKET) {
               process_brackets();
               continue;
           }
           if(!op_mapping_.count(c)) {
               throw UnknownOperatorException();
           } else if (!operator_stack_.empty() && operator_stack_.top() == OPEN_BRACKET) {
               operator_stack_.push(c);
               continue;
           } else if (!operator_stack_.empty() && op_mapping_[c]->get_priority() < op_mapping_[operator_stack_.top()]->get_priority()) {
               reduce();
               operator_stack_.push(c);
               continue;
           }
           operator_stack_.push(c);
        }
    }
    while (!operator_stack_.empty()) {
        reduce();
    }
    return operand_stack_.top();
}

void Calculator::reduce() {
    double op2 = operand_stack_.top();
    operand_stack_.pop();
    double op1 = operand_stack_.top();
    operand_stack_.pop();

    const Operator* op = op_mapping_[operator_stack_.top()];
    operator_stack_.pop();

    operand_stack_.push(op->calculate(op1, op2));
}

void Calculator::process_brackets() {
    while (operator_stack_.top() != OPEN_BRACKET) {
        reduce();
    }
    operator_stack_.pop();
}

std::string Calculator::clean_expression(std::string s) {
    /* Attempt to clean data before processing */

    const std::string::iterator begin = s.begin();
    const std::string::iterator end = s.end();

    long opened = std::count(begin, end, '(');
    long closed = std::count(begin, end, ')');

    if (opened != closed) {
        throw InvalidExpressionException();
    }

    std::remove(begin, end, ' ');

    std::smatch m;
    std::regex_search(s, m, EXPRESSION_RE);
    if (!m.size()) {
        throw InvalidExpressionException();
    }
    return s;
}
<commit_msg>Use static vars for calc validation<commit_after>#include "calc.h"
#include <cstdlib>
#include <iostream>
#include <algorithm>

Calculator::Calculator(std::string string): expression_(clean_expression(string)) {}

const char Calculator::OPEN_BRACKET = '(';
const char Calculator::CLOSE_BRACKET = ')';
const std::regex Calculator::DIGITS_RE("\\d+");
const std::regex Calculator::EXPRESSION_RE("^[\\d\\(\\)\\+\\*\\/\\-]*$");

void Calculator::register_operator(const Operator* op) {
    if(op_mapping_.count(op->get_operator()) > 0) {
        return;
    }
    op_mapping_[op->get_operator()] = op;
}

double Calculator::calculate() {
    std::smatch match;
    for(size_t i = 0; i < expression_.length(); i++) {
        char c = expression_[i];
        if(isdigit(c)) {
            std::regex_search(expression_.substr(i, expression_.length() - i), match, DIGITS_RE);
            const char* digits_ptr = match.str().c_str();
            operand_stack_.push(std::strtod(digits_ptr, nullptr)); // There is probably a better way...
            i += match.length() - 1;
            continue;
        } else {
           if(c == OPEN_BRACKET) {
               operator_stack_.push(c);
               continue;
           } else if(c == CLOSE_BRACKET) {
               process_brackets();
               continue;
           }
           if(!op_mapping_.count(c)) {
               throw UnknownOperatorException();
           } else if (!operator_stack_.empty() && operator_stack_.top() == OPEN_BRACKET) {
               operator_stack_.push(c);
               continue;
           } else if (!operator_stack_.empty() && op_mapping_[c]->get_priority() < op_mapping_[operator_stack_.top()]->get_priority()) {
               reduce();
               operator_stack_.push(c);
               continue;
           }
           operator_stack_.push(c);
        }
    }
    while (!operator_stack_.empty()) {
        reduce();
    }
    return operand_stack_.top();
}

void Calculator::reduce() {
    double op2 = operand_stack_.top();
    operand_stack_.pop();
    double op1 = operand_stack_.top();
    operand_stack_.pop();

    const Operator* op = op_mapping_[operator_stack_.top()];
    operator_stack_.pop();

    operand_stack_.push(op->calculate(op1, op2));
}

void Calculator::process_brackets() {
    while (operator_stack_.top() != OPEN_BRACKET) {
        reduce();
    }
    operator_stack_.pop();
}

std::string Calculator::clean_expression(std::string s) {
    /* Attempt to clean data before processing */

    const std::string::iterator begin = s.begin();
    const std::string::iterator end = s.end();

    long opened = std::count(begin, end, OPEN_BRACKET);
    long closed = std::count(begin, end, CLOSE_BRACKET);

    if (opened != closed) {
        throw InvalidExpressionException();
    }

    std::remove(begin, end, ' ');

    std::smatch m;
    std::regex_search(s, m, EXPRESSION_RE);
    if (!m.size()) {
        throw InvalidExpressionException();
    }
    return s;
}
<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: MultipleItemConverter.hxx,v $
 *
 *  $Revision: 1.5 $
 *
 *  last change: $Author: vg $ $Date: 2007-05-22 17:54:48 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    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
 *
 ************************************************************************/
#ifndef CHART_ALLAXISITEMCONVERTER_HXX
#define CHART_ALLAXISITEMCONVERTER_HXX

#ifndef _COM_SUN_STAR_FRAME_XMODEL_HPP_
#include <com/sun/star/frame/XModel.hpp>
#endif

#include "ItemConverter.hxx"

#include <vector>

namespace comphelper
{

/** Note: virtual const USHORT * GetWhichPairs() const; is still pure virtual
 */
class MultipleItemConverter : public ItemConverter
{
public:
    virtual ~MultipleItemConverter();

    virtual void FillItemSet( SfxItemSet & rOutItemSet ) const;
    virtual bool ApplyItemSet( const SfxItemSet & rItemSet );

    /// implemented empty (returns always false)
    virtual bool GetItemProperty( tWhichIdType nWhichId, tPropertyNameWithMemberId & rOutProperty ) const;

protected:
    MultipleItemConverter( SfxItemPool& rItemPool );

    ::std::vector< ItemConverter * >            m_aConverters;
};

} //  namespace comphelper

#endif
<commit_msg>INTEGRATION: CWS changefileheader (1.5.126); FILE MERGED 2008/04/01 10:50:22 thb 1.5.126.2: #i85898# Stripping all external header guards 2008/03/28 16:43:44 rt 1.5.126.1: #i87441# Change license header to LPGL v3.<commit_after>/*************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2008 by Sun Microsystems, Inc.
 *
 * OpenOffice.org - a multi-platform office productivity suite
 *
 * $RCSfile: MultipleItemConverter.hxx,v $
 * $Revision: 1.6 $
 *
 * This file is part of OpenOffice.org.
 *
 * OpenOffice.org is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License version 3
 * only, as published by the Free Software Foundation.
 *
 * OpenOffice.org 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 version 3 for more details
 * (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU Lesser General Public License
 * version 3 along with OpenOffice.org.  If not, see
 * <http://www.openoffice.org/license.html>
 * for a copy of the LGPLv3 License.
 *
 ************************************************************************/
#ifndef CHART_ALLAXISITEMCONVERTER_HXX
#define CHART_ALLAXISITEMCONVERTER_HXX

#include <com/sun/star/frame/XModel.hpp>

#include "ItemConverter.hxx"

#include <vector>

namespace comphelper
{

/** Note: virtual const USHORT * GetWhichPairs() const; is still pure virtual
 */
class MultipleItemConverter : public ItemConverter
{
public:
    virtual ~MultipleItemConverter();

    virtual void FillItemSet( SfxItemSet & rOutItemSet ) const;
    virtual bool ApplyItemSet( const SfxItemSet & rItemSet );

    /// implemented empty (returns always false)
    virtual bool GetItemProperty( tWhichIdType nWhichId, tPropertyNameWithMemberId & rOutProperty ) const;

protected:
    MultipleItemConverter( SfxItemPool& rItemPool );

    ::std::vector< ItemConverter * >            m_aConverters;
};

} //  namespace comphelper

#endif
<|endoftext|>


<commit_before>// Sh: A GPU metaprogramming language.
//
// Copyright 2003-2006 Serious Hack Inc.
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
// MA  02110-1301, USA
//////////////////////////////////////////////////////////////////////////////
#include "GlTextureStorage.hpp"
#include "ShTypeInfo.hpp"
#include "ShVariantFactory.hpp"
#include "FBOCache.hpp"
#include <sh.hpp>

namespace shgl {

using namespace SH;

GlTextureStorage::GlTextureStorage(ShMemory* memory, GLenum target,
                                   GLenum format, GLint internalFormat,
                                   ShValueType valueType,
                                   int width, int height, int depth, int tuplesize,
                                   GlTextureNamePtr name,
                                   GLint mipmap_level, bool internalRGB)
  : ShStorage(memory, valueType),
    m_name(name), m_target(target), m_format(format),
    m_internalFormat(internalFormat),
    m_width(width), m_height(height), m_depth(depth), m_tuplesize(tuplesize),
    m_write(false),
    m_internalFormatRGB(internalRGB),
    m_mipmap_level(mipmap_level)
{
  m_name->addStorage(this);
}

GlTextureStorage::~GlTextureStorage()
{
  m_name->removeStorage(this);
}

void GlTextureStorage::initTexture()
{
  HostGlTextureTransfer::instance->transfer(0, this);
}

HostGlTextureTransfer::HostGlTextureTransfer()
  : ShTransfer("host", "opengl:texture")
{
}

bool HostGlTextureTransfer::transfer(const ShStorage* from, ShStorage* to)
{
  const ShHostStorage* host = dynamic_cast<const ShHostStorage*>(from);
  GlTextureStorage* texture = dynamic_cast<GlTextureStorage*>(to);

  // Bind texture name for this scope.
  GlTextureName::Binding binding(texture->texName());

  GLenum type;
  ShValueType texture_type = texture->value_type();
  ShValueType converted_type;
  type = shGlType(texture_type, converted_type);

  int width = texture->width();
  int height = texture->height();
  int depth = texture->depth();
  int tuplesize = texture->tuplesize();

  ShVariantPtr data_variant;
  int count = 0;
  bool full_copy = false;
  if (host) {
    count = host->length() / host->value_size();
    full_copy = (count >= (width * height * depth));

    ShValueType host_type = host->value_type();
    // @todo a little hackish...but we promise host->data() will not change...
    ShVariantPtr host_variant = shVariantFactory(host_type, SH_MEM)->
      generate(count * tuplesize, const_cast<void*>(host->data()), false);
    SH_DEBUG_ASSERT(host_variant);

    if(converted_type != SH_VALUETYPE_END) {
      SH_DEBUG_WARN("GL backend does not handle " << shValueTypeName(texture_type)
              	    << " natively.  Converting to " << shValueTypeName(converted_type));
      texture->value_type(converted_type);
      data_variant = shVariantFactory(converted_type, SH_MEM)->generate(count * tuplesize);
      data_variant->set(host_variant);
    }
    else if (texture_type != host_type) {
      data_variant = shVariantFactory(texture_type, SH_MEM)->generate(count * tuplesize);
      data_variant->set(host_variant);
    } else {
      data_variant = host_variant;
    }
  }

  switch(texture->target()) {
  case GL_TEXTURE_1D:
    if (full_copy) {
      SH_GL_CHECK_ERROR(glTexImage1D(texture->target(), texture->mipmap_level(),
                                     texture->internalFormat(),
                                     width, 0, texture->format(), type,
                                     data_variant->array()));
    } else {
      SH_GL_CHECK_ERROR(glTexImage1D(texture->target(), texture->mipmap_level(),
                                     texture->internalFormat(),
                                     width, 0, texture->format(), type,
                                     NULL));
      if (host) {
        SH_GL_CHECK_ERROR(glTexSubImage1D(texture->target(), texture->mipmap_level(), 0,
                                          count, texture->format(), type,
                                          data_variant->array()));
      }
    }
    break;
  case GL_TEXTURE_2D:
  case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
  case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
  case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
  case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
  case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
  case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
#if defined( __APPLE__ )
  case GL_TEXTURE_RECTANGLE_EXT:
#else
  case GL_TEXTURE_RECTANGLE_NV:
#endif
    if (full_copy) {
      SH_GL_CHECK_ERROR(glTexImage2D(texture->target(), texture->mipmap_level(),
                                     texture->internalFormat(),
                                     width, height, 0, texture->format(),
                                     type, data_variant->array()));
    } else {
      SH_GL_CHECK_ERROR(glTexImage2D(texture->target(), texture->mipmap_level(),
                                     texture->internalFormat(),
                                     width, height, 0, texture->format(),
                                     type, NULL));
      if (host) {
        int last_row_count = count % width;
        int full_rows_count = count - last_row_count;
        int full_rows_height = full_rows_count / width;
        SH_GL_CHECK_ERROR(glTexSubImage2D(texture->target(), texture->mipmap_level(), 0, 0,
                                          width, full_rows_height, texture->format(),
                                          type, data_variant->array()));
        int array_offset = full_rows_height * width * data_variant->datasize() * tuplesize;
        SH_GL_CHECK_ERROR(glTexSubImage2D(texture->target(), texture->mipmap_level(), 0, full_rows_height,
                                          last_row_count, 1, texture->format(),
                                          type, static_cast<const char*>(data_variant->array()) + array_offset));
      }
    }
    break;
  case GL_TEXTURE_3D:
    if (full_copy) {
      SH_GL_CHECK_ERROR(glTexImage3D(texture->target(), texture->mipmap_level(),
                                     texture->internalFormat(),
                                     width, height,
                                     depth, 0, texture->format(),
                                     type, data_variant->array()));
    } else {
      SH_GL_CHECK_ERROR(glTexImage3D(texture->target(), texture->mipmap_level(),
                                     texture->internalFormat(),
                                     width, height,
                                     depth, 0, texture->format(),
                                     type, NULL));
      if (host) {
        int last_surface_count = count % (width * height);
        int last_row_count = last_surface_count % width;
        int full_rows_count = last_surface_count - last_row_count;
        int full_rows_height = full_rows_count / width;
        int full_surfaces_count = count - last_surface_count;
        int full_surfaces_depth = full_surfaces_count / (width * height);
        SH_GL_CHECK_ERROR(glTexSubImage3D(texture->target(), texture->mipmap_level(), 0, 0,
                                          0, width, height,
                                          full_surfaces_depth, texture->format(),
                                          type, data_variant->array()));
        int array_offset = full_surfaces_depth * width * height * data_variant->datasize() * tuplesize;
        SH_GL_CHECK_ERROR(glTexSubImage3D(texture->target(), texture->mipmap_level(), 0, 0,
                                          full_surfaces_depth, width, full_rows_height,
                                          1, texture->format(),
                                          type, static_cast<const char*>(data_variant->array()) + array_offset));
        array_offset += full_rows_height * width * data_variant->datasize() * tuplesize;
        SH_GL_CHECK_ERROR(glTexSubImage3D(texture->target(), texture->mipmap_level(), 0, full_rows_height,
                                          full_surfaces_depth, last_row_count, 1,
                                          1, texture->format(),
                                          type, static_cast<const char*>(data_variant->array()) + array_offset));
      }
    }
    break;
  default:
    SH_DEBUG_WARN("Texture target " << texture->target() << " not handled by GL backend");
    break;
  }

  return true;
}

int HostGlTextureTransfer::cost(const ShStorage* from, const ShStorage* to)
{
  // Texture downloads are expensive!
  return 100;
}

GlTextureHostTransfer::GlTextureHostTransfer()
  : ShTransfer("opengl:texture", "host")
{
}

bool GlTextureHostTransfer::transfer(const ShStorage* from, ShStorage* to)
{
  // Get rid of const so that we can do conversions
  GlTextureStorage* texture =
    dynamic_cast<GlTextureStorage*>(const_cast<ShStorage*>(from));
  ShHostStorage* host = dynamic_cast<ShHostStorage*>(to);

  GLenum type;
  ShValueType texture_type = texture->value_type();
  ShValueType converted_type;
  type = shGlType(texture_type, converted_type);

  // The conversion should have occured during download
  if (converted_type != SH_VALUETYPE_END) {
    // convert the storage. Should we warn (again) ?
    texture->value_type(converted_type);
    texture_type = texture->value_type();
  }

  int width = texture->width();
  int height = texture->height();
  int depth = texture->depth();
  int tuplesize = texture->tuplesize();
  int count = host->length() / host->value_size();
  if (count > width * height * depth)
    count = width * height * depth;

  ShVariantPtr dest_variant;
  ShValueType host_type = host->value_type();
  // @todo a little hackish...but we promise host->data() will not change...
  ShVariantPtr host_variant = shVariantFactory(host_type, SH_MEM)->
    generate(count * tuplesize, const_cast<void*>(host->data()), false);
  SH_DEBUG_ASSERT(host_variant);

  SH_DEBUG_ASSERT(tuplesize > 0 && tuplesize < 5)
  int glTuplesize[5] = { 0, 1, 3, 3, 4 };
  GLenum format[5] = { 0, GL_RED, GL_RGB, GL_RGB, GL_RGBA };

  if (converted_type != SH_VALUETYPE_END ||
      texture_type != host_type || tuplesize == 2) {
    dest_variant = shVariantFactory(texture_type, SH_MEM)->
      generate(width * height * depth * glTuplesize[tuplesize]);
  }
  else {
    dest_variant = host_variant;
  }

  FBOCache::instance()->bindFramebuffer();
  GLenum buffer = FBOCache::instance()->bindTexture(texture, 0);
  FBOCache::instance()->check();

  GLint prevRead;
  SH_GL_CHECK_ERROR(glGetIntegerv(GL_READ_BUFFER, &prevRead));
  SH_GL_CHECK_ERROR(glReadBuffer(buffer));

  SH_GL_CHECK_ERROR(glPushAttrib(GL_VIEWPORT_BIT));
  SH_GL_CHECK_ERROR(glViewport(0, 0, width, height));

  SH_GL_CHECK_ERROR(glReadPixels(0, 0, count > width ? width : count,
                                 count/width, format[tuplesize], type,
                                 dest_variant->array()));
  if (count % width) {
    SH_GL_CHECK_ERROR(glReadPixels(0, count/width, count % width, 1,
                                   format[tuplesize], type,
                                   static_cast<char *>(dest_variant->array())
                                   + (count - (count % width)) *
                                     glTuplesize[tuplesize] *
                                     dest_variant->datasize()));
  }

  if (dest_variant != host_variant) {
    if (tuplesize == 2) {
      dest_variant = dest_variant->get(false, ShSwizzle(3, 0, 1), count);
    }
    host_variant->set(dest_variant);
  }

  SH_GL_CHECK_ERROR(glPopAttrib());
  SH_GL_CHECK_ERROR(glReadBuffer(prevRead));
  FBOCache::instance()->unbindFramebuffer();

  return true;
}

int GlTextureHostTransfer::cost(const ShStorage* from, const ShStorage* to)
{
  // Reading data from GPU is waaay expensive
  return 1000;
}

GlTextureGlTextureTransfer::GlTextureGlTextureTransfer()
  : ShTransfer("opengl:texture", "opengl:texture")
{
  ShProgram vsh = SH_BEGIN_VERTEX_PROGRAM {
    ShInOutPosition4f pos;
    ShInOutTexCoord2f tc;
  } SH_END;
  ShProgram fsh = SH_BEGIN_FRAGMENT_PROGRAM {
    ShInputTexCoord2f tc;
    ShOutputColor4f o = source_texture(tc);
  } SH_END;
  render_to_tex_prog = new ShProgramSet(vsh, fsh);
}

bool GlTextureGlTextureTransfer::transfer(const ShStorage* from, ShStorage* to)
{
  GlTextureStorage* src_tex =
    dynamic_cast<GlTextureStorage*>(const_cast<ShStorage*>(from));
  GlTextureStorage* dst_tex = dynamic_cast<GlTextureStorage*>(to);

  SH_DEBUG_ASSERT(src_tex->width() == dst_tex->width());
  SH_DEBUG_ASSERT(src_tex->height() == dst_tex->height());

  GlTextureName::Binding binding(dst_tex->texName());

  if (dst_tex->internalFormatRGB()) {
    FBOCache::instance()->bindFramebuffer();
    GLenum buffer = FBOCache::instance()->bindTexture(dst_tex, 0);
    FBOCache::instance()->check();

    GLint prevDraw;
    SH_GL_CHECK_ERROR(glGetIntegerv(GL_DRAW_BUFFER, &prevDraw));
    SH_GL_CHECK_ERROR(glDrawBuffer(buffer));

    SH_GL_CHECK_ERROR(glPushAttrib(GL_VIEWPORT_BIT));
    SH_GL_CHECK_ERROR(glViewport(0, 0, dst_tex->width(), dst_tex->height()));

    std::ostringstream os;
    os << src_tex->name();
    source_texture.meta("opengl:texid", os.str());

    shBind(*render_to_tex_prog);
    glBegin(GL_QUADS); {
      glTexCoord2f(0,0);
      glVertex2f(-1, -1);
      glTexCoord2f(1,0);
      glVertex2f(1, -1);
      glTexCoord2f(1,1);
      glVertex2f(1, 1);
      glTexCoord2f(0,1);
      glVertex2f(-1, 1);
    } glEnd();
    shUnbind(*render_to_tex_prog);

    SH_GL_CHECK_ERROR(glPopAttrib());
    SH_GL_CHECK_ERROR(glDrawBuffer(prevDraw));
    FBOCache::instance()->unbindFramebuffer();
  }
  else {
    ShHostStoragePtr host =
      shref_dynamic_cast<ShHostStorage>(src_tex->memory()->findStorage("host"));
    host->sync();
    to->sync();
  }

  return true;
}

int GlTextureGlTextureTransfer::cost(const ShStorage* from, const ShStorage* to)
{
  const GlTextureStorage* dst_tex = dynamic_cast<const GlTextureStorage*>(to);

  if (dst_tex->internalFormatRGB())
    return 200;
  else
    return 2000;
}

HostGlTextureTransfer* HostGlTextureTransfer::instance;
GlTextureHostTransfer* GlTextureHostTransfer::instance;
GlTextureGlTextureTransfer* GlTextureGlTextureTransfer::instance;

}
<commit_msg>Use correct count when transferring textures.<commit_after>// Sh: A GPU metaprogramming language.
//
// Copyright 2003-2006 Serious Hack Inc.
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
// MA  02110-1301, USA
//////////////////////////////////////////////////////////////////////////////
#include "GlTextureStorage.hpp"
#include "ShTypeInfo.hpp"
#include "ShVariantFactory.hpp"
#include "FBOCache.hpp"
#include <sh.hpp>

namespace shgl {

using namespace SH;

GlTextureStorage::GlTextureStorage(ShMemory* memory, GLenum target,
                                   GLenum format, GLint internalFormat,
                                   ShValueType valueType,
                                   int width, int height, int depth, int tuplesize,
                                   GlTextureNamePtr name,
                                   GLint mipmap_level, bool internalRGB)
  : ShStorage(memory, valueType),
    m_name(name), m_target(target), m_format(format),
    m_internalFormat(internalFormat),
    m_width(width), m_height(height), m_depth(depth), m_tuplesize(tuplesize),
    m_write(false),
    m_internalFormatRGB(internalRGB),
    m_mipmap_level(mipmap_level)
{
  m_name->addStorage(this);
}

GlTextureStorage::~GlTextureStorage()
{
  m_name->removeStorage(this);
}

void GlTextureStorage::initTexture()
{
  HostGlTextureTransfer::instance->transfer(0, this);
}

HostGlTextureTransfer::HostGlTextureTransfer()
  : ShTransfer("host", "opengl:texture")
{
}

bool HostGlTextureTransfer::transfer(const ShStorage* from, ShStorage* to)
{
  const ShHostStorage* host = dynamic_cast<const ShHostStorage*>(from);
  GlTextureStorage* texture = dynamic_cast<GlTextureStorage*>(to);

  // Bind texture name for this scope.
  GlTextureName::Binding binding(texture->texName());

  GLenum type;
  ShValueType texture_type = texture->value_type();
  ShValueType converted_type;
  type = shGlType(texture_type, converted_type);

  int width = texture->width();
  int height = texture->height();
  int depth = texture->depth();
  int tuplesize = texture->tuplesize();

  ShVariantPtr data_variant;
  int count = 0;
  bool full_copy = false;
  if (host) {
    count = host->length() / host->value_size() / tuplesize;
    full_copy = (count >= (width * height * depth));

    ShValueType host_type = host->value_type();
    // @todo a little hackish...but we promise host->data() will not change...
    ShVariantPtr host_variant = shVariantFactory(host_type, SH_MEM)->
      generate(count * tuplesize, const_cast<void*>(host->data()), false);
    SH_DEBUG_ASSERT(host_variant);

    if(converted_type != SH_VALUETYPE_END) {
      SH_DEBUG_WARN("GL backend does not handle " << shValueTypeName(texture_type)
              	    << " natively.  Converting to " << shValueTypeName(converted_type));
      texture->value_type(converted_type);
      data_variant = shVariantFactory(converted_type, SH_MEM)->generate(count * tuplesize);
      data_variant->set(host_variant);
    }
    else if (texture_type != host_type) {
      data_variant = shVariantFactory(texture_type, SH_MEM)->generate(count * tuplesize);
      data_variant->set(host_variant);
    } else {
      data_variant = host_variant;
    }
  }

  switch(texture->target()) {
  case GL_TEXTURE_1D:
    if (full_copy) {
      SH_GL_CHECK_ERROR(glTexImage1D(texture->target(), texture->mipmap_level(),
                                     texture->internalFormat(),
                                     width, 0, texture->format(), type,
                                     data_variant->array()));
    } else {
      SH_GL_CHECK_ERROR(glTexImage1D(texture->target(), texture->mipmap_level(),
                                     texture->internalFormat(),
                                     width, 0, texture->format(), type,
                                     NULL));
      if (host) {
        SH_GL_CHECK_ERROR(glTexSubImage1D(texture->target(), texture->mipmap_level(), 0,
                                          count, texture->format(), type,
                                          data_variant->array()));
      }
    }
    break;
  case GL_TEXTURE_2D:
  case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
  case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
  case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
  case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
  case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
  case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
#if defined( __APPLE__ )
  case GL_TEXTURE_RECTANGLE_EXT:
#else
  case GL_TEXTURE_RECTANGLE_NV:
#endif
    if (full_copy) {
      SH_GL_CHECK_ERROR(glTexImage2D(texture->target(), texture->mipmap_level(),
                                     texture->internalFormat(),
                                     width, height, 0, texture->format(),
                                     type, data_variant->array()));
    } else {
      SH_GL_CHECK_ERROR(glTexImage2D(texture->target(), texture->mipmap_level(),
                                     texture->internalFormat(),
                                     width, height, 0, texture->format(),
                                     type, NULL));
      if (host) {
        int last_row_count = count % width;
        int full_rows_count = count - last_row_count;
        int full_rows_height = full_rows_count / width;
        SH_GL_CHECK_ERROR(glTexSubImage2D(texture->target(), texture->mipmap_level(), 0, 0,
                                          width, full_rows_height, texture->format(),
                                          type, data_variant->array()));
        int array_offset = full_rows_height * width * data_variant->datasize() * tuplesize;
        SH_GL_CHECK_ERROR(glTexSubImage2D(texture->target(), texture->mipmap_level(), 0, full_rows_height,
                                          last_row_count, 1, texture->format(),
                                          type, static_cast<const char*>(data_variant->array()) + array_offset));
      }
    }
    break;
  case GL_TEXTURE_3D:
    if (full_copy) {
      SH_GL_CHECK_ERROR(glTexImage3D(texture->target(), texture->mipmap_level(),
                                     texture->internalFormat(),
                                     width, height,
                                     depth, 0, texture->format(),
                                     type, data_variant->array()));
    } else {
      SH_GL_CHECK_ERROR(glTexImage3D(texture->target(), texture->mipmap_level(),
                                     texture->internalFormat(),
                                     width, height,
                                     depth, 0, texture->format(),
                                     type, NULL));
      if (host) {
        int last_surface_count = count % (width * height);
        int last_row_count = last_surface_count % width;
        int full_rows_count = last_surface_count - last_row_count;
        int full_rows_height = full_rows_count / width;
        int full_surfaces_count = count - last_surface_count;
        int full_surfaces_depth = full_surfaces_count / (width * height);
        SH_GL_CHECK_ERROR(glTexSubImage3D(texture->target(), texture->mipmap_level(), 0, 0,
                                          0, width, height,
                                          full_surfaces_depth, texture->format(),
                                          type, data_variant->array()));
        int array_offset = full_surfaces_depth * width * height * data_variant->datasize() * tuplesize;
        SH_GL_CHECK_ERROR(glTexSubImage3D(texture->target(), texture->mipmap_level(), 0, 0,
                                          full_surfaces_depth, width, full_rows_height,
                                          1, texture->format(),
                                          type, static_cast<const char*>(data_variant->array()) + array_offset));
        array_offset += full_rows_height * width * data_variant->datasize() * tuplesize;
        SH_GL_CHECK_ERROR(glTexSubImage3D(texture->target(), texture->mipmap_level(), 0, full_rows_height,
                                          full_surfaces_depth, last_row_count, 1,
                                          1, texture->format(),
                                          type, static_cast<const char*>(data_variant->array()) + array_offset));
      }
    }
    break;
  default:
    SH_DEBUG_WARN("Texture target " << texture->target() << " not handled by GL backend");
    break;
  }

  return true;
}

int HostGlTextureTransfer::cost(const ShStorage* from, const ShStorage* to)
{
  // Texture downloads are expensive!
  return 100;
}

GlTextureHostTransfer::GlTextureHostTransfer()
  : ShTransfer("opengl:texture", "host")
{
}

bool GlTextureHostTransfer::transfer(const ShStorage* from, ShStorage* to)
{
  // Get rid of const so that we can do conversions
  GlTextureStorage* texture =
    dynamic_cast<GlTextureStorage*>(const_cast<ShStorage*>(from));
  ShHostStorage* host = dynamic_cast<ShHostStorage*>(to);

  GLenum type;
  ShValueType texture_type = texture->value_type();
  ShValueType converted_type;
  type = shGlType(texture_type, converted_type);

  // The conversion should have occured during download
  if (converted_type != SH_VALUETYPE_END) {
    // convert the storage. Should we warn (again) ?
    texture->value_type(converted_type);
    texture_type = texture->value_type();
  }

  int width = texture->width();
  int height = texture->height();
  int depth = texture->depth();
  int tuplesize = texture->tuplesize();
  int count = host->length() / host->value_size() / tuplesize;
  if (count > width * height * depth)
    count = width * height * depth;

  ShVariantPtr dest_variant;
  ShValueType host_type = host->value_type();
  // @todo a little hackish...but we promise host->data() will not change...
  ShVariantPtr host_variant = shVariantFactory(host_type, SH_MEM)->
    generate(count * tuplesize, const_cast<void*>(host->data()), false);
  SH_DEBUG_ASSERT(host_variant);

  SH_DEBUG_ASSERT(tuplesize > 0 && tuplesize < 5)
  int glTuplesize[5] = { 0, 1, 3, 3, 4 };
  GLenum format[5] = { 0, GL_RED, GL_RGB, GL_RGB, GL_RGBA };

  if (converted_type != SH_VALUETYPE_END ||
      texture_type != host_type || tuplesize == 2) {
    dest_variant = shVariantFactory(texture_type, SH_MEM)->
      generate(width * height * depth * glTuplesize[tuplesize]);
  }
  else {
    dest_variant = host_variant;
  }

  FBOCache::instance()->bindFramebuffer();
  GLenum buffer = FBOCache::instance()->bindTexture(texture, 0);
  FBOCache::instance()->check();

  GLint prevRead;
  SH_GL_CHECK_ERROR(glGetIntegerv(GL_READ_BUFFER, &prevRead));
  SH_GL_CHECK_ERROR(glReadBuffer(buffer));

  SH_GL_CHECK_ERROR(glPushAttrib(GL_VIEWPORT_BIT));
  SH_GL_CHECK_ERROR(glViewport(0, 0, width, height));

  SH_GL_CHECK_ERROR(glReadPixels(0, 0, count > width ? width : count,
                                 count/width, format[tuplesize], type,
                                 dest_variant->array()));
  if (count % width) {
    SH_GL_CHECK_ERROR(glReadPixels(0, count/width, count % width, 1,
                                   format[tuplesize], type,
                                   static_cast<char *>(dest_variant->array())
                                   + (count - (count % width)) *
                                     glTuplesize[tuplesize] *
                                     dest_variant->datasize()));
  }

  if (dest_variant != host_variant) {
    if (tuplesize == 2) {
      dest_variant = dest_variant->get(false, ShSwizzle(3, 0, 1), count);
    }
    host_variant->set(dest_variant);
  }

  SH_GL_CHECK_ERROR(glPopAttrib());
  SH_GL_CHECK_ERROR(glReadBuffer(prevRead));
  FBOCache::instance()->unbindFramebuffer();

  return true;
}

int GlTextureHostTransfer::cost(const ShStorage* from, const ShStorage* to)
{
  // Reading data from GPU is waaay expensive
  return 1000;
}

GlTextureGlTextureTransfer::GlTextureGlTextureTransfer()
  : ShTransfer("opengl:texture", "opengl:texture")
{
  ShProgram vsh = SH_BEGIN_VERTEX_PROGRAM {
    ShInOutPosition4f pos;
    ShInOutTexCoord2f tc;
  } SH_END;
  ShProgram fsh = SH_BEGIN_FRAGMENT_PROGRAM {
    ShInputTexCoord2f tc;
    ShOutputColor4f o = source_texture(tc);
  } SH_END;
  render_to_tex_prog = new ShProgramSet(vsh, fsh);
}

bool GlTextureGlTextureTransfer::transfer(const ShStorage* from, ShStorage* to)
{
  GlTextureStorage* src_tex =
    dynamic_cast<GlTextureStorage*>(const_cast<ShStorage*>(from));
  GlTextureStorage* dst_tex = dynamic_cast<GlTextureStorage*>(to);

  SH_DEBUG_ASSERT(src_tex->width() == dst_tex->width());
  SH_DEBUG_ASSERT(src_tex->height() == dst_tex->height());

  GlTextureName::Binding binding(dst_tex->texName());

  if (dst_tex->internalFormatRGB()) {
    FBOCache::instance()->bindFramebuffer();
    GLenum buffer = FBOCache::instance()->bindTexture(dst_tex, 0);
    FBOCache::instance()->check();

    GLint prevDraw;
    SH_GL_CHECK_ERROR(glGetIntegerv(GL_DRAW_BUFFER, &prevDraw));
    SH_GL_CHECK_ERROR(glDrawBuffer(buffer));

    SH_GL_CHECK_ERROR(glPushAttrib(GL_VIEWPORT_BIT));
    SH_GL_CHECK_ERROR(glViewport(0, 0, dst_tex->width(), dst_tex->height()));

    std::ostringstream os;
    os << src_tex->name();
    source_texture.meta("opengl:texid", os.str());

    shBind(*render_to_tex_prog);
    glBegin(GL_QUADS); {
      glTexCoord2f(0,0);
      glVertex2f(-1, -1);
      glTexCoord2f(1,0);
      glVertex2f(1, -1);
      glTexCoord2f(1,1);
      glVertex2f(1, 1);
      glTexCoord2f(0,1);
      glVertex2f(-1, 1);
    } glEnd();
    shUnbind(*render_to_tex_prog);

    SH_GL_CHECK_ERROR(glPopAttrib());
    SH_GL_CHECK_ERROR(glDrawBuffer(prevDraw));
    FBOCache::instance()->unbindFramebuffer();
  }
  else {
    ShHostStoragePtr host =
      shref_dynamic_cast<ShHostStorage>(src_tex->memory()->findStorage("host"));
    host->sync();
    to->sync();
  }

  return true;
}

int GlTextureGlTextureTransfer::cost(const ShStorage* from, const ShStorage* to)
{
  const GlTextureStorage* dst_tex = dynamic_cast<const GlTextureStorage*>(to);

  if (dst_tex->internalFormatRGB())
    return 200;
  else
    return 2000;
}

HostGlTextureTransfer* HostGlTextureTransfer::instance;
GlTextureHostTransfer* GlTextureHostTransfer::instance;
GlTextureGlTextureTransfer* GlTextureGlTextureTransfer::instance;

}
<|endoftext|>


<commit_before>/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
 * Copyright 2012 LibreOffice contributors.
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 */

#include "templatedlg.hxx"

#include <comphelper/processfactory.hxx>
#include <sfx2/sfxresid.hxx>
#include <sfx2/templatefolderview.hxx>
#include <sfx2/thumbnailviewitem.hxx>
#include <vcl/toolbox.hxx>

#include <com/sun/star/frame/XComponentLoader.hpp>
#include <com/sun/star/lang/XComponent.hpp>
#include <com/sun/star/lang/XMultiServiceFactory.hpp>

#include "doc.hrc"
#include "templatedlg.hrc"

#define MAX_COLUMN_COUNT 4
#define MAX_LINE_COUNT 2

#define PADDING_TOOLBAR_VIEW    15

using namespace ::com::sun::star;
using namespace ::com::sun::star::frame;

SfxTemplateManagerDlg::SfxTemplateManagerDlg (Window *parent)
    : ModalDialog(parent, SfxResId(DLG_TEMPLATE_MANAGER)),
      aButtonAll(this,SfxResId(BTN_SELECT_ALL)),
      aButtonDocs(this,SfxResId(BTN_SELECT_DOCS)),
      aButtonPresents(this,SfxResId(BTN_SELECT_PRESENTATIONS)),
      aButtonSheets(this,SfxResId(BTN_SELECT_SHEETS)),
      aButtonDraws(this,SfxResId(BTN_SELECT_DRAWS)),
      maButtonSelMode(this,SfxResId(BTN_SELECTION_MODE)),
      mpViewBar( new ToolBox(this, SfxResId(TBX_ACTION_VIEW))),
      mpActionBar( new ToolBox(this, SfxResId(TBX_ACTION_ACTION))),
      mpTemplateBar( new ToolBox(this, SfxResId(TBX_ACTION_TEMPLATES))),
      maView(new TemplateFolderView(this,SfxResId(TEMPLATE_VIEW))),
      mnSelectionCount(0),
      mxDesktop(comphelper::getProcessServiceFactory()->createInstance( "com.sun.star.frame.Desktop" ),uno::UNO_QUERY )
{
    maButtonSelMode.SetStyle(maButtonSelMode.GetStyle() | WB_TOGGLE);

    // Calculate toolboxs size and positions
    Size aWinSize = GetOutputSize();
    Size aViewSize = mpViewBar->CalcMinimumWindowSizePixel();
    Size aActionSize = mpActionBar->CalcMinimumWindowSizePixel();
    Size aTemplateSize = mpTemplateBar->CalcMinimumWindowSizePixel();

    aActionSize.setWidth(2*aActionSize.getWidth());
    aViewSize.setWidth(aWinSize.getWidth()-aActionSize.getWidth()-mpViewBar->GetPosPixel().X());
    aTemplateSize.setWidth(aWinSize.getWidth());

    Point aActionPos = mpActionBar->GetPosPixel();
    aActionPos.setX(aWinSize.getWidth() - aActionSize.getWidth());

    mpViewBar->SetSizePixel(aViewSize);
    mpActionBar->SetPosSizePixel(aActionPos,aActionSize);
    mpTemplateBar->SetSizePixel(aTemplateSize);

    // Set toolbox styles
    mpViewBar->SetButtonType(BUTTON_SYMBOLTEXT);
    mpTemplateBar->SetButtonType(BUTTON_SYMBOLTEXT);

    // Set toolbox handlers
    mpViewBar->SetClickHdl(LINK(this,SfxTemplateManagerDlg,TBXViewHdl));
    mpActionBar->SetClickHdl(LINK(this,SfxTemplateManagerDlg,TBXActionHdl));
    mpTemplateBar->SetClickHdl(LINK(this,SfxTemplateManagerDlg,TBXTemplateHdl));

    // Set view position below toolbox
    Point aViewPos = maView->GetPosPixel();
    aViewPos.setY(aActionPos.Y() + aActionSize.getHeight() + PADDING_TOOLBAR_VIEW);
    maView->SetPosPixel(aViewPos);

    maView->SetStyle(WB_TABSTOP | WB_VSCROLL);
    maView->SetColCount(MAX_COLUMN_COUNT);
    maView->SetLineCount(MAX_LINE_COUNT);

    maView->setItemStateHdl(LINK(this,SfxTemplateManagerDlg,TVTemplateStateHdl));
    maView->setTemplateStateHdl(LINK(this,SfxTemplateManagerDlg,TVTemplateStateHdl));

    aButtonAll.SetClickHdl(LINK(this,SfxTemplateManagerDlg,ViewAllHdl));
    aButtonDocs.SetClickHdl(LINK(this,SfxTemplateManagerDlg,ViewDocsHdl));
    aButtonPresents.SetClickHdl(LINK(this,SfxTemplateManagerDlg,ViewPresentsHdl));
    aButtonSheets.SetClickHdl(LINK(this,SfxTemplateManagerDlg,ViewSheetsHdl));
    aButtonDraws.SetClickHdl(LINK(this,SfxTemplateManagerDlg,ViewDrawsHdl));
    maButtonSelMode.SetClickHdl(LINK(this,SfxTemplateManagerDlg,OnClickSelectionMode));

    mpViewBar->Show();
    mpActionBar->Show();

    maView->Populate();
    maView->Show();

    FreeResource();
}

SfxTemplateManagerDlg::~SfxTemplateManagerDlg ()
{
    delete maView;
}

IMPL_LINK_NOARG(SfxTemplateManagerDlg,ViewAllHdl)
{
    maView->filterTemplatesByApp(FILTER_APP_NONE);
    return 0;
}

IMPL_LINK_NOARG(SfxTemplateManagerDlg,ViewDocsHdl)
{
    maView->filterTemplatesByApp(FILTER_APP_WRITER);
    return 0;
}

IMPL_LINK_NOARG(SfxTemplateManagerDlg,ViewPresentsHdl)
{
    maView->filterTemplatesByApp(FILTER_APP_IMPRESS);
    return 0;
}

IMPL_LINK_NOARG(SfxTemplateManagerDlg,ViewSheetsHdl)
{
    maView->filterTemplatesByApp(FILTER_APP_CALC);
    return 0;
}

IMPL_LINK_NOARG(SfxTemplateManagerDlg,ViewDrawsHdl)
{
    maView->filterTemplatesByApp(FILTER_APP_DRAW);
    return 0;
}

void SfxTemplateManagerDlg::MouseButtonDown( const MouseEvent& rMEvt )
{
    if (!maView->GetActiveClipRegion().IsInside(rMEvt.GetPosPixel()) && maView->isOverlayVisible())
        maView->showOverlay(false);
}

IMPL_LINK (SfxTemplateManagerDlg, OnClickSelectionMode, ImageButton*, pButton)
{
    maView->setSelectionMode(pButton->GetState() == STATE_CHECK);
    return 0;
}

IMPL_LINK_NOARG(SfxTemplateManagerDlg,TBXViewHdl)
{
    switch(mpViewBar->GetCurItemId())
    {
    case TBI_TEMPLATE_CREATE:
        OnTemplateCreate();
        break;
    case TBI_TEMPLATE_IMPORT:
        OnTemplateImport();
        break;
    default:
        break;
    }

    return 0;
}

IMPL_LINK_NOARG(SfxTemplateManagerDlg,TBXActionHdl)
{
    switch(mpActionBar->GetCurItemId())
    {
    case TBI_TEMPLATE_SEARCH:
        OnTemplateSearch();
        break;
    case TBI_TEMPLATE_ACTION:
        OnTemplateAction();
        break;
    default:
        break;
    }

    return 0;
}

IMPL_LINK_NOARG(SfxTemplateManagerDlg,TBXTemplateHdl)
{
    switch(mpTemplateBar->GetCurItemId())
    {
    case TBI_TEMPLATE_EDIT:
        OnTemplateEdit();
        break;
    case TBI_TEMPLATE_PROPERTIES:
        OnTemplateProperties();
        break;
    case TBI_TEMPLATE_MOVE:
        OnTemplateMove();
        break;
    case TBI_TEMPLATE_DELETE:
        OnTemplateDelete();
        break;
    default:
        break;
    }

    return 0;
}

IMPL_LINK(SfxTemplateManagerDlg, TVFolderStateHdl, const ThumbnailViewItem*, pItem)
{
    return 0;
}

IMPL_LINK(SfxTemplateManagerDlg, TVTemplateStateHdl, const ThumbnailViewItem*, pItem)
{
    if (pItem->isSelected())
    {
        if (maSelTemplates.empty())
        {
            mpViewBar->Show(false);
            mpActionBar->Show(false);
            mpTemplateBar->Show();
        }

        maSelTemplates.insert(pItem);
    }
    else
    {
        if (maSelTemplates.find(pItem) != maSelTemplates.end())
        {
            maSelTemplates.erase(pItem);

            if (maSelTemplates.empty())
            {
                mpTemplateBar->Show(false);
                mpViewBar->Show();
                mpActionBar->Show();
            }
        }
    }

    return 0;
}

void SfxTemplateManagerDlg::OnTemplateCreate ()
{
}

void SfxTemplateManagerDlg::OnTemplateImport ()
{
}

void SfxTemplateManagerDlg::OnTemplateSearch ()
{
}

void SfxTemplateManagerDlg::OnTemplateAction ()
{
}

void SfxTemplateManagerDlg::OnTemplateEdit ()
{
}

void SfxTemplateManagerDlg::OnTemplateProperties ()
{
}

void SfxTemplateManagerDlg::OnTemplateMove ()
{
}

void SfxTemplateManagerDlg::OnTemplateDelete ()
{
}

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
<commit_msg>Open template for editing when clicking on the edit toolbox button.<commit_after>/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
 * Copyright 2012 LibreOffice contributors.
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 */

#include "templatedlg.hxx"

#include <comphelper/processfactory.hxx>
#include <sfx2/sfxresid.hxx>
#include <sfx2/templatefolderview.hxx>
#include <sfx2/templateviewitem.hxx>
#include <sfx2/thumbnailviewitem.hxx>
#include <tools/urlobj.hxx>
#include <vcl/toolbox.hxx>

#include <com/sun/star/beans/PropertyValue.hpp>
#include <com/sun/star/frame/XComponentLoader.hpp>
#include <com/sun/star/frame/XStorable.hpp>
#include <com/sun/star/lang/XComponent.hpp>
#include <com/sun/star/lang/XMultiServiceFactory.hpp>

#include "doc.hrc"
#include "templatedlg.hrc"

#define MAX_COLUMN_COUNT 4
#define MAX_LINE_COUNT 2

#define PADDING_TOOLBAR_VIEW    15

using namespace ::com::sun::star;
using namespace ::com::sun::star::beans;
using namespace ::com::sun::star::frame;

SfxTemplateManagerDlg::SfxTemplateManagerDlg (Window *parent)
    : ModalDialog(parent, SfxResId(DLG_TEMPLATE_MANAGER)),
      aButtonAll(this,SfxResId(BTN_SELECT_ALL)),
      aButtonDocs(this,SfxResId(BTN_SELECT_DOCS)),
      aButtonPresents(this,SfxResId(BTN_SELECT_PRESENTATIONS)),
      aButtonSheets(this,SfxResId(BTN_SELECT_SHEETS)),
      aButtonDraws(this,SfxResId(BTN_SELECT_DRAWS)),
      maButtonSelMode(this,SfxResId(BTN_SELECTION_MODE)),
      mpViewBar( new ToolBox(this, SfxResId(TBX_ACTION_VIEW))),
      mpActionBar( new ToolBox(this, SfxResId(TBX_ACTION_ACTION))),
      mpTemplateBar( new ToolBox(this, SfxResId(TBX_ACTION_TEMPLATES))),
      maView(new TemplateFolderView(this,SfxResId(TEMPLATE_VIEW))),
      mnSelectionCount(0),
      mxDesktop(comphelper::getProcessServiceFactory()->createInstance( "com.sun.star.frame.Desktop" ),uno::UNO_QUERY )
{
    maButtonSelMode.SetStyle(maButtonSelMode.GetStyle() | WB_TOGGLE);

    // Calculate toolboxs size and positions
    Size aWinSize = GetOutputSize();
    Size aViewSize = mpViewBar->CalcMinimumWindowSizePixel();
    Size aActionSize = mpActionBar->CalcMinimumWindowSizePixel();
    Size aTemplateSize = mpTemplateBar->CalcMinimumWindowSizePixel();

    aActionSize.setWidth(2*aActionSize.getWidth());
    aViewSize.setWidth(aWinSize.getWidth()-aActionSize.getWidth()-mpViewBar->GetPosPixel().X());
    aTemplateSize.setWidth(aWinSize.getWidth());

    Point aActionPos = mpActionBar->GetPosPixel();
    aActionPos.setX(aWinSize.getWidth() - aActionSize.getWidth());

    mpViewBar->SetSizePixel(aViewSize);
    mpActionBar->SetPosSizePixel(aActionPos,aActionSize);
    mpTemplateBar->SetSizePixel(aTemplateSize);

    // Set toolbox styles
    mpViewBar->SetButtonType(BUTTON_SYMBOLTEXT);
    mpTemplateBar->SetButtonType(BUTTON_SYMBOLTEXT);

    // Set toolbox handlers
    mpViewBar->SetClickHdl(LINK(this,SfxTemplateManagerDlg,TBXViewHdl));
    mpActionBar->SetClickHdl(LINK(this,SfxTemplateManagerDlg,TBXActionHdl));
    mpTemplateBar->SetClickHdl(LINK(this,SfxTemplateManagerDlg,TBXTemplateHdl));

    // Set view position below toolbox
    Point aViewPos = maView->GetPosPixel();
    aViewPos.setY(aActionPos.Y() + aActionSize.getHeight() + PADDING_TOOLBAR_VIEW);
    maView->SetPosPixel(aViewPos);

    maView->SetStyle(WB_TABSTOP | WB_VSCROLL);
    maView->SetColCount(MAX_COLUMN_COUNT);
    maView->SetLineCount(MAX_LINE_COUNT);

    maView->setItemStateHdl(LINK(this,SfxTemplateManagerDlg,TVTemplateStateHdl));
    maView->setTemplateStateHdl(LINK(this,SfxTemplateManagerDlg,TVTemplateStateHdl));

    aButtonAll.SetClickHdl(LINK(this,SfxTemplateManagerDlg,ViewAllHdl));
    aButtonDocs.SetClickHdl(LINK(this,SfxTemplateManagerDlg,ViewDocsHdl));
    aButtonPresents.SetClickHdl(LINK(this,SfxTemplateManagerDlg,ViewPresentsHdl));
    aButtonSheets.SetClickHdl(LINK(this,SfxTemplateManagerDlg,ViewSheetsHdl));
    aButtonDraws.SetClickHdl(LINK(this,SfxTemplateManagerDlg,ViewDrawsHdl));
    maButtonSelMode.SetClickHdl(LINK(this,SfxTemplateManagerDlg,OnClickSelectionMode));

    mpViewBar->Show();
    mpActionBar->Show();

    maView->Populate();
    maView->Show();

    FreeResource();
}

SfxTemplateManagerDlg::~SfxTemplateManagerDlg ()
{
    delete maView;
}

IMPL_LINK_NOARG(SfxTemplateManagerDlg,ViewAllHdl)
{
    maView->filterTemplatesByApp(FILTER_APP_NONE);
    return 0;
}

IMPL_LINK_NOARG(SfxTemplateManagerDlg,ViewDocsHdl)
{
    maView->filterTemplatesByApp(FILTER_APP_WRITER);
    return 0;
}

IMPL_LINK_NOARG(SfxTemplateManagerDlg,ViewPresentsHdl)
{
    maView->filterTemplatesByApp(FILTER_APP_IMPRESS);
    return 0;
}

IMPL_LINK_NOARG(SfxTemplateManagerDlg,ViewSheetsHdl)
{
    maView->filterTemplatesByApp(FILTER_APP_CALC);
    return 0;
}

IMPL_LINK_NOARG(SfxTemplateManagerDlg,ViewDrawsHdl)
{
    maView->filterTemplatesByApp(FILTER_APP_DRAW);
    return 0;
}

void SfxTemplateManagerDlg::MouseButtonDown( const MouseEvent& rMEvt )
{
    if (!maView->GetActiveClipRegion().IsInside(rMEvt.GetPosPixel()) && maView->isOverlayVisible())
        maView->showOverlay(false);
}

IMPL_LINK (SfxTemplateManagerDlg, OnClickSelectionMode, ImageButton*, pButton)
{
    maView->setSelectionMode(pButton->GetState() == STATE_CHECK);
    return 0;
}

IMPL_LINK_NOARG(SfxTemplateManagerDlg,TBXViewHdl)
{
    switch(mpViewBar->GetCurItemId())
    {
    case TBI_TEMPLATE_CREATE:
        OnTemplateCreate();
        break;
    case TBI_TEMPLATE_IMPORT:
        OnTemplateImport();
        break;
    default:
        break;
    }

    return 0;
}

IMPL_LINK_NOARG(SfxTemplateManagerDlg,TBXActionHdl)
{
    switch(mpActionBar->GetCurItemId())
    {
    case TBI_TEMPLATE_SEARCH:
        OnTemplateSearch();
        break;
    case TBI_TEMPLATE_ACTION:
        OnTemplateAction();
        break;
    default:
        break;
    }

    return 0;
}

IMPL_LINK_NOARG(SfxTemplateManagerDlg,TBXTemplateHdl)
{
    switch(mpTemplateBar->GetCurItemId())
    {
    case TBI_TEMPLATE_EDIT:
        OnTemplateEdit();
        break;
    case TBI_TEMPLATE_PROPERTIES:
        OnTemplateProperties();
        break;
    case TBI_TEMPLATE_MOVE:
        OnTemplateMove();
        break;
    case TBI_TEMPLATE_DELETE:
        OnTemplateDelete();
        break;
    default:
        break;
    }

    return 0;
}

IMPL_LINK(SfxTemplateManagerDlg, TVFolderStateHdl, const ThumbnailViewItem*, pItem)
{
    return 0;
}

IMPL_LINK(SfxTemplateManagerDlg, TVTemplateStateHdl, const ThumbnailViewItem*, pItem)
{
    if (pItem->isSelected())
    {
        if (maSelTemplates.empty())
        {
            mpViewBar->Show(false);
            mpActionBar->Show(false);
            mpTemplateBar->Show();
        }

        maSelTemplates.insert(pItem);
    }
    else
    {
        if (maSelTemplates.find(pItem) != maSelTemplates.end())
        {
            maSelTemplates.erase(pItem);

            if (maSelTemplates.empty())
            {
                mpTemplateBar->Show(false);
                mpViewBar->Show();
                mpActionBar->Show();
            }
        }
    }

    return 0;
}

void SfxTemplateManagerDlg::OnTemplateCreate ()
{
}

void SfxTemplateManagerDlg::OnTemplateImport ()
{
}

void SfxTemplateManagerDlg::OnTemplateSearch ()
{
}

void SfxTemplateManagerDlg::OnTemplateAction ()
{
}

void SfxTemplateManagerDlg::OnTemplateEdit ()
{
    uno::Sequence< PropertyValue > aArgs(1);
    aArgs[0].Name = "AsTemplate";
    aArgs[0].Value <<= sal_False;

    uno::Reference< XStorable > xStorable;
    std::set<const ThumbnailViewItem*>::const_iterator pIter;
    for (pIter = maSelTemplates.begin(); pIter != maSelTemplates.end(); ++pIter)
    {
        const TemplateViewItem *pItem = static_cast<const TemplateViewItem*>(*pIter);

        try
        {
            xStorable = uno::Reference< XStorable >(
                        mxDesktop->loadComponentFromURL(pItem->getPath(),rtl::OUString("_blank"), 0, aArgs ),
                        uno::UNO_QUERY );
        }
        catch( const uno::Exception& )
        {
        }
    }
}

void SfxTemplateManagerDlg::OnTemplateProperties ()
{
}

void SfxTemplateManagerDlg::OnTemplateMove ()
{
}

void SfxTemplateManagerDlg::OnTemplateDelete ()
{
}

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
<|endoftext|>


<commit_before>/**************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** Commercial Usage
**
** Licensees holding valid Qt Commercial licenses may use this file in
** accordance with the Qt Commercial License Agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Nokia.
**
** GNU Lesser General Public License Usage
**
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** If you are unsure which license is appropriate for your use, please
** contact the sales department at http://qt.nokia.com/contact.
**
**************************************************************************/

#include "basefilefind.h"

#include <coreplugin/icore.h>
#include <coreplugin/progressmanager/progressmanager.h>
#include <coreplugin/editormanager/editormanager.h>
#include <coreplugin/filemanager.h>
#include <find/textfindconstants.h>
#include <find/searchresultwindow.h>
#include <texteditor/itexteditor.h>
#include <texteditor/basetexteditor.h>
#include <utils/stylehelper.h>

#include <QtCore/QDebug>
#include <QtCore/QDirIterator>
#include <QtCore/QSettings>
#include <QtGui/QLabel>
#include <QtGui/QComboBox>
#include <QtGui/QCheckBox>
#include <QtGui/QPushButton>
#include <QtGui/QFileDialog>

using namespace Utils;
using namespace Find;
using namespace TextEditor;

BaseFileFind::BaseFileFind(SearchResultWindow *resultWindow)
  : m_resultWindow(resultWindow),
    m_isSearching(false),
    m_resultLabel(0),
    m_filterCombo(0),
    m_useRegExp(false),
    m_useRegExpCheckBox(0)
{
    m_watcher.setPendingResultsLimit(1);
    connect(&m_watcher, SIGNAL(resultReadyAt(int)), this, SLOT(displayResult(int)));
    connect(&m_watcher, SIGNAL(finished()), this, SLOT(searchFinished()));
}

bool BaseFileFind::isEnabled() const
{
    return !m_isSearching;
}

QStringList BaseFileFind::fileNameFilters() const
{
    QStringList filters;
    if (m_filterCombo && !m_filterCombo->currentText().isEmpty()) {
        QStringList parts = m_filterCombo->currentText().split(",");
        foreach (const QString &part, parts) {
            QString filter = part.trimmed();
            if (!filter.isEmpty()) {
                filters << filter;
            }
        }
    }
    return filters;
}

void BaseFileFind::findAll(const QString &txt, QTextDocument::FindFlags findFlags)
{
    m_isSearching = true;
    emit changed();
    if (m_filterCombo)
        updateComboEntries(m_filterCombo, false);
    m_watcher.setFuture(QFuture<FileSearchResult>());
    SearchResult *result = m_resultWindow->startNewSearch();
    connect(result, SIGNAL(activated(Find::SearchResultItem)), this, SLOT(openEditor(Find::SearchResultItem)));
    m_resultWindow->popup(true);
    if (m_useRegExp)
        m_watcher.setFuture(Utils::findInFilesRegExp(txt, files(), findFlags, ITextEditor::openedTextEditorsContents()));
    else
        m_watcher.setFuture(Utils::findInFiles(txt, files(), findFlags, ITextEditor::openedTextEditorsContents()));
    Core::FutureProgress *progress =
        Core::ICore::instance()->progressManager()->addTask(m_watcher.future(),
                                                                        "Search",
                                                                        Constants::TASK_SEARCH);
    progress->setWidget(createProgressWidget());
    connect(progress, SIGNAL(clicked()), m_resultWindow, SLOT(popup()));
}

void BaseFileFind::replaceAll(const QString &txt, QTextDocument::FindFlags findFlags)
{
    m_isSearching = true;
    emit changed();
    if (m_filterCombo)
        updateComboEntries(m_filterCombo, false);
    m_watcher.setFuture(QFuture<FileSearchResult>());
    SearchResult *result = m_resultWindow->startNewSearch(SearchResultWindow::SearchAndReplace);
    connect(result, SIGNAL(activated(Find::SearchResultItem)), this, SLOT(openEditor(Find::SearchResultItem)));
    connect(result, SIGNAL(replaceButtonClicked(QString,QList<Find::SearchResultItem>)),
            this, SLOT(doReplace(QString,QList<Find::SearchResultItem>)));
    m_resultWindow->popup(true);
    if (m_useRegExp)
        m_watcher.setFuture(Utils::findInFilesRegExp(txt, files(), findFlags, ITextEditor::openedTextEditorsContents()));
    else
        m_watcher.setFuture(Utils::findInFiles(txt, files(), findFlags, ITextEditor::openedTextEditorsContents()));
    Core::FutureProgress *progress =
        Core::ICore::instance()->progressManager()->addTask(m_watcher.future(),
                                                                        "Search",
                                                                        Constants::TASK_SEARCH);
    progress->setWidget(createProgressWidget());
    connect(progress, SIGNAL(clicked()), m_resultWindow, SLOT(popup()));
}

void BaseFileFind::doReplace(const QString &text,
                               const QList<Find::SearchResultItem> &items)
{
    QStringList files = replaceAll(text, items);
    Core::FileManager *fileManager = Core::ICore::instance()->fileManager();
    if (!files.isEmpty()) {
        fileManager->notifyFilesChangedInternally(files);
        m_resultWindow->hide();
    }
}

void BaseFileFind::displayResult(int index) {
    Utils::FileSearchResult result = m_watcher.future().resultAt(index);
    m_resultWindow->addResult(result.fileName,
                              result.lineNumber,
                              result.matchingLine,
                              result.matchStart,
                              result.matchLength);
    if (m_resultLabel)
        m_resultLabel->setText(tr("%1 found").arg(m_resultWindow->numberOfResults()));
}

void BaseFileFind::searchFinished()
{
    m_resultWindow->finishSearch();
    m_isSearching = false;
    m_resultLabel = 0;
    emit changed();
}

QWidget *BaseFileFind::createProgressWidget()
{
    m_resultLabel = new QLabel;
    m_resultLabel->setAlignment(Qt::AlignCenter);
    // ### TODO this setup should be done by style
    QFont f = m_resultLabel->font();
    f.setBold(true);
    f.setPointSizeF(StyleHelper::sidebarFontSize());
    m_resultLabel->setFont(f);
    m_resultLabel->setPalette(StyleHelper::sidebarFontPalette(m_resultLabel->palette()));
    m_resultLabel->setText(tr("%1 found").arg(m_resultWindow->numberOfResults()));
    return m_resultLabel;
}

QWidget *BaseFileFind::createPatternWidget()
{
/*
    QWidget *widget = new QWidget;
    QHBoxLayout *hlayout = new QHBoxLayout(widget);
    hlayout->setMargin(0);
    widget->setLayout(hlayout);
*/
    QString filterToolTip = tr("List of comma separated wildcard filters");
/*
    QLabel *label = new QLabel(tr("File &pattern:"));
    label->setToolTip(filterToolTip);
*/
/*
    hlayout->addWidget(label);
*/
    m_filterCombo = new QComboBox;
    m_filterCombo->setEditable(true);
    m_filterCombo->setModel(&m_filterStrings);
    m_filterCombo->setMaxCount(10);
    m_filterCombo->setMinimumContentsLength(10);
    m_filterCombo->setSizeAdjustPolicy(QComboBox::AdjustToMinimumContentsLengthWithIcon);
    m_filterCombo->setInsertPolicy(QComboBox::InsertAtBottom);
    m_filterCombo->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
    m_filterCombo->setToolTip(filterToolTip);
    syncComboWithSettings(m_filterCombo, m_filterSetting);
/*
    label->setBuddy(m_filterCombo);
    hlayout->addWidget(m_filterCombo);
*/
    return m_filterCombo;
}

QWidget *BaseFileFind::createRegExpWidget()
{
    m_useRegExpCheckBox = new QCheckBox(tr("Use Regular E&xpressions"));
    m_useRegExpCheckBox->setChecked(m_useRegExp);
    connect(m_useRegExpCheckBox, SIGNAL(toggled(bool)), this, SLOT(syncRegExpSetting(bool)));
    return m_useRegExpCheckBox;
}

void BaseFileFind::writeCommonSettings(QSettings *settings)
{
    settings->setValue("filters", m_filterStrings.stringList());
    if (m_filterCombo)
        settings->setValue("currentFilter", m_filterCombo->currentText());
    settings->setValue("useRegExp", m_useRegExp);
}

void BaseFileFind::readCommonSettings(QSettings *settings, const QString &defaultFilter)
{
    QStringList filters = settings->value("filters").toStringList();
    m_filterSetting = settings->value("currentFilter").toString();
    m_useRegExp = settings->value("useRegExp", false).toBool();
    if (m_useRegExpCheckBox)
        m_useRegExpCheckBox->setChecked(m_useRegExp);
    if (filters.isEmpty())
        filters << defaultFilter;
    if (m_filterSetting.isEmpty())
        m_filterSetting = filters.first();
    m_filterStrings.setStringList(filters);
    if (m_filterCombo)
        syncComboWithSettings(m_filterCombo, m_filterSetting);
}

void BaseFileFind::syncComboWithSettings(QComboBox *combo, const QString &setting)
{
    if (!combo)
        return;
    int index = combo->findText(setting);
    if (index < 0)
        combo->setEditText(setting);
    else
        combo->setCurrentIndex(index);
}

void BaseFileFind::updateComboEntries(QComboBox *combo, bool onTop)
{
    int index = combo->findText(combo->currentText());
    if (index < 0) {
        if (onTop) {
            combo->insertItem(0, combo->currentText());
        } else {
            combo->addItem(combo->currentText());
        }
        combo->setCurrentIndex(combo->findText(combo->currentText()));
    }
}

void BaseFileFind::syncRegExpSetting(bool useRegExp)
{
    m_useRegExp = useRegExp;
}

void BaseFileFind::openEditor(const Find::SearchResultItem &item)
{
    TextEditor::BaseTextEditor::openEditorAt(item.fileName, item.lineNumber, item.searchTermStart);
}

#pragma mark Static methods

static void applyChanges(QTextDocument *doc, const QString &text, const QList<Find::SearchResultItem> &items)
{
    QList<QTextCursor> cursors;

    foreach (const Find::SearchResultItem &item, items) {
        const int blockNumber = item.lineNumber - 1;
        QTextCursor tc(doc->findBlockByNumber(blockNumber));

        const int cursorPosition = tc.position() + item.searchTermStart;

        int cursorIndex = 0;
        for (; cursorIndex < cursors.size(); ++cursorIndex) {
            const QTextCursor &tc = cursors.at(cursorIndex);

            if (tc.position() == cursorPosition)
                break;
        }

        if (cursorIndex != cursors.size())
            continue; // skip this change.

        tc.setPosition(cursorPosition);
        tc.setPosition(tc.position() + item.searchTermLength,
                       QTextCursor::KeepAnchor);
        cursors.append(tc);
    }

    foreach (QTextCursor tc, cursors)
        tc.insertText(text);
}

QStringList BaseFileFind::replaceAll(const QString &text,
                               const QList<Find::SearchResultItem> &items)
{
    if (text.isEmpty() || items.isEmpty())
        return QStringList();

    QHash<QString, QList<Find::SearchResultItem> > changes;

    foreach (const Find::SearchResultItem &item, items)
        changes[item.fileName].append(item);

    Core::EditorManager *editorManager = Core::EditorManager::instance();

    QHashIterator<QString, QList<Find::SearchResultItem> > it(changes);
    while (it.hasNext()) {
        it.next();

        const QString fileName = it.key();
        const QList<Find::SearchResultItem> items = it.value();

        const QList<Core::IEditor *> editors = editorManager->editorsForFileName(fileName);
        TextEditor::BaseTextEditor *textEditor = 0;
        foreach (Core::IEditor *editor, editors) {
            textEditor = qobject_cast<TextEditor::BaseTextEditor *>(editor->widget());
            if (textEditor != 0)
                break;
        }

        if (textEditor != 0) {
            QTextCursor tc = textEditor->textCursor();
            tc.beginEditBlock();
            applyChanges(textEditor->document(), text, items);
            tc.endEditBlock();
        } else {
            QFile file(fileName);

            if (file.open(QFile::ReadOnly)) {
                QTextStream stream(&file);
                // ### set the encoding
                const QString plainText = stream.readAll();
                file.close();

                QTextDocument doc;
                doc.setPlainText(plainText);

                applyChanges(&doc, text, items);

                QFile newFile(fileName);
                if (newFile.open(QFile::WriteOnly)) {
                    QTextStream stream(&newFile);
                    // ### set the encoding
                    stream << doc.toPlainText();
                }
            }
        }
    }

    return changes.keys();
}
<commit_msg>Avoid compile warning<commit_after>/**************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** Commercial Usage
**
** Licensees holding valid Qt Commercial licenses may use this file in
** accordance with the Qt Commercial License Agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Nokia.
**
** GNU Lesser General Public License Usage
**
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** If you are unsure which license is appropriate for your use, please
** contact the sales department at http://qt.nokia.com/contact.
**
**************************************************************************/

#include "basefilefind.h"

#include <coreplugin/icore.h>
#include <coreplugin/progressmanager/progressmanager.h>
#include <coreplugin/editormanager/editormanager.h>
#include <coreplugin/filemanager.h>
#include <find/textfindconstants.h>
#include <find/searchresultwindow.h>
#include <texteditor/itexteditor.h>
#include <texteditor/basetexteditor.h>
#include <utils/stylehelper.h>

#include <QtCore/QDebug>
#include <QtCore/QDirIterator>
#include <QtCore/QSettings>
#include <QtGui/QLabel>
#include <QtGui/QComboBox>
#include <QtGui/QCheckBox>
#include <QtGui/QPushButton>
#include <QtGui/QFileDialog>

using namespace Utils;
using namespace Find;
using namespace TextEditor;

BaseFileFind::BaseFileFind(SearchResultWindow *resultWindow)
  : m_resultWindow(resultWindow),
    m_isSearching(false),
    m_resultLabel(0),
    m_filterCombo(0),
    m_useRegExp(false),
    m_useRegExpCheckBox(0)
{
    m_watcher.setPendingResultsLimit(1);
    connect(&m_watcher, SIGNAL(resultReadyAt(int)), this, SLOT(displayResult(int)));
    connect(&m_watcher, SIGNAL(finished()), this, SLOT(searchFinished()));
}

bool BaseFileFind::isEnabled() const
{
    return !m_isSearching;
}

QStringList BaseFileFind::fileNameFilters() const
{
    QStringList filters;
    if (m_filterCombo && !m_filterCombo->currentText().isEmpty()) {
        QStringList parts = m_filterCombo->currentText().split(",");
        foreach (const QString &part, parts) {
            QString filter = part.trimmed();
            if (!filter.isEmpty()) {
                filters << filter;
            }
        }
    }
    return filters;
}

void BaseFileFind::findAll(const QString &txt, QTextDocument::FindFlags findFlags)
{
    m_isSearching = true;
    emit changed();
    if (m_filterCombo)
        updateComboEntries(m_filterCombo, false);
    m_watcher.setFuture(QFuture<FileSearchResult>());
    SearchResult *result = m_resultWindow->startNewSearch();
    connect(result, SIGNAL(activated(Find::SearchResultItem)), this, SLOT(openEditor(Find::SearchResultItem)));
    m_resultWindow->popup(true);
    if (m_useRegExp)
        m_watcher.setFuture(Utils::findInFilesRegExp(txt, files(), findFlags, ITextEditor::openedTextEditorsContents()));
    else
        m_watcher.setFuture(Utils::findInFiles(txt, files(), findFlags, ITextEditor::openedTextEditorsContents()));
    Core::FutureProgress *progress =
        Core::ICore::instance()->progressManager()->addTask(m_watcher.future(),
                                                                        "Search",
                                                                        Constants::TASK_SEARCH);
    progress->setWidget(createProgressWidget());
    connect(progress, SIGNAL(clicked()), m_resultWindow, SLOT(popup()));
}

void BaseFileFind::replaceAll(const QString &txt, QTextDocument::FindFlags findFlags)
{
    m_isSearching = true;
    emit changed();
    if (m_filterCombo)
        updateComboEntries(m_filterCombo, false);
    m_watcher.setFuture(QFuture<FileSearchResult>());
    SearchResult *result = m_resultWindow->startNewSearch(SearchResultWindow::SearchAndReplace);
    connect(result, SIGNAL(activated(Find::SearchResultItem)), this, SLOT(openEditor(Find::SearchResultItem)));
    connect(result, SIGNAL(replaceButtonClicked(QString,QList<Find::SearchResultItem>)),
            this, SLOT(doReplace(QString,QList<Find::SearchResultItem>)));
    m_resultWindow->popup(true);
    if (m_useRegExp)
        m_watcher.setFuture(Utils::findInFilesRegExp(txt, files(), findFlags, ITextEditor::openedTextEditorsContents()));
    else
        m_watcher.setFuture(Utils::findInFiles(txt, files(), findFlags, ITextEditor::openedTextEditorsContents()));
    Core::FutureProgress *progress =
        Core::ICore::instance()->progressManager()->addTask(m_watcher.future(),
                                                                        "Search",
                                                                        Constants::TASK_SEARCH);
    progress->setWidget(createProgressWidget());
    connect(progress, SIGNAL(clicked()), m_resultWindow, SLOT(popup()));
}

void BaseFileFind::doReplace(const QString &text,
                               const QList<Find::SearchResultItem> &items)
{
    QStringList files = replaceAll(text, items);
    Core::FileManager *fileManager = Core::ICore::instance()->fileManager();
    if (!files.isEmpty()) {
        fileManager->notifyFilesChangedInternally(files);
        m_resultWindow->hide();
    }
}

void BaseFileFind::displayResult(int index) {
    Utils::FileSearchResult result = m_watcher.future().resultAt(index);
    m_resultWindow->addResult(result.fileName,
                              result.lineNumber,
                              result.matchingLine,
                              result.matchStart,
                              result.matchLength);
    if (m_resultLabel)
        m_resultLabel->setText(tr("%1 found").arg(m_resultWindow->numberOfResults()));
}

void BaseFileFind::searchFinished()
{
    m_resultWindow->finishSearch();
    m_isSearching = false;
    m_resultLabel = 0;
    emit changed();
}

QWidget *BaseFileFind::createProgressWidget()
{
    m_resultLabel = new QLabel;
    m_resultLabel->setAlignment(Qt::AlignCenter);
    // ### TODO this setup should be done by style
    QFont f = m_resultLabel->font();
    f.setBold(true);
    f.setPointSizeF(StyleHelper::sidebarFontSize());
    m_resultLabel->setFont(f);
    m_resultLabel->setPalette(StyleHelper::sidebarFontPalette(m_resultLabel->palette()));
    m_resultLabel->setText(tr("%1 found").arg(m_resultWindow->numberOfResults()));
    return m_resultLabel;
}

QWidget *BaseFileFind::createPatternWidget()
{
/*
    QWidget *widget = new QWidget;
    QHBoxLayout *hlayout = new QHBoxLayout(widget);
    hlayout->setMargin(0);
    widget->setLayout(hlayout);
*/
    QString filterToolTip = tr("List of comma separated wildcard filters");
/*
    QLabel *label = new QLabel(tr("File &pattern:"));
    label->setToolTip(filterToolTip);
*/
/*
    hlayout->addWidget(label);
*/
    m_filterCombo = new QComboBox;
    m_filterCombo->setEditable(true);
    m_filterCombo->setModel(&m_filterStrings);
    m_filterCombo->setMaxCount(10);
    m_filterCombo->setMinimumContentsLength(10);
    m_filterCombo->setSizeAdjustPolicy(QComboBox::AdjustToMinimumContentsLengthWithIcon);
    m_filterCombo->setInsertPolicy(QComboBox::InsertAtBottom);
    m_filterCombo->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
    m_filterCombo->setToolTip(filterToolTip);
    syncComboWithSettings(m_filterCombo, m_filterSetting);
/*
    label->setBuddy(m_filterCombo);
    hlayout->addWidget(m_filterCombo);
*/
    return m_filterCombo;
}

QWidget *BaseFileFind::createRegExpWidget()
{
    m_useRegExpCheckBox = new QCheckBox(tr("Use Regular E&xpressions"));
    m_useRegExpCheckBox->setChecked(m_useRegExp);
    connect(m_useRegExpCheckBox, SIGNAL(toggled(bool)), this, SLOT(syncRegExpSetting(bool)));
    return m_useRegExpCheckBox;
}

void BaseFileFind::writeCommonSettings(QSettings *settings)
{
    settings->setValue("filters", m_filterStrings.stringList());
    if (m_filterCombo)
        settings->setValue("currentFilter", m_filterCombo->currentText());
    settings->setValue("useRegExp", m_useRegExp);
}

void BaseFileFind::readCommonSettings(QSettings *settings, const QString &defaultFilter)
{
    QStringList filters = settings->value("filters").toStringList();
    m_filterSetting = settings->value("currentFilter").toString();
    m_useRegExp = settings->value("useRegExp", false).toBool();
    if (m_useRegExpCheckBox)
        m_useRegExpCheckBox->setChecked(m_useRegExp);
    if (filters.isEmpty())
        filters << defaultFilter;
    if (m_filterSetting.isEmpty())
        m_filterSetting = filters.first();
    m_filterStrings.setStringList(filters);
    if (m_filterCombo)
        syncComboWithSettings(m_filterCombo, m_filterSetting);
}

void BaseFileFind::syncComboWithSettings(QComboBox *combo, const QString &setting)
{
    if (!combo)
        return;
    int index = combo->findText(setting);
    if (index < 0)
        combo->setEditText(setting);
    else
        combo->setCurrentIndex(index);
}

void BaseFileFind::updateComboEntries(QComboBox *combo, bool onTop)
{
    int index = combo->findText(combo->currentText());
    if (index < 0) {
        if (onTop) {
            combo->insertItem(0, combo->currentText());
        } else {
            combo->addItem(combo->currentText());
        }
        combo->setCurrentIndex(combo->findText(combo->currentText()));
    }
}

void BaseFileFind::syncRegExpSetting(bool useRegExp)
{
    m_useRegExp = useRegExp;
}

void BaseFileFind::openEditor(const Find::SearchResultItem &item)
{
    TextEditor::BaseTextEditor::openEditorAt(item.fileName, item.lineNumber, item.searchTermStart);
}

// #pragma mark Static methods

static void applyChanges(QTextDocument *doc, const QString &text, const QList<Find::SearchResultItem> &items)
{
    QList<QTextCursor> cursors;

    foreach (const Find::SearchResultItem &item, items) {
        const int blockNumber = item.lineNumber - 1;
        QTextCursor tc(doc->findBlockByNumber(blockNumber));

        const int cursorPosition = tc.position() + item.searchTermStart;

        int cursorIndex = 0;
        for (; cursorIndex < cursors.size(); ++cursorIndex) {
            const QTextCursor &tc = cursors.at(cursorIndex);

            if (tc.position() == cursorPosition)
                break;
        }

        if (cursorIndex != cursors.size())
            continue; // skip this change.

        tc.setPosition(cursorPosition);
        tc.setPosition(tc.position() + item.searchTermLength,
                       QTextCursor::KeepAnchor);
        cursors.append(tc);
    }

    foreach (QTextCursor tc, cursors)
        tc.insertText(text);
}

QStringList BaseFileFind::replaceAll(const QString &text,
                               const QList<Find::SearchResultItem> &items)
{
    if (text.isEmpty() || items.isEmpty())
        return QStringList();

    QHash<QString, QList<Find::SearchResultItem> > changes;

    foreach (const Find::SearchResultItem &item, items)
        changes[item.fileName].append(item);

    Core::EditorManager *editorManager = Core::EditorManager::instance();

    QHashIterator<QString, QList<Find::SearchResultItem> > it(changes);
    while (it.hasNext()) {
        it.next();

        const QString fileName = it.key();
        const QList<Find::SearchResultItem> items = it.value();

        const QList<Core::IEditor *> editors = editorManager->editorsForFileName(fileName);
        TextEditor::BaseTextEditor *textEditor = 0;
        foreach (Core::IEditor *editor, editors) {
            textEditor = qobject_cast<TextEditor::BaseTextEditor *>(editor->widget());
            if (textEditor != 0)
                break;
        }

        if (textEditor != 0) {
            QTextCursor tc = textEditor->textCursor();
            tc.beginEditBlock();
            applyChanges(textEditor->document(), text, items);
            tc.endEditBlock();
        } else {
            QFile file(fileName);

            if (file.open(QFile::ReadOnly)) {
                QTextStream stream(&file);
                // ### set the encoding
                const QString plainText = stream.readAll();
                file.close();

                QTextDocument doc;
                doc.setPlainText(plainText);

                applyChanges(&doc, text, items);

                QFile newFile(fileName);
                if (newFile.open(QFile::WriteOnly)) {
                    QTextStream stream(&newFile);
                    // ### set the encoding
                    stream << doc.toPlainText();
                }
            }
        }
    }

    return changes.keys();
}
<|endoftext|>


<commit_before>7213868a-ad5a-11e7-a862-ac87a332f658<commit_msg>Does anyone even read these anymore???<commit_after>72b9f74a-ad5a-11e7-b88a-ac87a332f658<|endoftext|>


<commit_before><commit_msg>changes<commit_after><|endoftext|>