<commit_before>/**
 * @file lsh_test.cpp
 *
 * Unit tests for the 'LSHSearch' class.
 */
#include <mlpack/core.hpp>
#include <mlpack/core/metrics/lmetric.hpp>
#include <boost/test/unit_test.hpp>
#include "old_boost_test_definitions.hpp"

#include <mlpack/methods/lsh/lsh_search.hpp>
#include <mlpack/methods/neighbor_search/neighbor_search.hpp>

using namespace std;
using namespace mlpack;
using namespace mlpack::neighbor;

double compute_recall(arma::Mat<size_t> LSHneighbors,
        arma::Mat<size_t> groundTruth)
{
  const int n_queries = LSHneighbors.n_cols;
  const int n_neigh = LSHneighbors.n_rows;

  int found_same = 0;
  for (int q = 0; q < n_queries; ++q)
  {
    for (int n = 0; n < n_neigh; ++n)
    {
      found_same+=(LSHneighbors(n,q)==groundTruth(n,q));
    }
  }
  return static_cast<double>(found_same)/
      (static_cast<double>(n_queries*n_neigh));
}

BOOST_AUTO_TEST_SUITE(LSHTest);

BOOST_AUTO_TEST_CASE(LSHSearchTest)
{

  math::RandomSeed(time(0));
  //kNN and LSH parameters (use LSH default parameters)
  const int k = 4;
  const int numTables = 30;
  const int numProj = 10;
  const double hashWidth = 0;
  const int secondHashSize = 99901;
  const int bucketSize = 500;

  //test parameters
  const double epsilon = 0.1;

  //read iris training and testing data as reference and query
  const string data_train="iris_train.csv";
  const string data_test="iris_test.csv";
  arma::mat rdata;
  arma::mat qdata;
  data::Load(data_train, rdata, true);
  data::Load(data_test, qdata, true);

  //Run classic knn on reference data
  AllkNN knn(rdata);
  arma::Mat<size_t> groundTruth;
  arma::mat groundDistances;
  knn.Search(qdata, k, groundTruth, groundDistances);

  //Test: Run LSH with varying number of tables, keeping all other parameters
  //constant. Compute the recall, i.e. the number of reported neighbors that
  //are real neighbors of the query.
  //LSH's property is that (with high probability), increasing the number of
  //tables will increase recall. Epsilon ensures that if noise lightly affects
  //the projections, the test will not fail.

  const int numTries = 5; //tries for each test before declaring failure
  bool fail = false;

  for (int t = 0; t < numTries; ++t){

    const int Lsize = 6; //number of runs
    const int L_value[] = {1, 8, 16, 32, 64, 128}; //number of tables
    double L_value_recall[Lsize] = {0.0}; //recall of each LSH run

    for (int l=0; l < Lsize; ++l)
    {
      //run LSH with only numTables varying (other values default)
      LSHSearch<> lsh_test1(rdata, numProj, L_value[l],
          hashWidth, secondHashSize, bucketSize);
      arma::Mat<size_t> LSHneighbors;
      arma::mat LSHdistances;
      lsh_test1.Search(qdata, k, LSHneighbors, LSHdistances);

      //compute recall for each query
      L_value_recall[l] = compute_recall(LSHneighbors, groundTruth);

      if (l > 0){
        if(L_value_recall[l] < L_value_recall[l-1]-epsilon){
          fail = true; //if test fails at one point, stop and retry
          break;
        }
      }
    }
    if ( !fail ){
      break; //if test passes one time, it is sufficient
    }
  }
  BOOST_CHECK(fail == false);

  //Test: Run LSH with varying hash width, keeping all other parameters
  //constant. Compute the recall, i.e. the number of reported neighbors that
  //are real neighbors of the query.
  //LSH's property is that (with high probability), increasing the hash width
  //will increase recall. Epsilon ensures that if noise lightly affects the
  //projections, the test will not fail.

  const int Hsize = 7; //number of runs
  const double H_value[] = {0.1, 0.5, 1, 5, 10, 50, 500}; //hash width
  double H_value_recall[Hsize] = {0.0}; //recall of each run

  for (int h=0; h < Hsize; ++h)
  {
    //run LSH with only hashWidth varying (other values default)
    LSHSearch<> lsh_test2(rdata, numProj, numTables,
            H_value[h], secondHashSize, bucketSize);
    arma::Mat<size_t> LSHneighbors;
    arma::mat LSHdistances;
    lsh_test2.Search(qdata, k, LSHneighbors, LSHdistances);

    //compute recall for each query
    H_value_recall[h] = compute_recall(LSHneighbors, groundTruth);

    if (h > 0)
        BOOST_CHECK(H_value_recall[h] >= H_value_recall[h-1]-epsilon);

  }

  //Test: Run LSH with varying number of Projections, keeping all other parameters
  //constant. Compute the recall, i.e. the number of reported neighbors that
  //are real neighbors of the query.
  //LSH's property is that (with high probability), increasing the number of
  //projections per table will decrease recall. Epsilon ensures that if noise lightly
  //affects the projections, the test will not fail.

  const int Psize = 5; //number of runs
  const int P_value[] = {1, 10, 20, 50, 100}; //number of projections
  double P_value_recall[Psize] = {0.0}; //recall of each run

  for (int p=0; p < Psize; ++p)
  {
    //run LSH with only numProj varying (other values default)
    LSHSearch<> lsh_test3(rdata, P_value[p], numTables,
            hashWidth, secondHashSize, bucketSize);
    arma::Mat<size_t> LSHneighbors;
    arma::mat LSHdistances;
    lsh_test3.Search(qdata, k, LSHneighbors, LSHdistances);

    //compute recall for each query
    P_value_recall[p] = compute_recall(LSHneighbors, groundTruth);

    if (p > 0) //don't check first run, only that increasing P decreases recall
        BOOST_CHECK(P_value_recall[p] - epsilon <= P_value_recall[p-1]);
  }

  //Test: Run a very expensive LSH search, with a large number of hash tables
  //and a large hash width. This run should return an acceptable recall. We set
  //the bar very low (recall >= 50%) to make sure that a test fail means bad
  //implementation.

  const int H_exp = 10000; //first-level hash width
  const int K_exp = 1; //projections per table
  const int T_exp = 128; //number of tables
  const double recall_thresh_exp = 0.5;

  LSHSearch<> lsh_test_exp(rdata, K_exp, T_exp, H_exp, secondHashSize, bucketSize);
  arma::Mat<size_t> LSHneighbors_exp;
  arma::mat LSHdistances_exp;
  lsh_test_exp.Search(qdata, k, LSHneighbors_exp, LSHdistances_exp);

  const double recall_exp = compute_recall(LSHneighbors_exp, groundTruth);

  BOOST_CHECK(recall_exp >= recall_thresh_exp);

  //Test: Run a very cheap LSH search, with parameters that should cause recall
  //to be very low. Set the threshhold very high (recall <= 25%) to make sure
  //that a test fail means bad implementation.
  //This mainly checks that user-specified parameters are not ignored.

  const int H_chp = 1; //small first-level hash width
  const int K_chp = 1000; //large number of projections per table
  const int T_chp = 1; //only one table
  const double recall_thresh_chp = 0.25; //recall threshold

  LSHSearch<> lsh_test_chp(rdata, K_chp, T_chp, H_chp, secondHashSize, bucketSize);
  arma::Mat<size_t> LSHneighbors_chp;
  arma::mat LSHdistances_chp;
  lsh_test_chp.Search(qdata, k, LSHneighbors_chp, LSHdistances_chp);

  const double recall_chp = compute_recall(LSHneighbors_chp, groundTruth);
  BOOST_CHECK(recall_chp <= recall_thresh_chp);
}

BOOST_AUTO_TEST_CASE(LSHTrainTest)
{
  // This is a not very good test that simply checks that the re-trained LSH
  // model operates on the correct dimensionality and returns the correct number
  // of results.
  arma::mat referenceData = arma::randu<arma::mat>(3, 100);
  arma::mat newReferenceData = arma::randu<arma::mat>(10, 400);
  arma::mat queryData = arma::randu<arma::mat>(10, 200);

  LSHSearch<> lsh(referenceData, 3, 2, 2.0, 11, 3);

  lsh.Train(newReferenceData, 4, 3, 3.0, 12, 4);

  arma::Mat<size_t> neighbors;
  arma::mat distances;

  lsh.Search(queryData, 3, neighbors, distances);

  BOOST_REQUIRE_EQUAL(neighbors.n_cols, 200);
  BOOST_REQUIRE_EQUAL(neighbors.n_rows, 3);
  BOOST_REQUIRE_EQUAL(distances.n_cols, 200);
  BOOST_REQUIRE_EQUAL(distances.n_rows, 3);
}

BOOST_AUTO_TEST_CASE(EmptyConstructorTest)
{
  // If we create an empty LSH model and then call Search(), it should throw an
  // exception.
  LSHSearch<> lsh;

  arma::mat dataset = arma::randu<arma::mat>(5, 50);
  arma::mat distances;
  arma::Mat<size_t> neighbors;
  BOOST_REQUIRE_THROW(lsh.Search(dataset, 2, neighbors, distances),
      std::invalid_argument);

  // Now, train.
  lsh.Train(dataset, 4, 3, 3.0, 12, 4);

  lsh.Search(dataset, 3, neighbors, distances);

  BOOST_REQUIRE_EQUAL(neighbors.n_cols, 50);
  BOOST_REQUIRE_EQUAL(neighbors.n_rows, 3);
  BOOST_REQUIRE_EQUAL(distances.n_cols, 50);
  BOOST_REQUIRE_EQUAL(distances.n_rows, 3);
}

BOOST_AUTO_TEST_SUITE_END();
<commit_msg>Style Fixes<commit_after>/**
 * @file lsh_test.cpp
 *
 * Unit tests for the 'LSHSearch' class.
 */
#include <mlpack/core.hpp>
#include <mlpack/core/metrics/lmetric.hpp>
#include <boost/test/unit_test.hpp>
#include "old_boost_test_definitions.hpp"

#include <mlpack/methods/lsh/lsh_search.hpp>
#include <mlpack/methods/neighbor_search/neighbor_search.hpp>

using namespace std;
using namespace mlpack;
using namespace mlpack::neighbor;

double compute_recall(
    arma::Mat<size_t> LSHneighbors,
    arma::Mat<size_t> groundTruth)
{
  const int n_queries = LSHneighbors.n_cols;
  const int n_neigh = LSHneighbors.n_rows;

  int found_same = 0;
  for (int q = 0; q < n_queries; ++q)
  {
    for (int n = 0; n < n_neigh; ++n)
    {
      found_same+=(LSHneighbors(n,q)==groundTruth(n,q));
    }
  }
  return static_cast<double>(found_same)/
    (static_cast<double>(n_queries*n_neigh));
}

BOOST_AUTO_TEST_SUITE(LSHTest);

BOOST_AUTO_TEST_CASE(LSHSearchTest)
{

  math::RandomSeed(time(0));
  //kNN and LSH parameters (use LSH default parameters)
  const int k = 4;
  const int numTables = 30;
  const int numProj = 10;
  const double hashWidth = 0;
  const int secondHashSize = 99901;
  const int bucketSize = 500;

  //test parameters
  const double epsilon = 0.1;

  //read iris training and testing data as reference and query
  const string data_train="iris_train.csv";
  const string data_test="iris_test.csv";
  arma::mat rdata;
  arma::mat qdata;
  data::Load(data_train, rdata, true);
  data::Load(data_test, qdata, true);

  //Run classic knn on reference data
  AllkNN knn(rdata);
  arma::Mat<size_t> groundTruth;
  arma::mat groundDistances;
  knn.Search(qdata, k, groundTruth, groundDistances);

  //Test: Run LSH with varying number of tables, keeping all other parameters
  //constant. Compute the recall, i.e. the number of reported neighbors that
  //are real neighbors of the query.
  //LSH's property is that (with high probability), increasing the number of
  //tables will increase recall. Epsilon ensures that if noise lightly affects
  //the projections, the test will not fail.

  const int numTries = 5; //tries for each test before declaring failure
  bool fail = false;

  for (int t = 0; t < numTries; ++t){

    const int Lsize = 6; //number of runs
    const int L_value[] = {1, 8, 16, 32, 64, 128}; //number of tables
    double L_value_recall[Lsize] = {0.0}; //recall of each LSH run

    for (int l=0; l < Lsize; ++l)
    {
      //run LSH with only numTables varying (other values default)
      LSHSearch<> lsh_test1(rdata, numProj, L_value[l],
          hashWidth, secondHashSize, bucketSize);
      arma::Mat<size_t> LSHneighbors;
      arma::mat LSHdistances;
      lsh_test1.Search(qdata, k, LSHneighbors, LSHdistances);

      //compute recall for each query
      L_value_recall[l] = compute_recall(LSHneighbors, groundTruth);

      if (l > 0){
        if(L_value_recall[l] < L_value_recall[l-1]-epsilon){
          fail = true; //if test fails at one point, stop and retry
          break;
        }
      }
    }
    if ( !fail ){
      break; //if test passes one time, it is sufficient
    }
  }
  BOOST_CHECK(fail == false);

  //Test: Run LSH with varying hash width, keeping all other parameters
  //constant. Compute the recall, i.e. the number of reported neighbors that
  //are real neighbors of the query.
  //LSH's property is that (with high probability), increasing the hash width
  //will increase recall. Epsilon ensures that if noise lightly affects the
  //projections, the test will not fail.

  const int Hsize = 7; //number of runs
  const double H_value[] = {0.1, 0.5, 1, 5, 10, 50, 500}; //hash width
  double H_value_recall[Hsize] = {0.0}; //recall of each run

  for (int h=0; h < Hsize; ++h)
  {
    //run LSH with only hashWidth varying (other values default)
    LSHSearch<> lsh_test2(rdata, numProj, numTables,
            H_value[h], secondHashSize, bucketSize);
    arma::Mat<size_t> LSHneighbors;
    arma::mat LSHdistances;
    lsh_test2.Search(qdata, k, LSHneighbors, LSHdistances);

    //compute recall for each query
    H_value_recall[h] = compute_recall(LSHneighbors, groundTruth);

    if (h > 0)
        BOOST_CHECK(H_value_recall[h] >= H_value_recall[h-1]-epsilon);

  }

  //Test: Run LSH with varying number of projections, keeping other parameters
  //constant. Compute the recall, i.e. the number of reported neighbors that
  //are real neighbors of the query.
  //LSH's property is that (with high probability), increasing the number of
  //projections per table will decrease recall. Epsilon ensures that if noise
  //lightly affects the projections, the test will not fail.

  const int Psize = 5; //number of runs
  const int P_value[] = {1, 10, 20, 50, 100}; //number of projections
  double P_value_recall[Psize] = {0.0}; //recall of each run

  for (int p=0; p < Psize; ++p)
  {
    //run LSH with only numProj varying (other values default)
    LSHSearch<> lsh_test3(rdata, P_value[p], numTables,
            hashWidth, secondHashSize, bucketSize);
    arma::Mat<size_t> LSHneighbors;
    arma::mat LSHdistances;
    lsh_test3.Search(qdata, k, LSHneighbors, LSHdistances);

    //compute recall for each query
    P_value_recall[p] = compute_recall(LSHneighbors, groundTruth);

    if (p > 0) //don't check first run, only that increasing P decreases recall
        BOOST_CHECK(P_value_recall[p] - epsilon <= P_value_recall[p-1]);
  }

  //Test: Run a very expensive LSH search, with a large number of hash tables
  //and a large hash width. This run should return an acceptable recall. We set
  //the bar very low (recall >= 50%) to make sure that a test fail means bad
  //implementation.

  const int H_exp = 10000; //first-level hash width
  const int K_exp = 1; //projections per table
  const int T_exp = 128; //number of tables
  const double recall_thresh_exp = 0.5;

  LSHSearch<> lsh_test_exp(
      rdata,
      K_exp,
      T_exp,
      H_exp,
      secondHashSize,
      bucketSize);
  arma::Mat<size_t> LSHneighbors_exp;
  arma::mat LSHdistances_exp;
  lsh_test_exp.Search(qdata, k, LSHneighbors_exp, LSHdistances_exp);

  const double recall_exp = compute_recall(LSHneighbors_exp, groundTruth);

  BOOST_CHECK(recall_exp >= recall_thresh_exp);

  //Test: Run a very cheap LSH search, with parameters that should cause recall
  //to be very low. Set the threshhold very high (recall <= 25%) to make sure
  //that a test fail means bad implementation.
  //This mainly checks that user-specified parameters are not ignored.

  const int H_chp = 1; //small first-level hash width
  const int K_chp = 1000; //large number of projections per table
  const int T_chp = 1; //only one table
  const double recall_thresh_chp = 0.25; //recall threshold

  LSHSearch<> lsh_test_chp(
      rdata,
      K_chp,
      T_chp,
      H_chp,
      secondHashSize,
      bucketSize);
  arma::Mat<size_t> LSHneighbors_chp;
  arma::mat LSHdistances_chp;
  lsh_test_chp.Search(qdata, k, LSHneighbors_chp, LSHdistances_chp);

  const double recall_chp = compute_recall(LSHneighbors_chp, groundTruth);
  BOOST_CHECK(recall_chp <= recall_thresh_chp);
}

BOOST_AUTO_TEST_CASE(LSHTrainTest)
{
  // This is a not very good test that simply checks that the re-trained LSH
  // model operates on the correct dimensionality and returns the correct number
  // of results.
  arma::mat referenceData = arma::randu<arma::mat>(3, 100);
  arma::mat newReferenceData = arma::randu<arma::mat>(10, 400);
  arma::mat queryData = arma::randu<arma::mat>(10, 200);

  LSHSearch<> lsh(referenceData, 3, 2, 2.0, 11, 3);

  lsh.Train(newReferenceData, 4, 3, 3.0, 12, 4);

  arma::Mat<size_t> neighbors;
  arma::mat distances;

  lsh.Search(queryData, 3, neighbors, distances);

  BOOST_REQUIRE_EQUAL(neighbors.n_cols, 200);
  BOOST_REQUIRE_EQUAL(neighbors.n_rows, 3);
  BOOST_REQUIRE_EQUAL(distances.n_cols, 200);
  BOOST_REQUIRE_EQUAL(distances.n_rows, 3);
}

BOOST_AUTO_TEST_CASE(EmptyConstructorTest)
{
  // If we create an empty LSH model and then call Search(), it should throw an
  // exception.
  LSHSearch<> lsh;

  arma::mat dataset = arma::randu<arma::mat>(5, 50);
  arma::mat distances;
  arma::Mat<size_t> neighbors;
  BOOST_REQUIRE_THROW(lsh.Search(dataset, 2, neighbors, distances),
      std::invalid_argument);

  // Now, train.
  lsh.Train(dataset, 4, 3, 3.0, 12, 4);

  lsh.Search(dataset, 3, neighbors, distances);

  BOOST_REQUIRE_EQUAL(neighbors.n_cols, 50);
  BOOST_REQUIRE_EQUAL(neighbors.n_rows, 3);
  BOOST_REQUIRE_EQUAL(distances.n_cols, 50);
  BOOST_REQUIRE_EQUAL(distances.n_rows, 3);
}

BOOST_AUTO_TEST_SUITE_END();
<|endoftext|>


<commit_before>#pragma once

#include <algorithm>
#include <array>
#include <cassert>
#include <cmath>

#include "mocc-core/global_config.hpp"

const int N = 100000;

namespace mocc {
    /**
     * Base class defining a class of simple utility classes for computing
     * exponential functions. The base version uses the stock library call to
     * exp(), while derived versions can override this with more efficient table
     * lookups.
     */
    class Exponential {
    public:
        Exponential():
            max_error_( 0.0 )
        { }

        inline virtual real_t exp( real_t v ) {
            return std::exp(v);
        }

        real_t max_error() {
            return max_error_;
        }

    protected:
        real_t max_error_;
    };

    class Exponential_Linear: public Exponential {
    public:
        Exponential_Linear():
            min_( -10.0 ),
            space_( -min_/(real_t)(N-1)),
            rspace_( 1.0/space_ )
        {
            for( int i=0; i<N; i++ ) {
                d_[i] = std::exp(min_+i*space_);
            }

            for( int i=0; i<N-1; i++ ) {
                real_t x = min_+space_*(0.5+i);
                real_t err = std::abs(this->exp(x) - std::exp(x));
                max_error_ = std::max( max_error_, err );
            }
        }

        inline real_t exp( real_t v ) {
            assert((v < 0.0) && (v >= min_));
            int i = (v-min_)*rspace_;
            v -= space_*i+min_;
            return d_[i] + (d_[i+1] - d_[i])*v*rspace_;
        }
    private:
        real_t min_;
        real_t space_;
        real_t rspace_;
        std::array<real_t, N> d_;
    };
}
<commit_msg>Add contingency for out-of-bounds exponentials<commit_after>#pragma once

#include <algorithm>
#include <array>
#include <cassert>
#include <cmath>

#include "mocc-core/global_config.hpp"

const int N = 10000;

namespace mocc {
    /**
     * Base class defining a class of simple utility classes for computing
     * exponential functions. The base version uses the stock library call to
     * exp(), while derived versions can override this with more efficient table
     * lookups.
     */
    class Exponential {
    public:
        Exponential():
            max_error_( 0.0 )
        { }

        inline virtual real_t exp( real_t v ) {
            return std::exp(v);
        }

        real_t max_error() {
            return max_error_;
        }

    protected:
        real_t max_error_;
    };

    class Exponential_Linear: public Exponential {
    public:
        Exponential_Linear():
            min_( -10.0 ),
            space_( -min_/(real_t)(N-1)),
            rspace_( 1.0/space_ )
        {
            for( int i=0; i<N; i++ ) {
                d_[i] = std::exp(min_+i*space_);
            }

            for( int i=0; i<N-1; i++ ) {
                real_t x = min_+space_*(0.5+i);
                real_t err = std::abs(this->exp(x) - std::exp(x));
                max_error_ = std::max( max_error_, err );
            }
        }

        inline real_t exp( real_t v ) {
            assert((v < 0.0));
            if( v < min_ ) {
                std::cout << "Big exponential argument: " << v << std::endl;
                return std::exp(v);
            }
            int i = (v-min_)*rspace_;
            v -= space_*i+min_;
            return d_[i] + (d_[i+1] - d_[i])*v*rspace_;
        }
    private:
        real_t min_;
        real_t space_;
        real_t rspace_;
        std::array<real_t, N> d_;
    };
}
<|endoftext|>


<commit_before>#include "moc_sweeper.hpp"

#include <iomanip>
#include "error.hpp"

using std::endl;
using std::cout;
using std::cin;

mocc::VecF temp;

namespace mocc {

    MoCSweeper::MoCSweeper( const pugi::xml_node& input,
            const CoreMesh& mesh ):
        TransportSweeper( mesh ),
        mesh_( mesh ),
        ang_quad_( input.child("ang_quad") ),
        rays_( input.child("rays"), ang_quad_, mesh ),
        xstr_( n_reg_, 1 ),
        flux_1g_( n_reg_, 1 ),
        qbar_( n_reg_, 1 ),
        bc_type_( mesh_.boundary() )
    {
        // Make sure we have input from the XML
        if( input.empty() ) {
            Error("No input specified to initialize MoC sweeper.");
        }

        // Parse the number of inner iterations
        int int_in = input.attribute("n_inner").as_int(-1);
        if(int_in < 0) {
            Error("Invalid number of inner iterations specified (n_inner).");
        }
        n_inner_ = int_in;

        // Set up the array of volumes (surface area)
        int ireg = 0;
        for( auto &pin: mesh_ ) {
            const VecF& pin_vols = pin->vols();
            for( auto &v: pin_vols ) {
                vol_(ireg) = v;
                ireg++;
            }
        }

        // allocate space to store the boundary conditions
        boundary_.resize( ng_ );
        for( auto &group_rays: boundary_ ) {
            group_rays.resize( mesh_.nz() );
            for( auto &angle_rays: group_rays ) {
                // We actually allocate BCs for all 4 octants to make things a
                // little simpler.
                angle_rays.resize( ang_quad_.ndir_oct()*4 );
                int iang = 0;
                for( auto ang_it=ang_quad_.octant(1);
                        ang_it!=ang_quad_.octant(5); ang_it++ ) {
                    angle_rays[iang].resize(rays_.n_rays(iang));
                    iang++;
                }
            }
        }
        boundary_out_.resize( mesh_.nz() );
        for( auto &angle_rays: boundary_out_ ) {
            // We actually allocate BCs for all 4 octants to make things a
            // little simpler.
            angle_rays.resize( ang_quad_.ndir_oct()*4 );
            int iang = 0;
            for( auto ang_it=ang_quad_.octant(1);
                    ang_it!=ang_quad_.octant(5); ang_it++ ) {
                angle_rays[iang].resize(rays_.n_rays(iang));
                iang++;
            }
        }

        return;
    }

    void MoCSweeper::sweep( int group ) {
        assert(source_);

        // set up the xstr_ array
        for( auto &xsr: *xs_mesh_ ) {
            real_t xstr = xsr.xsmactr()[group];
            for( auto &ireg: xsr.reg() ) {
                xstr_(ireg) = xstr;
            }
        }

        flux_1g_ = flux_.col( group );

        // Perform inner iterations
        for( unsigned int inner=0; inner<n_inner_; inner++ ) {
            // update the self-scattering source
            source_->self_scatter( group, flux_1g_, qbar_ );
            // Perform the stock sweep unless we are on the last outer and have
            // a CoarseData object.
            if( inner == n_inner_-1 && coarse_data_ ) {
                this->sweep1g_final( group );
            } else {
                this->sweep1g( group );
            }
        }

        flux_.col( group ) = flux_1g_;

        return;
    }

    void MoCSweeper::update_boundary( int group ) {
        int iplane=0;
        for( auto &plane_bcs: boundary_[group] ) {
            for( unsigned int iang=0; iang<plane_bcs.size(); iang++ ) {
                int nx = rays_.nx(iang);
                int ny = rays_.ny(iang);

                // Determine based on the angle quadrant which surfaces are
                // upwind and need to be updated for the given angle
                Surface upwind[2];
                if(ang_quad_[iang].ox > 0.0) {
                    upwind[0] = Surface::WEST;
                } else {
                    upwind[0] = Surface::EAST;
                }
                if(ang_quad_[iang].oy > 0.0) {
                    upwind[1] = Surface::SOUTH;
                } else {
                    upwind[1] = Surface::NORTH;
                }

                // Treat the two surfaces that were determined above
                if( bc_type_[(int)upwind[0]] == Boundary::REFLECT ) {
                    int ang_ref = ang_quad_.reflect(iang, upwind[0]);
                    for( int ibc=0; ibc<ny; ibc++ ) {
                        plane_bcs[iang][ibc] =
                            boundary_out_[iplane][ang_ref][ibc];
                    }
                } else {
                    for( int ibc=0; ibc<ny; ibc++ ) {
                        plane_bcs[iang][ibc] = 0.0;
                    }
                }

                if( bc_type_[(int)upwind[1]] == Boundary::REFLECT ) {
                    int ang_ref = ang_quad_.reflect(iang, upwind[1]);
                    for( int ibc=ny; ibc<(nx+ny); ibc++ ) {
                        plane_bcs[iang][ibc] =
                            boundary_out_[iplane][ang_ref][ibc];
                    }
                } else {
                    for( int ibc=ny; ibc<(nx+ny); ibc++ ) {
                        plane_bcs[iang][ibc] = 0.0;
                    }
                }
            } // angle loop
            iplane++;
        } // plane loop
    }

    void MoCSweeper::initialize() {
        // There are better ways to do this, but for now, just start with 1.0
        flux_.fill(1.0);

        // Walk through the boundary conditions and initialize them the 1/4pi
        real_t val = 1.0/FPI;
        for( auto &group_rays: boundary_ ) {
            for( auto &plane_rays: group_rays ) {
                for( auto &angle_rays: plane_rays ) {
                    for( auto &ray: angle_rays ) {
                        ray = val;
                    }
                }
            }
        }
        return;
    }

    void MoCSweeper::homogenize( CoarseData &data ) const {

        return;
    }

    void MoCSweeper::get_pin_flux( int group, VecF& flux ) const {
        flux.resize( mesh_.n_pin() );
        for( auto &f: flux ) {
            f = 0.0;
        }

        int ireg = 0;
        int ipin = 0;
        for( auto &pin: mesh_ ) {
            Position pos = mesh_.pin_position(ipin);
            int i = mesh_.index_lex(pos);
            real_t v = 0.0;
            for( int ir=0; ir<pin->n_reg(); ir++) {
                v += vol_(ireg);
                flux[i] += flux_(ireg, group)*vol_(ireg);
                ireg++;
            }
            flux[i] /= v;
            ipin++;
        }

        return;
    }

    void MoCSweeper::output( H5File& file ) const {
        // Get core dimensions from the mesh
        const int nx = mesh_.nx();
        const int ny = mesh_.ny();
        const int nz = mesh_.nz();
        VecI dims;
        dims.push_back(nz);
        dims.push_back(ny);
        dims.push_back(nx);

        // Make a group in the file to store the flux
        file.mkdir("/flux");

        // Provide energy group upper bounds
        file.write("/eubounds", xs_mesh_->eubounds(), VecI(1, ng_));
        file.write("/ng", ng_);

        for( unsigned int ig=0; ig<ng_; ig++ ) {
            VecF flux;
            this->get_pin_flux(ig, flux);

            std::stringstream setname;
            setname << "/flux/" << std::setfill('0') << std::setw(3) << ig+1;

            file.write(setname.str(), flux, dims);
        }

        return;
    }

#include "moc_kernels.hpp.inc"
}
<commit_msg>Fix some whitespace<commit_after>#include "moc_sweeper.hpp"

#include <iomanip>
#include "error.hpp"

using std::endl;
using std::cout;
using std::cin;

mocc::VecF temp;

namespace mocc {

    MoCSweeper::MoCSweeper( const pugi::xml_node& input,
            const CoreMesh& mesh ):
        TransportSweeper( mesh ),
        mesh_( mesh ),
        ang_quad_( input.child("ang_quad") ),
        rays_( input.child("rays"), ang_quad_, mesh ),
        xstr_( n_reg_, 1 ),
        flux_1g_( n_reg_, 1 ),
        qbar_( n_reg_, 1 ),
        bc_type_( mesh_.boundary() )
    {
        // Make sure we have input from the XML
        if( input.empty() ) {
            Error("No input specified to initialize MoC sweeper.");
        }

        // Parse the number of inner iterations
        int int_in = input.attribute("n_inner").as_int(-1);
        if(int_in < 0) {
            Error("Invalid number of inner iterations specified (n_inner).");
        }
        n_inner_ = int_in;

        // Set up the array of volumes (surface area)
        int ireg = 0;
        for( auto &pin: mesh_ ) {
            const VecF& pin_vols = pin->vols();
            for( auto &v: pin_vols ) {
                vol_(ireg) = v;
                ireg++;
            }
        }

        // allocate space to store the boundary conditions
        boundary_.resize( ng_ );
        for( auto &group_rays: boundary_ ) {
            group_rays.resize( mesh_.nz() );
            for( auto &angle_rays: group_rays ) {
                // We actually allocate BCs for all 4 octants to make things a
                // little simpler.
                angle_rays.resize( ang_quad_.ndir_oct()*4 );
                int iang = 0;
                for( auto ang_it=ang_quad_.octant(1);
                        ang_it!=ang_quad_.octant(5); ang_it++ ) {
                    angle_rays[iang].resize(rays_.n_rays(iang));
                    iang++;
                }
            }
        }
        boundary_out_.resize( mesh_.nz() );
        for( auto &angle_rays: boundary_out_ ) {
            // We actually allocate BCs for all 4 octants to make things a
            // little simpler.
            angle_rays.resize( ang_quad_.ndir_oct()*4 );
            int iang = 0;
            for( auto ang_it=ang_quad_.octant(1);
                    ang_it!=ang_quad_.octant(5); ang_it++ ) {
                angle_rays[iang].resize(rays_.n_rays(iang));
                iang++;
            }
        }

        return;
    }

    void MoCSweeper::sweep( int group ) {
        assert(source_);

        // set up the xstr_ array
        for( auto &xsr: *xs_mesh_ ) {
            real_t xstr = xsr.xsmactr()[group];
            for( auto &ireg: xsr.reg() ) {
                xstr_(ireg) = xstr;
            }
        }

        flux_1g_ = flux_.col( group );

        // Perform inner iterations
        for( unsigned int inner=0; inner<n_inner_; inner++ ) {
            // update the self-scattering source
            source_->self_scatter( group, flux_1g_, qbar_ );
            // Perform the stock sweep unless we are on the last outer and have
            // a CoarseData object.
            if( inner == n_inner_-1 && coarse_data_ ) {
                this->sweep1g_final( group );
            } else {
                this->sweep1g( group );
            }
        }

        flux_.col( group ) = flux_1g_;

        return;
    }

    void MoCSweeper::update_boundary( int group ) {
        int iplane=0;
        for( auto &plane_bcs: boundary_[group] ) {
            for( unsigned int iang=0; iang<plane_bcs.size(); iang++ ) {
                int nx = rays_.nx(iang);
                int ny = rays_.ny(iang);

                // Determine based on the angle quadrant which surfaces are
                // upwind and need to be updated for the given angle
                Surface upwind[2];
                if(ang_quad_[iang].ox > 0.0) {
                    upwind[0] = Surface::WEST;
                } else {
                    upwind[0] = Surface::EAST;
                }
                if(ang_quad_[iang].oy > 0.0) {
                    upwind[1] = Surface::SOUTH;
                } else {
                    upwind[1] = Surface::NORTH;
                }

                // Treat the two surfaces that were determined above
                if( bc_type_[(int)upwind[0]] == Boundary::REFLECT ) {
                    int ang_ref = ang_quad_.reflect(iang, upwind[0]);
                    for( int ibc=0; ibc<ny; ibc++ ) {
                        plane_bcs[iang][ibc] =
                            boundary_out_[iplane][ang_ref][ibc];
                    }
                } else {
                    for( int ibc=0; ibc<ny; ibc++ ) {
                        plane_bcs[iang][ibc] = 0.0;
                    }
                }

                if( bc_type_[(int)upwind[1]] == Boundary::REFLECT ) {
                    int ang_ref = ang_quad_.reflect(iang, upwind[1]);
                    for( int ibc=ny; ibc<(nx+ny); ibc++ ) {
                        plane_bcs[iang][ibc] =
                            boundary_out_[iplane][ang_ref][ibc];
                    }
                } else {
                    for( int ibc=ny; ibc<(nx+ny); ibc++ ) {
                        plane_bcs[iang][ibc] = 0.0;
                    }
                }
            } // angle loop
            iplane++;
        } // plane loop
    }

    void MoCSweeper::initialize() {
        // There are better ways to do this, but for now, just start with 1.0
        flux_.fill(1.0);

        // Walk through the boundary conditions and initialize them the 1/4pi
        real_t val = 1.0/FPI;
        for( auto &group_rays: boundary_ ) {
            for( auto &plane_rays: group_rays ) {
                for( auto &angle_rays: plane_rays ) {
                    for( auto &ray: angle_rays ) {
                        ray = val;
                    }
                }
            }
        }
        return;
    }

    void MoCSweeper::homogenize( CoarseData &data ) const {

        return;
    }

    void MoCSweeper::get_pin_flux( int group, VecF& flux ) const {
        flux.resize( mesh_.n_pin() );
        for( auto &f: flux ) {
            f = 0.0;
        }

        int ireg = 0;
        int ipin = 0;
        for( auto &pin: mesh_ ) {
            Position pos = mesh_.pin_position(ipin);
            int i = mesh_.index_lex(pos);
            real_t v = 0.0;
            for( int ir=0; ir<pin->n_reg(); ir++ ) {
                v += vol_(ireg);
                flux[i] += flux_(ireg, group)*vol_(ireg);
                ireg++;
            }
            flux[i] /= v;
            ipin++;
        }

        return;
    }

    void MoCSweeper::output( H5File& file ) const {
        // Get core dimensions from the mesh
        const int nx = mesh_.nx();
        const int ny = mesh_.ny();
        const int nz = mesh_.nz();
        VecI dims;
        dims.push_back(nz);
        dims.push_back(ny);
        dims.push_back(nx);

        // Make a group in the file to store the flux
        file.mkdir("/flux");

        // Provide energy group upper bounds
        file.write("/eubounds", xs_mesh_->eubounds(), VecI(1, ng_));
        file.write("/ng", ng_);

        for( unsigned int ig=0; ig<ng_; ig++ ) {
            VecF flux;
            this->get_pin_flux(ig, flux);

            std::stringstream setname;
            setname << "/flux/" << std::setfill('0') << std::setw(3) << ig+1;

            file.write(setname.str(), flux, dims);
        }

        return;
    }

#include "moc_kernels.hpp.inc"
}
<|endoftext|>


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

#include "buildsettingspropertiespage.h"
#include "buildstep.h"
#include "buildstepspage.h"
#include "project.h"
#include "projectexplorerconstants.h"
#include "target.h"
#include "buildconfiguration.h"
#include "buildconfigurationmodel.h"

#include <coreplugin/coreconstants.h>
#include <extensionsystem/pluginmanager.h>
#include <utils/qtcassert.h>
#include <projectexplorer/projectexplorer.h>
#include <projectexplorer/buildmanager.h>

#include <QMargins>
#include <QTimer>
#include <QCoreApplication>
#include <QComboBox>
#include <QInputDialog>
#include <QLabel>
#include <QMenu>
#include <QMessageBox>
#include <QPushButton>
#include <QVBoxLayout>

using namespace ProjectExplorer;
using namespace ProjectExplorer::Internal;

///
// BuildSettingsPanelFactory
///

QString BuildSettingsPanelFactory::id() const
{
    return QLatin1String(BUILDSETTINGS_PANEL_ID);
}

QString BuildSettingsPanelFactory::displayName() const
{
    return QCoreApplication::translate("BuildSettingsPanelFactory", "Build Settings");
}

int BuildSettingsPanelFactory::priority() const
{
    return 10;
}

bool BuildSettingsPanelFactory::supports(Target *target)
{
    return IBuildConfigurationFactory::find(target);
}

PropertiesPanel *BuildSettingsPanelFactory::createPanel(Target *target)
{
    PropertiesPanel *panel = new PropertiesPanel;
    QWidget *w = new QWidget();
    QVBoxLayout *l = new QVBoxLayout(w);
    QWidget *b = new BuildSettingsWidget(target);
    l->addWidget(b);
    l->addSpacerItem(new QSpacerItem(0, 0, QSizePolicy::Minimum, QSizePolicy::Expanding));
    l->setContentsMargins(QMargins());
    panel->setWidget(w);
    panel->setIcon(QIcon(QLatin1String(":/projectexplorer/images/BuildSettings.png")));
    panel->setDisplayName(QCoreApplication::translate("BuildSettingsPanel", "Build Settings"));
    return panel;
}

///
// BuildSettingsWidget
///

BuildSettingsWidget::~BuildSettingsWidget()
{
    clear();
}

BuildSettingsWidget::BuildSettingsWidget(Target *target) :
    m_target(target),
    m_buildConfiguration(0)
{
    Q_ASSERT(m_target);

    QVBoxLayout *vbox = new QVBoxLayout(this);
    vbox->setContentsMargins(0, 0, 0, 0);

    if (!IBuildConfigurationFactory::find(m_target)) {
        QLabel *noSettingsLabel = new QLabel(this);
        noSettingsLabel->setText(tr("No build settings available"));
        QFont f = noSettingsLabel->font();
        f.setPointSizeF(f.pointSizeF() * 1.2);
        noSettingsLabel->setFont(f);
        vbox->addWidget(noSettingsLabel);
        return;
    }

    { // Edit Build Configuration row
        QHBoxLayout *hbox = new QHBoxLayout();
        hbox->setContentsMargins(0, 0, 0, 0);
        hbox->addWidget(new QLabel(tr("Edit build configuration:"), this));
        m_buildConfigurationComboBox = new QComboBox(this);
        m_buildConfigurationComboBox->setSizeAdjustPolicy(QComboBox::AdjustToContents);
        m_buildConfigurationComboBox->setModel(new BuildConfigurationModel(m_target, this));
        hbox->addWidget(m_buildConfigurationComboBox);

        m_addButton = new QPushButton(this);
        m_addButton->setText(tr("Add"));
        m_addButton->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
        hbox->addWidget(m_addButton);
        m_addButtonMenu = new QMenu(this);
        m_addButton->setMenu(m_addButtonMenu);

        m_removeButton = new QPushButton(this);
        m_removeButton->setText(tr("Remove"));
        m_removeButton->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
        hbox->addWidget(m_removeButton);

        m_renameButton = new QPushButton(this);
        m_renameButton->setText(tr("Rename..."));
        m_renameButton->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
        hbox->addWidget(m_renameButton);

        hbox->addSpacerItem(new QSpacerItem(0, 0, QSizePolicy::Expanding, QSizePolicy::Fixed));
        vbox->addLayout(hbox);
    }

    m_buildConfiguration = m_target->activeBuildConfiguration();
    BuildConfigurationModel *model = static_cast<BuildConfigurationModel *>(m_buildConfigurationComboBox->model());
    m_buildConfigurationComboBox->setCurrentIndex(model->indexFor(m_buildConfiguration).row());

    updateAddButtonMenu();
    updateBuildSettings();

    connect(m_buildConfigurationComboBox, SIGNAL(currentIndexChanged(int)),
            this, SLOT(currentIndexChanged(int)));

    connect(m_removeButton, SIGNAL(clicked()),
            this, SLOT(deleteConfiguration()));

    connect(m_renameButton, SIGNAL(clicked()),
            this, SLOT(renameConfiguration()));

    connect(m_target, SIGNAL(activeBuildConfigurationChanged(ProjectExplorer::BuildConfiguration*)),
            this, SLOT(updateActiveConfiguration()));

    connect(m_target, SIGNAL(kitChanged()), this, SLOT(updateAddButtonMenu()));
}

void BuildSettingsWidget::addSubWidget(BuildConfigWidget *widget)
{
    widget->setContentsMargins(0, 10, 0, 0);

    QLabel *label = new QLabel(this);
    label->setText(widget->displayName());
    connect(widget, SIGNAL(displayNameChanged(QString)),
            label, SLOT(setText(QString)));
    QFont f = label->font();
    f.setBold(true);
    f.setPointSizeF(f.pointSizeF() * 1.2);
    label->setFont(f);

    label->setContentsMargins(0, 10, 0, 0);

    layout()->addWidget(label);
    layout()->addWidget(widget);

    m_labels.append(label);
    m_subWidgets.append(widget);
}

void BuildSettingsWidget::clear()
{
    qDeleteAll(m_subWidgets);
    m_subWidgets.clear();
    qDeleteAll(m_labels);
    m_labels.clear();
}

QList<BuildConfigWidget *> BuildSettingsWidget::subWidgets() const
{
    return m_subWidgets;
}

void BuildSettingsWidget::updateAddButtonMenu()
{
    m_addButtonMenu->clear();
    if (m_target) {
        if (m_target->activeBuildConfiguration()) {
            m_addButtonMenu->addAction(tr("&Clone Selected"),
                                       this, SLOT(cloneConfiguration()));
        }
        IBuildConfigurationFactory * factory = IBuildConfigurationFactory::find(m_target);
        if (!factory)
            return;
        foreach (Core::Id id, factory->availableCreationIds(m_target)) {
            QAction *action = m_addButtonMenu->addAction(factory->displayNameForId(id), this, SLOT(createConfiguration()));
            action->setData(QVariant::fromValue(id));
        }
    }
}

void BuildSettingsWidget::updateBuildSettings()
{
    clear();

    // update buttons
    m_removeButton->setEnabled(m_target->buildConfigurations().size() > 1);

    // Add pages
    BuildConfigWidget *generalConfigWidget = m_buildConfiguration->createConfigWidget();
    addSubWidget(generalConfigWidget);

    addSubWidget(new BuildStepsPage(m_target, Core::Id(Constants::BUILDSTEPS_BUILD)));
    addSubWidget(new BuildStepsPage(m_target, Core::Id(Constants::BUILDSTEPS_CLEAN)));

    QList<BuildConfigWidget *> subConfigWidgets = m_buildConfiguration->createSubConfigWidgets();
    foreach (BuildConfigWidget *subConfigWidget, subConfigWidgets)
        addSubWidget(subConfigWidget);

    foreach (BuildConfigWidget *widget, subWidgets())
        widget->init(m_buildConfiguration);
}

void BuildSettingsWidget::currentIndexChanged(int index)
{
    BuildConfigurationModel *model = static_cast<BuildConfigurationModel *>(m_buildConfigurationComboBox->model());
    BuildConfiguration *buildConfiguration = model->buildConfigurationAt(index);
    m_target->setActiveBuildConfiguration(buildConfiguration);
}

void BuildSettingsWidget::updateActiveConfiguration()
{
    if (!m_buildConfiguration || m_buildConfiguration == m_target->activeBuildConfiguration())
        return;

    m_buildConfiguration = m_target->activeBuildConfiguration();

    BuildConfigurationModel *model = static_cast<BuildConfigurationModel *>(m_buildConfigurationComboBox->model());
    m_buildConfigurationComboBox->setCurrentIndex(model->indexFor(m_buildConfiguration).row());

    foreach (QWidget *widget, subWidgets()) {
        if (BuildConfigWidget *buildStepWidget = qobject_cast<BuildConfigWidget*>(widget)) {
            buildStepWidget->init(m_buildConfiguration);
        }
    }
}

void BuildSettingsWidget::createConfiguration()
{
    QAction *action = qobject_cast<QAction *>(sender());
    Core::Id id = action->data().value<Core::Id>();

    IBuildConfigurationFactory *factory = IBuildConfigurationFactory::find(m_target);
    if (!factory)
        return;

    BuildConfiguration *bc = factory->create(m_target, id);
    if (!bc)
        return;

    m_target->addBuildConfiguration(bc);

    QTC_CHECK(bc->id() == id);
    m_target->setActiveBuildConfiguration(bc);
    updateBuildSettings();
}

void BuildSettingsWidget::cloneConfiguration()
{
    cloneConfiguration(m_buildConfiguration);
}

void BuildSettingsWidget::deleteConfiguration()
{
    deleteConfiguration(m_buildConfiguration);
}

QString BuildSettingsWidget::uniqueName(const QString & name)
{
    QString result = name.trimmed();
    if (!result.isEmpty()) {
        QStringList bcNames;
        foreach (BuildConfiguration *bc, m_target->buildConfigurations()) {
            if (bc == m_buildConfiguration)
                continue;
            bcNames.append(bc->displayName());
        }
        result = Project::makeUnique(result, bcNames);
    }
    return result;
}

void BuildSettingsWidget::renameConfiguration()
{
    bool ok;
    QString name = QInputDialog::getText(this, tr("Rename..."),
                                         tr("New name for build configuration %1:").
                                            arg(m_buildConfiguration->displayName()),
                                         QLineEdit::Normal,
                                         m_buildConfiguration->displayName(), &ok);
    if (!ok)
        return;

    name = uniqueName(name);
    if (name.isEmpty())
        return;

    m_buildConfiguration->setDisplayName(name);

}

void BuildSettingsWidget::cloneConfiguration(BuildConfiguration *sourceConfiguration)
{
    if (!sourceConfiguration)
        return;
    IBuildConfigurationFactory *factory = IBuildConfigurationFactory::find(m_target);
    if (!factory)
        return;

    //: Title of a the cloned BuildConfiguration window, text of the window
    QString name = uniqueName(QInputDialog::getText(this, tr("Clone Configuration"), tr("New configuration name:")));
    if (name.isEmpty())
        return;

    BuildConfiguration *bc = factory->clone(m_target, sourceConfiguration);
    if (!bc)
        return;

    bc->setDisplayName(name);
    m_target->addBuildConfiguration(bc);
    updateBuildSettings();

    m_target->setActiveBuildConfiguration(bc);
}

void BuildSettingsWidget::deleteConfiguration(BuildConfiguration *deleteConfiguration)
{
    if (!deleteConfiguration ||
        m_target->buildConfigurations().size() <= 1)
        return;

    ProjectExplorer::BuildManager *bm = ProjectExplorerPlugin::instance()->buildManager();
    if (bm->isBuilding(deleteConfiguration)) {
        QMessageBox box;
        QPushButton *closeAnyway = box.addButton(tr("Cancel Build && Remove Build Configuration"), QMessageBox::AcceptRole);
        QPushButton *cancelClose = box.addButton(tr("Do Not Remove"), QMessageBox::RejectRole);
        box.setDefaultButton(cancelClose);
        box.setWindowTitle(tr("Remove Build Configuration %1?").arg(deleteConfiguration->displayName()));
        box.setText(tr("The build configuration %1 is currently being built.").arg(deleteConfiguration->displayName()));
        box.setInformativeText(tr("Do you want to cancel the build process and remove the Build Configuration anyway?"));
        box.exec();
        if (box.clickedButton() != closeAnyway)
            return;
        bm->cancel();
    } else {
        QMessageBox msgBox(QMessageBox::Question, tr("Remove Build Configuration?"),
                           tr("Do you really want to delete build configuration %1?").arg(deleteConfiguration->displayName()),
                           QMessageBox::Yes|QMessageBox::No, this);
        msgBox.setDefaultButton(QMessageBox::No);
        msgBox.setEscapeButton(QMessageBox::No);
        if (msgBox.exec() == QMessageBox::No)
            return;
    }

    m_target->removeBuildConfiguration(deleteConfiguration);

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

#include "buildsettingspropertiespage.h"
#include "buildstep.h"
#include "buildstepspage.h"
#include "project.h"
#include "projectexplorerconstants.h"
#include "target.h"
#include "buildconfiguration.h"
#include "buildconfigurationmodel.h"

#include <coreplugin/coreconstants.h>
#include <extensionsystem/pluginmanager.h>
#include <utils/qtcassert.h>
#include <projectexplorer/projectexplorer.h>
#include <projectexplorer/buildmanager.h>

#include <QMargins>
#include <QTimer>
#include <QCoreApplication>
#include <QComboBox>
#include <QInputDialog>
#include <QLabel>
#include <QMenu>
#include <QMessageBox>
#include <QPushButton>
#include <QVBoxLayout>

using namespace ProjectExplorer;
using namespace ProjectExplorer::Internal;

///
// BuildSettingsPanelFactory
///

QString BuildSettingsPanelFactory::id() const
{
    return QLatin1String(BUILDSETTINGS_PANEL_ID);
}

QString BuildSettingsPanelFactory::displayName() const
{
    return QCoreApplication::translate("BuildSettingsPanelFactory", "Build Settings");
}

int BuildSettingsPanelFactory::priority() const
{
    return 10;
}

bool BuildSettingsPanelFactory::supports(Target *target)
{
    return IBuildConfigurationFactory::find(target);
}

PropertiesPanel *BuildSettingsPanelFactory::createPanel(Target *target)
{
    PropertiesPanel *panel = new PropertiesPanel;
    QWidget *w = new QWidget();
    QVBoxLayout *l = new QVBoxLayout(w);
    QWidget *b = new BuildSettingsWidget(target);
    l->addWidget(b);
    l->addSpacerItem(new QSpacerItem(0, 0, QSizePolicy::Minimum, QSizePolicy::Expanding));
    l->setContentsMargins(QMargins());
    panel->setWidget(w);
    panel->setIcon(QIcon(QLatin1String(":/projectexplorer/images/BuildSettings.png")));
    panel->setDisplayName(QCoreApplication::translate("BuildSettingsPanel", "Build Settings"));
    return panel;
}

///
// BuildSettingsWidget
///

BuildSettingsWidget::~BuildSettingsWidget()
{
    clear();
}

BuildSettingsWidget::BuildSettingsWidget(Target *target) :
    m_target(target),
    m_buildConfiguration(0)
{
    Q_ASSERT(m_target);

    QVBoxLayout *vbox = new QVBoxLayout(this);
    vbox->setContentsMargins(0, 0, 0, 0);

    if (!IBuildConfigurationFactory::find(m_target)) {
        QLabel *noSettingsLabel = new QLabel(this);
        noSettingsLabel->setText(tr("No build settings available"));
        QFont f = noSettingsLabel->font();
        f.setPointSizeF(f.pointSizeF() * 1.2);
        noSettingsLabel->setFont(f);
        vbox->addWidget(noSettingsLabel);
        return;
    }

    { // Edit Build Configuration row
        QHBoxLayout *hbox = new QHBoxLayout();
        hbox->setContentsMargins(0, 0, 0, 0);
        hbox->addWidget(new QLabel(tr("Edit build configuration:"), this));
        m_buildConfigurationComboBox = new QComboBox(this);
        m_buildConfigurationComboBox->setSizeAdjustPolicy(QComboBox::AdjustToContents);
        m_buildConfigurationComboBox->setModel(new BuildConfigurationModel(m_target, this));
        hbox->addWidget(m_buildConfigurationComboBox);

        m_addButton = new QPushButton(this);
        m_addButton->setText(tr("Add"));
        m_addButton->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
        hbox->addWidget(m_addButton);
        m_addButtonMenu = new QMenu(this);
        m_addButton->setMenu(m_addButtonMenu);

        m_removeButton = new QPushButton(this);
        m_removeButton->setText(tr("Remove"));
        m_removeButton->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
        hbox->addWidget(m_removeButton);

        m_renameButton = new QPushButton(this);
        m_renameButton->setText(tr("Rename..."));
        m_renameButton->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
        hbox->addWidget(m_renameButton);

        hbox->addSpacerItem(new QSpacerItem(0, 0, QSizePolicy::Expanding, QSizePolicy::Fixed));
        vbox->addLayout(hbox);
    }

    m_buildConfiguration = m_target->activeBuildConfiguration();
    BuildConfigurationModel *model = static_cast<BuildConfigurationModel *>(m_buildConfigurationComboBox->model());
    m_buildConfigurationComboBox->setCurrentIndex(model->indexFor(m_buildConfiguration).row());

    updateAddButtonMenu();
    updateBuildSettings();

    connect(m_buildConfigurationComboBox, SIGNAL(currentIndexChanged(int)),
            this, SLOT(currentIndexChanged(int)));

    connect(m_removeButton, SIGNAL(clicked()),
            this, SLOT(deleteConfiguration()));

    connect(m_renameButton, SIGNAL(clicked()),
            this, SLOT(renameConfiguration()));

    connect(m_target, SIGNAL(activeBuildConfigurationChanged(ProjectExplorer::BuildConfiguration*)),
            this, SLOT(updateActiveConfiguration()));

    connect(m_target, SIGNAL(kitChanged()), this, SLOT(updateAddButtonMenu()));
}

void BuildSettingsWidget::addSubWidget(BuildConfigWidget *widget)
{
    widget->setContentsMargins(0, 10, 0, 0);

    QLabel *label = new QLabel(this);
    label->setText(widget->displayName());
    connect(widget, SIGNAL(displayNameChanged(QString)),
            label, SLOT(setText(QString)));
    QFont f = label->font();
    f.setBold(true);
    f.setPointSizeF(f.pointSizeF() * 1.2);
    label->setFont(f);

    label->setContentsMargins(0, 10, 0, 0);

    layout()->addWidget(label);
    layout()->addWidget(widget);

    m_labels.append(label);
    m_subWidgets.append(widget);
}

void BuildSettingsWidget::clear()
{
    qDeleteAll(m_subWidgets);
    m_subWidgets.clear();
    qDeleteAll(m_labels);
    m_labels.clear();
}

QList<BuildConfigWidget *> BuildSettingsWidget::subWidgets() const
{
    return m_subWidgets;
}

void BuildSettingsWidget::updateAddButtonMenu()
{
    m_addButtonMenu->clear();
    if (m_target) {
        if (m_target->activeBuildConfiguration()) {
            m_addButtonMenu->addAction(tr("&Clone Selected"),
                                       this, SLOT(cloneConfiguration()));
        }
        IBuildConfigurationFactory * factory = IBuildConfigurationFactory::find(m_target);
        if (!factory)
            return;
        foreach (Core::Id id, factory->availableCreationIds(m_target)) {
            QAction *action = m_addButtonMenu->addAction(factory->displayNameForId(id), this, SLOT(createConfiguration()));
            action->setData(QVariant::fromValue(id));
        }
    }
}

void BuildSettingsWidget::updateBuildSettings()
{
    clear();

    // update buttons
    m_removeButton->setEnabled(m_target->buildConfigurations().size() > 1);

    if (!m_buildConfiguration)
        return;

    // Add pages
    BuildConfigWidget *generalConfigWidget = m_buildConfiguration->createConfigWidget();
    addSubWidget(generalConfigWidget);

    addSubWidget(new BuildStepsPage(m_target, Core::Id(Constants::BUILDSTEPS_BUILD)));
    addSubWidget(new BuildStepsPage(m_target, Core::Id(Constants::BUILDSTEPS_CLEAN)));

    QList<BuildConfigWidget *> subConfigWidgets = m_buildConfiguration->createSubConfigWidgets();
    foreach (BuildConfigWidget *subConfigWidget, subConfigWidgets)
        addSubWidget(subConfigWidget);

    foreach (BuildConfigWidget *widget, subWidgets())
        widget->init(m_buildConfiguration);
}

void BuildSettingsWidget::currentIndexChanged(int index)
{
    BuildConfigurationModel *model = static_cast<BuildConfigurationModel *>(m_buildConfigurationComboBox->model());
    BuildConfiguration *buildConfiguration = model->buildConfigurationAt(index);
    m_target->setActiveBuildConfiguration(buildConfiguration);
}

void BuildSettingsWidget::updateActiveConfiguration()
{
    if (!m_buildConfiguration || m_buildConfiguration == m_target->activeBuildConfiguration())
        return;

    m_buildConfiguration = m_target->activeBuildConfiguration();

    BuildConfigurationModel *model = static_cast<BuildConfigurationModel *>(m_buildConfigurationComboBox->model());
    m_buildConfigurationComboBox->setCurrentIndex(model->indexFor(m_buildConfiguration).row());

    updateBuildSettings();
}

void BuildSettingsWidget::createConfiguration()
{
    QAction *action = qobject_cast<QAction *>(sender());
    Core::Id id = action->data().value<Core::Id>();

    IBuildConfigurationFactory *factory = IBuildConfigurationFactory::find(m_target);
    if (!factory)
        return;

    BuildConfiguration *bc = factory->create(m_target, id);
    if (!bc)
        return;

    m_target->addBuildConfiguration(bc);

    QTC_CHECK(bc->id() == id);
    m_target->setActiveBuildConfiguration(bc);
}

void BuildSettingsWidget::cloneConfiguration()
{
    cloneConfiguration(m_buildConfiguration);
}

void BuildSettingsWidget::deleteConfiguration()
{
    deleteConfiguration(m_buildConfiguration);
}

QString BuildSettingsWidget::uniqueName(const QString & name)
{
    QString result = name.trimmed();
    if (!result.isEmpty()) {
        QStringList bcNames;
        foreach (BuildConfiguration *bc, m_target->buildConfigurations()) {
            if (bc == m_buildConfiguration)
                continue;
            bcNames.append(bc->displayName());
        }
        result = Project::makeUnique(result, bcNames);
    }
    return result;
}

void BuildSettingsWidget::renameConfiguration()
{
    bool ok;
    QString name = QInputDialog::getText(this, tr("Rename..."),
                                         tr("New name for build configuration %1:").
                                            arg(m_buildConfiguration->displayName()),
                                         QLineEdit::Normal,
                                         m_buildConfiguration->displayName(), &ok);
    if (!ok)
        return;

    name = uniqueName(name);
    if (name.isEmpty())
        return;

    m_buildConfiguration->setDisplayName(name);

}

void BuildSettingsWidget::cloneConfiguration(BuildConfiguration *sourceConfiguration)
{
    if (!sourceConfiguration)
        return;
    IBuildConfigurationFactory *factory = IBuildConfigurationFactory::find(m_target);
    if (!factory)
        return;

    //: Title of a the cloned BuildConfiguration window, text of the window
    QString name = uniqueName(QInputDialog::getText(this, tr("Clone Configuration"), tr("New configuration name:")));
    if (name.isEmpty())
        return;

    BuildConfiguration *bc = factory->clone(m_target, sourceConfiguration);
    if (!bc)
        return;

    bc->setDisplayName(name);
    m_target->addBuildConfiguration(bc);
    m_target->setActiveBuildConfiguration(bc);
}

void BuildSettingsWidget::deleteConfiguration(BuildConfiguration *deleteConfiguration)
{
    if (!deleteConfiguration ||
        m_target->buildConfigurations().size() <= 1)
        return;

    ProjectExplorer::BuildManager *bm = ProjectExplorerPlugin::instance()->buildManager();
    if (bm->isBuilding(deleteConfiguration)) {
        QMessageBox box;
        QPushButton *closeAnyway = box.addButton(tr("Cancel Build && Remove Build Configuration"), QMessageBox::AcceptRole);
        QPushButton *cancelClose = box.addButton(tr("Do Not Remove"), QMessageBox::RejectRole);
        box.setDefaultButton(cancelClose);
        box.setWindowTitle(tr("Remove Build Configuration %1?").arg(deleteConfiguration->displayName()));
        box.setText(tr("The build configuration %1 is currently being built.").arg(deleteConfiguration->displayName()));
        box.setInformativeText(tr("Do you want to cancel the build process and remove the Build Configuration anyway?"));
        box.exec();
        if (box.clickedButton() != closeAnyway)
            return;
        bm->cancel();
    } else {
        QMessageBox msgBox(QMessageBox::Question, tr("Remove Build Configuration?"),
                           tr("Do you really want to delete build configuration %1?").arg(deleteConfiguration->displayName()),
                           QMessageBox::Yes|QMessageBox::No, this);
        msgBox.setDefaultButton(QMessageBox::No);
        msgBox.setEscapeButton(QMessageBox::No);
        if (msgBox.exec() == QMessageBox::No)
            return;
    }

    m_target->removeBuildConfiguration(deleteConfiguration);
}
<|endoftext|>


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

#include "qmlmodelview.h"
#include "qmlobjectnode.h"
#include "qmlitemnode.h"
#include "itemlibraryinfo.h"
#include "modelutilities.h"
#include "mathutils.h"
#include <QDir>
#include <QFileInfo>
#include <QDebug>

namespace QmlDesigner {

QmlModelView::QmlModelView(QObject *parent)
    : ForwardView<NodeInstanceView>(parent)
{
    NodeInstanceView *nodeInstanceView = new NodeInstanceView(this);
    nodeInstanceView->setQmlModelView(this);
    appendView(nodeInstanceView);
}

void QmlModelView::setCurrentState(const QmlModelState &state)
{
    if (!state.isValid())
        return;

    emitCustomNotification("__state changed__", QList<ModelNode>() << state.modelNode());
}

QmlModelState QmlModelView::currentState() const
{
    return m_state;
}

QmlModelState QmlModelView::baseState() const
{
    return QmlModelState::createBaseState(this);
}

QmlObjectNode QmlModelView::createQmlObjectNode(const QString &typeString,
                     int majorVersion,
                     int minorVersion,
                     const PropertyListType &propertyList)
{
    return QmlObjectNode(createModelNode(typeString, majorVersion, minorVersion, propertyList));
}

QmlItemNode QmlModelView::createQmlItemNode(const QString &typeString,
                                int majorVersion,
                                int minorVersion,
                                const PropertyListType &propertyList)
{
    return createQmlObjectNode(typeString, majorVersion, minorVersion, propertyList).toQmlItemNode();
}

QmlItemNode QmlModelView::createQmlItemNodeFromImage(const QString &imageName, const QPointF &position, QmlItemNode parentNode)
{
    if (!parentNode.isValid())
        parentNode = rootQmlItemNode();

    if (!parentNode.isValid())
        return QmlItemNode();

    QmlItemNode newNode;
    RewriterTransaction transaction = beginRewriterTransaction();
    {
        QList<QPair<QString, QVariant> > propertyPairList;
        propertyPairList.append(qMakePair(QString("x"), QVariant( round(position.x(), 4))));
        propertyPairList.append(qMakePair(QString("y"), QVariant( round(position.y(), 4))));

        QString relativeImageName = imageName;

        //use relative path
        if (QFileInfo(model()->fileUrl().toLocalFile()).exists()) {
            QDir fileDir(QFileInfo(model()->fileUrl().toLocalFile()).absolutePath());
            relativeImageName = fileDir.relativeFilePath(imageName);
        }

        propertyPairList.append(qMakePair(QString("source"), QVariant(relativeImageName)));
        newNode = createQmlItemNode("Qt/Image",4, 7, propertyPairList);
        parentNode.nodeAbstractProperty("data").reparentHere(newNode);

        Q_ASSERT(newNode.isValid());

        QString id;
        int i = 1;
        QString name("image");
        name.remove(QLatin1Char(' '));
        do {
            id = name + QString::number(i);
            i++;
        } while (hasId(id)); //If the name already exists count upwards

        newNode.setId(id);
        if (!currentState().isBaseState()) {
            newNode.modelNode().variantProperty("visible") = false;
            newNode.setVariantProperty("visible", true);
        }

        Q_ASSERT(newNode.isValid());
    }

    Q_ASSERT(newNode.isValid());

    return newNode;
}

QmlItemNode QmlModelView::createQmlItemNode(const ItemLibraryEntry &itemLibraryEntry, const QPointF &position, QmlItemNode parentNode)
{
    if (!parentNode.isValid())
        parentNode = rootQmlItemNode();

    Q_ASSERT(parentNode.isValid());

    QmlItemNode newNode;
    RewriterTransaction transaction = beginRewriterTransaction();
    {
        QList<QPair<QString, QVariant> > propertyPairList;
        propertyPairList.append(qMakePair(QString("x"), QVariant(round(position.x(), 4))));
        propertyPairList.append(qMakePair(QString("y"), QVariant(round(position.y(), 4))));

        foreach (const PropertyContainer &property, itemLibraryEntry.properties())
            propertyPairList.append(qMakePair(property.name(), property.value()));

        newNode = createQmlItemNode(itemLibraryEntry.typeName(), itemLibraryEntry.majorVersion(), itemLibraryEntry.minorVersion(), propertyPairList);
        parentNode.nodeAbstractProperty("data").reparentHere(newNode);

        Q_ASSERT(newNode.isValid());

        QString id;
        int i = 1;
        QString name(itemLibraryEntry.name().toLower());
        name.remove(QLatin1Char(' '));
        do {
            id = name + QString::number(i);
            i++;
        } while (hasId(id)); //If the name already exists count upwards

        newNode.setId(id);
        if (!currentState().isBaseState()) {
            newNode.modelNode().variantProperty("visible") = false;
            newNode.setVariantProperty("visible", true);
        }

        Q_ASSERT(newNode.isValid());
    }

    Q_ASSERT(newNode.isValid());

    return newNode;
}

QmlObjectNode QmlModelView::rootQmlObjectNode() const
{
    return QmlObjectNode(rootModelNode());
}

QmlItemNode QmlModelView::rootQmlItemNode() const
{
    return rootQmlObjectNode().toQmlItemNode();
}

void QmlModelView::setSelectedQmlObjectNodes(const QList<QmlObjectNode> &selectedNodeList)
{
    setSelectedModelNodes(QmlDesigner::toModelNodeList(selectedNodeList));
}

void QmlModelView::selectQmlObjectNode(const QmlObjectNode &node)
{
     selectModelNode(node.modelNode());
}

void QmlModelView::deselectQmlObjectNode(const QmlObjectNode &node)
{
    deselectModelNode(node.modelNode());
}

QList<QmlObjectNode> QmlModelView::selectedQmlObjectNodes() const
{
    return toQmlObjectNodeList(selectedModelNodes());
}

QList<QmlItemNode> QmlModelView::selectedQmlItemNodes() const
{
    return toQmlItemNodeList(selectedModelNodes());
}

void QmlModelView::setSelectedQmlItemNodes(const QList<QmlItemNode> &selectedNodeList)
{
    return setSelectedModelNodes(QmlDesigner::toModelNodeList(selectedNodeList));
}

QmlObjectNode QmlModelView::fxObjectNodeForId(const QString &id)
{
    return QmlObjectNode(modelNodeForId(id));
}

void QmlModelView::customNotification(const AbstractView * /* view */, const QString &identifier, const QList<ModelNode> &nodeList, const QList<QVariant> & /* data */)
{
    if (identifier == "__state changed__") {
        QmlModelState state(nodeList.first());
        if (state.isValid())
            activateState(state);
        else
            activateState(baseState());
    }
}

NodeInstance QmlModelView::instanceForModelNode(const ModelNode &modelNode)
{
    return nodeInstanceView()->instanceForNode(modelNode);
}

bool QmlModelView::hasInstanceForModelNode(const ModelNode &modelNode)
{
    return nodeInstanceView()->hasInstanceForNode(modelNode);
}

NodeInstanceView *QmlModelView::nodeInstanceView() const
{
    return firstView();
}

void QmlModelView::modelAttached(Model *model)
{
    m_state = QmlModelState();
    ForwardView<NodeInstanceView>::modelAttached(model);
    m_state = baseState();
    Q_ASSERT(m_state.isBaseState());
}

void QmlModelView::modelAboutToBeDetached(Model *model)
{
    ForwardView<NodeInstanceView>::modelAboutToBeDetached(model);
    m_state = QmlModelState();
}

static bool isTransformProperty(const QString &name)
{
    static QStringList transformProperties(QStringList() << "x"
                                                         << "y"
                                                         << "width"
                                                         << "height"
                                                         << "z"
                                                         << "rotation"
                                                         << "scale"
                                                         << "transformOrigin");

    return transformProperties.contains(name);
}

void QmlModelView::nodeInstancePropertyChanged(const ModelNode &node, const QString &propertyName)
{

    QmlObjectNode qmlObjectNode(node);

    if (!qmlObjectNode.isValid())
        return;

    if (isTransformProperty(propertyName))
        transformChanged(qmlObjectNode, propertyName);
    else if (propertyName == "parent")
        parentChanged(qmlObjectNode);
    else if (propertyName == "state")
        changeToState(node, qmlObjectNode.instanceValue(propertyName).toString());
    else
        otherPropertyChanged(qmlObjectNode, propertyName);
}

void QmlModelView::activateState(const QmlModelState &state)
{
    if (!state.isValid())
        return;

    if (m_state == state)
        return;

    QmlModelState oldState = m_state;

    NodeInstance newStateInstance = instanceForModelNode(state.modelNode());

    if (state.isBaseState()) {
        nodeInstanceView()->activateBaseState();
    } else {
        nodeInstanceView()->activateState(newStateInstance);
    }
}

void QmlModelView::changeToState(const ModelNode &node, const QString &stateName)
{
    QmlItemNode itemNode(node);

    QmlModelState newState;
    if (stateName.isEmpty())
        newState = baseState();
    else
        newState = itemNode.states().state(stateName);

    QmlModelState oldState = m_state;

    if (newState.isValid() && oldState != newState) {
        m_state = newState;
        stateChanged(newState, oldState);
    }
}

void QmlModelView::transformChanged(const QmlObjectNode &/*qmlObjectNode*/, const QString &/*propertyName*/)
{
}

void QmlModelView::parentChanged(const QmlObjectNode &/*qmlObjectNode*/)
{
}

void QmlModelView::otherPropertyChanged(const QmlObjectNode &/*qmlObjectNode*/, const QString &/*propertyName*/)
{
}

void  QmlModelView::stateChanged(const QmlModelState &/*newQmlModelState*/, const QmlModelState &/*oldQmlModelState*/)
{
}

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

#include "qmlmodelview.h"
#include "qmlobjectnode.h"
#include "qmlitemnode.h"
#include "itemlibraryinfo.h"
#include "modelutilities.h"
#include "mathutils.h"
#include "invalididexception.h"
#include <QDir>
#include <QFileInfo>
#include <QDebug>
#include <QMessageBox>

namespace QmlDesigner {

QmlModelView::QmlModelView(QObject *parent)
    : ForwardView<NodeInstanceView>(parent)
{
    NodeInstanceView *nodeInstanceView = new NodeInstanceView(this);
    nodeInstanceView->setQmlModelView(this);
    appendView(nodeInstanceView);
}

void QmlModelView::setCurrentState(const QmlModelState &state)
{
    if (!state.isValid())
        return;

    emitCustomNotification("__state changed__", QList<ModelNode>() << state.modelNode());
}

QmlModelState QmlModelView::currentState() const
{
    return m_state;
}

QmlModelState QmlModelView::baseState() const
{
    return QmlModelState::createBaseState(this);
}

QmlObjectNode QmlModelView::createQmlObjectNode(const QString &typeString,
                     int majorVersion,
                     int minorVersion,
                     const PropertyListType &propertyList)
{
    return QmlObjectNode(createModelNode(typeString, majorVersion, minorVersion, propertyList));
}

QmlItemNode QmlModelView::createQmlItemNode(const QString &typeString,
                                int majorVersion,
                                int minorVersion,
                                const PropertyListType &propertyList)
{
    return createQmlObjectNode(typeString, majorVersion, minorVersion, propertyList).toQmlItemNode();
}

QmlItemNode QmlModelView::createQmlItemNodeFromImage(const QString &imageName, const QPointF &position, QmlItemNode parentNode)
{
    if (!parentNode.isValid())
        parentNode = rootQmlItemNode();

    if (!parentNode.isValid())
        return QmlItemNode();

    QmlItemNode newNode;
    RewriterTransaction transaction = beginRewriterTransaction();
    {
        QList<QPair<QString, QVariant> > propertyPairList;
        propertyPairList.append(qMakePair(QString("x"), QVariant( round(position.x(), 4))));
        propertyPairList.append(qMakePair(QString("y"), QVariant( round(position.y(), 4))));

        QString relativeImageName = imageName;

        //use relative path
        if (QFileInfo(model()->fileUrl().toLocalFile()).exists()) {
            QDir fileDir(QFileInfo(model()->fileUrl().toLocalFile()).absolutePath());
            relativeImageName = fileDir.relativeFilePath(imageName);
        }

        propertyPairList.append(qMakePair(QString("source"), QVariant(relativeImageName)));
        newNode = createQmlItemNode("Qt/Image",4, 7, propertyPairList);
        parentNode.nodeAbstractProperty("data").reparentHere(newNode);

        Q_ASSERT(newNode.isValid());

        QString id;
        int i = 1;
        QString name("image");
        name.remove(QLatin1Char(' '));
        do {
            id = name + QString::number(i);
            i++;
        } while (hasId(id)); //If the name already exists count upwards

        newNode.setId(id);
        if (!currentState().isBaseState()) {
            newNode.modelNode().variantProperty("visible") = false;
            newNode.setVariantProperty("visible", true);
        }

        Q_ASSERT(newNode.isValid());
    }

    Q_ASSERT(newNode.isValid());

    return newNode;
}

QmlItemNode QmlModelView::createQmlItemNode(const ItemLibraryEntry &itemLibraryEntry, const QPointF &position, QmlItemNode parentNode)
{
    if (!parentNode.isValid())
        parentNode = rootQmlItemNode();

    Q_ASSERT(parentNode.isValid());

    QmlItemNode newNode;
    RewriterTransaction transaction = beginRewriterTransaction();
    {
        QList<QPair<QString, QVariant> > propertyPairList;
        propertyPairList.append(qMakePair(QString("x"), QVariant(round(position.x(), 4))));
        propertyPairList.append(qMakePair(QString("y"), QVariant(round(position.y(), 4))));

        foreach (const PropertyContainer &property, itemLibraryEntry.properties())
            propertyPairList.append(qMakePair(property.name(), property.value()));

        newNode = createQmlItemNode(itemLibraryEntry.typeName(), itemLibraryEntry.majorVersion(), itemLibraryEntry.minorVersion(), propertyPairList);
        parentNode.nodeAbstractProperty("data").reparentHere(newNode);

        Q_ASSERT(newNode.isValid());

        QString id;
        int i = 1;
        QString name(itemLibraryEntry.name().toLower());
        //remove forbidden characters
        name.replace(QRegExp(QLatin1String("[^a-zA-Z0-9_]")), QLatin1String("_"));
        do {
            id = name + QString::number(i);
            i++;
        } while (hasId(id)); //If the name already exists count upwards

        try {
            newNode.setId(id);
        } catch (InvalidIdException &e) {
            // should never happen
            QMessageBox::warning(0, tr("Invalid Id"), e.description());
        }

        if (!currentState().isBaseState()) {
            newNode.modelNode().variantProperty("visible") = false;
            newNode.setVariantProperty("visible", true);
        }

        Q_ASSERT(newNode.isValid());
    }

    Q_ASSERT(newNode.isValid());

    return newNode;
}

QmlObjectNode QmlModelView::rootQmlObjectNode() const
{
    return QmlObjectNode(rootModelNode());
}

QmlItemNode QmlModelView::rootQmlItemNode() const
{
    return rootQmlObjectNode().toQmlItemNode();
}

void QmlModelView::setSelectedQmlObjectNodes(const QList<QmlObjectNode> &selectedNodeList)
{
    setSelectedModelNodes(QmlDesigner::toModelNodeList(selectedNodeList));
}

void QmlModelView::selectQmlObjectNode(const QmlObjectNode &node)
{
     selectModelNode(node.modelNode());
}

void QmlModelView::deselectQmlObjectNode(const QmlObjectNode &node)
{
    deselectModelNode(node.modelNode());
}

QList<QmlObjectNode> QmlModelView::selectedQmlObjectNodes() const
{
    return toQmlObjectNodeList(selectedModelNodes());
}

QList<QmlItemNode> QmlModelView::selectedQmlItemNodes() const
{
    return toQmlItemNodeList(selectedModelNodes());
}

void QmlModelView::setSelectedQmlItemNodes(const QList<QmlItemNode> &selectedNodeList)
{
    return setSelectedModelNodes(QmlDesigner::toModelNodeList(selectedNodeList));
}

QmlObjectNode QmlModelView::fxObjectNodeForId(const QString &id)
{
    return QmlObjectNode(modelNodeForId(id));
}

void QmlModelView::customNotification(const AbstractView * /* view */, const QString &identifier, const QList<ModelNode> &nodeList, const QList<QVariant> & /* data */)
{
    if (identifier == "__state changed__") {
        QmlModelState state(nodeList.first());
        if (state.isValid())
            activateState(state);
        else
            activateState(baseState());
    }
}

NodeInstance QmlModelView::instanceForModelNode(const ModelNode &modelNode)
{
    return nodeInstanceView()->instanceForNode(modelNode);
}

bool QmlModelView::hasInstanceForModelNode(const ModelNode &modelNode)
{
    return nodeInstanceView()->hasInstanceForNode(modelNode);
}

NodeInstanceView *QmlModelView::nodeInstanceView() const
{
    return firstView();
}

void QmlModelView::modelAttached(Model *model)
{
    m_state = QmlModelState();
    ForwardView<NodeInstanceView>::modelAttached(model);
    m_state = baseState();
    Q_ASSERT(m_state.isBaseState());
}

void QmlModelView::modelAboutToBeDetached(Model *model)
{
    ForwardView<NodeInstanceView>::modelAboutToBeDetached(model);
    m_state = QmlModelState();
}

static bool isTransformProperty(const QString &name)
{
    static QStringList transformProperties(QStringList() << "x"
                                                         << "y"
                                                         << "width"
                                                         << "height"
                                                         << "z"
                                                         << "rotation"
                                                         << "scale"
                                                         << "transformOrigin");

    return transformProperties.contains(name);
}

void QmlModelView::nodeInstancePropertyChanged(const ModelNode &node, const QString &propertyName)
{

    QmlObjectNode qmlObjectNode(node);

    if (!qmlObjectNode.isValid())
        return;

    if (isTransformProperty(propertyName))
        transformChanged(qmlObjectNode, propertyName);
    else if (propertyName == "parent")
        parentChanged(qmlObjectNode);
    else if (propertyName == "state")
        changeToState(node, qmlObjectNode.instanceValue(propertyName).toString());
    else
        otherPropertyChanged(qmlObjectNode, propertyName);
}

void QmlModelView::activateState(const QmlModelState &state)
{
    if (!state.isValid())
        return;

    if (m_state == state)
        return;

    QmlModelState oldState = m_state;

    NodeInstance newStateInstance = instanceForModelNode(state.modelNode());

    if (state.isBaseState()) {
        nodeInstanceView()->activateBaseState();
    } else {
        nodeInstanceView()->activateState(newStateInstance);
    }
}

void QmlModelView::changeToState(const ModelNode &node, const QString &stateName)
{
    QmlItemNode itemNode(node);

    QmlModelState newState;
    if (stateName.isEmpty())
        newState = baseState();
    else
        newState = itemNode.states().state(stateName);

    QmlModelState oldState = m_state;

    if (newState.isValid() && oldState != newState) {
        m_state = newState;
        stateChanged(newState, oldState);
    }
}

void QmlModelView::transformChanged(const QmlObjectNode &/*qmlObjectNode*/, const QString &/*propertyName*/)
{
}

void QmlModelView::parentChanged(const QmlObjectNode &/*qmlObjectNode*/)
{
}

void QmlModelView::otherPropertyChanged(const QmlObjectNode &/*qmlObjectNode*/, const QString &/*propertyName*/)
{
}

void  QmlModelView::stateChanged(const QmlModelState &/*newQmlModelState*/, const QmlModelState &/*oldQmlModelState*/)
{
}

} //QmlDesigner
<|endoftext|>