<commit_before>/*  Namecoin RPC library.
 *  Copyright (C) 2013-2014  Daniel Kraft <d@domob.eu>
 *
 *  This program is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU Affero General Public License as published by
 *  the Free Software Foundation, either version 3 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU Affero General Public License for more details.
 *
 *  You should have received a copy of the GNU Affero General Public License
 *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *
 *  See the distributed file COPYING for additional permissions in addition
 *  to those of the GNU Affero General Public License.
 */

/* Utility program to update names.  */

#include "JsonRpc.hpp"
#include "NamecoinInterface.hpp"
#include "NameRegistration.hpp"

#include <algorithm>
#include <cassert>
#include <cstdlib>
#include <fstream>
#include <iostream>
#include <vector>

using namespace nmcrpc;

/**
 * Display the help message.
 */
static void
displayHelp ()
{
  std::cerr << "Usage: nmupdate COMMAND [OPTIONS]"
            << std::endl << std::endl;
  std::cerr << "Possible commands:" << std::endl;
  std::cerr << "  * help: Display this message." << std::endl;
  std::cerr << "  * list: List owned names and their expirey counter."
            << std::endl;
  std::cerr << "  * update NAME [VAL]: Update NAME to VAL (or existing value)."
            << std::endl;
  std::cerr << "  * send NAME ADDR [VAL]: Update NAME and send to ADDR."
            << std::endl;
  std::cerr << "  * update-multi FILE [VAL]: Update all names in FILE"
            << std::endl
            << "                             to VAL or"
            << " their current value." << std::endl;
  std::cerr << "  * send-multi FILE ADDR [VAL]: Send all names in FILE to ADDR."
            << std::endl;
}

/**
 * Read file into list of names.
 * @param fileName Name of file to read in.
 * @param names Store names here.
 * @throws std::runtime_error if reading fails.
 */
static void
readNames (const std::string& fileName, std::vector<std::string>& names)
{
  std::ifstream in (fileName.c_str ());
  if (!in)
    throw std::runtime_error ("Could not read list of names.");

  while (in)
    {
      std::string line;
      std::getline (in, line);

      if (!line.empty ())
        names.push_back (line);
    }
}

/**
 * Perform a name update operation on an array of names.
 * @param rpc Json RPC connection.
 * @param nc Namecoin high-level interface.
 * @param names Array of names to update.
 * @param hasVal Whether to set the value or leave it.
 * @param val The value, is ignored if !hasVal.
 * @param hasAddr Whether to send to a specified address.
 * @param addr Target address, ignored if !hasAddr.
 */
static void
performUpdate (JsonRpc& rpc, NamecoinInterface& nc,
               const std::vector<std::string>& names,
               bool hasVal, const std::string& val,
               bool hasAddr, const std::string& addr)
{
#ifdef CXX_11
  for (const auto& nm : names)
#else /* CXX_11  */
  for (std::vector<std::string>::const_iterator i = names.begin ();
       i != names.end (); ++i)
#endif /* CXX_11  */
    {
#ifndef CXX_11
      const std::string& nm = *i;
#endif /* !CXX_11  */

      std::cout << "Updating " << nm << ": ";
      NamecoinInterface::Name name = nc.queryName (nm);

      NameUpdate updater (rpc, nc, name);
      if (hasVal)
        updater.setValue (val);

      std::string txid;
      if (!hasAddr)
        txid = updater.execute ();
      else
        txid = updater.execute (nc.queryAddress (addr));

      std::cout << txid << std::endl;
    }
}

/**
 * Compare names for sorting by expiration date.
 * @param a First name.
 * @param b Second name.
 * @return True iff a expires later than b.
 */
static bool
compareNames (const NamecoinInterface::Name& a,
              const NamecoinInterface::Name& b)
{
  int diff = a.getExpireCounter () - b.getExpireCounter ();
  if (diff != 0)
    return (diff > 0);
  return a.getName () < b.getName ();
}

/* Functor instead of addName lambda if we don't have C++11.  */
#ifndef CXX_11
class addNameFunctor
{
private:

  std::vector<NamecoinInterface::Name>& names;

public:

  explicit inline
  addNameFunctor (std::vector<NamecoinInterface::Name>& n)
    : names(n)
  {}

  inline void
  operator() (const NamecoinInterface::Name& nm)
  {
    names.push_back (nm);
  }

};
#endif /* !CXX_11  */

/**
 * Main routine with the usual interface.
 */
int
main (int argc, char** argv)
{
  try
    {
      if (argc < 2)
        {
          displayHelp ();
          return EXIT_FAILURE;
        }
      const std::string command = argv[1];

      if (command == "help")
        {
          displayHelp ();
          return EXIT_SUCCESS;
        }

      RpcSettings settings;
      settings.readDefaultConfig ();
      JsonRpc rpc(settings);
      NamecoinInterface nc(rpc);

      if (command == "list")
        {
          std::vector<NamecoinInterface::Name> names;

#ifdef CXX_11
          const auto addName = [&names] (const NamecoinInterface::Name& nm)
            {
              names.push_back (nm);
            };
#else /* CXX_11  */
          addNameFunctor addName(names);
#endif /* CXX_11  */

          nc.forMyNames (addName);

          std::sort (names.begin (), names.end (), &compareNames);

#ifdef CXX_11
          for (const auto& el : names)
#else /* CXX_11  */
          std::vector<NamecoinInterface::Name>::const_iterator i;
          for (i = names.begin (); i != names.end (); ++i)
#endif /* CXX_11  */
            {
#ifndef CXX_11
              const NamecoinInterface::Name& el = *i;
#endif /* !CXX_11  */

              std::cout.width (30);
              std::cout << el.getName () << ": "
                        << el.getExpireCounter () << std::endl;
            }
        }
      else
        {
          std::string passphrase;
          if (nc.needWalletPassphrase ())
            {
              std::cout << "Enter wallet passphrase: ";
              std::getline (std::cin, passphrase);
            }
          NamecoinInterface::WalletUnlocker unlock(nc);
          unlock.unlock (passphrase);

          std::vector<std::string> names;

          if (command == "update")
            {
              if (argc < 3 || argc > 4)
                throw std::runtime_error ("Expected: nmupdate update"
                                          " NAME [VAL]");

              const std::string name = argv[2];
              std::string val;
              if (argc == 4)
                val = argv[3];

              names.push_back (name);
              performUpdate (rpc, nc, names, argc == 4, val, false, "");
            }
          else if (command == "update-multi")
            {
              if (argc < 3 || argc > 4)
                throw std::runtime_error ("Expected: nmupdate update-multi"
                                          " FILE [VAL]");

              const std::string file = argv[2];
              std::string val;
              if (argc == 4)
                val = argv[3];

              readNames (file, names);
              performUpdate (rpc, nc, names, argc == 4, val, false, "");
            }
          else if (command == "send")
            {
              if (argc < 4 || argc > 5)
                throw std::runtime_error ("Expected: nmupdate send"
                                          " NAME ADDR [VAL]");

              const std::string name = argv[2];
              const std::string addr = argv[3];
              std::string val;
              if (argc == 5)
                val = argv[4];

              names.push_back (name);
              performUpdate (rpc, nc, names, argc == 5, val, true, addr);
            }
          else if (command == "send-multi")
            {
              if (argc < 4 || argc > 5)
                throw std::runtime_error ("Expected: nmupdate send-multi"
                                          " FILE ADDR [VAL]");

              const std::string file = argv[2];
              const std::string addr = argv[3];
              std::string val;
              if (argc == 5)
                val = argv[4];

              readNames (file, names);
              performUpdate (rpc, nc, names, argc == 5, val, true, addr);
            }
          else
            throw std::runtime_error ("Unknown command '" + command + "'.");
        }
    }
  catch (const JsonRpc::RpcError& exc)
    {
      std::cerr << "JSON-RPC error:" << std::endl;
      std::cerr << exc.getErrorMessage () << std::endl;
      return EXIT_FAILURE;
    }
  catch (const std::exception& exc)
    {
      std::cerr << "Error: " << exc.what () << std::endl;
      return EXIT_FAILURE;
    }

  return EXIT_SUCCESS;
}
<commit_msg>Show only non-expired names in nmupdate list.<commit_after>/*  Namecoin RPC library.
 *  Copyright (C) 2013-2014  Daniel Kraft <d@domob.eu>
 *
 *  This program is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU Affero General Public License as published by
 *  the Free Software Foundation, either version 3 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU Affero General Public License for more details.
 *
 *  You should have received a copy of the GNU Affero General Public License
 *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *
 *  See the distributed file COPYING for additional permissions in addition
 *  to those of the GNU Affero General Public License.
 */

/* Utility program to update names.  */

#include "JsonRpc.hpp"
#include "NamecoinInterface.hpp"
#include "NameRegistration.hpp"

#include <algorithm>
#include <cassert>
#include <cstdlib>
#include <fstream>
#include <iostream>
#include <vector>

using namespace nmcrpc;

/**
 * Display the help message.
 */
static void
displayHelp ()
{
  std::cerr << "Usage: nmupdate COMMAND [OPTIONS]"
            << std::endl << std::endl;
  std::cerr << "Possible commands:" << std::endl;
  std::cerr << "  * help: Display this message." << std::endl;
  std::cerr << "  * list: List owned names and their expirey counter."
            << std::endl;
  std::cerr << "  * update NAME [VAL]: Update NAME to VAL (or existing value)."
            << std::endl;
  std::cerr << "  * send NAME ADDR [VAL]: Update NAME and send to ADDR."
            << std::endl;
  std::cerr << "  * update-multi FILE [VAL]: Update all names in FILE"
            << std::endl
            << "                             to VAL or"
            << " their current value." << std::endl;
  std::cerr << "  * send-multi FILE ADDR [VAL]: Send all names in FILE to ADDR."
            << std::endl;
}

/**
 * Read file into list of names.
 * @param fileName Name of file to read in.
 * @param names Store names here.
 * @throws std::runtime_error if reading fails.
 */
static void
readNames (const std::string& fileName, std::vector<std::string>& names)
{
  std::ifstream in (fileName.c_str ());
  if (!in)
    throw std::runtime_error ("Could not read list of names.");

  while (in)
    {
      std::string line;
      std::getline (in, line);

      if (!line.empty ())
        names.push_back (line);
    }
}

/**
 * Perform a name update operation on an array of names.
 * @param rpc Json RPC connection.
 * @param nc Namecoin high-level interface.
 * @param names Array of names to update.
 * @param hasVal Whether to set the value or leave it.
 * @param val The value, is ignored if !hasVal.
 * @param hasAddr Whether to send to a specified address.
 * @param addr Target address, ignored if !hasAddr.
 */
static void
performUpdate (JsonRpc& rpc, NamecoinInterface& nc,
               const std::vector<std::string>& names,
               bool hasVal, const std::string& val,
               bool hasAddr, const std::string& addr)
{
#ifdef CXX_11
  for (const auto& nm : names)
#else /* CXX_11  */
  for (std::vector<std::string>::const_iterator i = names.begin ();
       i != names.end (); ++i)
#endif /* CXX_11  */
    {
#ifndef CXX_11
      const std::string& nm = *i;
#endif /* !CXX_11  */

      std::cout << "Updating " << nm << ": ";
      NamecoinInterface::Name name = nc.queryName (nm);

      NameUpdate updater (rpc, nc, name);
      if (hasVal)
        updater.setValue (val);

      std::string txid;
      if (!hasAddr)
        txid = updater.execute ();
      else
        txid = updater.execute (nc.queryAddress (addr));

      std::cout << txid << std::endl;
    }
}

/**
 * Compare names for sorting by expiration date.
 * @param a First name.
 * @param b Second name.
 * @return True iff a expires later than b.
 */
static bool
compareNames (const NamecoinInterface::Name& a,
              const NamecoinInterface::Name& b)
{
  int diff = a.getExpireCounter () - b.getExpireCounter ();
  if (diff != 0)
    return (diff > 0);
  return a.getName () < b.getName ();
}

/* Functor instead of addName lambda if we don't have C++11.  */
#ifndef CXX_11
class addNameFunctor
{
private:

  std::vector<NamecoinInterface::Name>& names;

public:

  explicit inline
  addNameFunctor (std::vector<NamecoinInterface::Name>& n)
    : names(n)
  {}

  inline void
  operator() (const NamecoinInterface::Name& nm)
  {
    names.push_back (nm);
  }

};
#endif /* !CXX_11  */

/**
 * Main routine with the usual interface.
 */
int
main (int argc, char** argv)
{
  try
    {
      if (argc < 2)
        {
          displayHelp ();
          return EXIT_FAILURE;
        }
      const std::string command = argv[1];

      if (command == "help")
        {
          displayHelp ();
          return EXIT_SUCCESS;
        }

      RpcSettings settings;
      settings.readDefaultConfig ();
      JsonRpc rpc(settings);
      NamecoinInterface nc(rpc);

      if (command == "list")
        {
          std::vector<NamecoinInterface::Name> names;

#ifdef CXX_11
          const auto addName = [&names] (const NamecoinInterface::Name& nm)
            {
              names.push_back (nm);
            };
#else /* CXX_11  */
          addNameFunctor addName(names);
#endif /* CXX_11  */

          nc.forMyNames (addName);

          std::sort (names.begin (), names.end (), &compareNames);

#ifdef CXX_11
          for (const auto& el : names)
#else /* CXX_11  */
          std::vector<NamecoinInterface::Name>::const_iterator i;
          for (i = names.begin (); i != names.end (); ++i)
#endif /* CXX_11  */
            {
#ifndef CXX_11
              const NamecoinInterface::Name& el = *i;
#endif /* !CXX_11  */

              std::cout.width (30);
              if (!el.isExpired ())
                std::cout << el.getName () << ": "
                          << el.getExpireCounter () << std::endl;
            }
        }
      else
        {
          std::string passphrase;
          if (nc.needWalletPassphrase ())
            {
              std::cout << "Enter wallet passphrase: ";
              std::getline (std::cin, passphrase);
            }
          NamecoinInterface::WalletUnlocker unlock(nc);
          unlock.unlock (passphrase);

          std::vector<std::string> names;

          if (command == "update")
            {
              if (argc < 3 || argc > 4)
                throw std::runtime_error ("Expected: nmupdate update"
                                          " NAME [VAL]");

              const std::string name = argv[2];
              std::string val;
              if (argc == 4)
                val = argv[3];

              names.push_back (name);
              performUpdate (rpc, nc, names, argc == 4, val, false, "");
            }
          else if (command == "update-multi")
            {
              if (argc < 3 || argc > 4)
                throw std::runtime_error ("Expected: nmupdate update-multi"
                                          " FILE [VAL]");

              const std::string file = argv[2];
              std::string val;
              if (argc == 4)
                val = argv[3];

              readNames (file, names);
              performUpdate (rpc, nc, names, argc == 4, val, false, "");
            }
          else if (command == "send")
            {
              if (argc < 4 || argc > 5)
                throw std::runtime_error ("Expected: nmupdate send"
                                          " NAME ADDR [VAL]");

              const std::string name = argv[2];
              const std::string addr = argv[3];
              std::string val;
              if (argc == 5)
                val = argv[4];

              names.push_back (name);
              performUpdate (rpc, nc, names, argc == 5, val, true, addr);
            }
          else if (command == "send-multi")
            {
              if (argc < 4 || argc > 5)
                throw std::runtime_error ("Expected: nmupdate send-multi"
                                          " FILE ADDR [VAL]");

              const std::string file = argv[2];
              const std::string addr = argv[3];
              std::string val;
              if (argc == 5)
                val = argv[4];

              readNames (file, names);
              performUpdate (rpc, nc, names, argc == 5, val, true, addr);
            }
          else
            throw std::runtime_error ("Unknown command '" + command + "'.");
        }
    }
  catch (const JsonRpc::RpcError& exc)
    {
      std::cerr << "JSON-RPC error:" << std::endl;
      std::cerr << exc.getErrorMessage () << std::endl;
      return EXIT_FAILURE;
    }
  catch (const std::exception& exc)
    {
      std::cerr << "Error: " << exc.what () << std::endl;
      return EXIT_FAILURE;
    }

  return EXIT_SUCCESS;
}
<|endoftext|>


<commit_before>/*
    Copyright (c) 2010 Tobias Koenig <tokoe@kde.org>

    This library is free software; you can redistribute it and/or modify it
    under the terms of the GNU Library General Public License as published by
    the Free Software Foundation; either version 2 of the License, or (at your
    option) any later version.

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

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

#include "dbconfig.h"

#include "dbconfigmysql.h"
#include "dbconfigmysqlembedded.h"
#include "dbconfigpostgresql.h"
#include "dbconfigsqlite.h"
#include "dbconfigvirtuoso.h"

#include <akdebug.h>
#include <libs/xdgbasedirs_p.h>

using namespace Akonadi;

//TODO: make me Q_GLOBAL_STATIC
static DbConfig *s_DbConfigInstance = 0;

DbConfig::DbConfig()
{
  const QString serverConfigFile = XdgBaseDirs::akonadiServerConfigFile( XdgBaseDirs::ReadWrite );
  QSettings settings( serverConfigFile, QSettings::IniFormat );

  mSizeThreshold = 4096;
  const QVariant value = settings.value( QLatin1String( "General/SizeThreshold" ), mSizeThreshold );
  if ( value.canConvert<qint64>() )
    mSizeThreshold = value.value<qint64>();
  else
    mSizeThreshold = 0;

  if ( mSizeThreshold < 0 )
    mSizeThreshold = 0;

  mUseExternalPayloadFile = true;
  mUseExternalPayloadFile = settings.value( QLatin1String( "General/ExternalPayload" ), mUseExternalPayloadFile ).toBool();
}

DbConfig::~DbConfig()
{
}

DbConfig* DbConfig::configuredDatabase()
{
  if ( !s_DbConfigInstance ) {
    const QString serverConfigFile = XdgBaseDirs::akonadiServerConfigFile( XdgBaseDirs::ReadWrite );
    QSettings settings( serverConfigFile, QSettings::IniFormat );

    // determine driver to use
    const QString defaultDriver = QLatin1String( "QMYSQL" );
    QString driverName = settings.value( QLatin1String( "General/Driver" ), defaultDriver ).toString();
    if ( driverName.isEmpty() )
      driverName = defaultDriver;

    if ( driverName == QLatin1String( "QMYSQL" ) )
      s_DbConfigInstance = new DbConfigMysql;
    else if ( driverName == QLatin1String( "QMYSQL_EMBEDDED" ) )
      s_DbConfigInstance = new DbConfigMysqlEmbedded;
    else if ( driverName == QLatin1String( "QSQLITE" ) )
      s_DbConfigInstance = new DbConfigSqlite( DbConfigSqlite::Default );
    else if ( driverName == QLatin1String( "QSQLITE3" ) )
      s_DbConfigInstance = new DbConfigSqlite( DbConfigSqlite::Custom );
    else if ( driverName == QLatin1String( "QPSQL" ) )
      s_DbConfigInstance = new DbConfigPostgresql;
    else if ( driverName == QLatin1String( "QODBC" ) )
      s_DbConfigInstance = new DbConfigVirtuoso;
    else {
      akError() << "Unknown database driver: " << driverName;
      akError() << "Available drivers are: " << QSqlDatabase::drivers();
      akFatal();
    }
  }

  return s_DbConfigInstance;
}

void DbConfig::startInternalServer()
{
  // do nothing
}

void DbConfig::stopInternalServer()
{
  // do nothing
}

qint64 DbConfig::sizeThreshold() const
{
  return mSizeThreshold;
}

bool DbConfig::useExternalPayloadFile() const
{
  return mUseExternalPayloadFile;
}
<commit_msg>Use QSQLITE3 as the default driver on Windows CE<commit_after>/*
    Copyright (c) 2010 Tobias Koenig <tokoe@kde.org>

    This library is free software; you can redistribute it and/or modify it
    under the terms of the GNU Library General Public License as published by
    the Free Software Foundation; either version 2 of the License, or (at your
    option) any later version.

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

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

#include "dbconfig.h"

#include "dbconfigmysql.h"
#include "dbconfigmysqlembedded.h"
#include "dbconfigpostgresql.h"
#include "dbconfigsqlite.h"
#include "dbconfigvirtuoso.h"

#include <akdebug.h>
#include <libs/xdgbasedirs_p.h>

using namespace Akonadi;

//TODO: make me Q_GLOBAL_STATIC
static DbConfig *s_DbConfigInstance = 0;

DbConfig::DbConfig()
{
  const QString serverConfigFile = XdgBaseDirs::akonadiServerConfigFile( XdgBaseDirs::ReadWrite );
  QSettings settings( serverConfigFile, QSettings::IniFormat );

  mSizeThreshold = 4096;
  const QVariant value = settings.value( QLatin1String( "General/SizeThreshold" ), mSizeThreshold );
  if ( value.canConvert<qint64>() )
    mSizeThreshold = value.value<qint64>();
  else
    mSizeThreshold = 0;

  if ( mSizeThreshold < 0 )
    mSizeThreshold = 0;

  mUseExternalPayloadFile = true;
  mUseExternalPayloadFile = settings.value( QLatin1String( "General/ExternalPayload" ), mUseExternalPayloadFile ).toBool();
}

DbConfig::~DbConfig()
{
}

DbConfig* DbConfig::configuredDatabase()
{
  if ( !s_DbConfigInstance ) {
    const QString serverConfigFile = XdgBaseDirs::akonadiServerConfigFile( XdgBaseDirs::ReadWrite );
    QSettings settings( serverConfigFile, QSettings::IniFormat );

    // determine driver to use
#ifdef _WIN32_WCE
    // On Windows CE QSQLITE3 is the default driver for Akonadi
    const QString defaultDirver = QLatin1String( "QSQLITE3" );
#else
    const QString defaultDriver = QLatin1String( "QMYSQL" );
#endif
    QString driverName = settings.value( QLatin1String( "General/Driver" ), defaultDriver ).toString();
    if ( driverName.isEmpty() )
      driverName = defaultDriver;

    if ( driverName == QLatin1String( "QMYSQL" ) )
      s_DbConfigInstance = new DbConfigMysql;
    else if ( driverName == QLatin1String( "QMYSQL_EMBEDDED" ) )
      s_DbConfigInstance = new DbConfigMysqlEmbedded;
    else if ( driverName == QLatin1String( "QSQLITE" ) )
      s_DbConfigInstance = new DbConfigSqlite( DbConfigSqlite::Default );
    else if ( driverName == QLatin1String( "QSQLITE3" ) )
      s_DbConfigInstance = new DbConfigSqlite( DbConfigSqlite::Custom );
    else if ( driverName == QLatin1String( "QPSQL" ) )
      s_DbConfigInstance = new DbConfigPostgresql;
    else if ( driverName == QLatin1String( "QODBC" ) )
      s_DbConfigInstance = new DbConfigVirtuoso;
    else {
      akError() << "Unknown database driver: " << driverName;
      akError() << "Available drivers are: " << QSqlDatabase::drivers();
      akFatal();
    }
  }

  return s_DbConfigInstance;
}

void DbConfig::startInternalServer()
{
  // do nothing
}

void DbConfig::stopInternalServer()
{
  // do nothing
}

qint64 DbConfig::sizeThreshold() const
{
  return mSizeThreshold;
}

bool DbConfig::useExternalPayloadFile() const
{
  return mUseExternalPayloadFile;
}
<|endoftext|>


<commit_before>#ifndef _SDD_MEM_LINEAR_ALLOC_HH_
#define _SDD_MEM_LINEAR_ALLOC_HH_

#include <cassert>
#include <cstddef>
#include <memory>

namespace sdd { namespace mem {

/*------------------------------------------------------------------------------------------------*/

namespace {

/// @internal
struct arena
{
  using position_type = char*;

  const std::size_t size_;
  std::unique_ptr<char> buffer_;
  position_type position_;

  arena(std::size_t size)
  noexcept
    : size_(size)
    , buffer_(new char[size_])
    , position_(buffer_.get())
  {}

  ~arena()
  {
    assert(used() == 0 && "Memory arena not rewound.");
  }

  // Can't copy an arena.
  arena(const arena&) = delete;
  arena& operator=(const arena&) = delete;

  char*
  allocate(std::size_t n)
  {
    assert(pointer_in_buffer(position_) && "linear_alloc has outlived arena");
    if (buffer_.get() + size_ - position_ >= n)
    {
      char* r = position_;
      position_ += n;
      return r;
    }
    // Not enough room in the buffer, fallback to default allocator.
    return static_cast<char*>(::operator new(n));
  }

  void
  deallocate(char* p, std::size_t n)
  noexcept
  {
    assert(pointer_in_buffer(position_) && "linear_alloc has outlived arena");
    if (pointer_in_buffer(p))
    {
      if (p + n == position_) // The memory pointed by p was the last allocated one.
      {
        position_ = p;
      }
    }
    else
    {
      // The memory pointer by p was no allocated in this arena.
      ::operator delete(p);
    }
  }

  std::size_t
  used()
  const noexcept
  {
    return static_cast<std::size_t>(position_ - buffer_.get());
  }

  void
  rewind(position_type pos)
  noexcept
  {
    assert(pointer_in_buffer(pos));
    position_ = pos;
  }

  position_type
  position()
  const noexcept
  {
    return position_;
  }

  bool
  pointer_in_buffer(char* p)
  const noexcept
  {
    return buffer_.get() <= p and p <= buffer_.get() + size_;
  }
};

/*------------------------------------------------------------------------------------------------*/

/// @internal
/// @brief Rewind an arena to its initial position.
///
/// Use RAII to ensure that the arena is always rewound to its initial position .
struct rewinder
{
  /// @brief The associated memory arena.
  arena& a_;

  /// @brief The position where to rewind the associated arena.
  const arena::position_type pos_;

  /// @brief Constructor.
  ///
  /// Initialize the position to the current position of the arena.
  rewinder(arena& a)
  noexcept
    : a_(a), pos_(a.position())
  {}

  /// @brief Destructor.
  ///
  /// Rewind the arena to its position when this object was constructed;
  ~rewinder()
  {
    a_.rewind(pos_);
  }

  // Can't copy a rewinder.
  rewinder(const rewinder&) = delete;
  rewinder& operator=(const rewinder&) = delete;

  // Can't move a rewinder.
  rewinder(rewinder&&) = delete;
  rewinder& operator=(rewinder&&) = delete;
};

/*------------------------------------------------------------------------------------------------*/

} // namespace anonymous

/*------------------------------------------------------------------------------------------------*/

/// @internal
/// @brief Allocate memory contiguously in a preallocated buffer.
///
/// Memory is allocated by moving a pointer in the buffer. Only the memory which was the last
/// one thas was allocated can be deallocated. Thus, this allocator would mostly benefit to
/// recursive algorithms which need a stack.
/// It's an adaptation of http://home.roadrunner.com/~hinnant/stack_alloc.html .
template <class T>
struct linear_alloc
{
  using value_type = T;

  arena& a_;

  template <class _Up>
  struct rebind
  {
    using other = linear_alloc<_Up>;
  };

  linear_alloc(arena& a)
  noexcept
    : a_(a)
  {}

  template <class U>
  linear_alloc(const linear_alloc<U>& other)
  noexcept
    : a_(other.a_)
  {}

  linear_alloc(const linear_alloc&) = default;
  linear_alloc& operator=(const linear_alloc&) = delete;

  T*
  allocate(std::size_t n)
  const
  {
    return reinterpret_cast<T*>(a_.allocate(n*sizeof(T)));
  }

  void
  deallocate(T* p, std::size_t n)
  const noexcept
  {
    a_.deallocate(reinterpret_cast<char*>(p), n*sizeof(T));
  }

  template <class U, class V>
  friend
  bool
  operator==(const linear_alloc<U>& lhs, const linear_alloc<V>& rhs)
  noexcept
  {
    return &lhs.a_ == &rhs.a_;
  }

  template <class U> friend struct linear_alloc;
};

/*------------------------------------------------------------------------------------------------*/

}} // namespace sdd::mem

#endif // _SDD_MEM_LINEAR_ALLOC_HH_
<commit_msg>Refine the assertion made at the arena's end of life.<commit_after>#ifndef _SDD_MEM_LINEAR_ALLOC_HH_
#define _SDD_MEM_LINEAR_ALLOC_HH_

#include <cassert>
#include <cstddef>
#include <memory>

namespace sdd { namespace mem {

/*------------------------------------------------------------------------------------------------*/

namespace {

/// @internal
/// @brief A memory arena for linear_alloc.
///
/// Everything is private in this class: this arena can only be manipulated with a rewinder and
/// a linear_alloc.
struct arena
{
  // Can't copy an arena.
  arena(const arena&) = delete;
  arena& operator=(const arena&) = delete;

  using position_type = char*;

  /// @brief The size of this memory arena.
  const std::size_t size_;

  /// @brief The underlying memory buffer.
  std::unique_ptr<char> buffer_;

  /// @brief The beginning of the free memory.
  position_type position_;

#ifndef NDEBUG
  /// @brief The number of time this arena has been used with a rewinder.
  unsigned int active_;

  /// @brief The number of allocated bytes when this arena wasn't referenced by any rewinder.
  std::size_t unactive_allocated_;
#endif

  /// @brief Construct an arena with a given size.
  arena(std::size_t size)
  noexcept
    : size_(size)
    , buffer_(new char[size_])
    , position_(buffer_.get())
#ifndef NDEBUG
    , active_(0)
    , unactive_allocated_(0)
#endif
  {}

#ifndef NDEBUG
  ~arena()
  {
    // We admit that some bytes can never be deallocated. As a matter of fact, it would be very
    // complex to keep track of the memory allocated when no rewinder is used. For instance,
    // when the user creates a sum, the underlying container uses the linear allocator, but without
    // a rewinder. This is why we keep a trace of the number of rewinders with active_.
    assert(used() == unactive_allocated_ && "Memory arena not rewound.");
  }
#endif

  char*
  allocate(std::size_t n)
  {
    assert(pointer_in_buffer(position_) && "linear_alloc has outlived arena");
    if (buffer_.get() + size_ - position_ >= n)
    {
#ifndef NDEBUG
      if (active_ == 0)
      {
        unactive_allocated_ += n;
      }
#endif
      char* r = position_;
      position_ += n;
      return r;
    }
    // Not enough room in the buffer, fallback to the default allocator.
    return static_cast<char*>(::operator new(n));
  }

  void
  deallocate(char* p, std::size_t n)
  noexcept
  {
    assert(pointer_in_buffer(position_) && "linear_alloc has outlived arena");
    if (pointer_in_buffer(p))
    {
      if (p + n == position_) // The memory pointed by p was the last allocated one.
      {
#ifndef NDEBUG
        if (active_ == 0)
        {
          unactive_allocated_ -= n;
        }
#endif
        position_ = p;
      }
    }
    else
    {
      // The memory pointed by p was no allocated in this arena.
      ::operator delete(p);
    }
  }

  void
  rewind(position_type pos)
  noexcept
  {
    assert(pointer_in_buffer(pos));
    position_ = pos;
  }

  position_type
  position()
  const noexcept
  {
    return position_;
  }

  bool
  pointer_in_buffer(char* p)
  const noexcept
  {
    return buffer_.get() <= p and p <= buffer_.get() + size_;
  }

#ifndef NDEBUG
  std::size_t
  used()
  const noexcept
  {
    return static_cast<std::size_t>(position_ - buffer_.get());
  }

  void
  activate()
  noexcept
  {
    active_ += 1;
  }

  void
  deactivate()
  noexcept
  {
    active_ -= 1;
  }
#endif
};

/*------------------------------------------------------------------------------------------------*/

/// @internal
/// @brief Rewind an arena to its initial position.
///
/// Use RAII to ensure that the arena is always rewound to its initial position .
class rewinder
{
  // Can't copy a rewinder.
  rewinder(const rewinder&) = delete;
  rewinder& operator=(const rewinder&) = delete;

  // Can't move a rewinder.
  rewinder(rewinder&&) = delete;
  rewinder& operator=(rewinder&&) = delete;

private:

  /// @brief The associated memory arena.
  arena& a_;

  /// @brief The position where to rewind the associated arena.
  const arena::position_type pos_;

public:

  /// @brief Constructor.
  ///
  /// Initialize the position to the current position of the arena.
  rewinder(arena& a)
  noexcept
    : a_(a), pos_(a.position())
  {
#ifndef NDEBUG
    a_.activate();
#endif
  }

  /// @brief Destructor.
  ///
  /// Rewind the arena to its position when this object was constructed;
  ~rewinder()
  {
    a_.rewind(pos_);
#ifndef NDEBUG
    a_.deactivate();
#endif
  }
};

/*------------------------------------------------------------------------------------------------*/

} // namespace anonymous

/*------------------------------------------------------------------------------------------------*/

/// @internal
/// @brief Allocate memory contiguously in a preallocated buffer.
///
/// Memory is allocated by moving a pointer in the buffer. Only the memory which was the last
/// one thas was allocated can be deallocated. Thus, this allocator would mostly benefit to
/// recursive algorithms which need a stack.
/// It's an adaptation of http://home.roadrunner.com/~hinnant/stack_alloc.html .
template <typename T>
class linear_alloc
{
public:

  using value_type = T;

private:
  arena& a_;

public:

  template <typename _Up>
  struct rebind
  {
    using other = linear_alloc<_Up>;
  };

  linear_alloc(arena& a)
  noexcept
    : a_(a)
  {}

  template <typename U>
  linear_alloc(const linear_alloc<U>& other)
  noexcept
    : a_(other.a_)
  {}

  linear_alloc(const linear_alloc&) = default;
  linear_alloc& operator=(const linear_alloc&) = delete;

  T*
  allocate(std::size_t n)
  const
  {
    return reinterpret_cast<T*>(a_.allocate(n*sizeof(T)));
  }

  void
  deallocate(T* p, std::size_t n)
  const noexcept
  {
    a_.deallocate(reinterpret_cast<char*>(p), n*sizeof(T));
  }

  template <typename U, typename V>
  friend
  bool
  operator==(const linear_alloc<U>& lhs, const linear_alloc<V>& rhs)
  noexcept
  {
    return &lhs.a_ == &rhs.a_;
  }

  template <typename U> friend class linear_alloc;
};

/*------------------------------------------------------------------------------------------------*/

}} // namespace sdd::mem

#endif // _SDD_MEM_LINEAR_ALLOC_HH_
<|endoftext|>


<commit_before>#include "SavePresetDialog.hpp"

#include <cstddef>
#include <vector>
#include <string>
#include <boost/algorithm/string.hpp>

#include <wx/sizer.h>
#include <wx/stattext.h>
#include <wx/wupdlock.h>

#include "libslic3r/PresetBundle.hpp"

#include "GUI.hpp"
#include "GUI_App.hpp"
#include "format.hpp"
#include "Tab.hpp"

using Slic3r::GUI::format_wxstr;

namespace Slic3r {
namespace GUI {

#define BORDER_W 10

//-----------------------------------------------
//          SavePresetDialog::Item
//-----------------------------------------------

SavePresetDialog::Item::Item(Preset::Type type, const std::string& suffix, wxBoxSizer* sizer, SavePresetDialog* parent):
    m_type(type),
    m_parent(parent)
{
    Tab* tab = wxGetApp().get_tab(m_type);
    assert(tab);
    m_presets = tab->get_presets();

    const Preset& sel_preset = m_presets->get_selected_preset();
    std::string preset_name =   sel_preset.is_default ? "Untitled" :
                                sel_preset.is_system ? (boost::format(("%1% - %2%")) % sel_preset.name % suffix).str() :
                                sel_preset.name;

    // if name contains extension
    if (boost::iends_with(preset_name, ".ini")) {
        size_t len = preset_name.length() - 4;
        preset_name.resize(len);
    }

    std::vector<std::string> values;
    for (const Preset& preset : *m_presets) {
        if (preset.is_default || preset.is_system || preset.is_external)
            continue;
        values.push_back(preset.name);
    }

    wxStaticText* label_top = new wxStaticText(m_parent, wxID_ANY, from_u8((boost::format(_utf8(L("Save %s as:"))) % into_u8(tab->title())).str()));

    m_valid_bmp = new wxStaticBitmap(m_parent, wxID_ANY, create_scaled_bitmap("tick_mark", m_parent));

    m_combo = new wxComboBox(m_parent, wxID_ANY, from_u8(preset_name), wxDefaultPosition, wxSize(35 * wxGetApp().em_unit(), -1));
    for (const std::string& value : values)
        m_combo->Append(from_u8(value));

    m_combo->Bind(wxEVT_TEXT, [this](wxCommandEvent&) { update(); });
#ifdef __WXOSX__
    // Under OSX wxEVT_TEXT wasn't invoked after change selection in combobox,
    // So process wxEVT_COMBOBOX too
    m_combo->Bind(wxEVT_COMBOBOX, [this](wxCommandEvent&) { update(); });
#endif //__WXOSX__

    m_valid_label = new wxStaticText(m_parent, wxID_ANY, "");
    m_valid_label->SetFont(wxGetApp().bold_font());

    wxBoxSizer* combo_sizer = new wxBoxSizer(wxHORIZONTAL);
    combo_sizer->Add(m_valid_bmp,   0, wxALIGN_CENTER_VERTICAL | wxRIGHT, BORDER_W);
    combo_sizer->Add(m_combo,       1, wxEXPAND, BORDER_W);

    sizer->Add(label_top,       0, wxEXPAND | wxTOP| wxBOTTOM, BORDER_W);
    sizer->Add(combo_sizer,     0, wxEXPAND | wxBOTTOM, BORDER_W);
    sizer->Add(m_valid_label,   0, wxEXPAND | wxLEFT,   3*BORDER_W);

    if (m_type == Preset::TYPE_PRINTER)
        m_parent->add_info_for_edit_ph_printer(sizer);

    update();
}

void SavePresetDialog::Item::update()
{
    m_preset_name = into_u8(m_combo->GetValue());

    m_valid_type = Valid;
    wxString info_line;

    const char* unusable_symbols = "<>[]:/\\|?*\"";

    const std::string unusable_suffix = PresetCollection::get_suffix_modified();//"(modified)";
    for (size_t i = 0; i < std::strlen(unusable_symbols); i++) {
        if (m_preset_name.find_first_of(unusable_symbols[i]) != std::string::npos) {
            info_line = _L("The supplied name is not valid;") + "\n" +
                        _L("the following characters are not allowed:") + " " + unusable_symbols;
            m_valid_type = NoValid;
            break;
        }
    }

    if (m_valid_type == Valid && m_preset_name.find(unusable_suffix) != std::string::npos) {
        info_line = _L("The supplied name is not valid;") + "\n" +
                    _L("the following suffix is not allowed:") + "\n\t" +
                    from_u8(PresetCollection::get_suffix_modified());
        m_valid_type = NoValid;
    }

    if (m_valid_type == Valid && m_preset_name == "- default -") {
        info_line = _L("The supplied name is not available.");
        m_valid_type = NoValid;
    }

    const Preset* existing = m_presets->find_preset(m_preset_name, false);
    if (m_valid_type == Valid && existing && (existing->is_default || existing->is_system)) {
        info_line = _L("Cannot overwrite a system profile.");
        m_valid_type = NoValid;
    }

    if (m_valid_type == Valid && existing && (existing->is_external)) {
        info_line = _L("Cannot overwrite an external profile.");
        m_valid_type = NoValid;
    }

    if (m_valid_type == Valid && existing && m_preset_name != m_presets->get_selected_preset_name())
    {
        if (existing->is_compatible)
            info_line = from_u8((boost::format(_u8L("Preset with name \"%1%\" already exists.")) % m_preset_name).str());
        else
            info_line = from_u8((boost::format(_u8L("Preset with name \"%1%\" already exists and is imcopatible with selected printer.")) % m_preset_name).str());
        info_line += "\n" + _L("Note: This preset will be replaced after saving");
        m_valid_type = Warning;
    }

    if (m_valid_type == Valid && m_preset_name.empty()) {
        info_line = _L("The name cannot be empty.");
        m_valid_type = NoValid;
    }

    m_valid_label->SetLabel(info_line);
    m_valid_label->Show(!info_line.IsEmpty());

    update_valid_bmp();

    if (m_type == Preset::TYPE_PRINTER)
        m_parent->update_info_for_edit_ph_printer(m_preset_name);

    m_parent->layout();
}

void SavePresetDialog::Item::update_valid_bmp()
{
    std::string bmp_name =  m_valid_type == Warning ? "exclamation" :
                            m_valid_type == NoValid ? "cross"       : "tick_mark" ;
    m_valid_bmp->SetBitmap(create_scaled_bitmap(bmp_name, m_parent));
}

void SavePresetDialog::Item::accept()
{
    if (m_valid_type == Warning)
        m_presets->delete_preset(m_preset_name);
}

//-----------------------------------------------
//          SavePresetDialog
//-----------------------------------------------

SavePresetDialog::SavePresetDialog(wxWindow* parent, Preset::Type type, std::string suffix)
    : DPIDialog(parent, wxID_ANY, _L("Save preset"), wxDefaultPosition, wxSize(45 * wxGetApp().em_unit(), 5 * wxGetApp().em_unit()), wxDEFAULT_DIALOG_STYLE | wxICON_WARNING | wxRESIZE_BORDER)
{
    build(std::vector<Preset::Type>{type}, suffix);
}

SavePresetDialog::SavePresetDialog(wxWindow* parent, std::vector<Preset::Type> types, std::string suffix)
    : DPIDialog(parent, wxID_ANY, _L("Save preset"), wxDefaultPosition, wxSize(45 * wxGetApp().em_unit(), 5 * wxGetApp().em_unit()), wxDEFAULT_DIALOG_STYLE | wxICON_WARNING | wxRESIZE_BORDER)
{
    build(types, suffix);
}

SavePresetDialog::~SavePresetDialog()
{
    for (auto  item : m_items) {
        delete item;
    }
}

void SavePresetDialog::build(std::vector<Preset::Type> types, std::string suffix)
{
    SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW));
#if ENABLE_WX_3_1_3_DPI_CHANGED_EVENT && defined(__WXMSW__)
    // ys_FIXME! temporary workaround for correct font scaling
    // Because of from wxWidgets 3.1.3 auto rescaling is implemented for the Fonts,
    // From the very beginning set dialog font to the wxSYS_DEFAULT_GUI_FONT
    this->SetFont(wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT));
#endif // ENABLE_WX_3_1_3_DPI_CHANGED_EVENT

    if (suffix.empty())
        suffix = _CTX_utf8(L_CONTEXT("Copy", "PresetName"), "PresetName");

    wxBoxSizer* topSizer = new wxBoxSizer(wxVERTICAL);

    m_presets_sizer = new wxBoxSizer(wxVERTICAL);

    // Add first item
    for (Preset::Type type : types)
        AddItem(type, suffix);

    // Add dialog's buttons
    wxStdDialogButtonSizer* btns = this->CreateStdDialogButtonSizer(wxOK | wxCANCEL);
    wxButton* btnOK = static_cast<wxButton*>(this->FindWindowById(wxID_OK, this));
    btnOK->Bind(wxEVT_BUTTON,    [this](wxCommandEvent&)        { accept(); });
    btnOK->Bind(wxEVT_UPDATE_UI, [this](wxUpdateUIEvent& evt)   { evt.Enable(enable_ok_btn()); });

    topSizer->Add(m_presets_sizer,  0, wxEXPAND | wxALL, BORDER_W);
    topSizer->Add(btns,             0, wxEXPAND | wxALL, BORDER_W);

    SetSizer(topSizer);
    topSizer->SetSizeHints(this);

    this->CenterOnScreen();
}

void SavePresetDialog::AddItem(Preset::Type type, const std::string& suffix)
{
    m_items.emplace_back(new Item{type, suffix, m_presets_sizer, this});
}

std::string SavePresetDialog::get_name()
{
    return m_items.front()->preset_name();
}

std::string SavePresetDialog::get_name(Preset::Type type)
{
    for (const Item* item : m_items)
        if (item->type() == type)
            return item->preset_name();
    return "";
}

bool SavePresetDialog::enable_ok_btn() const
{
    for (const Item* item : m_items)
        if (!item->is_valid())
            return false;

    return true;
}

void SavePresetDialog::add_info_for_edit_ph_printer(wxBoxSizer* sizer)
{
    PhysicalPrinterCollection& printers = wxGetApp().preset_bundle->physical_printers;
    m_ph_printer_name = printers.get_selected_printer_name();
    m_old_preset_name = printers.get_selected_printer_preset_name();

    wxString msg_text = from_u8((boost::format(_u8L("You have selected physical printer \"%1%\" \n"
                                                    "with related printer preset \"%2%\"")) %
                                                    m_ph_printer_name % m_old_preset_name).str());
    m_label = new wxStaticText(this, wxID_ANY, msg_text);
    m_label->SetFont(wxGetApp().bold_font());

    wxString choices[] = {"","",""};

    m_action_radio_box = new wxRadioBox(this, wxID_ANY, "", wxDefaultPosition, wxDefaultSize,
                                        WXSIZEOF(choices), choices, 3, wxRA_SPECIFY_ROWS);
    m_action_radio_box->SetSelection(0);
    m_action_radio_box->Bind(wxEVT_RADIOBOX, [this](wxCommandEvent& e) {
        m_action = (ActionType)e.GetSelection(); });
    m_action = ChangePreset;

    m_radio_sizer = new wxBoxSizer(wxHORIZONTAL);
    m_radio_sizer->Add(m_action_radio_box, 1, wxEXPAND | wxTOP, 2*BORDER_W);

    sizer->Add(m_label,         0, wxEXPAND | wxLEFT | wxTOP,   3*BORDER_W);
    sizer->Add(m_radio_sizer,   1, wxEXPAND | wxLEFT,           3*BORDER_W);
}

void SavePresetDialog::update_info_for_edit_ph_printer(const std::string& preset_name)
{
    bool show = wxGetApp().preset_bundle->physical_printers.has_selection() && m_old_preset_name != preset_name;

    m_label->Show(show);
    m_radio_sizer->ShowItems(show);
    if (!show) {
        this->SetMinSize(wxSize(100,50));
        return;
    }

    wxString msg_text = from_u8((boost::format(_u8L("What would you like to do with \"%1%\" preset after saving?")) % preset_name).str());
    m_action_radio_box->SetLabel(msg_text);

    wxString choices[] = { from_u8((boost::format(_u8L("Change \"%1%\" to \"%2%\" for this physical printer \"%3%\"")) % m_old_preset_name % preset_name % m_ph_printer_name).str()),
                           from_u8((boost::format(_u8L("Add \"%1%\" as a next preset for the the physical printer \"%2%\"")) % preset_name % m_ph_printer_name).str()),
                           from_u8((boost::format(_u8L("Just switch to \"%1%\" preset")) % preset_name).str()) };

    int n = 0;
    for(const wxString& label: choices)
        m_action_radio_box->SetString(n++, label);
}

void SavePresetDialog::layout()
{
    this->Layout();
    this->Fit();
}

void SavePresetDialog::on_dpi_changed(const wxRect& suggested_rect)
{
    const int& em = em_unit();

    msw_buttons_rescale(this, em, { wxID_OK, wxID_CANCEL });

    for (Item* item : m_items)
        item->update_valid_bmp();

    //const wxSize& size = wxSize(45 * em, 35 * em);
    SetMinSize(/*size*/wxSize(100, 50));

    Fit();
    Refresh();
}

void SavePresetDialog::update_physical_printers(const std::string& preset_name)
{
    if (m_action == UndefAction)
        return;

    PhysicalPrinterCollection& physical_printers = wxGetApp().preset_bundle->physical_printers;
    if (!physical_printers.has_selection())
        return;

    std::string printer_preset_name = physical_printers.get_selected_printer_preset_name();

    if (m_action == Switch)
        // unselect physical printer, if it was selected
        physical_printers.unselect_printer();
    else
    {
        PhysicalPrinter printer = physical_printers.get_selected_printer();

        if (m_action == ChangePreset)
            printer.delete_preset(printer_preset_name);

        if (printer.add_preset(preset_name))
            physical_printers.save_printer(printer);

        physical_printers.select_printer(printer.get_full_name(preset_name));
    }
}

void SavePresetDialog::accept()
{
    for (Item* item : m_items) {
        item->accept();
        if (item->type() == Preset::TYPE_PRINTER)
            update_physical_printers(item->preset_name());
    }

    EndModal(wxID_OK);
}

}}    // namespace Slic3r::GUI
<commit_msg>Fixes Spelling Error in Unsaved changes dialog (#5363)<commit_after>#include "SavePresetDialog.hpp"

#include <cstddef>
#include <vector>
#include <string>
#include <boost/algorithm/string.hpp>

#include <wx/sizer.h>
#include <wx/stattext.h>
#include <wx/wupdlock.h>

#include "libslic3r/PresetBundle.hpp"

#include "GUI.hpp"
#include "GUI_App.hpp"
#include "format.hpp"
#include "Tab.hpp"

using Slic3r::GUI::format_wxstr;

namespace Slic3r {
namespace GUI {

#define BORDER_W 10

//-----------------------------------------------
//          SavePresetDialog::Item
//-----------------------------------------------

SavePresetDialog::Item::Item(Preset::Type type, const std::string& suffix, wxBoxSizer* sizer, SavePresetDialog* parent):
    m_type(type),
    m_parent(parent)
{
    Tab* tab = wxGetApp().get_tab(m_type);
    assert(tab);
    m_presets = tab->get_presets();

    const Preset& sel_preset = m_presets->get_selected_preset();
    std::string preset_name =   sel_preset.is_default ? "Untitled" :
                                sel_preset.is_system ? (boost::format(("%1% - %2%")) % sel_preset.name % suffix).str() :
                                sel_preset.name;

    // if name contains extension
    if (boost::iends_with(preset_name, ".ini")) {
        size_t len = preset_name.length() - 4;
        preset_name.resize(len);
    }

    std::vector<std::string> values;
    for (const Preset& preset : *m_presets) {
        if (preset.is_default || preset.is_system || preset.is_external)
            continue;
        values.push_back(preset.name);
    }

    wxStaticText* label_top = new wxStaticText(m_parent, wxID_ANY, from_u8((boost::format(_utf8(L("Save %s as:"))) % into_u8(tab->title())).str()));

    m_valid_bmp = new wxStaticBitmap(m_parent, wxID_ANY, create_scaled_bitmap("tick_mark", m_parent));

    m_combo = new wxComboBox(m_parent, wxID_ANY, from_u8(preset_name), wxDefaultPosition, wxSize(35 * wxGetApp().em_unit(), -1));
    for (const std::string& value : values)
        m_combo->Append(from_u8(value));

    m_combo->Bind(wxEVT_TEXT, [this](wxCommandEvent&) { update(); });
#ifdef __WXOSX__
    // Under OSX wxEVT_TEXT wasn't invoked after change selection in combobox,
    // So process wxEVT_COMBOBOX too
    m_combo->Bind(wxEVT_COMBOBOX, [this](wxCommandEvent&) { update(); });
#endif //__WXOSX__

    m_valid_label = new wxStaticText(m_parent, wxID_ANY, "");
    m_valid_label->SetFont(wxGetApp().bold_font());

    wxBoxSizer* combo_sizer = new wxBoxSizer(wxHORIZONTAL);
    combo_sizer->Add(m_valid_bmp,   0, wxALIGN_CENTER_VERTICAL | wxRIGHT, BORDER_W);
    combo_sizer->Add(m_combo,       1, wxEXPAND, BORDER_W);

    sizer->Add(label_top,       0, wxEXPAND | wxTOP| wxBOTTOM, BORDER_W);
    sizer->Add(combo_sizer,     0, wxEXPAND | wxBOTTOM, BORDER_W);
    sizer->Add(m_valid_label,   0, wxEXPAND | wxLEFT,   3*BORDER_W);

    if (m_type == Preset::TYPE_PRINTER)
        m_parent->add_info_for_edit_ph_printer(sizer);

    update();
}

void SavePresetDialog::Item::update()
{
    m_preset_name = into_u8(m_combo->GetValue());

    m_valid_type = Valid;
    wxString info_line;

    const char* unusable_symbols = "<>[]:/\\|?*\"";

    const std::string unusable_suffix = PresetCollection::get_suffix_modified();//"(modified)";
    for (size_t i = 0; i < std::strlen(unusable_symbols); i++) {
        if (m_preset_name.find_first_of(unusable_symbols[i]) != std::string::npos) {
            info_line = _L("The supplied name is not valid;") + "\n" +
                        _L("the following characters are not allowed:") + " " + unusable_symbols;
            m_valid_type = NoValid;
            break;
        }
    }

    if (m_valid_type == Valid && m_preset_name.find(unusable_suffix) != std::string::npos) {
        info_line = _L("The supplied name is not valid;") + "\n" +
                    _L("the following suffix is not allowed:") + "\n\t" +
                    from_u8(PresetCollection::get_suffix_modified());
        m_valid_type = NoValid;
    }

    if (m_valid_type == Valid && m_preset_name == "- default -") {
        info_line = _L("The supplied name is not available.");
        m_valid_type = NoValid;
    }

    const Preset* existing = m_presets->find_preset(m_preset_name, false);
    if (m_valid_type == Valid && existing && (existing->is_default || existing->is_system)) {
        info_line = _L("Cannot overwrite a system profile.");
        m_valid_type = NoValid;
    }

    if (m_valid_type == Valid && existing && (existing->is_external)) {
        info_line = _L("Cannot overwrite an external profile.");
        m_valid_type = NoValid;
    }

    if (m_valid_type == Valid && existing && m_preset_name != m_presets->get_selected_preset_name())
    {
        if (existing->is_compatible)
            info_line = from_u8((boost::format(_u8L("Preset with name \"%1%\" already exists.")) % m_preset_name).str());
        else
            info_line = from_u8((boost::format(_u8L("Preset with name \"%1%\" already exists and is incopatible with selected printer.")) % m_preset_name).str());
        info_line += "\n" + _L("Note: This preset will be replaced after saving");
        m_valid_type = Warning;
    }

    if (m_valid_type == Valid && m_preset_name.empty()) {
        info_line = _L("The name cannot be empty.");
        m_valid_type = NoValid;
    }

    m_valid_label->SetLabel(info_line);
    m_valid_label->Show(!info_line.IsEmpty());

    update_valid_bmp();

    if (m_type == Preset::TYPE_PRINTER)
        m_parent->update_info_for_edit_ph_printer(m_preset_name);

    m_parent->layout();
}

void SavePresetDialog::Item::update_valid_bmp()
{
    std::string bmp_name =  m_valid_type == Warning ? "exclamation" :
                            m_valid_type == NoValid ? "cross"       : "tick_mark" ;
    m_valid_bmp->SetBitmap(create_scaled_bitmap(bmp_name, m_parent));
}

void SavePresetDialog::Item::accept()
{
    if (m_valid_type == Warning)
        m_presets->delete_preset(m_preset_name);
}

//-----------------------------------------------
//          SavePresetDialog
//-----------------------------------------------

SavePresetDialog::SavePresetDialog(wxWindow* parent, Preset::Type type, std::string suffix)
    : DPIDialog(parent, wxID_ANY, _L("Save preset"), wxDefaultPosition, wxSize(45 * wxGetApp().em_unit(), 5 * wxGetApp().em_unit()), wxDEFAULT_DIALOG_STYLE | wxICON_WARNING | wxRESIZE_BORDER)
{
    build(std::vector<Preset::Type>{type}, suffix);
}

SavePresetDialog::SavePresetDialog(wxWindow* parent, std::vector<Preset::Type> types, std::string suffix)
    : DPIDialog(parent, wxID_ANY, _L("Save preset"), wxDefaultPosition, wxSize(45 * wxGetApp().em_unit(), 5 * wxGetApp().em_unit()), wxDEFAULT_DIALOG_STYLE | wxICON_WARNING | wxRESIZE_BORDER)
{
    build(types, suffix);
}

SavePresetDialog::~SavePresetDialog()
{
    for (auto  item : m_items) {
        delete item;
    }
}

void SavePresetDialog::build(std::vector<Preset::Type> types, std::string suffix)
{
    SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW));
#if ENABLE_WX_3_1_3_DPI_CHANGED_EVENT && defined(__WXMSW__)
    // ys_FIXME! temporary workaround for correct font scaling
    // Because of from wxWidgets 3.1.3 auto rescaling is implemented for the Fonts,
    // From the very beginning set dialog font to the wxSYS_DEFAULT_GUI_FONT
    this->SetFont(wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT));
#endif // ENABLE_WX_3_1_3_DPI_CHANGED_EVENT

    if (suffix.empty())
        suffix = _CTX_utf8(L_CONTEXT("Copy", "PresetName"), "PresetName");

    wxBoxSizer* topSizer = new wxBoxSizer(wxVERTICAL);

    m_presets_sizer = new wxBoxSizer(wxVERTICAL);

    // Add first item
    for (Preset::Type type : types)
        AddItem(type, suffix);

    // Add dialog's buttons
    wxStdDialogButtonSizer* btns = this->CreateStdDialogButtonSizer(wxOK | wxCANCEL);
    wxButton* btnOK = static_cast<wxButton*>(this->FindWindowById(wxID_OK, this));
    btnOK->Bind(wxEVT_BUTTON,    [this](wxCommandEvent&)        { accept(); });
    btnOK->Bind(wxEVT_UPDATE_UI, [this](wxUpdateUIEvent& evt)   { evt.Enable(enable_ok_btn()); });

    topSizer->Add(m_presets_sizer,  0, wxEXPAND | wxALL, BORDER_W);
    topSizer->Add(btns,             0, wxEXPAND | wxALL, BORDER_W);

    SetSizer(topSizer);
    topSizer->SetSizeHints(this);

    this->CenterOnScreen();
}

void SavePresetDialog::AddItem(Preset::Type type, const std::string& suffix)
{
    m_items.emplace_back(new Item{type, suffix, m_presets_sizer, this});
}

std::string SavePresetDialog::get_name()
{
    return m_items.front()->preset_name();
}

std::string SavePresetDialog::get_name(Preset::Type type)
{
    for (const Item* item : m_items)
        if (item->type() == type)
            return item->preset_name();
    return "";
}

bool SavePresetDialog::enable_ok_btn() const
{
    for (const Item* item : m_items)
        if (!item->is_valid())
            return false;

    return true;
}

void SavePresetDialog::add_info_for_edit_ph_printer(wxBoxSizer* sizer)
{
    PhysicalPrinterCollection& printers = wxGetApp().preset_bundle->physical_printers;
    m_ph_printer_name = printers.get_selected_printer_name();
    m_old_preset_name = printers.get_selected_printer_preset_name();

    wxString msg_text = from_u8((boost::format(_u8L("You have selected physical printer \"%1%\" \n"
                                                    "with related printer preset \"%2%\"")) %
                                                    m_ph_printer_name % m_old_preset_name).str());
    m_label = new wxStaticText(this, wxID_ANY, msg_text);
    m_label->SetFont(wxGetApp().bold_font());

    wxString choices[] = {"","",""};

    m_action_radio_box = new wxRadioBox(this, wxID_ANY, "", wxDefaultPosition, wxDefaultSize,
                                        WXSIZEOF(choices), choices, 3, wxRA_SPECIFY_ROWS);
    m_action_radio_box->SetSelection(0);
    m_action_radio_box->Bind(wxEVT_RADIOBOX, [this](wxCommandEvent& e) {
        m_action = (ActionType)e.GetSelection(); });
    m_action = ChangePreset;

    m_radio_sizer = new wxBoxSizer(wxHORIZONTAL);
    m_radio_sizer->Add(m_action_radio_box, 1, wxEXPAND | wxTOP, 2*BORDER_W);

    sizer->Add(m_label,         0, wxEXPAND | wxLEFT | wxTOP,   3*BORDER_W);
    sizer->Add(m_radio_sizer,   1, wxEXPAND | wxLEFT,           3*BORDER_W);
}

void SavePresetDialog::update_info_for_edit_ph_printer(const std::string& preset_name)
{
    bool show = wxGetApp().preset_bundle->physical_printers.has_selection() && m_old_preset_name != preset_name;

    m_label->Show(show);
    m_radio_sizer->ShowItems(show);
    if (!show) {
        this->SetMinSize(wxSize(100,50));
        return;
    }

    wxString msg_text = from_u8((boost::format(_u8L("What would you like to do with \"%1%\" preset after saving?")) % preset_name).str());
    m_action_radio_box->SetLabel(msg_text);

    wxString choices[] = { from_u8((boost::format(_u8L("Change \"%1%\" to \"%2%\" for this physical printer \"%3%\"")) % m_old_preset_name % preset_name % m_ph_printer_name).str()),
                           from_u8((boost::format(_u8L("Add \"%1%\" as a next preset for the the physical printer \"%2%\"")) % preset_name % m_ph_printer_name).str()),
                           from_u8((boost::format(_u8L("Just switch to \"%1%\" preset")) % preset_name).str()) };

    int n = 0;
    for(const wxString& label: choices)
        m_action_radio_box->SetString(n++, label);
}

void SavePresetDialog::layout()
{
    this->Layout();
    this->Fit();
}

void SavePresetDialog::on_dpi_changed(const wxRect& suggested_rect)
{
    const int& em = em_unit();

    msw_buttons_rescale(this, em, { wxID_OK, wxID_CANCEL });

    for (Item* item : m_items)
        item->update_valid_bmp();

    //const wxSize& size = wxSize(45 * em, 35 * em);
    SetMinSize(/*size*/wxSize(100, 50));

    Fit();
    Refresh();
}

void SavePresetDialog::update_physical_printers(const std::string& preset_name)
{
    if (m_action == UndefAction)
        return;

    PhysicalPrinterCollection& physical_printers = wxGetApp().preset_bundle->physical_printers;
    if (!physical_printers.has_selection())
        return;

    std::string printer_preset_name = physical_printers.get_selected_printer_preset_name();

    if (m_action == Switch)
        // unselect physical printer, if it was selected
        physical_printers.unselect_printer();
    else
    {
        PhysicalPrinter printer = physical_printers.get_selected_printer();

        if (m_action == ChangePreset)
            printer.delete_preset(printer_preset_name);

        if (printer.add_preset(preset_name))
            physical_printers.save_printer(printer);

        physical_printers.select_printer(printer.get_full_name(preset_name));
    }
}

void SavePresetDialog::accept()
{
    for (Item* item : m_items) {
        item->accept();
        if (item->type() == Preset::TYPE_PRINTER)
            update_physical_printers(item->preset_name());
    }

    EndModal(wxID_OK);
}

}}    // namespace Slic3r::GUI
<|endoftext|>


<commit_before>#ifndef slic3r_SavePresetDialog_hpp_
#define slic3r_SavePresetDialog_hpp_

//#include <wx/gdicmn.h>

#include "libslic3r/Preset.hpp"
#include "wxExtensions.hpp"
#include "GUI_Utils.hpp"

class wxString;
class wxStaticText;
class wxComboBox;
class wxStaticBitmap;

namespace Slic3r {

namespace GUI {

class SavePresetDialog : public DPIDialog
{
    enum ActionType
    {
        ChangePreset,
        AddPreset,
        Switch,
        UndefAction
    };

    struct Item
    {
        enum ValidationType
        {
            Valid,
            NoValid,
            Warning
        };

        Item(Preset::Type type, const std::string& suffix, wxBoxSizer* sizer, SavePresetDialog* parent);

        void            update_valid_bmp();
        void            accept();

        bool            is_valid()      const { return m_valid_type != NoValid; }
        Preset::Type    type()          const { return m_type; }
        std::string     preset_name()   const { return m_preset_name; }

    private:
        Preset::Type    m_type;
        ValidationType  m_valid_type;
        std::string		m_preset_name;

        SavePresetDialog*   m_parent        {nullptr};
        wxStaticBitmap*     m_valid_bmp     {nullptr};
        wxComboBox*         m_combo         {nullptr};
        wxStaticText*       m_valid_label   {nullptr};

        PresetCollection*   m_presets       {nullptr};

        void update();
    };

    std::vector<Item*>   m_items;

    wxBoxSizer*         m_presets_sizer     {nullptr};
    wxStaticText*       m_label             {nullptr};
    wxRadioBox*         m_action_radio_box  {nullptr};
    wxBoxSizer*         m_radio_sizer       {nullptr};
    ActionType          m_action            {UndefAction};

    std::string         m_ph_printer_name;
    std::string         m_old_preset_name;

public:

    SavePresetDialog(Preset::Type type, std::string suffix = "");
    SavePresetDialog(std::vector<Preset::Type> types, std::string suffix = "");
    ~SavePresetDialog();

    void AddItem(Preset::Type type, const std::string& suffix);

    std::string get_name();
    std::string get_name(Preset::Type type);

    bool enable_ok_btn() const;
    void add_info_for_edit_ph_printer(wxBoxSizer *sizer);
    void update_info_for_edit_ph_printer(const std::string &preset_name);
    void layout();

protected:
    void on_dpi_changed(const wxRect& suggested_rect) override;
    void on_sys_color_changed() override {}

private:
    void build(std::vector<Preset::Type> types, std::string suffix = "");
    void update_physical_printers(const std::string& preset_name);
    void accept();
};

} // namespace GUI
} // namespace Slic3r

#endif
<commit_msg>Added missing forward declaration for gcc<commit_after>#ifndef slic3r_SavePresetDialog_hpp_
#define slic3r_SavePresetDialog_hpp_

//#include <wx/gdicmn.h>

#include "libslic3r/Preset.hpp"
#include "wxExtensions.hpp"
#include "GUI_Utils.hpp"

class wxString;
class wxStaticText;
class wxComboBox;
class wxRadioBox;
class wxStaticBitmap;

namespace Slic3r {

namespace GUI {

class SavePresetDialog : public DPIDialog
{
    enum ActionType
    {
        ChangePreset,
        AddPreset,
        Switch,
        UndefAction
    };

    struct Item
    {
        enum ValidationType
        {
            Valid,
            NoValid,
            Warning
        };

        Item(Preset::Type type, const std::string& suffix, wxBoxSizer* sizer, SavePresetDialog* parent);

        void            update_valid_bmp();
        void            accept();

        bool            is_valid()      const { return m_valid_type != NoValid; }
        Preset::Type    type()          const { return m_type; }
        std::string     preset_name()   const { return m_preset_name; }

    private:
        Preset::Type    m_type;
        ValidationType  m_valid_type;
        std::string		m_preset_name;

        SavePresetDialog*   m_parent        {nullptr};
        wxStaticBitmap*     m_valid_bmp     {nullptr};
        wxComboBox*         m_combo         {nullptr};
        wxStaticText*       m_valid_label   {nullptr};

        PresetCollection*   m_presets       {nullptr};

        void update();
    };

    std::vector<Item*>   m_items;

    wxBoxSizer*         m_presets_sizer     {nullptr};
    wxStaticText*       m_label             {nullptr};
    wxRadioBox*         m_action_radio_box  {nullptr};
    wxBoxSizer*         m_radio_sizer       {nullptr};
    ActionType          m_action            {UndefAction};

    std::string         m_ph_printer_name;
    std::string         m_old_preset_name;

public:

    SavePresetDialog(Preset::Type type, std::string suffix = "");
    SavePresetDialog(std::vector<Preset::Type> types, std::string suffix = "");
    ~SavePresetDialog();

    void AddItem(Preset::Type type, const std::string& suffix);

    std::string get_name();
    std::string get_name(Preset::Type type);

    bool enable_ok_btn() const;
    void add_info_for_edit_ph_printer(wxBoxSizer *sizer);
    void update_info_for_edit_ph_printer(const std::string &preset_name);
    void layout();

protected:
    void on_dpi_changed(const wxRect& suggested_rect) override;
    void on_sys_color_changed() override {}

private:
    void build(std::vector<Preset::Type> types, std::string suffix = "");
    void update_physical_printers(const std::string& preset_name);
    void accept();
};

} // namespace GUI
} // namespace Slic3r

#endif
<|endoftext|>


<commit_before>/*
   Copyright 2016 Mitchell Young

   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.
*/

#include "particle_pusher.hpp"

#include <cmath>
#include <iostream>

#include "particle.hpp"

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

namespace mocc {
ParticlePusher::ParticlePusher(const CoreMesh &mesh, const XSMesh &xs_mesh)
    : mesh_(mesh),
      xs_mesh_(xs_mesh),
      n_group_(xs_mesh.n_group()),
      do_implicit_capture_(true) {
    // Build the map from mesh regions into the XS mesh
    xsmesh_regions_.reserve(mesh.n_reg());

    int ixs = 0;
    for (const auto &xsreg : xs_mesh_) {
        for (const auto &ireg : xsreg.reg()) {
            xsmesh_regions_[ireg] = ixs;
        }
        ixs++;
    }
    return;
}

void ParticlePusher::collide(Particle &p, int ixsreg) {
    // Sample the type of interaction;
//cout << "collision!" << endl;
    const auto &xsreg = xs_mesh_[ixsreg];
    real_t r = RNG_MC.random();

    real_t xs_scat_out = xsreg.xsmacsc().out(p.group);
    real_t xs_cum = xs_scat_out;
    if (r < xs_cum) {
//cout << "scatter" << endl;
        // scatter. only isotropic for now
        // sample new energy
        VecF cdf = xsreg.xsmacsc().out_cdf(p.group);
        p.group = RNG_MC.sample_cdf(xsreg.xsmacsc().out_cdf(p.group));

        // sample new angle
        p.direction = Direction(RNG_MC.random(TWOPI), RNG_MC.random(-HPI, HPI));
//cout << "new group | direction: " << p.group << " | " << p.direction << endl;

//cin.ignore();
        return;
    }

    xs_cum += xsreg.xsmacf(p.group);
    if (r < xs_cum) {
//cout << "fission" << endl;
        // fission
        // sample number of new particles to generate
        real_t nu = xsreg.xsmacnf(p.group) / xsreg.xsmacf(p.group);
        int n_fis =
            (RNG_MC.random() < (nu - (int)nu)) ? std::ceil(nu) : std::floor(nu);

        // Make new particles and push them onto the fission bank
        for (int i = 0; i < n_fis; i++) {
            int ig = RNG_MC.sample_cdf(xsreg.chi_cdf());
            Particle new_p(
                p.location_global,
                Direction(RNG_MC.random(TWOPI), RNG_MC.random(-HPI, HPI)), ig);
            fission_bank_.push_back(new_p);
        }
//cin.ignore();
        return;
    }
//cout << "capture" << endl;

//cin.ignore();
    // capture
    //if (!do_implicit_capture_) {
        p.alive = false;
    //}

    return;
}

void ParticlePusher::simulate(Particle p) {
    // Figure out where the particle is
    auto location_info =
        mesh_.get_location_info(p.location_global, p.direction);
    p.location = location_info.local_point;
    int ireg = location_info.reg_offset +
        location_info.pm->find_reg(p.location);
//cout << "starting new" << endl;
    int ixsreg = xsmesh_regions_[ireg];

    real_t z_min = mesh_.z(location_info.pos.z);
    real_t z_max = mesh_.z(location_info.pos.z + 1);

    p.alive = true;

    while (p.alive) {
//cout << "particle at:" << endl<< p << endl;
//cout << "in region: " << ireg << endl << endl;

        // Determine distance to nearest surface
        auto d_to_surf =
            location_info.pm->distance_to_surface(p.location, p.direction);
        // Determine distance to plane boundaries. If it is less than the
        // distance to surface, use it as the distance to surf and force a pin
        // intersection
        real_t d_to_plane =
            (p.direction.oz > 0.0)
                ? (z_max - p.location_global.z) / p.direction.oz
                : (z_min - p.location_global.z) / p.direction.oz;
        if (d_to_plane < d_to_surf.first) {
            d_to_surf.first = d_to_plane;
            d_to_surf.second =
                (p.direction.oz > 0.0) ? Surface::TOP : Surface::BOTTOM;
        }

//cout << "distance to surface: " << d_to_surf.first << " " << d_to_surf.second << endl;

        // Sample distance to collision
        real_t xstr = xs_mesh_[ixsreg].xsmactr(p.group);
        real_t d_to_collision = -std::log(RNG_MC.random()) / xstr;

//cout << "xst | distance to collision: "  << xstr << " " << d_to_collision << endl;

        if (d_to_collision < d_to_surf.first) {
            // Particle collided within the current region. Move particle to
            // collision site and handle interaction.
            p.move(d_to_collision);
            this->collide(p, ixsreg);
        } else {
            // Particle reached a surface before colliding. Move to the
            // surface and re-sample distance to collision.
            if (d_to_surf.second == Surface::INTERNAL) {
                // Particle crossed an internal boundary in the pin.
                // Update its location and region index
                p.move(d_to_surf.first);
                ireg = location_info.pm->find_reg(p.location, p.direction) +
                    location_info.reg_offset;
                ixsreg = xsmesh_regions_[ireg];

            } else {
//cout << "moving to new pin cell:" << endl;
                // Particle crossed a pin boundary. Move to neighboring pin,
                // handle boundary condition, etc.
                // Regardless of what happens, move the particle
                p.move(d_to_surf.first);

                // Check for domain boundary crossing
                Surface bound_surf = mesh_.boundary_surface(p.location_global,
                                                            p.direction);
                if (bound_surf != Surface::INTERNAL) {
                    // We are exiting a domain boundary. Handle the boundary
                    // condition.
//cout << "at domain boundary"  << " "  << bound_surf << endl;
                    auto bc = mesh_.boundary_condition(bound_surf);
//cout << "boundary condition: " << bc << endl;
                    switch (bc) {
                        case Boundary::REFLECT:
                            p.direction.reflect(bound_surf);
//cout << "new direction: " << p.direction << endl;
                            break;
                        case Boundary::VACUUM:
                            // Just kill the thing
//cout << "particle leak" << endl;
//cin.ignore();
                            p.alive = false;
                            break;
                        default:
                            throw EXCEPT("Unsupported boundary condition");
                    }
                }
                // Figure out where we are again
                location_info =
                    mesh_.get_location_info(p.location_global, p.direction);
                z_min = mesh_.z(location_info.pos.z);
                z_max = mesh_.z(location_info.pos.z) + 1;
                p.location = location_info.local_point;
                ireg = location_info.reg_offset +
                    location_info.pm->find_reg(p.location);
                ixsreg = xsmesh_regions_[ireg];
//cout  << "particle now at: " << endl << p << endl;
            }
        } // collision or new region?
    } // particle alive
//cin.ignore();
    return;
}

/**
 * This method operates by generating a full-blown Particle for each fission
 * site in the \ref FissionBank and calling \c this->simulate() for that
 * particle.
 */
void ParticlePusher::simulate(const FissionBank &bank) {
    // Clear the internal FissionBank to store new fission sites for this
    // cycle
    fission_bank_.clear();

    for (const auto &p : bank) {
        this->simulate(p);
    }
    return;
}

}  // namespace mocc
<commit_msg>Fix interaction sampling in ParticlePusher<commit_after>/*
   Copyright 2016 Mitchell Young

   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.
*/

#include "particle_pusher.hpp"

#include <cmath>
#include <iostream>

#include "particle.hpp"

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

namespace mocc {
ParticlePusher::ParticlePusher(const CoreMesh &mesh, const XSMesh &xs_mesh)
    : mesh_(mesh),
      xs_mesh_(xs_mesh),
      n_group_(xs_mesh.n_group()),
      do_implicit_capture_(true) {
    // Build the map from mesh regions into the XS mesh
    xsmesh_regions_.reserve(mesh.n_reg());

    int ixs = 0;
    for (const auto &xsreg : xs_mesh_) {
        for (const auto &ireg : xsreg.reg()) {
            xsmesh_regions_[ireg] = ixs;
        }
        ixs++;
    }
    return;
}

void ParticlePusher::collide(Particle &p, int ixsreg) {
    // Sample the type of interaction;
    const auto &xsreg = xs_mesh_[ixsreg];
    Reaction reaction =
        (Reaction)RNG_MC.sample_cdf(xsreg.reaction_cdf(p.group));

    switch( reaction ) {
    case Reaction::SCATTER:
        {
        // scatter. only isotropic for now
        // sample new energy
        VecF cdf = xsreg.xsmacsc().out_cdf(p.group);
        p.group = RNG_MC.sample_cdf(xsreg.xsmacsc().out_cdf(p.group));

        // sample new angle
        p.direction = Direction(RNG_MC.random(TWOPI), RNG_MC.random(-HPI, HPI));
        }
        break;

    case Reaction::FISSION:
        // fission
        // sample number of new particles to generate
        {
        real_t nu = xsreg.xsmacnf(p.group) / xsreg.xsmacf(p.group);
        int n_fis =
            (RNG_MC.random() < (nu - (int)nu)) ? std::ceil(nu) : std::floor(nu);

        // Make new particles and push them onto the fission bank
        for (int i = 0; i < n_fis; i++) {
            int ig = RNG_MC.sample_cdf(xsreg.chi_cdf());
            Particle new_p(
                p.location_global,
                Direction(RNG_MC.random(TWOPI), RNG_MC.random(-HPI, HPI)), ig);
            fission_bank_.push_back(new_p);
        }
        }
        p.alive = false;
        break;
    default:
        // capture
        p.alive = false;
    }

    return;
}

void ParticlePusher::simulate(Particle p) {
    // Figure out where the particle is
    auto location_info =
        mesh_.get_location_info(p.location_global, p.direction);
    p.location = location_info.local_point;
    int ireg = location_info.reg_offset +
        location_info.pm->find_reg(p.location);
    int ixsreg = xsmesh_regions_[ireg];

    real_t z_min = mesh_.z(location_info.pos.z);
    real_t z_max = mesh_.z(location_info.pos.z + 1);

    p.alive = true;

    while (p.alive) {
        // Determine distance to nearest surface
        auto d_to_surf =
            location_info.pm->distance_to_surface(p.location, p.direction);
        // Determine distance to plane boundaries. If it is less than the
        // distance to surface, use it as the distance to surf and force a pin
        // intersection
        real_t d_to_plane =
            (p.direction.oz > 0.0)
                ? (z_max - p.location_global.z) / p.direction.oz
                : (z_min - p.location_global.z) / p.direction.oz;
        if (d_to_plane < d_to_surf.first) {
            d_to_surf.first = d_to_plane;
            d_to_surf.second =
                (p.direction.oz > 0.0) ? Surface::TOP : Surface::BOTTOM;
        }

        // Sample distance to collision
        real_t xstr = xs_mesh_[ixsreg].xsmactr(p.group);
        real_t d_to_collision = -std::log(RNG_MC.random()) / xstr;

        if (d_to_collision < d_to_surf.first) {
            // Particle collided within the current region. Move particle to
            // collision site and handle interaction.
            p.move(d_to_collision);
            this->collide(p, ixsreg);
        } else {
            // Particle reached a surface before colliding. Move to the
            // surface and re-sample distance to collision.
            if (d_to_surf.second == Surface::INTERNAL) {
                // Particle crossed an internal boundary in the pin.
                // Update its location and region index
                p.move(d_to_surf.first);
                ireg = location_info.pm->find_reg(p.location, p.direction) +
                    location_info.reg_offset;
                ixsreg = xsmesh_regions_[ireg];

            } else {
                // Particle crossed a pin boundary. Move to neighboring pin,
                // handle boundary condition, etc.
                // Regardless of what happens, move the particle
                p.move(d_to_surf.first);

                // Check for domain boundary crossing
                Surface bound_surf = mesh_.boundary_surface(p.location_global,
                                                            p.direction);
                if (bound_surf != Surface::INTERNAL) {
                    // We are exiting a domain boundary. Handle the boundary
                    // condition.
                    auto bc = mesh_.boundary_condition(bound_surf);
                    switch (bc) {
                        case Boundary::REFLECT:
                            p.direction.reflect(bound_surf);
                            break;
                        case Boundary::VACUUM:
                            // Just kill the thing
                            p.alive = false;
                            break;
                        default:
                            throw EXCEPT("Unsupported boundary condition");
                    }
                }
                // Figure out where we are again
                location_info =
                    mesh_.get_location_info(p.location_global, p.direction);
                z_min = mesh_.z(location_info.pos.z);
                z_max = mesh_.z(location_info.pos.z) + 1;
                p.location = location_info.local_point;
                ireg = location_info.reg_offset +
                    location_info.pm->find_reg(p.location);
                ixsreg = xsmesh_regions_[ireg];
            }
        } // collision or new region?
    } // particle alive
    return;
}

/**
 * This method operates by generating a full-blown Particle for each fission
 * site in the \ref FissionBank and calling \c this->simulate() for that
 * particle.
 */
void ParticlePusher::simulate(const FissionBank &bank) {
    // Clear the internal FissionBank to store new fission sites for this
    // cycle
    fission_bank_.clear();

    for (const auto &p : bank) {
        this->simulate(p);
    }
    return;
}

}  // namespace mocc
<|endoftext|>


<commit_before>#include "system/terms/term.h"

#include "test_helpers/gmock_wrapper.h"

namespace  {

using namespace bart;

/* This testing suite is designed to test the linear and bilinear term classes
 * to ensure they are adding vectors and matrices properly when the
 * GetFullTerm method is called. For tests that verify that the setters and
 * getters work, see linear_term_test.cc. These tests will use a full dealii
 * test environment to provide the needed MPI matrices and vectors.
 */

class SystemTermsFullTermTest : public ::testing::Test {
 protected:
};

TEST_F(SystemTermsFullTermTest, FullTermOperation) {
  EXPECT_TRUE(true);
}

} // namespace<commit_msg>added test for FullTerm for Bilinear<commit_after>#include "system/terms/term.h"

#include "test_helpers/test_assertions.h"
#include "test_helpers/dealii_test_domain.h"
#include "test_helpers/gmock_wrapper.h"

namespace  {

using namespace bart;

/* This testing suite is designed to test the linear and bilinear term classes
 * to ensure they are adding vectors and matrices properly when the
 * GetFullTerm method is called. For tests that verify that the setters and
 * getters work, see linear_term_test.cc. These tests will use a full dealii
 * test environment to provide the needed MPI matrices and vectors.
 */

class SystemTermsFullTermTest : public ::testing::Test,
                                public bart::testing::DealiiTestDomain<2> {
 protected:
  void SetUp() override;
};

void SystemTermsFullTermTest::SetUp() {
  SetUpDealii();
}

TEST_F(SystemTermsFullTermTest, BilinearFullTermOperationMPI) {
  auto other_source = system::terms::VariableBilinearTerms::kOther;
  system::terms::MPIBilinearTerm test_bilinear_term({other_source});

  std::shared_ptr<system::MPISparseMatrix> fixed_term_ptr, variable_term_ptr;
  fixed_term_ptr.reset(&matrix_1);
  variable_term_ptr.reset(&matrix_2);

  StampMatrix(matrix_1, 2);
  StampMatrix(matrix_2, 1);
  StampMatrix(matrix_3, 3);

  test_bilinear_term.SetFixedTermPtr({0, 0}, fixed_term_ptr);
  test_bilinear_term.SetVariableTermPtr({0, 0}, other_source, variable_term_ptr);

  auto term_matrix_ptr = test_bilinear_term.GetFullTermPtr({0,0});
  EXPECT_TRUE(bart::testing::CompareMPIMatrices(matrix_3, *term_matrix_ptr));
}

} // namespace<|endoftext|>