<commit_before>// Copyright (c) 2021 by Apex.AI Inc. All rights reserved.
// Copyright (c) 2021 by Robert Bosch GmbH. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// SPDX-License-Identifier: Apache-2.0

#if !defined(_WIN32)
#include "test.hpp"

#include "iceoryx_posh/roudi/roudi_cmd_line_parser_config_file_option.hpp"
#include "iceoryx_utils/cxx/string.hpp"

#include <memory>

using namespace ::testing;
using ::testing::Return;

using namespace iox::cxx;
using namespace iox::config;

namespace iox
{
namespace test
{
class CmdLineParserConfigFileOption_test : public Test
{
  public:
    void SetUp(){};
    void TearDown()
    {
        // Reset optind to be able to parse again
        optind = 0;
    };
};

TEST_F(CmdLineParserConfigFileOption_test, NoConfigPathOptionLeadsToEmptyPath)
{
    constexpr uint8_t NUMBER_OF_ARGS{1U};
    char* args[NUMBER_OF_ARGS];
    char appName[] = "./foo";
    args[0] = &appName[0];

    CmdLineParserConfigFileOption sut;
    auto result = sut.parse(NUMBER_OF_ARGS, args);

    ASSERT_FALSE(result.has_error());
    EXPECT_THAT(result.value().configFilePath.c_str(), StrEq(""));
}

TEST_F(CmdLineParserConfigFileOption_test, ConfigPathShortOptionIsCorrectlyRead)
{
    constexpr uint8_t NUMBER_OF_ARGS{3U};
    char* args[NUMBER_OF_ARGS];
    char appName[] = "./foo";
    char option[] = "-c";
    char path[] = "/foo/bar.toml";
    args[0] = &appName[0];
    args[1] = &option[0];
    args[2] = &path[0];

    CmdLineParserConfigFileOption sut;
    auto result = sut.parse(NUMBER_OF_ARGS, args);

    ASSERT_FALSE(result.has_error());
    EXPECT_THAT(result.value().configFilePath.c_str(), StrEq(path));
}

TEST_F(CmdLineParserConfigFileOption_test, ConfigPathLongOptionIsCorrectlyRead)
{
    constexpr uint8_t NUMBER_OF_ARGS{3U};
    char* args[NUMBER_OF_ARGS];
    char appName[] = "./foo";
    char option[] = "--config-file";
    char path[] = "/foo/bar/baz.toml";
    args[0] = &appName[0];
    args[1] = &option[0];
    args[2] = &path[0];

    CmdLineParserConfigFileOption sut;
    auto result = sut.parse(NUMBER_OF_ARGS, args);

    ASSERT_FALSE(result.has_error());
    EXPECT_THAT(result.value().configFilePath.c_str(), StrEq(path));
}

TEST_F(CmdLineParserConfigFileOption_test, HelpLongOptionLeadsProgrammNotRunning)
{
    constexpr uint8_t NUMBER_OF_ARGS{2U};
    char* args[NUMBER_OF_ARGS];
    char appName[] = "./foo";
    char option[] = "--help";
    args[0] = &appName[0];
    args[1] = &option[0];

    CmdLineParserConfigFileOption sut;
    auto result = sut.parse(NUMBER_OF_ARGS, args);

    ASSERT_FALSE(result.has_error());
    EXPECT_FALSE(result.value().run);
}

TEST_F(CmdLineParserConfigFileOption_test, WrongOptionLeadsUnkownOptionResult)
{
    constexpr uint8_t NUMBER_OF_ARGS{2U};
    char* args[NUMBER_OF_ARGS];
    char appName[] = "./foo";
    char unknownOption[] = "--unknown";
    args[0] = &appName[0];
    args[1] = &unknownOption[0];

    CmdLineParserConfigFileOption sut;
    auto result = sut.parse(NUMBER_OF_ARGS, args);

    ASSERT_TRUE(result.has_error());
    EXPECT_EQ(result.get_error(), CmdLineParserResult::UNKNOWN_OPTION_USED);
}

TEST_F(CmdLineParserConfigFileOption_test, UniqueIdOptionLeadsCallingCmdLineParserParseReturningNoError)
{
    constexpr uint8_t NUMBER_OF_ARGS{3U};
    char* args[NUMBER_OF_ARGS];
    char appName[] = "./foo";
    char option[] = "-u";
    char value[] = "4242";
    args[0] = &appName[0];
    args[1] = &option[0];
    args[2] = &value[0];

    CmdLineParserConfigFileOption sut;
    auto result = sut.parse(NUMBER_OF_ARGS, args);

    ASSERT_FALSE(result.has_error());
    ASSERT_TRUE(result.value().uniqueRouDiId.has_value());
    EXPECT_EQ(result.value().uniqueRouDiId.value(), 4242);
}

TEST_F(CmdLineParserConfigFileOption_test, CmdLineParsingModeEqualToOneHandleOnlyTheFirstOption)
{
    constexpr uint8_t NUMBER_OF_ARGS{5U};
    char* args[NUMBER_OF_ARGS];
    char appName[] = "./foo";
    char uniqueIdOption[] = "-u";
    char value[] = "4242";
    char customOption[] = "-c";
    char path[] = "/foo/bar.toml";
    args[0] = &appName[0];
    args[1] = &uniqueIdOption[0];
    args[2] = &value[0];
    args[3] = &customOption[0];
    args[4] = &path[0];

    CmdLineParserConfigFileOption sut;
    auto result = sut.parse(NUMBER_OF_ARGS, args, CmdLineParser::CmdLineArgumentParsingMode::ONE);

    ASSERT_FALSE(result.has_error());
    ASSERT_TRUE(result.value().uniqueRouDiId.has_value());
    EXPECT_EQ(result.value().uniqueRouDiId.value(), 4242);
    EXPECT_THAT(result.value().configFilePath.c_str(), StrEq(""));

    optind = 0;

    auto res = sut.parse(NUMBER_OF_ARGS, args);

    ASSERT_FALSE(res.has_error());
    ASSERT_TRUE(result.value().uniqueRouDiId.has_value());
    EXPECT_EQ(result.value().uniqueRouDiId.value(), 4242);
    EXPECT_THAT(res.value().configFilePath.c_str(), StrEq(path));
}

} // namespace test
} // namespace iox

#endif
<commit_msg>iox-#454 Fix name<commit_after>// Copyright (c) 2021 by Apex.AI Inc. All rights reserved.
// Copyright (c) 2021 by Robert Bosch GmbH. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// SPDX-License-Identifier: Apache-2.0

#if !defined(_WIN32)
#include "test.hpp"

#include "iceoryx_posh/roudi/roudi_cmd_line_parser_config_file_option.hpp"
#include "iceoryx_utils/cxx/string.hpp"

#include <memory>

using namespace ::testing;
using ::testing::Return;

using namespace iox::cxx;
using namespace iox::config;

namespace iox
{
namespace test
{
class CmdLineParserConfigFileOption_test : public Test
{
  public:
    void SetUp(){};
    void TearDown()
    {
        // Reset optind to be able to parse again
        optind = 0;
    };
};

TEST_F(CmdLineParserConfigFileOption_test, NoConfigPathOptionLeadsToEmptyPath)
{
    constexpr uint8_t NUMBER_OF_ARGS{1U};
    char* args[NUMBER_OF_ARGS];
    char appName[] = "./foo";
    args[0] = &appName[0];

    CmdLineParserConfigFileOption sut;
    auto result = sut.parse(NUMBER_OF_ARGS, args);

    ASSERT_FALSE(result.has_error());
    EXPECT_THAT(result.value().configFilePath.c_str(), StrEq(""));
}

TEST_F(CmdLineParserConfigFileOption_test, ConfigPathShortOptionIsCorrectlyRead)
{
    constexpr uint8_t NUMBER_OF_ARGS{3U};
    char* args[NUMBER_OF_ARGS];
    char appName[] = "./foo";
    char option[] = "-c";
    char path[] = "/foo/bar.toml";
    args[0] = &appName[0];
    args[1] = &option[0];
    args[2] = &path[0];

    CmdLineParserConfigFileOption sut;
    auto result = sut.parse(NUMBER_OF_ARGS, args);

    ASSERT_FALSE(result.has_error());
    EXPECT_THAT(result.value().configFilePath.c_str(), StrEq(path));
}

TEST_F(CmdLineParserConfigFileOption_test, ConfigPathLongOptionIsCorrectlyRead)
{
    constexpr uint8_t NUMBER_OF_ARGS{3U};
    char* args[NUMBER_OF_ARGS];
    char appName[] = "./foo";
    char option[] = "--config-file";
    char path[] = "/foo/bar/baz.toml";
    args[0] = &appName[0];
    args[1] = &option[0];
    args[2] = &path[0];

    CmdLineParserConfigFileOption sut;
    auto result = sut.parse(NUMBER_OF_ARGS, args);

    ASSERT_FALSE(result.has_error());
    EXPECT_THAT(result.value().configFilePath.c_str(), StrEq(path));
}

TEST_F(CmdLineParserConfigFileOption_test, HelpLongOptionLeadsProgrammNotRunning)
{
    constexpr uint8_t NUMBER_OF_ARGS{2U};
    char* args[NUMBER_OF_ARGS];
    char appName[] = "./foo";
    char option[] = "--help";
    args[0] = &appName[0];
    args[1] = &option[0];

    CmdLineParserConfigFileOption sut;
    auto result = sut.parse(NUMBER_OF_ARGS, args);

    ASSERT_FALSE(result.has_error());
    EXPECT_FALSE(result.value().run);
}

TEST_F(CmdLineParserConfigFileOption_test, WrongOptionLeadsUnkownOptionResult)
{
    constexpr uint8_t NUMBER_OF_ARGS{2U};
    char* args[NUMBER_OF_ARGS];
    char appName[] = "./foo";
    char unknownOption[] = "--unknown";
    args[0] = &appName[0];
    args[1] = &unknownOption[0];

    CmdLineParserConfigFileOption sut;
    auto result = sut.parse(NUMBER_OF_ARGS, args);

    ASSERT_TRUE(result.has_error());
    EXPECT_EQ(result.get_error(), CmdLineParserResult::UNKNOWN_OPTION_USED);
}

TEST_F(CmdLineParserConfigFileOption_test, UniqueIdOptionLeadsCallingCmdLineParserParseReturningNoError)
{
    constexpr uint8_t NUMBER_OF_ARGS{3U};
    char* args[NUMBER_OF_ARGS];
    char appName[] = "./foo";
    char option[] = "-u";
    char value[] = "4242";
    args[0] = &appName[0];
    args[1] = &option[0];
    args[2] = &value[0];

    CmdLineParserConfigFileOption sut;
    auto result = sut.parse(NUMBER_OF_ARGS, args);

    ASSERT_FALSE(result.has_error());
    ASSERT_TRUE(result.value().uniqueRouDiId.has_value());
    EXPECT_EQ(result.value().uniqueRouDiId.value(), 4242);
}

TEST_F(CmdLineParserConfigFileOption_test, CmdLineParsingModeEqualToOneHandleOnlyTheFirstOptionReturningNoError)
{
    constexpr uint8_t NUMBER_OF_ARGS{5U};
    char* args[NUMBER_OF_ARGS];
    char appName[] = "./foo";
    char uniqueIdOption[] = "-u";
    char value[] = "4242";
    char customOption[] = "-c";
    char path[] = "/foo/bar.toml";
    args[0] = &appName[0];
    args[1] = &uniqueIdOption[0];
    args[2] = &value[0];
    args[3] = &customOption[0];
    args[4] = &path[0];

    CmdLineParserConfigFileOption sut;
    auto result = sut.parse(NUMBER_OF_ARGS, args, CmdLineParser::CmdLineArgumentParsingMode::ONE);

    ASSERT_FALSE(result.has_error());
    ASSERT_TRUE(result.value().uniqueRouDiId.has_value());
    EXPECT_EQ(result.value().uniqueRouDiId.value(), 4242);
    EXPECT_THAT(result.value().configFilePath.c_str(), StrEq(""));

    optind = 0;

    auto res = sut.parse(NUMBER_OF_ARGS, args);

    ASSERT_FALSE(res.has_error());
    ASSERT_TRUE(result.value().uniqueRouDiId.has_value());
    EXPECT_EQ(result.value().uniqueRouDiId.value(), 4242);
    EXPECT_THAT(res.value().configFilePath.c_str(), StrEq(path));
}

} // namespace test
} // namespace iox

#endif
<|endoftext|>


<commit_before>// This file is part of the dune-stuff project:
//   https://github.com/wwu-numerik/dune-stuff/
// Copyright holders: Rene Milk, Felix Schindler
// License: BSD 2-Clause License (http://opensource.org/licenses/BSD-2-Clause)

#ifndef DUNE_STUFF_FUNCTIONS_SPE10_HH
#define DUNE_STUFF_FUNCTIONS_SPE10_HH

#include <iostream>
#include <memory>

#include <dune/stuff/common/exceptions.hh>
#include <dune/stuff/common/configuration.hh>
#include <dune/stuff/common/color.hh>
#include <dune/stuff/common/string.hh>
#include <dune/stuff/common/fvector.hh>
#include <dune/stuff/common/type_utils.hh>

#include "checkerboard.hh"

namespace Dune {
namespace Stuff {
namespace Exceptions {

class spe10_data_file_missing : public Dune::IOError {};

} // namespace Exceptions
namespace Functions {
namespace Spe10 {
namespace internal {

static const std::string model1_filename = "perm_case1.dat";
static const size_t model1_x_elements = 100;
static const size_t model1_y_elements = 1;
static const size_t model1_z_elements = 20;
static const double model_1_length_x = 762.0;
static const double model_1_length_y = 7.62;
static const double model_1_length_z = 15.24;
static const double model1_min_value = 0.001;
static const double model1_max_value = 998.915;

template< class EntityImp, class DomainFieldImp, class RangeFieldImp, size_t r, size_t rC >
class Model1Base
  : public Checkerboard< EntityImp, DomainFieldImp, 2, RangeFieldImp, r, rC >
{
  typedef Checkerboard< EntityImp, DomainFieldImp, 2, RangeFieldImp, r, rC > BaseType;
public:
  typedef typename BaseType::EntityType         EntityType;
  typedef typename BaseType::LocalfunctionType  LocalfunctionType;

  typedef typename BaseType::DomainType       DomainType;
  typedef typename BaseType::RangeFieldType   RangeFieldType;
  typedef typename BaseType::RangeType        RangeType;

  static const bool available = true;

  static std::string static_id()
  {
    return LocalizableFunctionInterface
        < EntityImp, DomainFieldImp, 2, RangeFieldImp, 1, 1 >::static_id() + ".spe10.model1";
  } // ... static_id(...)

private:
  static std::vector< RangeType > read_values_from_file(const std::string& filename,
                                                        const RangeFieldType& min,
                                                        const RangeFieldType& max,
                                                        const RangeType& unit_range)

  {
    if (!(max > min))
      DUNE_THROW(Dune::RangeError,
                 "max (is " << max << ") has to be larger than min (is " << min << ")!");
    const RangeFieldType scale = (max - min) / (internal::model1_max_value - internal::model1_min_value);
    const RangeFieldType shift = min - scale*internal::model1_min_value;
    // read all the data from the file
    std::ifstream datafile(filename);
    if (datafile.is_open()) {
      static const size_t entriesPerDim = model1_x_elements*model1_y_elements*model1_z_elements;
      // create storage (there should be exactly 6000 values in the file, but we onyl read the first 2000)
      std::vector< RangeType > data(entriesPerDim, unit_range);
      double tmp = 0;
      size_t counter = 0;
      while (datafile >> tmp && counter < entriesPerDim)
        data[counter++] *= (tmp*scale) + shift;
      datafile.close();
      if (counter != entriesPerDim)
        DUNE_THROW(Dune::IOError,
                   "wrong number of entries in '" << filename << "' (are " << counter << ", should be "
                   << entriesPerDim << ")!");
      return data;
    } else
      DUNE_THROW(Exceptions::spe10_data_file_missing, "could not open '" << filename << "'!");
  } // ... read_values_from_file(...)

public:
  static Common::Configuration default_config(const std::string sub_name = "")
  {
    Common::Configuration config;
    config["filename"] = internal::model1_filename;
    config["lower_left"] = "[0.0 0.0]";
    config["upper_right"] = "[" + Common::toString(internal::model_1_length_x)
                            + " " + Common::toString(internal::model_1_length_z) + "]";
    config.set("min_value", internal::model1_min_value);
    config.set("max_value", internal::model1_max_value);
    config["name"] = static_id();
    if (sub_name.empty())
      return config;
    else {
      Common::Configuration tmp;
      tmp.add(config, sub_name);
      return tmp;
    }
  } // ... default_config(...)

  template< class DerivedType >
  static std::unique_ptr< DerivedType > create_derived(const Common::Configuration config, const std::string sub_name)
  {
    // get correct config
    const Common::Configuration cfg = config.has_sub(sub_name) ? config.sub(sub_name) : config;
    const Common::Configuration default_cfg = default_config();
    // create
    return Common::make_unique< DerivedType >(
          cfg.get("filename",     default_cfg.get< std::string >("filename")),
          cfg.get("lower_left",   default_cfg.get< DomainType >("lower_left")),
          cfg.get("upper_right",  default_cfg.get< DomainType >("upper_right")),
          cfg.get("min_value",    default_cfg.get< RangeFieldType >("min_value")),
          cfg.get("max_value",    default_cfg.get< RangeFieldType >("max_value")),
          cfg.get("name",         default_cfg.get< std::string >("name")));
  } // ... create(...)

  Model1Base(const std::string& filename,
             const DomainType& lowerLeft,
             const DomainType& upperRight,
             const RangeFieldType min,
             const RangeFieldType max,
             const std::string nm,
             const RangeType& unit_range)
    : BaseType(lowerLeft,
               upperRight,
               {model1_x_elements, model1_z_elements},
               read_values_from_file(filename, min, max, unit_range),
               nm)
  {}

  virtual std::string type() const override
  {
    return BaseType::static_id() + ".spe10.model1";
  }
}; // class Model1Base

} // namespace internal

// default, to allow for specialization
template< class E, class D, size_t d, class R, size_t r, size_t rC = 1 >
class Model1
  : public LocalizableFunctionInterface< E, D, d, R, r, rC >
{
  Model1() { static_assert(AlwaysFalse< E >::value, "Not available for these dimensions!"); }
};

/**
 * We read only the Kx values from file and scale the unit matrix atm.
 */
template< class EntityImp, class DomainFieldImp, class RangeFieldImp, size_t r >
class Model1< EntityImp, DomainFieldImp, 2, RangeFieldImp, r, r >
  : public internal::Model1Base< EntityImp, DomainFieldImp, RangeFieldImp, r, r >
{
  typedef internal::Model1Base< EntityImp, DomainFieldImp, RangeFieldImp, r, r > BaseType;
  typedef Model1< EntityImp, DomainFieldImp, 2, RangeFieldImp, r, r > ThisType;
public:
  using typename BaseType::DomainFieldType;
  using BaseType::dimDomain;
  using typename BaseType::RangeFieldType;
  using typename BaseType::RangeType;

  static std::unique_ptr< ThisType > create(const Common::Configuration config = BaseType::default_config(),
                                            const std::string sub_name = BaseType::static_id())
  {
    return BaseType::template create_derived< ThisType >(config, sub_name);
  } // ... create(...)

  Model1(const std::string& filename,
         const Common::FieldVector< DomainFieldType, dimDomain >& lower_left,
         const Common::FieldVector< DomainFieldType, dimDomain >& upper_right,
         const RangeFieldType min = internal::model1_min_value,
         const RangeFieldType max = internal::model1_max_value,
         const std::string nm = BaseType::static_id())
    : BaseType(filename, lower_left, upper_right, min, max, nm, unit_matrix())
  {}

private:
  template< size_t d, bool anything = true >
  struct Call
  {
    static RangeType unit_matrix()
    {
      RangeType ret(0.0);
      for (size_t rr = 0; rr < r; ++rr)
        ret[rr][rr] = 1.0;
      return ret;
    }
  };

  template< bool anything >
  struct Call< 1, anything >
  {
    static RangeType unit_matrix()
    {
      return RangeType(1);
    }
  };

  static RangeType unit_matrix()
  {
    return Call< r >::unit_matrix();
  }
}; // class Model1< ..., 2, ..., r, r >

template <class EntityImp, class DomainFieldImp, size_t dim_domain, class RangeFieldImp, size_t r, size_t rC>
class Model2 : public Stuff::GlobalFunctionInterface<EntityImp, DomainFieldImp, dim_domain, RangeFieldImp, r, rC> {
  static_assert(r==rC,"");
  static_assert(dim_domain==rC,"");
  static_assert(dim_domain==3,"");
  typedef Stuff::GlobalFunctionInterface<EntityImp, DomainFieldImp, dim_domain, RangeFieldImp, r, rC> BaseType;
public:
  Model2(std::string data_filename = "perm_case2a.dat")
    : deltas_{{6.096, 3.048, 0.6096}}
    , permeability_(nullptr)
    , permMatrix_(0.0)
    , filename_(data_filename)
  {
    readPermeability();
  }

  virtual ~Model2() {
    delete permeability_;
    permeability_ = nullptr;
  }

  //! currently used in gdt assembler
  virtual void evaluate(const typename BaseType::DomainType& x, typename BaseType::RangeType& diffusion) const final override {

    if (!permeability_) {
      DSC_LOG_ERROR_0 << "The SPE10-permeability data file could not be opened. This file does\n"
                      << "not come with the dune-multiscale repository due to file size. To download it\n"
                      << "execute\n"
                      << "wget http://www.spe.org/web/csp/datasets/por_perm_case2a.zip\n"
                      << "unzip the file and move the file 'spe_perm.dat' to\n"
                      << "dune-multiscale/dune/multiscale/problems/spe10_permeability.dat!\n";
      DUNE_THROW(IOError, "Data file for Groundwaterflow permeability could not be opened!");
    }
    // 3 is the maximum space dimension
    for (size_t dim = 0; dim < dim_domain; ++dim)
      permIntervalls_[dim] = std::floor(x[dim] / deltas_[dim]);

    const int offset = permIntervalls_[0] + permIntervalls_[1] * 60 + permIntervalls_[2] * 220 * 60;
    for (size_t dim = 0; dim < dim_domain; ++dim)
      diffusion[dim][dim] = permeability_[offset + dim * 1122000];
  }

  virtual size_t order() const {
    return 0u;
  }
private:
  void readPermeability() {
    std::ifstream file(filename_);
    double val;
    if (!file) { // file couldn't be opened
      return;
    }
    file >> val;
    int counter = 0;
    permeability_ = new double[3366000];
    while (!file.eof()) {
      // keep reading until end-of-file
      permeability_[counter++] = val;
      file >> val; // sets EOF flag if no value found
    }
    file.close();
  }

  std::array<double, dim_domain> deltas_;
  double* permeability_; //! TODO automatic memory
  mutable typename BaseType::DomainType permIntervalls_;
  mutable Dune::FieldMatrix<double, BaseType::DomainType::dimension, BaseType::DomainType::dimension> permMatrix_;
  const std::string filename_;
};

} // namespace Spe10
} // namespace Functions
} // namespace Stuff
} // namespace Dune

#endif // DUNE_STUFF_FUNCTIONS_SPE10_HH
<commit_msg>[functions.spe10] note grid dimensions<commit_after>// This file is part of the dune-stuff project:
//   https://github.com/wwu-numerik/dune-stuff/
// Copyright holders: Rene Milk, Felix Schindler
// License: BSD 2-Clause License (http://opensource.org/licenses/BSD-2-Clause)

#ifndef DUNE_STUFF_FUNCTIONS_SPE10_HH
#define DUNE_STUFF_FUNCTIONS_SPE10_HH

#include <iostream>
#include <memory>

#include <dune/stuff/common/exceptions.hh>
#include <dune/stuff/common/configuration.hh>
#include <dune/stuff/common/color.hh>
#include <dune/stuff/common/string.hh>
#include <dune/stuff/common/fvector.hh>
#include <dune/stuff/common/type_utils.hh>

#include "checkerboard.hh"

namespace Dune {
namespace Stuff {
namespace Exceptions {

class spe10_data_file_missing : public Dune::IOError {};

} // namespace Exceptions
namespace Functions {
namespace Spe10 {
namespace internal {

static const std::string model1_filename = "perm_case1.dat";
static const size_t model1_x_elements = 100;
static const size_t model1_y_elements = 1;
static const size_t model1_z_elements = 20;
static const double model_1_length_x = 762.0;
static const double model_1_length_y = 7.62;
static const double model_1_length_z = 15.24;
static const double model1_min_value = 0.001;
static const double model1_max_value = 998.915;

template< class EntityImp, class DomainFieldImp, class RangeFieldImp, size_t r, size_t rC >
class Model1Base
  : public Checkerboard< EntityImp, DomainFieldImp, 2, RangeFieldImp, r, rC >
{
  typedef Checkerboard< EntityImp, DomainFieldImp, 2, RangeFieldImp, r, rC > BaseType;
public:
  typedef typename BaseType::EntityType         EntityType;
  typedef typename BaseType::LocalfunctionType  LocalfunctionType;

  typedef typename BaseType::DomainType       DomainType;
  typedef typename BaseType::RangeFieldType   RangeFieldType;
  typedef typename BaseType::RangeType        RangeType;

  static const bool available = true;

  static std::string static_id()
  {
    return LocalizableFunctionInterface
        < EntityImp, DomainFieldImp, 2, RangeFieldImp, 1, 1 >::static_id() + ".spe10.model1";
  } // ... static_id(...)

private:
  static std::vector< RangeType > read_values_from_file(const std::string& filename,
                                                        const RangeFieldType& min,
                                                        const RangeFieldType& max,
                                                        const RangeType& unit_range)

  {
    if (!(max > min))
      DUNE_THROW(Dune::RangeError,
                 "max (is " << max << ") has to be larger than min (is " << min << ")!");
    const RangeFieldType scale = (max - min) / (internal::model1_max_value - internal::model1_min_value);
    const RangeFieldType shift = min - scale*internal::model1_min_value;
    // read all the data from the file
    std::ifstream datafile(filename);
    if (datafile.is_open()) {
      static const size_t entriesPerDim = model1_x_elements*model1_y_elements*model1_z_elements;
      // create storage (there should be exactly 6000 values in the file, but we onyl read the first 2000)
      std::vector< RangeType > data(entriesPerDim, unit_range);
      double tmp = 0;
      size_t counter = 0;
      while (datafile >> tmp && counter < entriesPerDim)
        data[counter++] *= (tmp*scale) + shift;
      datafile.close();
      if (counter != entriesPerDim)
        DUNE_THROW(Dune::IOError,
                   "wrong number of entries in '" << filename << "' (are " << counter << ", should be "
                   << entriesPerDim << ")!");
      return data;
    } else
      DUNE_THROW(Exceptions::spe10_data_file_missing, "could not open '" << filename << "'!");
  } // ... read_values_from_file(...)

public:
  static Common::Configuration default_config(const std::string sub_name = "")
  {
    Common::Configuration config;
    config["filename"] = internal::model1_filename;
    config["lower_left"] = "[0.0 0.0]";
    config["upper_right"] = "[" + Common::toString(internal::model_1_length_x)
                            + " " + Common::toString(internal::model_1_length_z) + "]";
    config.set("min_value", internal::model1_min_value);
    config.set("max_value", internal::model1_max_value);
    config["name"] = static_id();
    if (sub_name.empty())
      return config;
    else {
      Common::Configuration tmp;
      tmp.add(config, sub_name);
      return tmp;
    }
  } // ... default_config(...)

  template< class DerivedType >
  static std::unique_ptr< DerivedType > create_derived(const Common::Configuration config, const std::string sub_name)
  {
    // get correct config
    const Common::Configuration cfg = config.has_sub(sub_name) ? config.sub(sub_name) : config;
    const Common::Configuration default_cfg = default_config();
    // create
    return Common::make_unique< DerivedType >(
          cfg.get("filename",     default_cfg.get< std::string >("filename")),
          cfg.get("lower_left",   default_cfg.get< DomainType >("lower_left")),
          cfg.get("upper_right",  default_cfg.get< DomainType >("upper_right")),
          cfg.get("min_value",    default_cfg.get< RangeFieldType >("min_value")),
          cfg.get("max_value",    default_cfg.get< RangeFieldType >("max_value")),
          cfg.get("name",         default_cfg.get< std::string >("name")));
  } // ... create(...)

  Model1Base(const std::string& filename,
             const DomainType& lowerLeft,
             const DomainType& upperRight,
             const RangeFieldType min,
             const RangeFieldType max,
             const std::string nm,
             const RangeType& unit_range)
    : BaseType(lowerLeft,
               upperRight,
               {model1_x_elements, model1_z_elements},
               read_values_from_file(filename, min, max, unit_range),
               nm)
  {}

  virtual std::string type() const override
  {
    return BaseType::static_id() + ".spe10.model1";
  }
}; // class Model1Base

} // namespace internal

// default, to allow for specialization
template< class E, class D, size_t d, class R, size_t r, size_t rC = 1 >
class Model1
  : public LocalizableFunctionInterface< E, D, d, R, r, rC >
{
  Model1() { static_assert(AlwaysFalse< E >::value, "Not available for these dimensions!"); }
};

/**
 * We read only the Kx values from file and scale the unit matrix atm.
 */
template< class EntityImp, class DomainFieldImp, class RangeFieldImp, size_t r >
class Model1< EntityImp, DomainFieldImp, 2, RangeFieldImp, r, r >
  : public internal::Model1Base< EntityImp, DomainFieldImp, RangeFieldImp, r, r >
{
  typedef internal::Model1Base< EntityImp, DomainFieldImp, RangeFieldImp, r, r > BaseType;
  typedef Model1< EntityImp, DomainFieldImp, 2, RangeFieldImp, r, r > ThisType;
public:
  using typename BaseType::DomainFieldType;
  using BaseType::dimDomain;
  using typename BaseType::RangeFieldType;
  using typename BaseType::RangeType;

  static std::unique_ptr< ThisType > create(const Common::Configuration config = BaseType::default_config(),
                                            const std::string sub_name = BaseType::static_id())
  {
    return BaseType::template create_derived< ThisType >(config, sub_name);
  } // ... create(...)

  Model1(const std::string& filename,
         const Common::FieldVector< DomainFieldType, dimDomain >& lower_left,
         const Common::FieldVector< DomainFieldType, dimDomain >& upper_right,
         const RangeFieldType min = internal::model1_min_value,
         const RangeFieldType max = internal::model1_max_value,
         const std::string nm = BaseType::static_id())
    : BaseType(filename, lower_left, upper_right, min, max, nm, unit_matrix())
  {}

private:
  template< size_t d, bool anything = true >
  struct Call
  {
    static RangeType unit_matrix()
    {
      RangeType ret(0.0);
      for (size_t rr = 0; rr < r; ++rr)
        ret[rr][rr] = 1.0;
      return ret;
    }
  };

  template< bool anything >
  struct Call< 1, anything >
  {
    static RangeType unit_matrix()
    {
      return RangeType(1);
    }
  };

  static RangeType unit_matrix()
  {
    return Call< r >::unit_matrix();
  }
}; // class Model1< ..., 2, ..., r, r >

/**
 * Grid is currently mandated to have LL (0,0,0) to UR (365.76, 670.56, 51.816) corners
 */
template <class EntityImp, class DomainFieldImp, size_t dim_domain, class RangeFieldImp, size_t r, size_t rC>
class Model2 : public Stuff::GlobalFunctionInterface<EntityImp, DomainFieldImp, dim_domain, RangeFieldImp, r, rC> {
  static_assert(r==rC,"");
  static_assert(dim_domain==rC,"");
  static_assert(dim_domain==3,"");
  typedef Stuff::GlobalFunctionInterface<EntityImp, DomainFieldImp, dim_domain, RangeFieldImp, r, rC> BaseType;
public:
  Model2(std::string data_filename = "perm_case2a.dat")
    : deltas_{{6.096, 3.048, 0.6096}}
    , permeability_(nullptr)
    , permMatrix_(0.0)
    , filename_(data_filename)
  {
    readPermeability();
  }

  virtual ~Model2() {
    delete permeability_;
    permeability_ = nullptr;
  }

  //! currently used in gdt assembler
  virtual void evaluate(const typename BaseType::DomainType& x, typename BaseType::RangeType& diffusion) const final override {

    if (!permeability_) {
      DSC_LOG_ERROR_0 << "The SPE10-permeability data file could not be opened. This file does\n"
                      << "not come with the dune-multiscale repository due to file size. To download it\n"
                      << "execute\n"
                      << "wget http://www.spe.org/web/csp/datasets/por_perm_case2a.zip\n"
                      << "unzip the file and move the file 'spe_perm.dat' to\n"
                      << "dune-multiscale/dune/multiscale/problems/spe10_permeability.dat!\n";
      DUNE_THROW(IOError, "Data file for Groundwaterflow permeability could not be opened!");
    }
    // 3 is the maximum space dimension
    for (size_t dim = 0; dim < dim_domain; ++dim)
      permIntervalls_[dim] = std::floor(x[dim] / deltas_[dim]);

    const int offset = permIntervalls_[0] + permIntervalls_[1] * 60 + permIntervalls_[2] * 220 * 60;
    for (size_t dim = 0; dim < dim_domain; ++dim)
      diffusion[dim][dim] = permeability_[offset + dim * 1122000];
  }

  virtual size_t order() const {
    return 0u;
  }
private:
  void readPermeability() {
    std::ifstream file(filename_);
    double val;
    if (!file) { // file couldn't be opened
      return;
    }
    file >> val;
    int counter = 0;
    permeability_ = new double[3366000];
    while (!file.eof()) {
      // keep reading until end-of-file
      permeability_[counter++] = val;
      file >> val; // sets EOF flag if no value found
    }
    file.close();
  }

  std::array<double, dim_domain> deltas_;
  double* permeability_; //! TODO automatic memory
  mutable typename BaseType::DomainType permIntervalls_;
  mutable Dune::FieldMatrix<double, BaseType::DomainType::dimension, BaseType::DomainType::dimension> permMatrix_;
  const std::string filename_;
};

} // namespace Spe10
} // namespace Functions
} // namespace Stuff
} // namespace Dune

#endif // DUNE_STUFF_FUNCTIONS_SPE10_HH
<|endoftext|>


<commit_before>#include <QtGui>

#include "MainWindow.h"

MainWindow::MainWindow()
{
	QScrollArea *scrollArea = new QScrollArea;
	renderWidget = new Renderer;
	renderWidget->setSizePolicy(QSizePolicy::Ignored, QSizePolicy::Ignored);

	scrollArea->setAlignment(Qt::AlignCenter);

	QWidget *widget = new QWidget;
	setCentralWidget(widget);

	QVBoxLayout *layout = new QVBoxLayout;
	layout->setMargin(5);
	scrollArea->setWidget(renderWidget);
	layout->addWidget(scrollArea);
	widget->setLayout(layout);

	signalMapper = new QSignalMapper(this);
	createActions();
	createMenus();

	this->setWindowTitle("IGP 3.0");
	this->setWindowIcon(QIcon("./Resources/IGP.png"));
}

void MainWindow::newFile()
{
	ResizeDialog resizeDialog(1, 1, 1, 1, 2000, 2000, QString("New Image Size"));

	if (resizeDialog.exec() == QDialog::Accepted)
	{
		renderWidget->newImage(resizeDialog.getWidth(),resizeDialog.getHeight());
		renderWidget->resize(renderWidget->getMinSize());;
	}
}

void MainWindow::openFile()
{
	QString fileName = QFileDialog::getOpenFileName(this, tr("Open Image"), "./Img/", tr("Image Files (*.png *.jpg *.bmp)"));
	if (!fileName.isEmpty())
		renderWidget->loadImage(fileName);

	renderWidget->resize(renderWidget->getMinSize());
}

void MainWindow::openFileImport()
{
	QString fileName = QFileDialog::getOpenFileName(this, tr("Open Image"), "./Img/", tr("Image Files (*.png *.jpg *.bmp)"));
	if (!fileName.isEmpty())
	{
		renderWidget->loadImage(fileName);
		resizeImage();
	}

	renderWidget->resize(renderWidget->getMinSize());
}

void MainWindow::resizeImage()
{
	QSize currentSize = renderWidget->getImageSize();
	ResizeDialog resizeDialog(currentSize.width(), currentSize.height(), 1, 1, 2000, 2000);

	if (resizeDialog.exec() == QDialog::Accepted)
	{
		renderWidget->resizeImage(resizeDialog.getWidth(),resizeDialog.getHeight());
		renderWidget->resize(renderWidget->getMinSize());;
	}
}

void MainWindow::saveFile()
{
	QString fileName = QFileDialog::getOpenFileName(this, tr("Save Image"), "./Img/", tr("Image Files (*.png *.jpg *.bmp)"));
	if (!fileName.isEmpty())
		renderWidget->saveImage(fileName);
}

void MainWindow::setBrushColor()
{
	QColor color = QColorDialog::getColor(Qt::white, this, tr("Select Brush Color"));
	if (color.isValid())
		renderWidget->setBrushColor(color);
}

void MainWindow::setBackgroundColor()
{
	QColor color = QColorDialog::getColor(Qt::white, this, tr("Select Background Color"));
	if (color.isValid())
		renderWidget->setBackgroundColor(color);
}

void MainWindow::setOutlineColor()
{
	QColor color = QColorDialog::getColor(Qt::black, this, tr("Select Background Color"));
	if (color.isValid())
		renderWidget->setOutlineColor(color);
}

void MainWindow::setColorPalette()
{
	QString fileName = QFileDialog::getOpenFileName(this, tr("Open Palette"), "./Palettes/", tr("Image Files (*.png *.jpg *.bmp)"));
	if (!fileName.isEmpty())
		renderWidget->changePalette(fileName);

}

void MainWindow::openPattern(QString dir)
{
	renderWidget->setPattern(QDir(dir));
	renderWidget->resize(renderWidget->getMinSize());
}

void MainWindow::rotateTranspose()
{
	renderWidget->rotateTranspose();
	renderWidget->resize(renderWidget->getMinSize());
}

void MainWindow::rotateClockwise()
{
	renderWidget->rotateClockwise();
	renderWidget->resize(renderWidget->getMinSize());
}

void MainWindow::rotateCounterClockwise()
{
	renderWidget->rotateCounterClockwise();
	renderWidget->resize(renderWidget->getMinSize());
}

void MainWindow::rotate180()
{
	renderWidget->rotate180();
	renderWidget->resize(renderWidget->getMinSize());
}

void MainWindow::rotateFlipX()
{
	renderWidget->rotateFlipX();
	renderWidget->resize(renderWidget->getMinSize());
}

void MainWindow::rotateFlipY()
{
	renderWidget->rotateFlipY();
	renderWidget->resize(renderWidget->getMinSize());
}

void MainWindow::zoomIn()
{
	renderWidget->zoomIn();
	renderWidget->resize(renderWidget->getMinSize());
}

void MainWindow::zoomOut()
{
	renderWidget->zoomOut();
	renderWidget->resize(renderWidget->getMinSize());
}

void MainWindow::zoomNormal()
{
	renderWidget->zoomNormal();
	renderWidget->resize(renderWidget->getMinSize());
}

void MainWindow::about()
{
	QMessageBox::about(this, tr("About IGP 3.0"), tr("The Irregular Grid Painter [IGP] allows the user to paint patterned tiles. This program's first version originated within the chainmaille community at M.A.I.L. by user Zlosk. The second version, written by user aganim, ended up being a HTML5 port. This final version is written by user TrenchCoatGuy [Brian Geuther] using the QT framework."));
}

void MainWindow::createActions()
{
	// File Actions
	newAct = new QAction(tr("&New"), this);
    newAct->setShortcuts(QKeySequence::New);
    newAct->setStatusTip(tr("Create a new image grid"));
    connect(newAct, SIGNAL(triggered()), this, SLOT(newFile()));

	openAct = new QAction(tr("&Open"), this);
    openAct->setShortcuts(QKeySequence::Open);
    openAct->setStatusTip(tr("Open an existing image"));
    connect(openAct, SIGNAL(triggered()), this, SLOT(openFile()));

	openImportAct = new QAction(tr("&Import"), this);
    openImportAct->setStatusTip(tr("Open an existing image and scale it"));
    connect(openImportAct, SIGNAL(triggered()), this, SLOT(openFileImport()));

	resizeImageAct = new QAction(tr("&Resize"), this);
    resizeImageAct->setStatusTip(tr("Resize current image"));
    connect(resizeImageAct, SIGNAL(triggered()), this, SLOT(resizeImage()));

	saveAct = new QAction(tr("&Save"), this);
    saveAct->setShortcuts(QKeySequence::Save);
    saveAct->setStatusTip(tr("Save the opened image"));
    connect(saveAct, SIGNAL(triggered()), this, SLOT(saveFile()));

	// Rotate Image Actions
	rotateTransposeAct = new QAction(tr("Transpose Image"), this);
    rotateTransposeAct->setStatusTip(tr("Transposes the source image file"));
    connect(rotateTransposeAct, SIGNAL(triggered()), this, SLOT(rotateTranspose()));

	rotateClockwiseAct = new QAction(tr("Rotate Clockwise"), this);
    rotateClockwiseAct->setStatusTip(tr("Rotates the source image file by 90 degrees clockwise"));
    connect(rotateClockwiseAct, SIGNAL(triggered()), this, SLOT(rotateClockwise()));

	rotateCounterClockwiseAct = new QAction(tr("Rotate Counter-Clockwise"), this);
    rotateCounterClockwiseAct->setStatusTip(tr("Rotates the source image file by 90 degrees counter-clockwise"));
    connect(rotateCounterClockwiseAct, SIGNAL(triggered()), this, SLOT(rotateCounterClockwise()));

	rotate180Act = new QAction(tr("Rotate 180"), this);
    rotate180Act->setStatusTip(tr("Rotates the source image file by 180 degrees"));
    connect(rotate180Act, SIGNAL(triggered()), this, SLOT(rotate180()));

	rotateFlipXAct = new QAction(tr("Reflect X axis"), this);
    rotateFlipXAct->setStatusTip(tr("Reflects the source image files X axis"));
    connect(rotateFlipXAct, SIGNAL(triggered()), this, SLOT(rotateFlipX()));

	rotateFlipYAct = new QAction(tr("Reflect Y axis"), this);
    rotateFlipYAct->setStatusTip(tr("Reflects the source image files Y axis"));
    connect(rotateFlipYAct, SIGNAL(triggered()), this, SLOT(rotateFlipY()));

	// Zoom Actions
	zoomInAct = new QAction(tr("Zoom In"), this);
	zoomInAct->setShortcuts(QKeySequence::ZoomIn);
    zoomInAct->setStatusTip(tr("Increases size of image by 10%"));
    connect(zoomInAct, SIGNAL(triggered()), this, SLOT(zoomIn()));

	zoomOutAct = new QAction(tr("Zoom Out"), this);
	zoomOutAct->setShortcuts(QKeySequence::ZoomOut);
    zoomOutAct->setStatusTip(tr("Decreases size of image by 10%"));
    connect(zoomOutAct, SIGNAL(triggered()), this, SLOT(zoomOut()));

	zoomNormalAct = new QAction(tr("Zoom Reset"), this);
    zoomNormalAct->setStatusTip(tr("Resets the zoom to 100%"));
    connect(zoomNormalAct, SIGNAL(triggered()), this, SLOT(zoomNormal()));

	// Color Actions
	setBrushColorAct = new QAction(tr("&Brush"), this);
    setBrushColorAct->setStatusTip(tr("Select a new brush color"));
    connect(setBrushColorAct, SIGNAL(triggered()), this, SLOT(setBrushColor()));

	setBackgroundColorAct = new QAction(tr("Back&ground"), this);
    setBackgroundColorAct->setStatusTip(tr("Select a new background color"));
    connect(setBackgroundColorAct, SIGNAL(triggered()), this, SLOT(setBackgroundColor()));

	setOutlineColorAct = new QAction(tr("&Outline"), this);
    setOutlineColorAct->setStatusTip(tr("Select a new outline color"));
    connect(setOutlineColorAct, SIGNAL(triggered()), this, SLOT(setOutlineColor()));

	setColorPaletteAct = new QAction(tr("&Palette Change"), this);
    setColorPaletteAct->setStatusTip(tr("Limit colors to the current image"));
    connect(setColorPaletteAct, SIGNAL(triggered()), this, SLOT(setColorPalette()));

	// About Action
	aboutAct = new QAction(tr("&About"), this);
    aboutAct->setShortcuts(QKeySequence::HelpContents);
    aboutAct->setStatusTip(tr("Description of this program"));
    connect(aboutAct, SIGNAL(triggered()), this, SLOT(about()));
}

void MainWindow::createMenus()
{
	fileMenu = menuBar()->addMenu(tr("&File"));
	fileMenu->addAction(newAct);
	fileMenu->addAction(openAct);
	fileMenu->addAction(openImportAct);
	fileMenu->addAction(resizeImageAct);
	fileMenu->addAction(saveAct);

	editMenu = menuBar()->addMenu(tr("&Edit"));
	transformSubMenu = editMenu->addMenu(tr("&Transforms"));
	transformSubMenu->addAction(rotateTransposeAct);
	transformSubMenu->addAction(rotateClockwiseAct);
	transformSubMenu->addAction(rotateCounterClockwiseAct);
	transformSubMenu->addAction(rotate180Act);
	transformSubMenu->addAction(rotateFlipXAct);
	transformSubMenu->addAction(rotateFlipYAct);
	zoomSubMenu = editMenu->addMenu(tr("&Zoom"));
	zoomSubMenu->addAction(zoomInAct);
	zoomSubMenu->addAction(zoomOutAct);
	zoomSubMenu->addAction(zoomNormalAct);

	colorMenu = menuBar()->addMenu(tr("&Color"));
	colorMenu->addAction(setBrushColorAct);
	colorMenu->addAction(setBackgroundColorAct);
	colorMenu->addAction(setOutlineColorAct);
	colorMenu->addAction(setColorPaletteAct);

	patternMenu = menuBar()->addMenu(tr("&Patterns"));
	connect(signalMapper, SIGNAL(mapped(QString)), this, SLOT(openPattern(QString)));
	findPatterns(patternMenu);

	menuBar()->addSeparator();

    aboutMenu = menuBar()->addMenu(tr("About"));
    aboutMenu->addAction(aboutAct);
}

void MainWindow::findPatterns(QMenu *menu, QDir dir)
{
	// Filter for subfolders
	QStringList filters;
	filters << "*";
	dir.setFilter(QDir::Dirs | QDir::NoDotAndDotDot);
	QStringList subDirs = dir.entryList(filters);

	while (subDirs.length())
	{
		QString folder = subDirs.takeFirst();
		QDir newDir(dir.path());
		newDir.cd(folder);

		// Check subfolder for ini file
		if (newDir.exists(folder+QString(".ini")))
		{
			QAction *newAct = new QAction(folder, this);
			signalMapper->setMapping(newAct, newDir.path());
			connect(newAct, SIGNAL(triggered()), signalMapper, SLOT(map()));
			menu->addAction(newAct);
			//std::cout << "Pattern Found: " << folder.toStdString() << "\n";
		}
		// Recursively repeat
		else
		{
			QMenu *subMenu;
			subMenu = menu->addMenu(folder);
			findPatterns(subMenu, newDir);
		}
	}
}

<commit_msg>Updating about message<commit_after>#include <QtGui>

#include "MainWindow.h"

MainWindow::MainWindow()
{
	QScrollArea *scrollArea = new QScrollArea;
	renderWidget = new Renderer;
	renderWidget->setSizePolicy(QSizePolicy::Ignored, QSizePolicy::Ignored);

	scrollArea->setAlignment(Qt::AlignCenter);

	QWidget *widget = new QWidget;
	setCentralWidget(widget);

	QVBoxLayout *layout = new QVBoxLayout;
	layout->setMargin(5);
	scrollArea->setWidget(renderWidget);
	layout->addWidget(scrollArea);
	widget->setLayout(layout);

	signalMapper = new QSignalMapper(this);
	createActions();
	createMenus();

	this->setWindowTitle("IGP 3.0");
	this->setWindowIcon(QIcon("./Resources/IGP.png"));
}

void MainWindow::newFile()
{
	ResizeDialog resizeDialog(1, 1, 1, 1, 2000, 2000, QString("New Image Size"));

	if (resizeDialog.exec() == QDialog::Accepted)
	{
		renderWidget->newImage(resizeDialog.getWidth(),resizeDialog.getHeight());
		renderWidget->resize(renderWidget->getMinSize());;
	}
}

void MainWindow::openFile()
{
	QString fileName = QFileDialog::getOpenFileName(this, tr("Open Image"), "./Img/", tr("Image Files (*.png *.jpg *.bmp)"));
	if (!fileName.isEmpty())
		renderWidget->loadImage(fileName);

	renderWidget->resize(renderWidget->getMinSize());
}

void MainWindow::openFileImport()
{
	QString fileName = QFileDialog::getOpenFileName(this, tr("Open Image"), "./Img/", tr("Image Files (*.png *.jpg *.bmp)"));
	if (!fileName.isEmpty())
	{
		renderWidget->loadImage(fileName);
		resizeImage();
	}

	renderWidget->resize(renderWidget->getMinSize());
}

void MainWindow::resizeImage()
{
	QSize currentSize = renderWidget->getImageSize();
	ResizeDialog resizeDialog(currentSize.width(), currentSize.height(), 1, 1, 2000, 2000);

	if (resizeDialog.exec() == QDialog::Accepted)
	{
		renderWidget->resizeImage(resizeDialog.getWidth(),resizeDialog.getHeight());
		renderWidget->resize(renderWidget->getMinSize());;
	}
}

void MainWindow::saveFile()
{
	QString fileName = QFileDialog::getOpenFileName(this, tr("Save Image"), "./Img/", tr("Image Files (*.png *.jpg *.bmp)"));
	if (!fileName.isEmpty())
		renderWidget->saveImage(fileName);
}

void MainWindow::setBrushColor()
{
	QColor color = QColorDialog::getColor(Qt::white, this, tr("Select Brush Color"));
	if (color.isValid())
		renderWidget->setBrushColor(color);
}

void MainWindow::setBackgroundColor()
{
	QColor color = QColorDialog::getColor(Qt::white, this, tr("Select Background Color"));
	if (color.isValid())
		renderWidget->setBackgroundColor(color);
}

void MainWindow::setOutlineColor()
{
	QColor color = QColorDialog::getColor(Qt::black, this, tr("Select Background Color"));
	if (color.isValid())
		renderWidget->setOutlineColor(color);
}

void MainWindow::setColorPalette()
{
	QString fileName = QFileDialog::getOpenFileName(this, tr("Open Palette"), "./Palettes/", tr("Image Files (*.png *.jpg *.bmp)"));
	if (!fileName.isEmpty())
		renderWidget->changePalette(fileName);

}

void MainWindow::openPattern(QString dir)
{
	renderWidget->setPattern(QDir(dir));
	renderWidget->resize(renderWidget->getMinSize());
}

void MainWindow::rotateTranspose()
{
	renderWidget->rotateTranspose();
	renderWidget->resize(renderWidget->getMinSize());
}

void MainWindow::rotateClockwise()
{
	renderWidget->rotateClockwise();
	renderWidget->resize(renderWidget->getMinSize());
}

void MainWindow::rotateCounterClockwise()
{
	renderWidget->rotateCounterClockwise();
	renderWidget->resize(renderWidget->getMinSize());
}

void MainWindow::rotate180()
{
	renderWidget->rotate180();
	renderWidget->resize(renderWidget->getMinSize());
}

void MainWindow::rotateFlipX()
{
	renderWidget->rotateFlipX();
	renderWidget->resize(renderWidget->getMinSize());
}

void MainWindow::rotateFlipY()
{
	renderWidget->rotateFlipY();
	renderWidget->resize(renderWidget->getMinSize());
}

void MainWindow::zoomIn()
{
	renderWidget->zoomIn();
	renderWidget->resize(renderWidget->getMinSize());
}

void MainWindow::zoomOut()
{
	renderWidget->zoomOut();
	renderWidget->resize(renderWidget->getMinSize());
}

void MainWindow::zoomNormal()
{
	renderWidget->zoomNormal();
	renderWidget->resize(renderWidget->getMinSize());
}

void MainWindow::about()
{
	QMessageBox::about(this, tr("About IGP 3.0"), tr("The Irregular Grid Painter [IGP] allows the user to paint patterned tiles. This program's first version originated within the chainmaille community at M.A.I.L. by user Zlosk using the .Net framework. The second version, written by user aganim, used javascript and HTML5. This version is written by user TrenchCoatGuy [Brian Geuther] using the QT framework."));
}

void MainWindow::createActions()
{
	// File Actions
	newAct = new QAction(tr("&New"), this);
    newAct->setShortcuts(QKeySequence::New);
    newAct->setStatusTip(tr("Create a new image grid"));
    connect(newAct, SIGNAL(triggered()), this, SLOT(newFile()));

	openAct = new QAction(tr("&Open"), this);
    openAct->setShortcuts(QKeySequence::Open);
    openAct->setStatusTip(tr("Open an existing image"));
    connect(openAct, SIGNAL(triggered()), this, SLOT(openFile()));

	openImportAct = new QAction(tr("&Import"), this);
    openImportAct->setStatusTip(tr("Open an existing image and scale it"));
    connect(openImportAct, SIGNAL(triggered()), this, SLOT(openFileImport()));

	resizeImageAct = new QAction(tr("&Resize"), this);
    resizeImageAct->setStatusTip(tr("Resize current image"));
    connect(resizeImageAct, SIGNAL(triggered()), this, SLOT(resizeImage()));

	saveAct = new QAction(tr("&Save"), this);
    saveAct->setShortcuts(QKeySequence::Save);
    saveAct->setStatusTip(tr("Save the opened image"));
    connect(saveAct, SIGNAL(triggered()), this, SLOT(saveFile()));

	// Rotate Image Actions
	rotateTransposeAct = new QAction(tr("Transpose Image"), this);
    rotateTransposeAct->setStatusTip(tr("Transposes the source image file"));
    connect(rotateTransposeAct, SIGNAL(triggered()), this, SLOT(rotateTranspose()));

	rotateClockwiseAct = new QAction(tr("Rotate Clockwise"), this);
    rotateClockwiseAct->setStatusTip(tr("Rotates the source image file by 90 degrees clockwise"));
    connect(rotateClockwiseAct, SIGNAL(triggered()), this, SLOT(rotateClockwise()));

	rotateCounterClockwiseAct = new QAction(tr("Rotate Counter-Clockwise"), this);
    rotateCounterClockwiseAct->setStatusTip(tr("Rotates the source image file by 90 degrees counter-clockwise"));
    connect(rotateCounterClockwiseAct, SIGNAL(triggered()), this, SLOT(rotateCounterClockwise()));

	rotate180Act = new QAction(tr("Rotate 180"), this);
    rotate180Act->setStatusTip(tr("Rotates the source image file by 180 degrees"));
    connect(rotate180Act, SIGNAL(triggered()), this, SLOT(rotate180()));

	rotateFlipXAct = new QAction(tr("Reflect X axis"), this);
    rotateFlipXAct->setStatusTip(tr("Reflects the source image files X axis"));
    connect(rotateFlipXAct, SIGNAL(triggered()), this, SLOT(rotateFlipX()));

	rotateFlipYAct = new QAction(tr("Reflect Y axis"), this);
    rotateFlipYAct->setStatusTip(tr("Reflects the source image files Y axis"));
    connect(rotateFlipYAct, SIGNAL(triggered()), this, SLOT(rotateFlipY()));

	// Zoom Actions
	zoomInAct = new QAction(tr("Zoom In"), this);
	zoomInAct->setShortcuts(QKeySequence::ZoomIn);
    zoomInAct->setStatusTip(tr("Increases size of image by 10%"));
    connect(zoomInAct, SIGNAL(triggered()), this, SLOT(zoomIn()));

	zoomOutAct = new QAction(tr("Zoom Out"), this);
	zoomOutAct->setShortcuts(QKeySequence::ZoomOut);
    zoomOutAct->setStatusTip(tr("Decreases size of image by 10%"));
    connect(zoomOutAct, SIGNAL(triggered()), this, SLOT(zoomOut()));

	zoomNormalAct = new QAction(tr("Zoom Reset"), this);
    zoomNormalAct->setStatusTip(tr("Resets the zoom to 100%"));
    connect(zoomNormalAct, SIGNAL(triggered()), this, SLOT(zoomNormal()));

	// Color Actions
	setBrushColorAct = new QAction(tr("&Brush"), this);
    setBrushColorAct->setStatusTip(tr("Select a new brush color"));
    connect(setBrushColorAct, SIGNAL(triggered()), this, SLOT(setBrushColor()));

	setBackgroundColorAct = new QAction(tr("Back&ground"), this);
    setBackgroundColorAct->setStatusTip(tr("Select a new background color"));
    connect(setBackgroundColorAct, SIGNAL(triggered()), this, SLOT(setBackgroundColor()));

	setOutlineColorAct = new QAction(tr("&Outline"), this);
    setOutlineColorAct->setStatusTip(tr("Select a new outline color"));
    connect(setOutlineColorAct, SIGNAL(triggered()), this, SLOT(setOutlineColor()));

	setColorPaletteAct = new QAction(tr("&Palette Change"), this);
    setColorPaletteAct->setStatusTip(tr("Limit colors to the current image"));
    connect(setColorPaletteAct, SIGNAL(triggered()), this, SLOT(setColorPalette()));

	// About Action
	aboutAct = new QAction(tr("&About"), this);
    aboutAct->setShortcuts(QKeySequence::HelpContents);
    aboutAct->setStatusTip(tr("Description of this program"));
    connect(aboutAct, SIGNAL(triggered()), this, SLOT(about()));
}

void MainWindow::createMenus()
{
	fileMenu = menuBar()->addMenu(tr("&File"));
	fileMenu->addAction(newAct);
	fileMenu->addAction(openAct);
	fileMenu->addAction(openImportAct);
	fileMenu->addAction(resizeImageAct);
	fileMenu->addAction(saveAct);

	editMenu = menuBar()->addMenu(tr("&Edit"));
	transformSubMenu = editMenu->addMenu(tr("&Transforms"));
	transformSubMenu->addAction(rotateTransposeAct);
	transformSubMenu->addAction(rotateClockwiseAct);
	transformSubMenu->addAction(rotateCounterClockwiseAct);
	transformSubMenu->addAction(rotate180Act);
	transformSubMenu->addAction(rotateFlipXAct);
	transformSubMenu->addAction(rotateFlipYAct);
	zoomSubMenu = editMenu->addMenu(tr("&Zoom"));
	zoomSubMenu->addAction(zoomInAct);
	zoomSubMenu->addAction(zoomOutAct);
	zoomSubMenu->addAction(zoomNormalAct);

	colorMenu = menuBar()->addMenu(tr("&Color"));
	colorMenu->addAction(setBrushColorAct);
	colorMenu->addAction(setBackgroundColorAct);
	colorMenu->addAction(setOutlineColorAct);
	colorMenu->addAction(setColorPaletteAct);

	patternMenu = menuBar()->addMenu(tr("&Patterns"));
	connect(signalMapper, SIGNAL(mapped(QString)), this, SLOT(openPattern(QString)));
	findPatterns(patternMenu);

	menuBar()->addSeparator();

    aboutMenu = menuBar()->addMenu(tr("About"));
    aboutMenu->addAction(aboutAct);
}

void MainWindow::findPatterns(QMenu *menu, QDir dir)
{
	// Filter for subfolders
	QStringList filters;
	filters << "*";
	dir.setFilter(QDir::Dirs | QDir::NoDotAndDotDot);
	QStringList subDirs = dir.entryList(filters);

	while (subDirs.length())
	{
		QString folder = subDirs.takeFirst();
		QDir newDir(dir.path());
		newDir.cd(folder);

		// Check subfolder for ini file
		if (newDir.exists(folder+QString(".ini")))
		{
			QAction *newAct = new QAction(folder, this);
			signalMapper->setMapping(newAct, newDir.path());
			connect(newAct, SIGNAL(triggered()), signalMapper, SLOT(map()));
			menu->addAction(newAct);
			//std::cout << "Pattern Found: " << folder.toStdString() << "\n";
		}
		// Recursively repeat
		else
		{
			QMenu *subMenu;
			subMenu = menu->addMenu(folder);
			findPatterns(subMenu, newDir);
		}
	}
}

<|endoftext|>


<commit_before>#include <QtGui>

#include <iostream>

#include "GLCamera.h"
#include "MainWindow.h"
#include "GLModelWidget.h"

#include <QFileDialog>
#include <QColorDialog>

MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent)
{
    // Windows
    m_glModelWidget = new GLModelWidget;
    setCentralWidget(m_glModelWidget);

    // The docking palette
    m_paletteDocker = new QDockWidget(tr("Palette"), this);
    m_paletteDocker->setAllowedAreas(Qt::LeftDockWidgetArea | Qt::RightDockWidgetArea);
    m_paletteWidget = new PaletteWidget(this);
    m_paletteDocker->setWidget(m_paletteWidget);
    addDockWidget(Qt::RightDockWidgetArea, m_paletteDocker);

    // Connect some window signals together
    QObject::connect(m_paletteWidget, SIGNAL(activeColorChanged(Imath::Color4f)),
                     m_glModelWidget, SLOT(setActiveColor(Imath::Color4f)));
    QObject::connect(m_glModelWidget, SIGNAL(colorSampled(Imath::Color4f)),
                     m_paletteWidget, SLOT(setActiveColor(Imath::Color4f)));

    // Toolbar
    m_toolbar = new QToolBar("Tools", this);
    m_toolbar->setOrientation(Qt::Vertical);
    addToolBar(Qt::LeftToolBarArea, m_toolbar);

    // Actions & Menus
    menuBar()->show();
    m_menuFile = menuBar()->addMenu("Fi&le");

    m_actFileNew = new QAction("&New", this);
    m_actFileNew->setShortcut(Qt::CTRL + Qt::Key_N);
    m_menuFile->addAction(m_actFileNew);
    connect(m_actFileNew, SIGNAL(triggered()),
            this, SLOT(newGrid()));

    m_menuFile->addSeparator();

    m_actFileOpen = new QAction("&Open", this);
    m_actFileOpen->setShortcut(Qt::CTRL + Qt::Key_O);
    m_menuFile->addAction(m_actFileOpen);
    connect(m_actFileOpen, SIGNAL(triggered()),
            this, SLOT(openFile()));

    m_actFileSave = new QAction("&Save", this);
    m_actFileSave->setShortcut(Qt::CTRL + Qt::Key_S);
    m_menuFile->addAction(m_actFileSave);
    connect(m_actFileSave, SIGNAL(triggered()),
            this, SLOT(saveFile()));

    m_menuFile->addSeparator();

    m_actQuit = new QAction("&Quit", this);
    m_actQuit->setShortcut(Qt::CTRL + Qt::Key_Q);
    m_menuFile->addAction(m_actQuit);
    connect(m_actQuit, SIGNAL(triggered()),
            qApp, SLOT(quit()));

    // ------ edit menu
    m_menuEdit = menuBar()->addMenu("&Edit");

    m_actUndo = new QAction("Undo", this);
    m_actUndo->setShortcut(Qt::CTRL + Qt::Key_Z);
    m_menuEdit->addAction(m_actUndo);
    connect(m_actUndo, SIGNAL(triggered()),
            m_glModelWidget, SLOT(undo()));

    m_actRedo = new QAction("Redo", this);
    m_actRedo->setShortcut(Qt::CTRL + Qt::SHIFT + Qt::Key_Z);
    m_menuEdit->addAction(m_actRedo);
    connect(m_actRedo, SIGNAL(triggered()),
            m_glModelWidget, SLOT(redo()));

    m_menuEdit->addSeparator();

    m_actShiftUp = new QAction("Shift up", this);
    m_actShiftUp->setShortcut(Qt::CTRL + Qt::Key_BracketRight);
    m_menuEdit->addAction(m_actShiftUp);
    connect(m_actShiftUp, SIGNAL(triggered()),
            this, SLOT(shiftUp()));

    m_actShiftDown = new QAction("Shift down", this);
    m_actShiftDown->setShortcut(Qt::CTRL + Qt::Key_BracketLeft);
    m_menuEdit->addAction(m_actShiftDown);
    connect(m_actShiftDown, SIGNAL(triggered()),
            this, SLOT(shiftDown()));

    m_actShiftWrap = new QAction("Wrap shift ops", this);
    m_actShiftWrap->setCheckable(true);
    m_actShiftWrap->setChecked(m_glModelWidget->shiftWrap());
    m_menuEdit->addAction(m_actShiftWrap);
    connect(m_actShiftWrap, SIGNAL(toggled(bool)),
            m_glModelWidget, SLOT(setShiftWrap(bool)));

    m_menuEdit->addSeparator();

    m_actUpRes = new QAction("Double grid resolution", this);
    m_actUpRes->setShortcut(Qt::CTRL + Qt::Key_Plus);
    m_menuEdit->addAction(m_actUpRes);
    connect(m_actUpRes, SIGNAL(triggered()),
            this, SLOT(upRes()));

    m_actDownRes = new QAction("Half grid resolution", this);
    m_actDownRes->setShortcut(Qt::CTRL + Qt::Key_Minus);
    m_menuEdit->addAction(m_actDownRes);
    connect(m_actDownRes, SIGNAL(triggered()),
            this, SLOT(downRes()));

    // ------ view menu
    m_menuView = menuBar()->addMenu("&View");

    m_actViewGrid = new QAction("View Grid", this);
    m_actViewGrid->setShortcut(Qt::CTRL + Qt::Key_G);
    m_actViewGrid->setCheckable(true);
    m_actViewGrid->setChecked(m_glModelWidget->drawGrid());
    m_menuView->addAction(m_actViewGrid);
    connect(m_actViewGrid, SIGNAL(toggled(bool)),
            m_glModelWidget, SLOT(setDrawGrid(bool)));

    m_actViewVoxgrid = new QAction("Voxel Grid", this);
    m_actViewVoxgrid->setShortcut(Qt::Key_G);
    m_actViewVoxgrid->setCheckable(true);
    m_actViewVoxgrid->setChecked(m_glModelWidget->drawVoxelGrid());
    m_menuView->addAction(m_actViewVoxgrid);
    connect(m_actViewVoxgrid, SIGNAL(toggled(bool)),
            m_glModelWidget, SLOT(setDrawVoxelGrid(bool)));

    m_actViewBBox = new QAction("Bounding Box", this);
    m_actViewBBox->setShortcut(Qt::CTRL + Qt::Key_B);
    m_actViewBBox->setCheckable(true);
    m_actViewBBox->setChecked(m_glModelWidget->drawBoundingBox());
    m_menuView->addAction(m_actViewBBox);
    connect(m_actViewBBox, SIGNAL(toggled(bool)),
            m_glModelWidget, SLOT(setDrawBoundingBox(bool)));

    // ------ window menu
    m_menuWindow = menuBar()->addMenu("&Window");
    m_menuWindow->addAction(m_toolbar->toggleViewAction());
    m_menuWindow->addAction(m_paletteDocker->toggleViewAction());

    // ------ toolbar hookups
    m_toolbarActionGroup = new QActionGroup(this);

    m_actToolSplat = new QAction("Splat", m_toolbarActionGroup);
    m_actToolSplat->setIcon(QIcon(QPixmap(":/icons/splat.png")));
    m_actToolSplat->setCheckable(true);
    connect(m_actToolSplat, SIGNAL(toggled(bool)), this, SLOT(setToolSplat(bool)));

    m_actToolReplace = new QAction("Replace", m_toolbarActionGroup);
    m_actToolReplace->setIcon(QIcon(QPixmap(":/icons/pencil.png")));
    m_actToolReplace->setCheckable(true);
    connect(m_actToolReplace, SIGNAL(toggled(bool)), this, SLOT(setToolReplace(bool)));

    m_actToolFlood = new QAction("Flood", m_toolbarActionGroup);
    m_actToolFlood->setIcon(QIcon(QPixmap(":/icons/paintBucket.png")));
    m_actToolFlood->setCheckable(true);
    connect(m_actToolFlood, SIGNAL(toggled(bool)), this, SLOT(setToolFlood(bool)));

    m_actToolDropper = new QAction("Dropper", m_toolbarActionGroup);
    m_actToolDropper->setIcon(QIcon(QPixmap(":/icons/eyeDropper.png")));
    m_actToolDropper->setCheckable(true);
    connect(m_actToolDropper, SIGNAL(toggled(bool)), this, SLOT(setToolDropper(bool)));

    m_actToolEraser = new QAction("Eraser", m_toolbarActionGroup);
    m_actToolEraser->setIcon(QIcon(QPixmap(":/icons/eraser.png")));
    m_actToolEraser->setCheckable(true);
    connect(m_actToolEraser, SIGNAL(toggled(bool)), this, SLOT(setToolEraser(bool)));

    m_actToolSlab = new QAction("Slab", m_toolbarActionGroup);
    m_actToolSlab->setIcon(QIcon(QPixmap(":/icons/slab.png")));
    m_actToolSlab->setCheckable(true);
    connect(m_actToolSlab, SIGNAL(toggled(bool)), this, SLOT(setToolSlab(bool)));

    //m_actToolRay = new QAction("Ray", this);

    m_actToolSplat->setChecked(true);
    m_toolbar->addActions(m_toolbarActionGroup->actions());

    // Remaining verbosity
    setWindowTitle(tr("Sproxel " SPROXEL_VERSION));
    statusBar()->showMessage(tr("Ready"));
}

void MainWindow::keyPressEvent(QKeyEvent* event)
{
    const bool altDown = event->modifiers() & Qt::AltModifier;
    const bool ctrlDown = event->modifiers() & Qt::ControlModifier;
    //const bool shiftDown = event->modifiers() & Qt::ShiftModifier;

    if (altDown && event->key() == Qt::Key_X)
    {
        m_glModelWidget->setCurrentAxis(GLModelWidget::X_AXIS);
    }
    else if (altDown && event->key() == Qt::Key_Y)
    {
        m_glModelWidget->setCurrentAxis(GLModelWidget::Y_AXIS);
    }
    else if (altDown && event->key() == Qt::Key_Z)
    {
        m_glModelWidget->setCurrentAxis(GLModelWidget::Z_AXIS);
    }
    else if (ctrlDown && event->key() == Qt::Key_C)
    {
        QColor color = QColorDialog::getColor(Qt::white, this);
        m_paletteWidget->setActiveColor(Imath::Color4f((float)color.red()/255.0f,
                                                       (float)color.green()/255.0f,
                                                       (float)color.blue()/255.0f,
                                                       (float)color.alpha()/255.0f));
    }
    else if (ctrlDown && event->key() == Qt::Key_F)
    {
        // Frame the full extents no matter what
        m_glModelWidget->frame(true);
    }
    else if (event->key() == Qt::Key_F)
    {
        // Frame the data if it exists
        m_glModelWidget->frame(false);
    }
    else if (event->key() == Qt::Key_X)
    {
        m_paletteWidget->swapColors();
    }
    //else if (event->key() == Qt::Key_D)
    //{
    //    m_paletteWidget->setDefaultColors();
    //}

    else if (event->key() == Qt::Key_Q) m_actToolSplat->setChecked(true);
    else if (event->key() == Qt::Key_W) m_actToolReplace->setChecked(true);
    else if (event->key() == Qt::Key_E) m_actToolFlood->setChecked(true);
    else if (event->key() == Qt::Key_R) m_actToolDropper->setChecked(true);
    else if (event->key() == Qt::Key_T) m_actToolEraser->setChecked(true);
    else if (event->key() == Qt::Key_Y) m_actToolSlab->setChecked(true);

    else if (event->key() >= Qt::Key_Left && event->key() <= Qt::Key_PageDown)
    {
        m_glModelWidget->handleArrows(event);
    }
    else if (event->key() == Qt::Key_Space)
    {
        // It's okay to call setVoxelColor once on the model widget, but any more requires an internal wrapper
        m_glModelWidget->setVoxelColor(m_glModelWidget->activeVoxel(),
                                       m_glModelWidget->activeColor());
        m_glModelWidget->updateGL();
    }
    else if (event->key() == Qt::Key_Delete)
    {
        // It's okay to call setVoxelColor once on the model widget, but any more requires an internal wrapper
        m_glModelWidget->setVoxelColor(m_glModelWidget->activeVoxel(),
                                       Imath::Color4f(0.0f, 0.0f, 0.0f, 0.0f));
        m_glModelWidget->updateGL();
    }
}

void MainWindow::newGrid()
{
    NewGridDialog dlg(this);

    dlg.setModal(true);
    if (dlg.exec())
    {
        m_glModelWidget->resizeVoxelGrid(dlg.getVoxelSize());
    }
}

void MainWindow::saveFile()
{
    QString filename = QFileDialog::getSaveFileName(this,
        tr("Save voxels (CSV format) file as..."),
        QString(""),
        tr("CSV Files (*.csv)"));
    if (!filename.isEmpty())
    {
        m_glModelWidget->saveGridCSV(filename.toStdString());
    }
}

void MainWindow::openFile()
{
    QString filename = QFileDialog::getOpenFileName(this,
        tr("Select CSV file to Open..."),
        QString(),
        tr("CSV Files (*.csv)"));
    if (!filename.isEmpty())
    {
        m_glModelWidget->loadGridCSV(filename.toStdString());
    }
}

// Trampoline functions because QSignalMapper can't do complex args
// Search for QBoundMethod for a custom approach, but I'm too lazy to include it for now.
void MainWindow::shiftUp()
{
    m_glModelWidget->shiftVoxels(m_glModelWidget->currentAxis(), true, m_glModelWidget->shiftWrap());
}
void MainWindow::shiftDown()
{
    m_glModelWidget->shiftVoxels(m_glModelWidget->currentAxis(), false, m_glModelWidget->shiftWrap());
}

void MainWindow::upRes()   { m_glModelWidget->reresVoxelGrid(2.0f); }
void MainWindow::downRes() { m_glModelWidget->reresVoxelGrid(0.5f); }

void MainWindow::setToolSplat(bool stat)   { if (stat) m_glModelWidget->setActiveTool(GLModelWidget::TOOL_SPLAT); }
void MainWindow::setToolFlood(bool stat)   { if (stat) m_glModelWidget->setActiveTool(GLModelWidget::TOOL_FLOOD); }
void MainWindow::setToolRay(bool stat)     { if (stat) m_glModelWidget->setActiveTool(GLModelWidget::TOOL_RAY); }
void MainWindow::setToolDropper(bool stat) { if (stat) m_glModelWidget->setActiveTool(GLModelWidget::TOOL_DROPPER); }
void MainWindow::setToolEraser(bool stat)  { if (stat) m_glModelWidget->setActiveTool(GLModelWidget::TOOL_ERASER); }
void MainWindow::setToolReplace(bool stat) { if (stat) m_glModelWidget->setActiveTool(GLModelWidget::TOOL_REPLACE); }
void MainWindow::setToolSlab(bool stat)    { if (stat) m_glModelWidget->setActiveTool(GLModelWidget::TOOL_SLAB); }

// // Steal keypresses from your children!
// bool MainWindow::eventFilter(QObject* qo, QEvent* ev)
// {
//     if (ev->type() != QEvent::KeyPress) return false;
//     keyPressEvent(dynamic_cast<QKeyEvent*>(ev));
//     return true;
// }

<commit_msg>References where the icons came from.<commit_after>#include <QtGui>

#include <iostream>

#include "GLCamera.h"
#include "MainWindow.h"
#include "GLModelWidget.h"

#include <QFileDialog>
#include <QColorDialog>

MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent)
{
    // Windows
    m_glModelWidget = new GLModelWidget;
    setCentralWidget(m_glModelWidget);

    // The docking palette
    m_paletteDocker = new QDockWidget(tr("Palette"), this);
    m_paletteDocker->setAllowedAreas(Qt::LeftDockWidgetArea | Qt::RightDockWidgetArea);
    m_paletteWidget = new PaletteWidget(this);
    m_paletteDocker->setWidget(m_paletteWidget);
    addDockWidget(Qt::RightDockWidgetArea, m_paletteDocker);

    // Connect some window signals together
    QObject::connect(m_paletteWidget, SIGNAL(activeColorChanged(Imath::Color4f)),
                     m_glModelWidget, SLOT(setActiveColor(Imath::Color4f)));
    QObject::connect(m_glModelWidget, SIGNAL(colorSampled(Imath::Color4f)),
                     m_paletteWidget, SLOT(setActiveColor(Imath::Color4f)));

    // Toolbar
    m_toolbar = new QToolBar("Tools", this);
    m_toolbar->setOrientation(Qt::Vertical);
    addToolBar(Qt::LeftToolBarArea, m_toolbar);

    // Actions & Menus
    menuBar()->show();
    m_menuFile = menuBar()->addMenu("Fi&le");

    m_actFileNew = new QAction("&New", this);
    m_actFileNew->setShortcut(Qt::CTRL + Qt::Key_N);
    m_menuFile->addAction(m_actFileNew);
    connect(m_actFileNew, SIGNAL(triggered()),
            this, SLOT(newGrid()));

    m_menuFile->addSeparator();

    m_actFileOpen = new QAction("&Open", this);
    m_actFileOpen->setShortcut(Qt::CTRL + Qt::Key_O);
    m_menuFile->addAction(m_actFileOpen);
    connect(m_actFileOpen, SIGNAL(triggered()),
            this, SLOT(openFile()));

    m_actFileSave = new QAction("&Save", this);
    m_actFileSave->setShortcut(Qt::CTRL + Qt::Key_S);
    m_menuFile->addAction(m_actFileSave);
    connect(m_actFileSave, SIGNAL(triggered()),
            this, SLOT(saveFile()));

    m_menuFile->addSeparator();

    m_actQuit = new QAction("&Quit", this);
    m_actQuit->setShortcut(Qt::CTRL + Qt::Key_Q);
    m_menuFile->addAction(m_actQuit);
    connect(m_actQuit, SIGNAL(triggered()),
            qApp, SLOT(quit()));

    // ------ edit menu
    m_menuEdit = menuBar()->addMenu("&Edit");

    m_actUndo = new QAction("Undo", this);
    m_actUndo->setShortcut(Qt::CTRL + Qt::Key_Z);
    m_menuEdit->addAction(m_actUndo);
    connect(m_actUndo, SIGNAL(triggered()),
            m_glModelWidget, SLOT(undo()));

    m_actRedo = new QAction("Redo", this);
    m_actRedo->setShortcut(Qt::CTRL + Qt::SHIFT + Qt::Key_Z);
    m_menuEdit->addAction(m_actRedo);
    connect(m_actRedo, SIGNAL(triggered()),
            m_glModelWidget, SLOT(redo()));

    m_menuEdit->addSeparator();

    m_actShiftUp = new QAction("Shift up", this);
    m_actShiftUp->setShortcut(Qt::CTRL + Qt::Key_BracketRight);
    m_menuEdit->addAction(m_actShiftUp);
    connect(m_actShiftUp, SIGNAL(triggered()),
            this, SLOT(shiftUp()));

    m_actShiftDown = new QAction("Shift down", this);
    m_actShiftDown->setShortcut(Qt::CTRL + Qt::Key_BracketLeft);
    m_menuEdit->addAction(m_actShiftDown);
    connect(m_actShiftDown, SIGNAL(triggered()),
            this, SLOT(shiftDown()));

    m_actShiftWrap = new QAction("Wrap shift ops", this);
    m_actShiftWrap->setCheckable(true);
    m_actShiftWrap->setChecked(m_glModelWidget->shiftWrap());
    m_menuEdit->addAction(m_actShiftWrap);
    connect(m_actShiftWrap, SIGNAL(toggled(bool)),
            m_glModelWidget, SLOT(setShiftWrap(bool)));

    m_menuEdit->addSeparator();

    m_actUpRes = new QAction("Double grid resolution", this);
    m_actUpRes->setShortcut(Qt::CTRL + Qt::Key_Plus);
    m_menuEdit->addAction(m_actUpRes);
    connect(m_actUpRes, SIGNAL(triggered()),
            this, SLOT(upRes()));

    m_actDownRes = new QAction("Half grid resolution", this);
    m_actDownRes->setShortcut(Qt::CTRL + Qt::Key_Minus);
    m_menuEdit->addAction(m_actDownRes);
    connect(m_actDownRes, SIGNAL(triggered()),
            this, SLOT(downRes()));

    // ------ view menu
    m_menuView = menuBar()->addMenu("&View");

    m_actViewGrid = new QAction("View Grid", this);
    m_actViewGrid->setShortcut(Qt::CTRL + Qt::Key_G);
    m_actViewGrid->setCheckable(true);
    m_actViewGrid->setChecked(m_glModelWidget->drawGrid());
    m_menuView->addAction(m_actViewGrid);
    connect(m_actViewGrid, SIGNAL(toggled(bool)),
            m_glModelWidget, SLOT(setDrawGrid(bool)));

    m_actViewVoxgrid = new QAction("Voxel Grid", this);
    m_actViewVoxgrid->setShortcut(Qt::Key_G);
    m_actViewVoxgrid->setCheckable(true);
    m_actViewVoxgrid->setChecked(m_glModelWidget->drawVoxelGrid());
    m_menuView->addAction(m_actViewVoxgrid);
    connect(m_actViewVoxgrid, SIGNAL(toggled(bool)),
            m_glModelWidget, SLOT(setDrawVoxelGrid(bool)));

    m_actViewBBox = new QAction("Bounding Box", this);
    m_actViewBBox->setShortcut(Qt::CTRL + Qt::Key_B);
    m_actViewBBox->setCheckable(true);
    m_actViewBBox->setChecked(m_glModelWidget->drawBoundingBox());
    m_menuView->addAction(m_actViewBBox);
    connect(m_actViewBBox, SIGNAL(toggled(bool)),
            m_glModelWidget, SLOT(setDrawBoundingBox(bool)));

    // ------ window menu
    m_menuWindow = menuBar()->addMenu("&Window");
    m_menuWindow->addAction(m_toolbar->toggleViewAction());
    m_menuWindow->addAction(m_paletteDocker->toggleViewAction());

    // ------ toolbar hookups
	// Icons from the brilliant icon pack located at : http://pen-art.ru/
    m_toolbarActionGroup = new QActionGroup(this);

    m_actToolSplat = new QAction("Splat", m_toolbarActionGroup);
    m_actToolSplat->setIcon(QIcon(QPixmap(":/icons/splat.png")));
    m_actToolSplat->setCheckable(true);
    connect(m_actToolSplat, SIGNAL(toggled(bool)), this, SLOT(setToolSplat(bool)));

    m_actToolReplace = new QAction("Replace", m_toolbarActionGroup);
    m_actToolReplace->setIcon(QIcon(QPixmap(":/icons/pencil.png")));
    m_actToolReplace->setCheckable(true);
    connect(m_actToolReplace, SIGNAL(toggled(bool)), this, SLOT(setToolReplace(bool)));

    m_actToolFlood = new QAction("Flood", m_toolbarActionGroup);
    m_actToolFlood->setIcon(QIcon(QPixmap(":/icons/paintBucket.png")));
    m_actToolFlood->setCheckable(true);
    connect(m_actToolFlood, SIGNAL(toggled(bool)), this, SLOT(setToolFlood(bool)));

    m_actToolDropper = new QAction("Dropper", m_toolbarActionGroup);
    m_actToolDropper->setIcon(QIcon(QPixmap(":/icons/eyeDropper.png")));
    m_actToolDropper->setCheckable(true);
    connect(m_actToolDropper, SIGNAL(toggled(bool)), this, SLOT(setToolDropper(bool)));

    m_actToolEraser = new QAction("Eraser", m_toolbarActionGroup);
    m_actToolEraser->setIcon(QIcon(QPixmap(":/icons/eraser.png")));
    m_actToolEraser->setCheckable(true);
    connect(m_actToolEraser, SIGNAL(toggled(bool)), this, SLOT(setToolEraser(bool)));

    m_actToolSlab = new QAction("Slab", m_toolbarActionGroup);
    m_actToolSlab->setIcon(QIcon(QPixmap(":/icons/slab.png")));
    m_actToolSlab->setCheckable(true);
    connect(m_actToolSlab, SIGNAL(toggled(bool)), this, SLOT(setToolSlab(bool)));

    //m_actToolRay = new QAction("Ray", this);

    m_actToolSplat->setChecked(true);
    m_toolbar->addActions(m_toolbarActionGroup->actions());

    // Remaining verbosity
    setWindowTitle(tr("Sproxel " SPROXEL_VERSION));
    statusBar()->showMessage(tr("Ready"));
}

void MainWindow::keyPressEvent(QKeyEvent* event)
{
    const bool altDown = event->modifiers() & Qt::AltModifier;
    const bool ctrlDown = event->modifiers() & Qt::ControlModifier;
    //const bool shiftDown = event->modifiers() & Qt::ShiftModifier;

    if (altDown && event->key() == Qt::Key_X)
    {
        m_glModelWidget->setCurrentAxis(GLModelWidget::X_AXIS);
    }
    else if (altDown && event->key() == Qt::Key_Y)
    {
        m_glModelWidget->setCurrentAxis(GLModelWidget::Y_AXIS);
    }
    else if (altDown && event->key() == Qt::Key_Z)
    {
        m_glModelWidget->setCurrentAxis(GLModelWidget::Z_AXIS);
    }
    else if (ctrlDown && event->key() == Qt::Key_C)
    {
        QColor color = QColorDialog::getColor(Qt::white, this);
        m_paletteWidget->setActiveColor(Imath::Color4f((float)color.red()/255.0f,
                                                       (float)color.green()/255.0f,
                                                       (float)color.blue()/255.0f,
                                                       (float)color.alpha()/255.0f));
    }
    else if (ctrlDown && event->key() == Qt::Key_F)
    {
        // Frame the full extents no matter what
        m_glModelWidget->frame(true);
    }
    else if (event->key() == Qt::Key_F)
    {
        // Frame the data if it exists
        m_glModelWidget->frame(false);
    }
    else if (event->key() == Qt::Key_X)
    {
        m_paletteWidget->swapColors();
    }
    //else if (event->key() == Qt::Key_D)
    //{
    //    m_paletteWidget->setDefaultColors();
    //}

    else if (event->key() == Qt::Key_Q) m_actToolSplat->setChecked(true);
    else if (event->key() == Qt::Key_W) m_actToolReplace->setChecked(true);
    else if (event->key() == Qt::Key_E) m_actToolFlood->setChecked(true);
    else if (event->key() == Qt::Key_R) m_actToolDropper->setChecked(true);
    else if (event->key() == Qt::Key_T) m_actToolEraser->setChecked(true);
    else if (event->key() == Qt::Key_Y) m_actToolSlab->setChecked(true);

    else if (event->key() >= Qt::Key_Left && event->key() <= Qt::Key_PageDown)
    {
        m_glModelWidget->handleArrows(event);
    }
    else if (event->key() == Qt::Key_Space)
    {
        // It's okay to call setVoxelColor once on the model widget, but any more requires an internal wrapper
        m_glModelWidget->setVoxelColor(m_glModelWidget->activeVoxel(),
                                       m_glModelWidget->activeColor());
        m_glModelWidget->updateGL();
    }
    else if (event->key() == Qt::Key_Delete)
    {
        // It's okay to call setVoxelColor once on the model widget, but any more requires an internal wrapper
        m_glModelWidget->setVoxelColor(m_glModelWidget->activeVoxel(),
                                       Imath::Color4f(0.0f, 0.0f, 0.0f, 0.0f));
        m_glModelWidget->updateGL();
    }
}

void MainWindow::newGrid()
{
    NewGridDialog dlg(this);

    dlg.setModal(true);
    if (dlg.exec())
    {
        m_glModelWidget->resizeVoxelGrid(dlg.getVoxelSize());
    }
}

void MainWindow::saveFile()
{
    QString filename = QFileDialog::getSaveFileName(this,
        tr("Save voxels (CSV format) file as..."),
        QString(""),
        tr("CSV Files (*.csv)"));
    if (!filename.isEmpty())
    {
        m_glModelWidget->saveGridCSV(filename.toStdString());
    }
}

void MainWindow::openFile()
{
    QString filename = QFileDialog::getOpenFileName(this,
        tr("Select CSV file to Open..."),
        QString(),
        tr("CSV Files (*.csv)"));
    if (!filename.isEmpty())
    {
        m_glModelWidget->loadGridCSV(filename.toStdString());
    }
}

// Trampoline functions because QSignalMapper can't do complex args
// Search for QBoundMethod for a custom approach, but I'm too lazy to include it for now.
void MainWindow::shiftUp()
{
    m_glModelWidget->shiftVoxels(m_glModelWidget->currentAxis(), true, m_glModelWidget->shiftWrap());
}
void MainWindow::shiftDown()
{
    m_glModelWidget->shiftVoxels(m_glModelWidget->currentAxis(), false, m_glModelWidget->shiftWrap());
}

void MainWindow::upRes()   { m_glModelWidget->reresVoxelGrid(2.0f); }
void MainWindow::downRes() { m_glModelWidget->reresVoxelGrid(0.5f); }

void MainWindow::setToolSplat(bool stat)   { if (stat) m_glModelWidget->setActiveTool(GLModelWidget::TOOL_SPLAT); }
void MainWindow::setToolFlood(bool stat)   { if (stat) m_glModelWidget->setActiveTool(GLModelWidget::TOOL_FLOOD); }
void MainWindow::setToolRay(bool stat)     { if (stat) m_glModelWidget->setActiveTool(GLModelWidget::TOOL_RAY); }
void MainWindow::setToolDropper(bool stat) { if (stat) m_glModelWidget->setActiveTool(GLModelWidget::TOOL_DROPPER); }
void MainWindow::setToolEraser(bool stat)  { if (stat) m_glModelWidget->setActiveTool(GLModelWidget::TOOL_ERASER); }
void MainWindow::setToolReplace(bool stat) { if (stat) m_glModelWidget->setActiveTool(GLModelWidget::TOOL_REPLACE); }
void MainWindow::setToolSlab(bool stat)    { if (stat) m_glModelWidget->setActiveTool(GLModelWidget::TOOL_SLAB); }

// // Steal keypresses from your children!
// bool MainWindow::eventFilter(QObject* qo, QEvent* ev)
// {
//     if (ev->type() != QEvent::KeyPress) return false;
//     keyPressEvent(dynamic_cast<QKeyEvent*>(ev));
//     return true;
// }

<|endoftext|>


<commit_before>/****************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the Qt Mobility Components.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial Usage
** Licensees holding valid Qt Commercial licenses may use this file in
** accordance with the Qt Solutions 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.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights.  These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3.0 as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU General Public License version 3.0 requirements will be
** met: http://www.gnu.org/copyleft/gpl.html.
**
** Please note Third Party Software included with Qt Solutions may impose
** additional restrictions and it is the user's responsibility to ensure
** that they have met the licensing requirements of the GPL, LGPL, or Qt
** Solutions Commercial license and the relevant license of the Third
** Party Software they are using.
**
** If you are unsure which license is appropriate for your use, please
** contact the sales department at qt-sales@nokia.com.
** $QT_END_LICENSE$
**
****************************************************************************/

#include <QApplication>
#include <QMainWindow>
#include <QDeclarativeView>
#include <QDeclarativeContext>
#include "buzzer.h"

int main(int argc, char *argv[])
{
    QApplication app(argc, argv);

    QMainWindow mw;
    QDeclarativeView *view = new QDeclarativeView(&mw);
    view->setResizeMode(QDeclarativeView::SizeRootObjectToView);
    view->rootContext()->setContextProperty("hapticplayer", new Buzzer);

    view->setSource(QUrl::fromLocalFile(":/hapticsquare.qml"));
    mw.setCentralWidget(view);
    mw.showMaximized();

    return app.exec();
}
<commit_msg>fix hapticsquare qml resource loading bug.<commit_after>/****************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the Qt Mobility Components.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial Usage
** Licensees holding valid Qt Commercial licenses may use this file in
** accordance with the Qt Solutions 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.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights.  These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3.0 as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU General Public License version 3.0 requirements will be
** met: http://www.gnu.org/copyleft/gpl.html.
**
** Please note Third Party Software included with Qt Solutions may impose
** additional restrictions and it is the user's responsibility to ensure
** that they have met the licensing requirements of the GPL, LGPL, or Qt
** Solutions Commercial license and the relevant license of the Third
** Party Software they are using.
**
** If you are unsure which license is appropriate for your use, please
** contact the sales department at qt-sales@nokia.com.
** $QT_END_LICENSE$
**
****************************************************************************/

#include <QApplication>
#include <QMainWindow>
#include <QDeclarativeView>
#include <QDeclarativeContext>
#include "buzzer.h"

int main(int argc, char *argv[])
{
    QApplication app(argc, argv);

    QMainWindow mw;
    QDeclarativeView *view = new QDeclarativeView(&mw);
    view->setResizeMode(QDeclarativeView::SizeRootObjectToView);
    view->rootContext()->setContextProperty("hapticplayer", new Buzzer);

    view->setSource(QUrl("qrc:hapticsquare.qml"));
    mw.setCentralWidget(view);
    mw.showMaximized();

    return app.exec();
}
<|endoftext|>


<commit_before>// Copyright 2008, Google Inc. All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
//  1. Redistributions of source code must retain the above copyright notice,
//     this list of conditions and the following disclaimer.
//  2. Redistributions in binary form must reproduce the above copyright notice,
//     this list of conditions and the following disclaimer in the documentation
//     and/or other materials provided with the distribution.
//  3. Neither the name of Google Inc. nor the names of its contributors may be
//     used to endorse or promote products derived from this software without
//     specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
// EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
// OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

#include "curlfetch.h"
#include <string>
#include <curl/curl.h>

using std::string;

// CURLOPT_WRITEFUNCTION:
// size*nmemb bytes of data are at ptr, stream is user data
// return must be size*nmemb or curl itself will fail.
static size_t FetchToString(void* ptr, size_t size, size_t nmemb, void* user) {
  // static function, only user is DoCurlToString which uses CURLOPT_WRITEDATA
  // to set the "user" arg which is the C++ string (buffer) to write to.
  assert(user);
  size_t nbytes = size * nmemb;
  string *output_buffer = reinterpret_cast<string*>(user);
  output_buffer->append(reinterpret_cast<char*>(ptr), nbytes);
  return nbytes;
}

// Separate worker function to simplify bool return logic.
static bool DoCurlToString(CURL* curl, const char* url, string* data) {
  CURLcode result;
#define CURLOK(f) (f == CURLE_OK)
  if (CURLOK(curl_easy_setopt(curl, CURLOPT_URL, url)) &&
      CURLOK(curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, FetchToString)) &&
      CURLOK(curl_easy_setopt(curl, CURLOPT_WRITEDATA,
                              reinterpret_cast<void*>(data))) &&
      CURLOK(curl_easy_perform(curl))) {
    return true;
  }
  return false;
}

// Wrapper to manage curl handle.  Very simple stateless implementation.  Less
// simplistic would be to reuse the CURL* handle between invocations.
bool CurlToString(const char* url, string* data) {
  CURL* curl = curl_easy_init();
  bool ret = DoCurlToString(curl, url, data);
  curl_easy_cleanup(curl);
  return ret;
}
<commit_msg>Remove the assert() from curlfetch.cc<commit_after>// Copyright 2008, Google Inc. All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
//  1. Redistributions of source code must retain the above copyright notice,
//     this list of conditions and the following disclaimer.
//  2. Redistributions in binary form must reproduce the above copyright notice,
//     this list of conditions and the following disclaimer in the documentation
//     and/or other materials provided with the distribution.
//  3. Neither the name of Google Inc. nor the names of its contributors may be
//     used to endorse or promote products derived from this software without
//     specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
// EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
// OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

#include "curlfetch.h"
#include <string>
#include <curl/curl.h>

using std::string;

// CURLOPT_WRITEFUNCTION:
// size*nmemb bytes of data are at ptr, stream is user data
// return must be size*nmemb or curl itself will fail.
static size_t FetchToString(void* ptr, size_t size, size_t nmemb, void* user) {
  // static function, only user is DoCurlToString which uses CURLOPT_WRITEDATA
  // to set the "user" arg which is the C++ string (buffer) to write to.
  size_t nbytes = size * nmemb;
  string *output_buffer = reinterpret_cast<string*>(user);
  output_buffer->append(reinterpret_cast<char*>(ptr), nbytes);
  return nbytes;
}

// Separate worker function to simplify bool return logic.
static bool DoCurlToString(CURL* curl, const char* url, string* data) {
  CURLcode result;
#define CURLOK(f) (f == CURLE_OK)
  if (CURLOK(curl_easy_setopt(curl, CURLOPT_URL, url)) &&
      CURLOK(curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, FetchToString)) &&
      CURLOK(curl_easy_setopt(curl, CURLOPT_WRITEDATA,
                              reinterpret_cast<void*>(data))) &&
      CURLOK(curl_easy_perform(curl))) {
    return true;
  }
  return false;
}

// Wrapper to manage curl handle.  Very simple stateless implementation.  Less
// simplistic would be to reuse the CURL* handle between invocations.
bool CurlToString(const char* url, string* data) {
  CURL* curl = curl_easy_init();
  bool ret = DoCurlToString(curl, url, data);
  curl_easy_cleanup(curl);
  return ret;
}
<|endoftext|>