<commit_before>
// Copyright (c) 2012, 2013 Pierre MOULON.

// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.

#include <cstdlib>

#include "openMVG/features/ImageDescriberCommon.hpp"
#include "openMVG/sfm/sfm.hpp"
#include "openMVG/sfm/pipelines/RegionsIO.hpp"
#include "openMVG/system/timer.hpp"

#include "third_party/cmdLine/cmdLine.h"
#include "third_party/stlplus3/filesystemSimplified/file_system.hpp"

using namespace openMVG;
using namespace openMVG::cameras;
using namespace openMVG::sfm;
using namespace openMVG::features;

/**
 * @brief Retrieve the view id in the sfmData from the image filename.
 *
 * @param[in] sfm_data the SfM scene
 * @param[in] initialName the image name to find (filename or path)
 * @param[out] out_viewId the id found
 * @return if a view is found
 */
bool retrieveViewIdFromImageName(
  const SfM_Data & sfm_data,
  const std::string& initialName,
  IndexT& out_viewId)
{
  out_viewId = UndefinedIndexT;

  bool isName = (initialName == stlplus::filename_part(initialName));

  /// List views filenames and find the one that correspond to the user ones:
  for(Views::const_iterator it = sfm_data.GetViews().begin();
    it != sfm_data.GetViews().end(); ++it)
  {
    const View * v = it->second.get();
    std::string filename;

    if(isName)
    {
      filename = stlplus::filename_part(v->s_Img_path);
    }
    else
    {
      if(stlplus::is_full_path(v->s_Img_path))
      {
        filename = v->s_Img_path;
      }
      else
      {
        filename = sfm_data.s_root_path + v->s_Img_path;
      }
    }

    if (filename == initialName)
    {
      if(out_viewId == UndefinedIndexT)
      {
          out_viewId = v->id_view;
      }
      else
      {
        std::cout<<"Error: Two pictures named :" << initialName << " !" << std::endl;
      }
    }
  }
  return out_viewId != UndefinedIndexT;
}

int main(int argc, char **argv)
{
  using namespace std;
  std::cout << "Sequential/Incremental reconstruction" << std::endl
            << " Perform incremental SfM (Initial Pair Essential + Resection)." << std::endl
            << std::endl;

  CmdLine cmd;

  std::string sSfM_Data_Filename;
  std::string describerMethods = "SIFT";
  std::string sMatchesDir;
  std::string sFeaturesDir;
  std::string sOutDir = "";
  std::string sOutSfMDataFilepath = "";
  std::string sOutInterFileExtension = ".ply";
  std::pair<std::string,std::string> initialPairString("","");
  bool bRefineIntrinsics = true;
  int minInputTrackLength = 2;
  int i_User_camera_model = PINHOLE_CAMERA_RADIAL3;
  bool allowUserInteraction = true;

  cmd.add( make_option('i', sSfM_Data_Filename, "input_file") );
  cmd.add( make_option('d', describerMethods, "describerMethods") );
  cmd.add( make_option('m', sMatchesDir, "matchdir") );
  cmd.add( make_option('F', sFeaturesDir, "featuresDir") );
  cmd.add( make_option('o', sOutDir, "outdir") );
  cmd.add( make_option('s', sOutSfMDataFilepath, "out_sfmdata_file") );
  cmd.add( make_option('e', sOutInterFileExtension, "inter_file_extension") );
  cmd.add( make_option('a', initialPairString.first, "initialPairA") );
  cmd.add( make_option('b', initialPairString.second, "initialPairB") );
  cmd.add( make_option('c', i_User_camera_model, "camera_model") );
  cmd.add( make_option('f', bRefineIntrinsics, "refineIntrinsics") );
  cmd.add( make_option('t', minInputTrackLength, "minInputTrackLength") );
  cmd.add( make_option('u', allowUserInteraction, "allowUserInteraction") );

  try {
    if (argc == 1) throw std::string("Invalid parameter.");
    cmd.process(argc, argv);
  } catch(const std::string& s) {
    std::cerr << "Usage: " << argv[0] << '\n'
    << "[-i|--input_file] path to a SfM_Data scene\n"
    << "[-d|--describerMethods]\n"
    << "  (methods to use to describe an image):\n"
    << "   SIFT (default),\n"
    << "   SIFT_FLOAT to use SIFT stored as float,\n"
    << "   AKAZE: AKAZE with floating point descriptors,\n"
    << "   AKAZE_MLDB:  AKAZE with binary descriptors\n"
#if OPENMVG_IS_DEFINED(OPENMVG_HAVE_CCTAG)
    << "   CCTAG3: CCTAG markers with 3 crowns\n"
    << "   CCTAG4: CCTAG markers with 4 crowns\n"
#endif //OPENMVG_HAVE_CCTAG
#if OPENMVG_IS_DEFINED(OPENMVG_HAVE_OPENCV)
#if OPENMVG_IS_DEFINED(OPENMVG_HAVE_OCVSIFT)
    << "   SIFT_OCV: OpenCV SIFT\n"
#endif //OPENMVG_HAVE_OCVSIFT
    << "   AKAZE_OCV: OpenCV AKAZE\n"
#endif //OPENMVG_HAVE_OPENCV
    << "[-m|--matchdir] path to the matches that corresponds to the provided SfM_Data scene\n"
    << "[-F|--featuresDir] path to directory containing the extracted features (default: $matchdir)\n"
    << "[-o|--outdir] path where the output data will be stored\n"
    << "[-s|--out_sfmdata_file] path of the output sfmdata file (default: $outdir/sfm_data.json)\n"
    << "[-e|--inter_file_extension] extension of the intermediate file export (default: .ply)\n"
    << "[-a|--initialPairA] filename of the first image (without path)\n"
    << "[-b|--initialPairB] filename of the second image (without path)\n"
    << "[-c|--camera_model] Camera model type for view with unknown intrinsic:\n"
      << "\t 1: Pinhole \n"
      << "\t 2: Pinhole radial 1\n"
      << "\t 3: Pinhole radial 3 (default)\n"
    << "[-f|--refineIntrinsics] \n"
    << "\t 0-> intrinsic parameters are kept as constant\n"
    << "\t 1-> refine intrinsic parameters (default). \n"
    << "[-t|--minInputTrackLength N] minimum track length in input of SfM (default: 2)\n"
    << "[-p|--matchFilePerImage] \n"
    << "\t To use one match file per image instead of a global file.\n"
    << "[-u|--allowUserInteraction] Enable/Disable user interactions. (default: true)\n"
    << "\t If the process is done on renderfarm, it doesn't make sense to wait for user inputs.\n"
    << std::endl;

    std::cerr << s << std::endl;
    return EXIT_FAILURE;
  }

  if(sOutSfMDataFilepath.empty())
    sOutSfMDataFilepath = stlplus::create_filespec(sOutDir, "sfm_data", "json");

  // Load input SfM_Data scene
  SfM_Data sfm_data;
  if (!Load(sfm_data, sSfM_Data_Filename, ESfM_Data(VIEWS|INTRINSICS))) {
    std::cerr << std::endl
      << "The input SfM_Data file \""<< sSfM_Data_Filename << "\" cannot be read." << std::endl;
    return EXIT_FAILURE;
  }

  if(sFeaturesDir.empty()) {
    sFeaturesDir = sMatchesDir;
  }

  // Get imageDescriberMethodType
  const std::vector<features::EImageDescriberType> describerTypes = features::EImageDescriberType_stringToEnums(describerMethods);

  // Features reading
  features::FeaturesPerView featuresPerView;
  if(!sfm::loadFeaturesPerView(featuresPerView, sfm_data, sFeaturesDir, describerTypes))
  {
    std::cerr << std::endl
      << "Invalid features." << std::endl;
    return EXIT_FAILURE;
  }

  // Matches reading
  matching::PairwiseMatches pairwiseMatches;

  if(!loadPairwiseMatches(pairwiseMatches, sfm_data, sMatchesDir, describerTypes, "f"))
  {
    std::cerr << std::endl << "Unable to load matches file from: " << sMatchesDir << std::endl;
    return EXIT_FAILURE;
  }

  if (sOutDir.empty())
  {
    std::cerr << "\nIt is an invalid output directory" << std::endl;
    return EXIT_FAILURE;
  }

  if (!stlplus::folder_exists(sOutDir))
    stlplus::folder_create(sOutDir);

  //---------------------------------------
  // Sequential reconstruction process
  //---------------------------------------

  openMVG::system::Timer timer;
  SequentialSfMReconstructionEngine sfmEngine(
    sfm_data,
    sOutDir,
    stlplus::create_filespec(sOutDir, "Reconstruction_Report.html"));

  // Configure the featuresPerView & the matches_provider
  sfmEngine.setFeatures(&featuresPerView);
  sfmEngine.setMatches(&pairwiseMatches);

  // Configure reconstruction parameters
  sfmEngine.Set_bFixedIntrinsics(!bRefineIntrinsics);
  sfmEngine.SetUnknownCameraType(EINTRINSIC(i_User_camera_model));
  sfmEngine.setMinInputTrackLength(minInputTrackLength);
  sfmEngine.setSfmdataInterFileExtension(sOutInterFileExtension);
  sfmEngine.setAllowUserInteraction(allowUserInteraction);

  // Handle Initial pair parameter
  if (!initialPairString.first.empty() && !initialPairString.second.empty())
  {
    if (initialPairString.first == initialPairString.second)
    {
      std::cerr << "\nInvalid image names. You cannot use the same image to initialize a pair." << std::endl;
      return EXIT_FAILURE;
    }

    Pair initialPairIndex;
    if(!retrieveViewIdFromImageName(sfm_data, initialPairString.first, initialPairIndex.first)
            || !retrieveViewIdFromImageName(sfm_data, initialPairString.second, initialPairIndex.second))
    {
        std::cerr << "Could not find the initial pairs <" << initialPairString.first
          <<  ", " << initialPairString.second << ">!\n";
        return EXIT_FAILURE;
    }

    sfmEngine.setInitialPair(initialPairIndex);
  }

  if (!sfmEngine.Process())
  {
    return EXIT_FAILURE;
  }

  // get the color for the 3D points
  if(!sfmEngine.Colorize())
  {
    std::cerr << "Colorize failed!" << std::endl;
  }

  sfmEngine.Get_SfM_Data().setFeatureFolder(sFeaturesDir);
  sfmEngine.Get_SfM_Data().setMatchingFolder(sMatchesDir);

  std::cout << std::endl << " Total Ac-Sfm took (s): " << timer.elapsed() << std::endl;

  std::cout << "...Generating SfM_Report.html" << std::endl;
  Generate_SfM_Report(sfmEngine.Get_SfM_Data(),
    stlplus::create_filespec(sOutDir, "SfMReconstruction_Report.html"));

  //-- Export to disk computed scene (data & visualizable results)
  std::cout << "...Export SfM_Data to disk:" << std::endl;
  std::cout << "   " << sOutSfMDataFilepath << std::endl;

  Save(sfmEngine.Get_SfM_Data(), sOutSfMDataFilepath, ESfM_Data(ALL));

  Save(sfmEngine.Get_SfM_Data(), stlplus::create_filespec(sOutDir, "cloud_and_poses", sOutInterFileExtension), ESfM_Data(VIEWS | EXTRINSICS | INTRINSICS | STRUCTURE));

  return EXIT_SUCCESS;
}
<commit_msg>[software] fix : load full SfMData in `main_IncrementalSfM.cpp`<commit_after>
// Copyright (c) 2012, 2013 Pierre MOULON.

// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.

#include <cstdlib>

#include "openMVG/features/ImageDescriberCommon.hpp"
#include "openMVG/sfm/sfm.hpp"
#include "openMVG/sfm/pipelines/RegionsIO.hpp"
#include "openMVG/system/timer.hpp"

#include "third_party/cmdLine/cmdLine.h"
#include "third_party/stlplus3/filesystemSimplified/file_system.hpp"

using namespace openMVG;
using namespace openMVG::cameras;
using namespace openMVG::sfm;
using namespace openMVG::features;

/**
 * @brief Retrieve the view id in the sfmData from the image filename.
 *
 * @param[in] sfm_data the SfM scene
 * @param[in] initialName the image name to find (filename or path)
 * @param[out] out_viewId the id found
 * @return if a view is found
 */
bool retrieveViewIdFromImageName(
  const SfM_Data & sfm_data,
  const std::string& initialName,
  IndexT& out_viewId)
{
  out_viewId = UndefinedIndexT;

  bool isName = (initialName == stlplus::filename_part(initialName));

  /// List views filenames and find the one that correspond to the user ones:
  for(Views::const_iterator it = sfm_data.GetViews().begin();
    it != sfm_data.GetViews().end(); ++it)
  {
    const View * v = it->second.get();
    std::string filename;

    if(isName)
    {
      filename = stlplus::filename_part(v->s_Img_path);
    }
    else
    {
      if(stlplus::is_full_path(v->s_Img_path))
      {
        filename = v->s_Img_path;
      }
      else
      {
        filename = sfm_data.s_root_path + v->s_Img_path;
      }
    }

    if (filename == initialName)
    {
      if(out_viewId == UndefinedIndexT)
      {
          out_viewId = v->id_view;
      }
      else
      {
        std::cout<<"Error: Two pictures named :" << initialName << " !" << std::endl;
      }
    }
  }
  return out_viewId != UndefinedIndexT;
}

int main(int argc, char **argv)
{
  using namespace std;
  std::cout << "Sequential/Incremental reconstruction" << std::endl
            << " Perform incremental SfM (Initial Pair Essential + Resection)." << std::endl
            << std::endl;

  CmdLine cmd;

  std::string sSfM_Data_Filename;
  std::string describerMethods = "SIFT";
  std::string sMatchesDir;
  std::string sFeaturesDir;
  std::string sOutDir = "";
  std::string sOutSfMDataFilepath = "";
  std::string sOutInterFileExtension = ".ply";
  std::pair<std::string,std::string> initialPairString("","");
  bool bRefineIntrinsics = true;
  int minInputTrackLength = 2;
  int i_User_camera_model = PINHOLE_CAMERA_RADIAL3;
  bool allowUserInteraction = true;

  cmd.add( make_option('i', sSfM_Data_Filename, "input_file") );
  cmd.add( make_option('d', describerMethods, "describerMethods") );
  cmd.add( make_option('m', sMatchesDir, "matchdir") );
  cmd.add( make_option('F', sFeaturesDir, "featuresDir") );
  cmd.add( make_option('o', sOutDir, "outdir") );
  cmd.add( make_option('s', sOutSfMDataFilepath, "out_sfmdata_file") );
  cmd.add( make_option('e', sOutInterFileExtension, "inter_file_extension") );
  cmd.add( make_option('a', initialPairString.first, "initialPairA") );
  cmd.add( make_option('b', initialPairString.second, "initialPairB") );
  cmd.add( make_option('c', i_User_camera_model, "camera_model") );
  cmd.add( make_option('f', bRefineIntrinsics, "refineIntrinsics") );
  cmd.add( make_option('t', minInputTrackLength, "minInputTrackLength") );
  cmd.add( make_option('u', allowUserInteraction, "allowUserInteraction") );

  try {
    if (argc == 1) throw std::string("Invalid parameter.");
    cmd.process(argc, argv);
  } catch(const std::string& s) {
    std::cerr << "Usage: " << argv[0] << '\n'
    << "[-i|--input_file] path to a SfM_Data scene\n"
    << "[-d|--describerMethods]\n"
    << "  (methods to use to describe an image):\n"
    << "   SIFT (default),\n"
    << "   SIFT_FLOAT to use SIFT stored as float,\n"
    << "   AKAZE: AKAZE with floating point descriptors,\n"
    << "   AKAZE_MLDB:  AKAZE with binary descriptors\n"
#if OPENMVG_IS_DEFINED(OPENMVG_HAVE_CCTAG)
    << "   CCTAG3: CCTAG markers with 3 crowns\n"
    << "   CCTAG4: CCTAG markers with 4 crowns\n"
#endif //OPENMVG_HAVE_CCTAG
#if OPENMVG_IS_DEFINED(OPENMVG_HAVE_OPENCV)
#if OPENMVG_IS_DEFINED(OPENMVG_HAVE_OCVSIFT)
    << "   SIFT_OCV: OpenCV SIFT\n"
#endif //OPENMVG_HAVE_OCVSIFT
    << "   AKAZE_OCV: OpenCV AKAZE\n"
#endif //OPENMVG_HAVE_OPENCV
    << "[-m|--matchdir] path to the matches that corresponds to the provided SfM_Data scene\n"
    << "[-F|--featuresDir] path to directory containing the extracted features (default: $matchdir)\n"
    << "[-o|--outdir] path where the output data will be stored\n"
    << "[-s|--out_sfmdata_file] path of the output sfmdata file (default: $outdir/sfm_data.json)\n"
    << "[-e|--inter_file_extension] extension of the intermediate file export (default: .ply)\n"
    << "[-a|--initialPairA] filename of the first image (without path)\n"
    << "[-b|--initialPairB] filename of the second image (without path)\n"
    << "[-c|--camera_model] Camera model type for view with unknown intrinsic:\n"
      << "\t 1: Pinhole \n"
      << "\t 2: Pinhole radial 1\n"
      << "\t 3: Pinhole radial 3 (default)\n"
    << "[-f|--refineIntrinsics] \n"
    << "\t 0-> intrinsic parameters are kept as constant\n"
    << "\t 1-> refine intrinsic parameters (default). \n"
    << "[-t|--minInputTrackLength N] minimum track length in input of SfM (default: 2)\n"
    << "[-p|--matchFilePerImage] \n"
    << "\t To use one match file per image instead of a global file.\n"
    << "[-u|--allowUserInteraction] Enable/Disable user interactions. (default: true)\n"
    << "\t If the process is done on renderfarm, it doesn't make sense to wait for user inputs.\n"
    << std::endl;

    std::cerr << s << std::endl;
    return EXIT_FAILURE;
  }

  if(sOutSfMDataFilepath.empty())
    sOutSfMDataFilepath = stlplus::create_filespec(sOutDir, "sfm_data", "json");

  // Load input SfM_Data scene
  SfM_Data sfm_data;
  if (!Load(sfm_data, sSfM_Data_Filename, ESfM_Data(ALL))) {
    std::cerr << std::endl
      << "The input SfM_Data file \""<< sSfM_Data_Filename << "\" cannot be read." << std::endl;
    return EXIT_FAILURE;
  }

  if(sFeaturesDir.empty()) {
    sFeaturesDir = sMatchesDir;
  }

  // Get imageDescriberMethodType
  const std::vector<features::EImageDescriberType> describerTypes = features::EImageDescriberType_stringToEnums(describerMethods);

  // Features reading
  features::FeaturesPerView featuresPerView;
  if(!sfm::loadFeaturesPerView(featuresPerView, sfm_data, sFeaturesDir, describerTypes))
  {
    std::cerr << std::endl
      << "Invalid features." << std::endl;
    return EXIT_FAILURE;
  }

  // Matches reading
  matching::PairwiseMatches pairwiseMatches;

  if(!loadPairwiseMatches(pairwiseMatches, sfm_data, sMatchesDir, describerTypes, "f"))
  {
    std::cerr << std::endl << "Unable to load matches file from: " << sMatchesDir << std::endl;
    return EXIT_FAILURE;
  }

  if (sOutDir.empty())
  {
    std::cerr << "\nIt is an invalid output directory" << std::endl;
    return EXIT_FAILURE;
  }

  if (!stlplus::folder_exists(sOutDir))
    stlplus::folder_create(sOutDir);

  //---------------------------------------
  // Sequential reconstruction process
  //---------------------------------------

  openMVG::system::Timer timer;
  SequentialSfMReconstructionEngine sfmEngine(
    sfm_data,
    sOutDir,
    stlplus::create_filespec(sOutDir, "Reconstruction_Report.html"));

  // Configure the featuresPerView & the matches_provider
  sfmEngine.setFeatures(&featuresPerView);
  sfmEngine.setMatches(&pairwiseMatches);

  // Configure reconstruction parameters
  sfmEngine.Set_bFixedIntrinsics(!bRefineIntrinsics);
  sfmEngine.SetUnknownCameraType(EINTRINSIC(i_User_camera_model));
  sfmEngine.setMinInputTrackLength(minInputTrackLength);
  sfmEngine.setSfmdataInterFileExtension(sOutInterFileExtension);
  sfmEngine.setAllowUserInteraction(allowUserInteraction);

  // Handle Initial pair parameter
  if (!initialPairString.first.empty() && !initialPairString.second.empty())
  {
    if (initialPairString.first == initialPairString.second)
    {
      std::cerr << "\nInvalid image names. You cannot use the same image to initialize a pair." << std::endl;
      return EXIT_FAILURE;
    }

    Pair initialPairIndex;
    if(!retrieveViewIdFromImageName(sfm_data, initialPairString.first, initialPairIndex.first)
            || !retrieveViewIdFromImageName(sfm_data, initialPairString.second, initialPairIndex.second))
    {
        std::cerr << "Could not find the initial pairs <" << initialPairString.first
          <<  ", " << initialPairString.second << ">!\n";
        return EXIT_FAILURE;
    }

    sfmEngine.setInitialPair(initialPairIndex);
  }

  if (!sfmEngine.Process())
  {
    return EXIT_FAILURE;
  }

  // get the color for the 3D points
  if(!sfmEngine.Colorize())
  {
    std::cerr << "Colorize failed!" << std::endl;
  }

  sfmEngine.Get_SfM_Data().setFeatureFolder(sFeaturesDir);
  sfmEngine.Get_SfM_Data().setMatchingFolder(sMatchesDir);

  std::cout << std::endl << " Total Ac-Sfm took (s): " << timer.elapsed() << std::endl;

  std::cout << "...Generating SfM_Report.html" << std::endl;
  Generate_SfM_Report(sfmEngine.Get_SfM_Data(),
    stlplus::create_filespec(sOutDir, "SfMReconstruction_Report.html"));

  //-- Export to disk computed scene (data & visualizable results)
  std::cout << "...Export SfM_Data to disk:" << std::endl;
  std::cout << "   " << sOutSfMDataFilepath << std::endl;

  Save(sfmEngine.Get_SfM_Data(), sOutSfMDataFilepath, ESfM_Data(ALL));

  Save(sfmEngine.Get_SfM_Data(), stlplus::create_filespec(sOutDir, "cloud_and_poses", sOutInterFileExtension), ESfM_Data(VIEWS | EXTRINSICS | INTRINSICS | STRUCTURE));

  return EXIT_SUCCESS;
}
<|endoftext|>


<commit_before>#include <QSqlQuery>
#include <QSqlRecord>
#include <QSqlError>

#include "kernel.h"
#include "symboltable.h"
#include "astnode.h"
#include "idnode.h"
#include "operationnode.h"
#include "expressionnode.h"
#include "symboltable.h"
#include "assignmentnode.h"
#include "formatter.h"
#include "formatters.h"
#include "scriptnode.h"
#include "raster.h"
#include "ilwisdata.h"
#include "domain.h"
#include "numericrange.h"
#include "numericdomain.h"
#include "columndefinition.h"
#include "table.h"
#include "connectorinterface.h"
#include "factory.h"
#include "abstractfactory.h"
#include "connectorfactory.h"
#include "catalog.h"
#include "ilwiscontext.h"
#include "juliantime.h"

using namespace Ilwis;

AssignmentNode::AssignmentNode() : _defintion(false)
{
}

bool AssignmentNode::isDefinition() const
{
    return _defintion;
}

void AssignmentNode::setDefintion(bool yesno)
{
    _defintion= yesno;
}

void AssignmentNode::setResult(IDNode *node)
{
    _result =QSharedPointer<IDNode>(node);
}

void AssignmentNode::setFormatPart(ASTNode *node)
{
    _typemodifier = QSharedPointer<ASTNode>(node);
}

void AssignmentNode::setExpression(ExpressionNode *node)
{
    _expression =QSharedPointer<ExpressionNode>(node);
}

QString AssignmentNode::nodeType() const
{
    return "assignment";
}

bool AssignmentNode::evaluate(SymbolTable& symbols, int scope)
{
    if ( _expression.isNull())
        return false;

    QString format, fnamespace;
    bool res = _expression->evaluate(symbols, scope);
    if ( res) {
        if ( !_typemodifier.isNull()) {
            ASTNode *node = static_cast<ASTNode *>(_typemodifier.data());
            if ( node->noOfChilderen()!= 1)
                return ERROR2(ERR_NO_OBJECT_TYPE_FOR_2, "Output object", "expression");

            Formatter *fnode = static_cast<Formatter *>(node->child(0).data());
            format = fnode->format();
            fnamespace = fnode->fnamespace();
        }
        NodeValue val = _expression->value();
        if ( val.typeName() == QString("Ilwis::IGridCoverage")) {
            if ( format == "" || format == sUNDEF) {
                Formatter *fnode = ScriptNode::activeFormat(itGRIDCOVERAGE);
                if ( fnode) {
                    format = fnode->format();
                    fnamespace = fnode->fnamespace();
                }
            }
            if ( format == "" || format == sUNDEF) {
                return false;
            }
            Ilwis::IGridCoverage gcresult = val.value<Ilwis::IGridCoverage>();
            QString result = _result->id();
            gcresult->setName(result);
            gcresult->connectTo(QUrl(), format, fnamespace, Ilwis::IlwisObject::cmOUTPUT);
            gcresult->setCreateTime(Ilwis::Time::now());
            gcresult->store(Ilwis::IlwisObject::smMETADATA | Ilwis::IlwisObject::smBINARYDATA);
        }
        Symbol sym = symbols.getSymbol(_result->id(),SymbolTable::gaREMOVEIFANON);
        IlwisTypes tp = sym.isValid() ? sym._type : itUNKNOWN;

        symbols.addSymbol(_result->id(), scope, tp, _expression->value())  ;
        return true;
    }
    return false;
}

<commit_msg>non-internal objects are now added to the mastercatalog<commit_after>#include <QSqlQuery>
#include <QSqlRecord>
#include <QSqlError>

#include "kernel.h"
#include "symboltable.h"
#include "astnode.h"
#include "idnode.h"
#include "operationnode.h"
#include "expressionnode.h"
#include "symboltable.h"
#include "assignmentnode.h"
#include "formatter.h"
#include "formatters.h"
#include "scriptnode.h"
#include "raster.h"
#include "ilwisdata.h"
#include "domain.h"
#include "numericrange.h"
#include "numericdomain.h"
#include "columndefinition.h"
#include "table.h"
#include "connectorinterface.h"
#include "factory.h"
#include "abstractfactory.h"
#include "connectorfactory.h"
#include "catalog.h"
#include "mastercatalog.h"
#include "ilwiscontext.h"
#include "juliantime.h"

using namespace Ilwis;

AssignmentNode::AssignmentNode() : _defintion(false)
{
}

bool AssignmentNode::isDefinition() const
{
    return _defintion;
}

void AssignmentNode::setDefintion(bool yesno)
{
    _defintion= yesno;
}

void AssignmentNode::setResult(IDNode *node)
{
    _result =QSharedPointer<IDNode>(node);
}

void AssignmentNode::setFormatPart(ASTNode *node)
{
    _typemodifier = QSharedPointer<ASTNode>(node);
}

void AssignmentNode::setExpression(ExpressionNode *node)
{
    _expression =QSharedPointer<ExpressionNode>(node);
}

QString AssignmentNode::nodeType() const
{
    return "assignment";
}

bool AssignmentNode::evaluate(SymbolTable& symbols, int scope)
{
    if ( _expression.isNull())
        return false;

    QString format, fnamespace;
    bool res = _expression->evaluate(symbols, scope);
    if ( res) {
        if ( !_typemodifier.isNull()) {
            ASTNode *node = static_cast<ASTNode *>(_typemodifier.data());
            if ( node->noOfChilderen()!= 1)
                return ERROR2(ERR_NO_OBJECT_TYPE_FOR_2, "Output object", "expression");

            Formatter *fnode = static_cast<Formatter *>(node->child(0).data());
            format = fnode->format();
            fnamespace = fnode->fnamespace();
        }
        NodeValue val = _expression->value();
        if ( val.typeName() == QString("Ilwis::IGridCoverage")) {
            if ( format == "" || format == sUNDEF) {
                Formatter *fnode = ScriptNode::activeFormat(itGRIDCOVERAGE);
                if ( fnode) {
                    format = fnode->format();
                    fnamespace = fnode->fnamespace();
                }
            }
            if ( format == "" || format == sUNDEF) {
                return false;
            }
            Ilwis::IGridCoverage gcresult = val.value<Ilwis::IGridCoverage>();
            QString result = _result->id();
            gcresult->setName(result);
            gcresult->connectTo(QUrl(), format, fnamespace, Ilwis::IlwisObject::cmOUTPUT);
            gcresult->setCreateTime(Ilwis::Time::now());
            gcresult->store(Ilwis::IlwisObject::smMETADATA | Ilwis::IlwisObject::smBINARYDATA);
            if ( result.indexOf(INTERNAL_PREFIX) == -1) {
                mastercatalog()->addItems({gcresult->source()});
            }
        }
        Symbol sym = symbols.getSymbol(_result->id(),SymbolTable::gaREMOVEIFANON);
        IlwisTypes tp = sym.isValid() ? sym._type : itUNKNOWN;

        symbols.addSymbol(_result->id(), scope, tp, _expression->value());
        return true;
    }
    return false;
}

<|endoftext|>


<commit_before>/**
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you 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 <gmock/gmock.h>
#include <gtest/gtest.h>

#include <process/future.hpp>

#include "tests/flags.hpp"
#include "tests/mesos.hpp"

#include "slave/slave.hpp"
#include "slave/containerizer/docker.hpp"

using namespace mesos;
using namespace mesos::internal;
using namespace mesos::internal::tests;

using mesos::internal::master::Master;

using mesos::internal::slave::Slave;
using mesos::internal::slave::DockerContainerizer;

using process::Future;
using process::PID;

using std::vector;
using std::list;
using std::string;

using testing::_;
using testing::DoDefault;
using testing::Eq;
using testing::Return;

class DockerContainerizerTest : public MesosTest {};

class MockDockerContainerizer : public slave::DockerContainerizer {
public:
  MockDockerContainerizer(
    const slave::Flags& flags,
    bool local,
    const Docker& docker) : DockerContainerizer(flags, local, docker) {}

  process::Future<bool> launch(
    const ContainerID& containerId,
    const TaskInfo& taskInfo,
    const ExecutorInfo& executorInfo,
    const std::string& directory,
    const Option<std::string>& user,
    const SlaveID& slaveId,
    const process::PID<Slave>& slavePid,
    bool checkpoint)
  {
    // Keeping the last launched container id.
    lastContainerId = containerId;
    return slave::DockerContainerizer::launch(
             containerId,
             taskInfo,
             executorInfo,
             directory,
             user,
             slaveId,
             slavePid,
             checkpoint);
  }

  ContainerID lastContainerId;
};

TEST_F(DockerContainerizerTest, DOCKER_Launch)
{
  Try<PID<Master> > master = StartMaster();
  ASSERT_SOME(master);

  slave::Flags flags = CreateSlaveFlags();

  Docker docker(tests::flags.docker);

  MockDockerContainerizer dockerContainer(flags, true, docker);

  Try<PID<Slave> > slave = StartSlave((slave::Containerizer*) &dockerContainer);
  ASSERT_SOME(slave);

  MockScheduler sched;
  MesosSchedulerDriver driver(
    &sched, DEFAULT_FRAMEWORK_INFO, master.get(), DEFAULT_CREDENTIAL);

  Future<FrameworkID> frameworkId;
  EXPECT_CALL(sched, registered(&driver, _, _))
    .WillOnce(FutureArg<1>(&frameworkId));

  Future<vector<Offer> > offers;
  EXPECT_CALL(sched, resourceOffers(&driver, _))
    .WillOnce(FutureArg<1>(&offers))
    .WillRepeatedly(Return()); // Ignore subsequent offers.

  driver.start();

  AWAIT_READY(frameworkId);

  AWAIT_READY(offers);
  EXPECT_NE(0u, offers.get().size());

  const Offer& offer = offers.get()[0];

  TaskInfo task;
  task.set_name("");
  task.mutable_task_id()->set_value("1");
  task.mutable_slave_id()->CopyFrom(offer.slave_id());
  task.mutable_resources()->CopyFrom(offer.resources());

  CommandInfo command;
  CommandInfo::ContainerInfo* containerInfo = command.mutable_container();
  containerInfo->set_image("docker://busybox");
  command.set_value("sleep 120");

  task.mutable_command()->CopyFrom(command);

  Future<TaskStatus> statusRunning;

  vector<TaskInfo> tasks;
  tasks.push_back(task);

  EXPECT_CALL(sched, statusUpdate(&driver, _))
    .WillOnce(FutureArg<1>(&statusRunning))
    .WillRepeatedly(DoDefault());

  driver.launchTasks(offers.get()[0].id(), tasks);

  AWAIT_READY_FOR(statusRunning, Seconds(60));
  EXPECT_EQ(TASK_RUNNING, statusRunning.get().state());

  Future<list<Docker::Container> > containers = docker.ps();

  AWAIT_READY(containers);

  ASSERT_TRUE(containers.get().size() > 0);

  bool foundContainer = false;
  string expectedName =
    slave::DOCKER_NAME_PREFIX + dockerContainer.lastContainerId.value();

  foreach (const Docker::Container& container, containers.get()) {
    // Docker inspect name contains an extra slash in the beginning.
    if (strings::contains(container.name(), expectedName)) {
      foundContainer = true;
      break;
    }
  }

  ASSERT_TRUE(foundContainer);

  dockerContainer.destroy(dockerContainer.lastContainerId);

  driver.stop();
  driver.join();

  Shutdown();
}

// This test tests DockerContainerizer::usage().
TEST_F(DockerContainerizerTest, DOCKER_Usage)
{
  Try<PID<Master> > master = StartMaster();
  ASSERT_SOME(master);

  slave::Flags flags = CreateSlaveFlags();

  Docker docker(tests::flags.docker);

  MockDockerContainerizer dockerContainer(flags, true, docker);

  Try<PID<Slave> > slave = StartSlave((slave::Containerizer*) &dockerContainer);
  ASSERT_SOME(slave);

  MockScheduler sched;
  MesosSchedulerDriver driver(
    &sched, DEFAULT_FRAMEWORK_INFO, master.get(), DEFAULT_CREDENTIAL);

  Future<FrameworkID> frameworkId;
  EXPECT_CALL(sched, registered(&driver, _, _))
    .WillOnce(FutureArg<1>(&frameworkId));

  Future<vector<Offer> > offers;
  EXPECT_CALL(sched, resourceOffers(&driver, _))
    .WillOnce(FutureArg<1>(&offers))
    .WillRepeatedly(Return()); // Ignore subsequent offers.

  driver.start();

  AWAIT_READY(frameworkId);

  AWAIT_READY(offers);
  EXPECT_NE(0u, offers.get().size());

  const Offer& offer = offers.get()[0];

  TaskInfo task;
  task.set_name("");
  task.mutable_task_id()->set_value("1");
  task.mutable_slave_id()->CopyFrom(offer.slave_id());
  task.mutable_resources()->CopyFrom(offer.resources());

  CommandInfo command;
  CommandInfo::ContainerInfo* containerInfo = command.mutable_container();
  containerInfo->set_image("docker://busybox");
  command.set_value("sleep 120");

  task.mutable_command()->CopyFrom(command);

  Future<TaskStatus> statusRunning;

  vector<TaskInfo> tasks;
  tasks.push_back(task);

  EXPECT_CALL(sched, statusUpdate(&driver, _))
    .WillOnce(FutureArg<1>(&statusRunning))
    .WillRepeatedly(DoDefault());

  // Usage() should fail since the container is not launched.
  Future<ResourceStatistics> usage =
    dockerContainer.usage(dockerContainer.lastContainerId);

  AWAIT_FAILED(usage);

  driver.launchTasks(offers.get()[0].id(), tasks);

  AWAIT_READY_FOR(statusRunning, Seconds(60));
  EXPECT_EQ(TASK_RUNNING, statusRunning.get().state());

  usage = dockerContainer.usage(dockerContainer.lastContainerId);
  AWAIT_READY(usage);
  // TODO(yifan): Verify the usage.

  dockerContainer.destroy(dockerContainer.lastContainerId);

  // Usage() should fail again since the container is destroyed.
  usage = dockerContainer.usage(dockerContainer.lastContainerId);
  AWAIT_FAILED(usage);

  driver.stop();
  driver.join();

  Shutdown();
}
<commit_msg>Renamed variable to be more accurate.<commit_after>/**
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you 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 <gmock/gmock.h>
#include <gtest/gtest.h>

#include <process/future.hpp>

#include "tests/flags.hpp"
#include "tests/mesos.hpp"

#include "slave/slave.hpp"
#include "slave/containerizer/docker.hpp"

using namespace mesos;
using namespace mesos::internal;
using namespace mesos::internal::tests;

using mesos::internal::master::Master;

using mesos::internal::slave::Slave;
using mesos::internal::slave::DockerContainerizer;

using process::Future;
using process::PID;

using std::vector;
using std::list;
using std::string;

using testing::_;
using testing::DoDefault;
using testing::Eq;
using testing::Return;

class DockerContainerizerTest : public MesosTest {};

class MockDockerContainerizer : public slave::DockerContainerizer {
public:
  MockDockerContainerizer(
    const slave::Flags& flags,
    bool local,
    const Docker& docker) : DockerContainerizer(flags, local, docker) {}

  process::Future<bool> launch(
    const ContainerID& containerId,
    const TaskInfo& taskInfo,
    const ExecutorInfo& executorInfo,
    const std::string& directory,
    const Option<std::string>& user,
    const SlaveID& slaveId,
    const process::PID<Slave>& slavePid,
    bool checkpoint)
  {
    // Keeping the last launched container id.
    lastContainerId = containerId;
    return slave::DockerContainerizer::launch(
             containerId,
             taskInfo,
             executorInfo,
             directory,
             user,
             slaveId,
             slavePid,
             checkpoint);
  }

  ContainerID lastContainerId;
};

TEST_F(DockerContainerizerTest, DOCKER_Launch)
{
  Try<PID<Master> > master = StartMaster();
  ASSERT_SOME(master);

  slave::Flags flags = CreateSlaveFlags();

  Docker docker(tests::flags.docker);

  MockDockerContainerizer dockerContainerizer(flags, true, docker);

  Try<PID<Slave> > slave = StartSlave(&dockerContainerizer);
  ASSERT_SOME(slave);

  MockScheduler sched;
  MesosSchedulerDriver driver(
    &sched, DEFAULT_FRAMEWORK_INFO, master.get(), DEFAULT_CREDENTIAL);

  Future<FrameworkID> frameworkId;
  EXPECT_CALL(sched, registered(&driver, _, _))
    .WillOnce(FutureArg<1>(&frameworkId));

  Future<vector<Offer> > offers;
  EXPECT_CALL(sched, resourceOffers(&driver, _))
    .WillOnce(FutureArg<1>(&offers))
    .WillRepeatedly(Return()); // Ignore subsequent offers.

  driver.start();

  AWAIT_READY(frameworkId);

  AWAIT_READY(offers);
  EXPECT_NE(0u, offers.get().size());

  const Offer& offer = offers.get()[0];

  TaskInfo task;
  task.set_name("");
  task.mutable_task_id()->set_value("1");
  task.mutable_slave_id()->CopyFrom(offer.slave_id());
  task.mutable_resources()->CopyFrom(offer.resources());

  CommandInfo command;
  CommandInfo::ContainerInfo* containerInfo = command.mutable_container();
  containerInfo->set_image("docker://busybox");
  command.set_value("sleep 120");

  task.mutable_command()->CopyFrom(command);

  Future<TaskStatus> statusRunning;

  vector<TaskInfo> tasks;
  tasks.push_back(task);

  EXPECT_CALL(sched, statusUpdate(&driver, _))
    .WillOnce(FutureArg<1>(&statusRunning))
    .WillRepeatedly(DoDefault());

  driver.launchTasks(offers.get()[0].id(), tasks);

  AWAIT_READY_FOR(statusRunning, Seconds(60));
  EXPECT_EQ(TASK_RUNNING, statusRunning.get().state());

  Future<list<Docker::Container> > containers = docker.ps();

  AWAIT_READY(containers);

  ASSERT_TRUE(containers.get().size() > 0);

  bool foundContainer = false;
  string expectedName =
    slave::DOCKER_NAME_PREFIX + dockerContainerizer.lastContainerId.value();

  foreach (const Docker::Container& container, containers.get()) {
    // Docker inspect name contains an extra slash in the beginning.
    if (strings::contains(container.name(), expectedName)) {
      foundContainer = true;
      break;
    }
  }

  ASSERT_TRUE(foundContainer);

  dockerContainerizer.destroy(dockerContainerizer.lastContainerId);

  driver.stop();
  driver.join();

  Shutdown();
}

// This test tests DockerContainerizer::usage().
TEST_F(DockerContainerizerTest, DOCKER_Usage)
{
  Try<PID<Master> > master = StartMaster();
  ASSERT_SOME(master);

  slave::Flags flags = CreateSlaveFlags();

  Docker docker(tests::flags.docker);

  MockDockerContainerizer dockerContainerizer(flags, true, docker);

  Try<PID<Slave> > slave = StartSlave(&dockerContainerizer);
  ASSERT_SOME(slave);

  MockScheduler sched;
  MesosSchedulerDriver driver(
    &sched, DEFAULT_FRAMEWORK_INFO, master.get(), DEFAULT_CREDENTIAL);

  Future<FrameworkID> frameworkId;
  EXPECT_CALL(sched, registered(&driver, _, _))
    .WillOnce(FutureArg<1>(&frameworkId));

  Future<vector<Offer> > offers;
  EXPECT_CALL(sched, resourceOffers(&driver, _))
    .WillOnce(FutureArg<1>(&offers))
    .WillRepeatedly(Return()); // Ignore subsequent offers.

  driver.start();

  AWAIT_READY(frameworkId);

  AWAIT_READY(offers);
  EXPECT_NE(0u, offers.get().size());

  const Offer& offer = offers.get()[0];

  TaskInfo task;
  task.set_name("");
  task.mutable_task_id()->set_value("1");
  task.mutable_slave_id()->CopyFrom(offer.slave_id());
  task.mutable_resources()->CopyFrom(offer.resources());

  CommandInfo command;
  CommandInfo::ContainerInfo* containerInfo = command.mutable_container();
  containerInfo->set_image("docker://busybox");
  command.set_value("sleep 120");

  task.mutable_command()->CopyFrom(command);

  Future<TaskStatus> statusRunning;

  vector<TaskInfo> tasks;
  tasks.push_back(task);

  EXPECT_CALL(sched, statusUpdate(&driver, _))
    .WillOnce(FutureArg<1>(&statusRunning))
    .WillRepeatedly(DoDefault());

  // Usage() should fail since the container is not launched.
  Future<ResourceStatistics> usage =
    dockerContainerizer.usage(dockerContainerizer.lastContainerId);

  AWAIT_FAILED(usage);

  driver.launchTasks(offers.get()[0].id(), tasks);

  AWAIT_READY_FOR(statusRunning, Seconds(60));
  EXPECT_EQ(TASK_RUNNING, statusRunning.get().state());

  usage = dockerContainerizer.usage(dockerContainerizer.lastContainerId);
  AWAIT_READY(usage);
  // TODO(yifan): Verify the usage.

  dockerContainerizer.destroy(dockerContainerizer.lastContainerId);

  // Usage() should fail again since the container is destroyed.
  usage = dockerContainerizer.usage(dockerContainerizer.lastContainerId);
  AWAIT_FAILED(usage);

  driver.stop();
  driver.join();

  Shutdown();
}
<|endoftext|>


<commit_before>#include "setupdialog.h"

WARNINGS_DISABLE
#include <QDateTime>
#include <QDir>
#include <QFileDialog>
#include <QFileInfo>
#include <QStandardPaths>

// This is used for QHostInfo::localHostName().  It could be replaced with
// QSysInfo::machineHostName() to remove the dependency on the Qt network
// library, but only if we require Qt 5.6+.
#include <QHostInfo>

#include "ui_setupdialog.h"
WARNINGS_ENABLE

#include "debug.h"
#include "tasks-defs.h"
#include "utils.h"

#include <TSettings.h>

SetupDialog::SetupDialog(QWidget *parent)
    : QDialog(parent), _ui(new Ui::SetupDialog)
{
    _ui->setupUi(this);
    setWindowFlags((windowFlags() | Qt::CustomizeWindowHint)
                   & ~Qt::WindowMaximizeButtonHint);

    // These should be done before connecting objects to
    // validateAdvancedSetupPage() to avoid calling that function
    // unnecessarily.
    _tarsnapDir = Utils::findTarsnapClientInPath("", true);
    _ui->tarsnapPathLineEdit->setText(_tarsnapDir);
    _ui->machineNameLineEdit->setText(QHostInfo::localHostName());
    _ui->wizardStackedWidget->setCurrentWidget(_ui->welcomePage);

    _appDataDir = QStandardPaths::writableLocation(APPDATA);
    QDir keysDir(_appDataDir);
    if(!keysDir.exists())
        keysDir.mkpath(_appDataDir);
    _ui->appDataPathLineEdit->setText(_appDataDir);

    // find existing keys
    for(const QFileInfo &file : Utils::findKeysInPath(_appDataDir))
        _ui->machineKeyCombo->addItem(file.canonicalFilePath());

    _tarsnapCacheDir =
        QStandardPaths::writableLocation(QStandardPaths::CacheLocation);
    QDir cacheDir(_tarsnapCacheDir);
    if(!cacheDir.exists())
        cacheDir.mkpath(_tarsnapCacheDir);
    _ui->tarsnapCacheLineEdit->setText(_tarsnapCacheDir);

    _ui->advancedCLIWidget->hide();

    // All pages
    connect(_ui->backButton, &QPushButton::clicked, this,
            &SetupDialog::backButtonClicked);
    connect(_ui->nextButton, &QPushButton::clicked, this,
            &SetupDialog::nextButtonClicked);
    connect(_ui->welcomePageRadioButton, &QRadioButton::clicked, this,
            &SetupDialog::skipToPage);
    connect(_ui->advancedPageRadioButton, &QRadioButton::clicked, this,
            &SetupDialog::skipToPage);
    connect(_ui->registerPageRadioButton, &QRadioButton::clicked, this,
            &SetupDialog::skipToPage);
    connect(_ui->donePageRadioButton, &QRadioButton::clicked, this,
            &SetupDialog::skipToPage);

    connect(_ui->wizardStackedWidget, &QStackedWidget::currentChanged, this,
            &SetupDialog::wizardPageChanged);

    // Advanced setup page
    connect(_ui->advancedCLIButton, &QPushButton::toggled,
            _ui->advancedCLIWidget, &QWidget::setVisible);
    connect(_ui->tarsnapPathBrowseButton, &QPushButton::clicked, this,
            &SetupDialog::showTarsnapPathBrowse);
    connect(_ui->tarsnapPathLineEdit, &QLineEdit::textChanged, this,
            &SetupDialog::validateAdvancedSetupPage);
    connect(_ui->tarsnapCacheBrowseButton, &QPushButton::clicked, this,
            &SetupDialog::showTarsnapCacheBrowse);
    connect(_ui->tarsnapCacheLineEdit, &QLineEdit::textChanged, this,
            &SetupDialog::validateAdvancedSetupPage);
    connect(_ui->appDataBrowseButton, &QPushButton::clicked, this,
            &SetupDialog::showAppDataBrowse);
    connect(_ui->appDataPathLineEdit, &QLineEdit::textChanged, this,
            &SetupDialog::validateAdvancedSetupPage);

    // Register page
    connect(_ui->restoreNoButton, &QPushButton::clicked, this,
            &SetupDialog::restoreNo);
    connect(_ui->restoreYesButton, &QPushButton::clicked, this,
            &SetupDialog::restoreYes);
    connect(_ui->tarsnapUserLineEdit, &QLineEdit::textChanged, this,
            &SetupDialog::validateRegisterPage);
    connect(_ui->tarsnapPasswordLineEdit, &QLineEdit::textChanged, this,
            &SetupDialog::validateRegisterPage);
    connect(_ui->machineNameLineEdit, &QLineEdit::textChanged, this,
            &SetupDialog::validateRegisterPage);
    connect(_ui->machineKeyCombo, &QComboBox::currentTextChanged, this,
            &SetupDialog::validateRegisterPage);
    connect(_ui->browseKeyButton, &QPushButton::clicked, this,
            &SetupDialog::registerHaveKeyBrowse);

    wizardPageChanged(0);
}

SetupDialog::~SetupDialog()
{
    delete _ui;
}

void SetupDialog::wizardPageChanged(int)
{
    // Values which might be overwritten below.
    _ui->backButton->setText(tr("Back"));
    _ui->nextButton->setText(tr("Next"));
    _ui->nextButton->setEnabled(true);

    if(_ui->wizardStackedWidget->currentWidget() == _ui->welcomePage)
    {
        _ui->welcomePageRadioButton->setChecked(true);
        _ui->titleLabel->setText(tr("Setup wizard"));
        _ui->backButton->setText(tr("Skip wizard"));
    }
    else if(_ui->wizardStackedWidget->currentWidget() == _ui->advancedPage)
    {
        _ui->advancedPageRadioButton->setChecked(true);
        _ui->titleLabel->setText(tr("Command-line utilities"));
    }
    else if(_ui->wizardStackedWidget->currentWidget() == _ui->registerPage)
    {
        _ui->registerPageRadioButton->setChecked(true);
        _ui->titleLabel->setText(tr("Register with server"));
        _ui->nextButton->setText(tr("Register machine"));
        if(_ui->machineKeyCombo->count() > 0)
        {
            _ui->restoreYesButton->setChecked(true);
            restoreYes();
        }
        else
        {
            _ui->restoreNoButton->setChecked(true);
            restoreNo();
        }
    }
    else if(_ui->wizardStackedWidget->currentWidget() == _ui->donePage)
    {
        _ui->donePageRadioButton->setChecked(true);
        _ui->titleLabel->setText(tr("Setup complete!"));
        _ui->nextButton->setText(tr("Start using Tarsnap"));
    }
}

void SetupDialog::backButtonClicked()
{
    int nextIndex = _ui->wizardStackedWidget->currentIndex() - 1;
    if(nextIndex < 0)
        commitSettings(true);
    else
        _ui->wizardStackedWidget->setCurrentIndex(nextIndex);
}

void SetupDialog::nextButtonClicked()
{
    if(_ui->wizardStackedWidget->currentWidget() == _ui->registerPage)
        registerMachine();
    else if(_ui->wizardStackedWidget->currentWidget() == _ui->donePage)
        commitSettings(false);
    else
        setNextPage();
}

void SetupDialog::skipToPage()
{
    if(sender() == _ui->welcomePageRadioButton)
        _ui->wizardStackedWidget->setCurrentWidget(_ui->welcomePage);
    else if(sender() == _ui->advancedPageRadioButton)
        _ui->wizardStackedWidget->setCurrentWidget(_ui->advancedPage);
    else if(sender() == _ui->registerPageRadioButton)
        _ui->wizardStackedWidget->setCurrentWidget(_ui->registerPage);
    else if(sender() == _ui->donePageRadioButton)
        _ui->wizardStackedWidget->setCurrentWidget(_ui->donePage);
}

void SetupDialog::setNextPage()
{
    if(_ui->wizardStackedWidget->currentWidget() == _ui->welcomePage)
    {
        _ui->wizardStackedWidget->setCurrentWidget(_ui->advancedPage);
        _ui->advancedPageRadioButton->setEnabled(true);
        // Disable this until we know the version number.
        _ui->nextButton->setEnabled(false);
        bool advancedOk = validateAdvancedSetupPage();
        _ui->advancedCLIButton->setChecked(!advancedOk);
    }
    else if(_ui->wizardStackedWidget->currentWidget() == _ui->advancedPage)
    {
        _ui->wizardStackedWidget->setCurrentWidget(_ui->registerPage);
        _ui->registerPageRadioButton->setEnabled(true);
        if(validateRegisterPage())
            _ui->nextButton->setFocus();
    }
    else if(_ui->wizardStackedWidget->currentWidget() == _ui->registerPage)
    {
        _ui->wizardStackedWidget->setCurrentWidget(_ui->donePage);
        _ui->donePageRadioButton->setEnabled(true);
    }
}

void SetupDialog::showTarsnapPathBrowse()
{
    QString tarsnapPath =
        QFileDialog::getExistingDirectory(this, tr("Find Tarsnap client"), "");
    _ui->tarsnapPathLineEdit->setText(tarsnapPath);
}

void SetupDialog::showTarsnapCacheBrowse()
{
    QString tarsnapCacheDir =
        QFileDialog::getExistingDirectory(this, tr("Tarsnap cache location"),
                                          _tarsnapCacheDir);
    _ui->tarsnapCacheLineEdit->setText(tarsnapCacheDir);
}

void SetupDialog::showAppDataBrowse()
{
    QString appDataDir =
        QFileDialog::getExistingDirectory(this, tr("App data location"), "");
    _ui->appDataPathLineEdit->setText(appDataDir);
}

bool SetupDialog::validateAdvancedSetupPage()
{
    bool result = true;

    _appDataDir = Utils::validateAppDataDir(_ui->appDataPathLineEdit->text());
    if(_appDataDir.isEmpty())
    {
        _ui->advancedValidationLabel->setText(tr("Invalid App data directory "
                                                 "set."));
        result = false;
    }

    _tarsnapCacheDir =
        Utils::validateTarsnapCache(_ui->tarsnapCacheLineEdit->text());
    if(result && _tarsnapCacheDir.isEmpty())
    {
        _ui->advancedValidationLabel->setText(
            tr("Invalid Tarsnap cache directory"
               " set."));
        result = false;
    }

    _tarsnapDir =
        Utils::findTarsnapClientInPath(_ui->tarsnapPathLineEdit->text(), true);
    if(result && _tarsnapDir.isEmpty())
    {
        _ui->advancedValidationLabel->setText(
            tr("Tarsnap utilities not found. Visit "
               "tarsnap.com "
               "for help with acquiring them."));
        result = false;
    }
    else if(result)
    {
        TSettings settings;
        settings.setValue("tarsnap/path", _tarsnapDir);
        // Wipe previous version number before asking for a new one.
        settings.setValue("tarsnap/version", "");
        emit tarsnapVersionRequested();
    }

    // If `results` is true, then we might still be waiting for
    // the result of tarsnapVersion, so we can't enable this yet.
    if(!result)
        _ui->nextButton->setEnabled(false);

    return result;
}

void SetupDialog::restoreNo()
{
    _ui->registerKeyStackedWidget->setCurrentWidget(_ui->keyNoPage);
    // Share machineNameLineEdit in both pages of the keyStackedWidget
    _ui->gridKeyNoLayout->addWidget(_ui->machineNameLineEdit, 1, 1);
    _ui->statusLabel->clear();
    if(validateRegisterPage())
        _ui->nextButton->setFocus();
}

void SetupDialog::restoreYes()
{
    _ui->registerKeyStackedWidget->setCurrentWidget(_ui->keyYesPage);
    // Share machineNameLineEdit in both pages of the keyStackedWidget
    _ui->gridKeyYesLayout->addWidget(_ui->machineNameLineEdit, 1, 1);
    _ui->statusLabel->clear();
    if(validateRegisterPage())
        _ui->nextButton->setFocus();
}

bool SetupDialog::validateRegisterPage()
{
    bool result = false;
    if(_ui->restoreYesButton->isChecked())
    {
        // user specified key
        QFileInfo machineKeyFile(_ui->machineKeyCombo->currentText());
        if(!_ui->machineNameLineEdit->text().isEmpty()
           && machineKeyFile.exists() && machineKeyFile.isFile()
           && machineKeyFile.isReadable())
        {
            result = true;
        }
    }
    else
    {
        if(!_ui->tarsnapUserLineEdit->text().isEmpty()
           && !_ui->tarsnapPasswordLineEdit->text().isEmpty()
           && !_ui->machineNameLineEdit->text().isEmpty())
        {
            result = true;
        }
    }

    _ui->nextButton->setEnabled(result);
    return result;
}

void SetupDialog::registerHaveKeyBrowse()
{
    QString keyFilter = tr("Tarsnap key files (*.key *.keys)");
    QString existingMachineKey =
        QFileDialog::getOpenFileName(this,
                                     tr("Browse for existing machine key"), "",
                                     tr("All files (*);;") + keyFilter,
                                     &keyFilter);
    if(!existingMachineKey.isEmpty())
        _ui->machineKeyCombo->setCurrentText(existingMachineKey);
}

void SetupDialog::registerMachine()
{
    bool useExistingKeyfile = false;
    _ui->nextButton->setEnabled(false);
    _ui->statusLabel->clear();
    _ui->statusLabel->setStyleSheet("");
    if(_ui->restoreYesButton->isChecked())
    {
        useExistingKeyfile = true;
        _ui->statusLabel->setText("Verifying archive integrity...");
        _tarsnapKeyFile = _ui->machineKeyCombo->currentText();
    }
    else
    {
        _ui->statusLabel->setText("Generating keyfile...");
        _tarsnapKeyFile =
            _appDataDir + QDir::separator() + _ui->machineNameLineEdit->text()
            + "-" + QDateTime::currentDateTime().toString("yyyy-MM-dd-HH-mm-ss")
            + ".key";
    }

    TSettings settings;
    settings.setValue("tarsnap/cache", _tarsnapCacheDir);
    settings.setValue("tarsnap/key", _tarsnapKeyFile);
    settings.setValue("tarsnap/user", _ui->tarsnapUserLineEdit->text());
    settings.setValue("tarsnap/machine", _ui->machineNameLineEdit->text());

    emit registerMachineRequested(_ui->tarsnapPasswordLineEdit->text(),
                                  useExistingKeyfile);
}

void SetupDialog::registerMachineResponse(TaskStatus status, QString reason)
{
    switch(status)
    {
    case TaskStatus::Completed:
        _ui->statusLabel->clear();
        _ui->doneKeyFileNameLabel->setText(
            QString("%2")
                .arg(QUrl::fromLocalFile(
                         QFileInfo(_tarsnapKeyFile).absolutePath())
                         .toString())
                .arg(_tarsnapKeyFile));
        _ui->nextButton->setEnabled(true);
        setNextPage();
        break;
    case TaskStatus::Failed:
        _ui->statusLabel->setText(reason);
        _ui->statusLabel->setStyleSheet("#statusLabel { color: darkred; }");
        _ui->nextButton->setEnabled(true);
        break;
    default:
        // We shouldn't receive anything else, so ignore it.
        break;
    }
}

void SetupDialog::updateLoadingAnimation(bool idle)
{
    _ui->busyWidget->animate(!idle);
}

void SetupDialog::tarsnapVersionResponse(TaskStatus status,
                                         QString    versionString)
{
    // Sanity check.
    if(versionString.isEmpty())
        status = TaskStatus::Failed;

    // Handle response.
    switch(status)
    {
    case TaskStatus::Completed:
        _tarsnapVersion = versionString;
        _ui->advancedValidationLabel->setText(
            tr("Tarsnap CLI version ") + _tarsnapVersion + tr(" detected.  ✔"));
        // Enable progress
        _ui->nextButton->setEnabled(true);
        _ui->nextButton->setFocus();
        break;
    case TaskStatus::VersionTooLow:
        // Don't record the too-low version number.
        _ui->advancedValidationLabel->setText(
            tr("Tarsnap CLI version ") + versionString
            + tr(" too low; must be at least %1").arg(TARSNAP_MIN_VERSION));
        break;
    case TaskStatus::Failed:
        _ui->advancedValidationLabel->setText(
            tr("Error retrieving Tarsnap CLI verison"));
        break;
    default:
        break;
    }
}

void SetupDialog::commitSettings(bool skipped)
{
    TSettings settings;

    settings.setValue("app/wizard_done", true);

    if(!skipped)
    {
        settings.setValue("app/app_data", _appDataDir);
        settings.setValue("tarsnap/version", _tarsnapVersion);
    }
    settings.sync();

    accept();
}
<commit_msg>SetupDialog: trivial reformatting<commit_after>#include "setupdialog.h"

WARNINGS_DISABLE
#include <QDateTime>
#include <QDir>
#include <QFileDialog>
#include <QFileInfo>
#include <QStandardPaths>

// This is used for QHostInfo::localHostName().  It could be replaced with
// QSysInfo::machineHostName() to remove the dependency on the Qt network
// library, but only if we require Qt 5.6+.
#include <QHostInfo>

#include "ui_setupdialog.h"
WARNINGS_ENABLE

#include "debug.h"
#include "tasks-defs.h"
#include "utils.h"

#include <TSettings.h>

SetupDialog::SetupDialog(QWidget *parent)
    : QDialog(parent), _ui(new Ui::SetupDialog)
{
    _ui->setupUi(this);
    setWindowFlags((windowFlags() | Qt::CustomizeWindowHint)
                   & ~Qt::WindowMaximizeButtonHint);

    // This should be done before connecting objects to
    // validateAdvancedSetupPage() to avoid calling that function
    // unnecessarily.
    _tarsnapDir = Utils::findTarsnapClientInPath("", true);
    _ui->tarsnapPathLineEdit->setText(_tarsnapDir);
    _ui->machineNameLineEdit->setText(QHostInfo::localHostName());

    _appDataDir = QStandardPaths::writableLocation(APPDATA);
    QDir keysDir(_appDataDir);
    if(!keysDir.exists())
        keysDir.mkpath(_appDataDir);
    _ui->appDataPathLineEdit->setText(_appDataDir);

    // find existing keys
    for(const QFileInfo &file : Utils::findKeysInPath(_appDataDir))
        _ui->machineKeyCombo->addItem(file.canonicalFilePath());

    _tarsnapCacheDir =
        QStandardPaths::writableLocation(QStandardPaths::CacheLocation);
    QDir cacheDir(_tarsnapCacheDir);
    if(!cacheDir.exists())
        cacheDir.mkpath(_tarsnapCacheDir);
    _ui->tarsnapCacheLineEdit->setText(_tarsnapCacheDir);

    _ui->advancedCLIWidget->hide();

    // All pages
    connect(_ui->backButton, &QPushButton::clicked, this,
            &SetupDialog::backButtonClicked);
    connect(_ui->nextButton, &QPushButton::clicked, this,
            &SetupDialog::nextButtonClicked);
    connect(_ui->welcomePageRadioButton, &QRadioButton::clicked, this,
            &SetupDialog::skipToPage);
    connect(_ui->advancedPageRadioButton, &QRadioButton::clicked, this,
            &SetupDialog::skipToPage);
    connect(_ui->registerPageRadioButton, &QRadioButton::clicked, this,
            &SetupDialog::skipToPage);
    connect(_ui->donePageRadioButton, &QRadioButton::clicked, this,
            &SetupDialog::skipToPage);

    connect(_ui->wizardStackedWidget, &QStackedWidget::currentChanged, this,
            &SetupDialog::wizardPageChanged);

    // Advanced setup page
    connect(_ui->advancedCLIButton, &QPushButton::toggled,
            _ui->advancedCLIWidget, &QWidget::setVisible);
    connect(_ui->tarsnapPathBrowseButton, &QPushButton::clicked, this,
            &SetupDialog::showTarsnapPathBrowse);
    connect(_ui->tarsnapPathLineEdit, &QLineEdit::textChanged, this,
            &SetupDialog::validateAdvancedSetupPage);
    connect(_ui->tarsnapCacheBrowseButton, &QPushButton::clicked, this,
            &SetupDialog::showTarsnapCacheBrowse);
    connect(_ui->tarsnapCacheLineEdit, &QLineEdit::textChanged, this,
            &SetupDialog::validateAdvancedSetupPage);
    connect(_ui->appDataBrowseButton, &QPushButton::clicked, this,
            &SetupDialog::showAppDataBrowse);
    connect(_ui->appDataPathLineEdit, &QLineEdit::textChanged, this,
            &SetupDialog::validateAdvancedSetupPage);

    // Register page
    connect(_ui->restoreNoButton, &QPushButton::clicked, this,
            &SetupDialog::restoreNo);
    connect(_ui->restoreYesButton, &QPushButton::clicked, this,
            &SetupDialog::restoreYes);
    connect(_ui->tarsnapUserLineEdit, &QLineEdit::textChanged, this,
            &SetupDialog::validateRegisterPage);
    connect(_ui->tarsnapPasswordLineEdit, &QLineEdit::textChanged, this,
            &SetupDialog::validateRegisterPage);
    connect(_ui->machineNameLineEdit, &QLineEdit::textChanged, this,
            &SetupDialog::validateRegisterPage);
    connect(_ui->machineKeyCombo, &QComboBox::currentTextChanged, this,
            &SetupDialog::validateRegisterPage);
    connect(_ui->browseKeyButton, &QPushButton::clicked, this,
            &SetupDialog::registerHaveKeyBrowse);

    // Initial state
    _ui->wizardStackedWidget->setCurrentWidget(_ui->welcomePage);
    wizardPageChanged(0);
}

SetupDialog::~SetupDialog()
{
    delete _ui;
}

void SetupDialog::wizardPageChanged(int)
{
    // Values which might be overwritten below.
    _ui->backButton->setText(tr("Back"));
    _ui->nextButton->setText(tr("Next"));
    _ui->nextButton->setEnabled(true);

    if(_ui->wizardStackedWidget->currentWidget() == _ui->welcomePage)
    {
        _ui->welcomePageRadioButton->setChecked(true);
        _ui->titleLabel->setText(tr("Setup wizard"));
        _ui->backButton->setText(tr("Skip wizard"));
    }
    else if(_ui->wizardStackedWidget->currentWidget() == _ui->advancedPage)
    {
        _ui->advancedPageRadioButton->setChecked(true);
        _ui->titleLabel->setText(tr("Command-line utilities"));
    }
    else if(_ui->wizardStackedWidget->currentWidget() == _ui->registerPage)
    {
        _ui->registerPageRadioButton->setChecked(true);
        _ui->titleLabel->setText(tr("Register with server"));
        _ui->nextButton->setText(tr("Register machine"));
        if(_ui->machineKeyCombo->count() > 0)
        {
            _ui->restoreYesButton->setChecked(true);
            restoreYes();
        }
        else
        {
            _ui->restoreNoButton->setChecked(true);
            restoreNo();
        }
    }
    else if(_ui->wizardStackedWidget->currentWidget() == _ui->donePage)
    {
        _ui->donePageRadioButton->setChecked(true);
        _ui->titleLabel->setText(tr("Setup complete!"));
        _ui->nextButton->setText(tr("Start using Tarsnap"));
    }
}

void SetupDialog::backButtonClicked()
{
    int nextIndex = _ui->wizardStackedWidget->currentIndex() - 1;
    if(nextIndex < 0)
        commitSettings(true);
    else
        _ui->wizardStackedWidget->setCurrentIndex(nextIndex);
}

void SetupDialog::nextButtonClicked()
{
    if(_ui->wizardStackedWidget->currentWidget() == _ui->registerPage)
        registerMachine();
    else if(_ui->wizardStackedWidget->currentWidget() == _ui->donePage)
        commitSettings(false);
    else
        setNextPage();
}

void SetupDialog::skipToPage()
{
    if(sender() == _ui->welcomePageRadioButton)
        _ui->wizardStackedWidget->setCurrentWidget(_ui->welcomePage);
    else if(sender() == _ui->advancedPageRadioButton)
        _ui->wizardStackedWidget->setCurrentWidget(_ui->advancedPage);
    else if(sender() == _ui->registerPageRadioButton)
        _ui->wizardStackedWidget->setCurrentWidget(_ui->registerPage);
    else if(sender() == _ui->donePageRadioButton)
        _ui->wizardStackedWidget->setCurrentWidget(_ui->donePage);
}

void SetupDialog::setNextPage()
{
    if(_ui->wizardStackedWidget->currentWidget() == _ui->welcomePage)
    {
        _ui->wizardStackedWidget->setCurrentWidget(_ui->advancedPage);
        _ui->advancedPageRadioButton->setEnabled(true);
        // Disable this until we know the version number.
        _ui->nextButton->setEnabled(false);
        bool advancedOk = validateAdvancedSetupPage();
        _ui->advancedCLIButton->setChecked(!advancedOk);
    }
    else if(_ui->wizardStackedWidget->currentWidget() == _ui->advancedPage)
    {
        _ui->wizardStackedWidget->setCurrentWidget(_ui->registerPage);
        _ui->registerPageRadioButton->setEnabled(true);
        if(validateRegisterPage())
            _ui->nextButton->setFocus();
    }
    else if(_ui->wizardStackedWidget->currentWidget() == _ui->registerPage)
    {
        _ui->wizardStackedWidget->setCurrentWidget(_ui->donePage);
        _ui->donePageRadioButton->setEnabled(true);
    }
}

void SetupDialog::showTarsnapPathBrowse()
{
    QString tarsnapPath =
        QFileDialog::getExistingDirectory(this, tr("Find Tarsnap client"), "");
    _ui->tarsnapPathLineEdit->setText(tarsnapPath);
}

void SetupDialog::showTarsnapCacheBrowse()
{
    QString tarsnapCacheDir =
        QFileDialog::getExistingDirectory(this, tr("Tarsnap cache location"),
                                          _tarsnapCacheDir);
    _ui->tarsnapCacheLineEdit->setText(tarsnapCacheDir);
}

void SetupDialog::showAppDataBrowse()
{
    QString appDataDir =
        QFileDialog::getExistingDirectory(this, tr("App data location"), "");
    _ui->appDataPathLineEdit->setText(appDataDir);
}

bool SetupDialog::validateAdvancedSetupPage()
{
    bool result = true;

    _appDataDir = Utils::validateAppDataDir(_ui->appDataPathLineEdit->text());
    if(_appDataDir.isEmpty())
    {
        _ui->advancedValidationLabel->setText(tr("Invalid App data directory "
                                                 "set."));
        result = false;
    }

    _tarsnapCacheDir =
        Utils::validateTarsnapCache(_ui->tarsnapCacheLineEdit->text());
    if(result && _tarsnapCacheDir.isEmpty())
    {
        _ui->advancedValidationLabel->setText(
            tr("Invalid Tarsnap cache directory"
               " set."));
        result = false;
    }

    _tarsnapDir =
        Utils::findTarsnapClientInPath(_ui->tarsnapPathLineEdit->text(), true);
    if(result && _tarsnapDir.isEmpty())
    {
        _ui->advancedValidationLabel->setText(
            tr("Tarsnap utilities not found. Visit "
               "tarsnap.com "
               "for help with acquiring them."));
        result = false;
    }
    else if(result)
    {
        TSettings settings;
        settings.setValue("tarsnap/path", _tarsnapDir);
        // Wipe previous version number before asking for a new one.
        settings.setValue("tarsnap/version", "");
        emit tarsnapVersionRequested();
    }

    // If `results` is true, then we might still be waiting for
    // the result of tarsnapVersion, so we can't enable this yet.
    if(!result)
        _ui->nextButton->setEnabled(false);

    return result;
}

void SetupDialog::restoreNo()
{
    _ui->registerKeyStackedWidget->setCurrentWidget(_ui->keyNoPage);
    // Share machineNameLineEdit in both pages of the keyStackedWidget
    _ui->gridKeyNoLayout->addWidget(_ui->machineNameLineEdit, 1, 1);
    _ui->statusLabel->clear();
    if(validateRegisterPage())
        _ui->nextButton->setFocus();
}

void SetupDialog::restoreYes()
{
    _ui->registerKeyStackedWidget->setCurrentWidget(_ui->keyYesPage);
    // Share machineNameLineEdit in both pages of the keyStackedWidget
    _ui->gridKeyYesLayout->addWidget(_ui->machineNameLineEdit, 1, 1);
    _ui->statusLabel->clear();
    if(validateRegisterPage())
        _ui->nextButton->setFocus();
}

bool SetupDialog::validateRegisterPage()
{
    bool result = false;
    if(_ui->restoreYesButton->isChecked())
    {
        // user specified key
        QFileInfo machineKeyFile(_ui->machineKeyCombo->currentText());
        if(!_ui->machineNameLineEdit->text().isEmpty()
           && machineKeyFile.exists() && machineKeyFile.isFile()
           && machineKeyFile.isReadable())
        {
            result = true;
        }
    }
    else
    {
        if(!_ui->tarsnapUserLineEdit->text().isEmpty()
           && !_ui->tarsnapPasswordLineEdit->text().isEmpty()
           && !_ui->machineNameLineEdit->text().isEmpty())
        {
            result = true;
        }
    }

    _ui->nextButton->setEnabled(result);
    return result;
}

void SetupDialog::registerHaveKeyBrowse()
{
    QString keyFilter = tr("Tarsnap key files (*.key *.keys)");
    QString existingMachineKey =
        QFileDialog::getOpenFileName(this,
                                     tr("Browse for existing machine key"), "",
                                     tr("All files (*);;") + keyFilter,
                                     &keyFilter);
    if(!existingMachineKey.isEmpty())
        _ui->machineKeyCombo->setCurrentText(existingMachineKey);
}

void SetupDialog::registerMachine()
{
    TSettings settings;

    bool useExistingKeyfile = false;
    _ui->nextButton->setEnabled(false);
    _ui->statusLabel->clear();
    _ui->statusLabel->setStyleSheet("");
    if(_ui->restoreYesButton->isChecked())
    {
        useExistingKeyfile = true;
        _ui->statusLabel->setText("Verifying archive integrity...");
        _tarsnapKeyFile = _ui->machineKeyCombo->currentText();
    }
    else
    {
        _ui->statusLabel->setText("Generating keyfile...");
        _tarsnapKeyFile =
            _appDataDir + QDir::separator() + _ui->machineNameLineEdit->text()
            + "-" + QDateTime::currentDateTime().toString("yyyy-MM-dd-HH-mm-ss")
            + ".key";
    }

    settings.setValue("tarsnap/cache", _tarsnapCacheDir);
    settings.setValue("tarsnap/key", _tarsnapKeyFile);
    settings.setValue("tarsnap/user", _ui->tarsnapUserLineEdit->text());
    settings.setValue("tarsnap/machine", _ui->machineNameLineEdit->text());

    emit registerMachineRequested(_ui->tarsnapPasswordLineEdit->text(),
                                  useExistingKeyfile);
}

void SetupDialog::registerMachineResponse(TaskStatus status, QString reason)
{
    switch(status)
    {
    case TaskStatus::Completed:
        _ui->statusLabel->clear();
        _ui->doneKeyFileNameLabel->setText(
            QString("%2")
                .arg(QUrl::fromLocalFile(
                         QFileInfo(_tarsnapKeyFile).absolutePath())
                         .toString())
                .arg(_tarsnapKeyFile));
        _ui->nextButton->setEnabled(true);
        setNextPage();
        break;
    case TaskStatus::Failed:
        _ui->statusLabel->setText(reason);
        _ui->statusLabel->setStyleSheet("#statusLabel { color: darkred; }");
        _ui->nextButton->setEnabled(true);
        break;
    default:
        // We shouldn't receive anything else, so ignore it.
        break;
    }
}

void SetupDialog::updateLoadingAnimation(bool idle)
{
    _ui->busyWidget->animate(!idle);
}

void SetupDialog::tarsnapVersionResponse(TaskStatus status,
                                         QString    versionString)
{
    // Sanity check.
    if(versionString.isEmpty())
        status = TaskStatus::Failed;

    // Handle response.
    switch(status)
    {
    case TaskStatus::Completed:
        _tarsnapVersion = versionString;
        _ui->advancedValidationLabel->setText(
            tr("Tarsnap CLI version ") + _tarsnapVersion + tr(" detected.  ✔"));
        // Enable progress
        _ui->nextButton->setEnabled(true);
        _ui->nextButton->setFocus();
        break;
    case TaskStatus::VersionTooLow:
        // Don't record the too-low version number.
        _ui->advancedValidationLabel->setText(
            tr("Tarsnap CLI version ") + versionString
            + tr(" too low; must be at least %1").arg(TARSNAP_MIN_VERSION));
        break;
    case TaskStatus::Failed:
        _ui->advancedValidationLabel->setText(
            tr("Error retrieving Tarsnap CLI verison"));
        break;
    default:
        break;
    }
}

void SetupDialog::commitSettings(bool skipped)
{
    TSettings settings;

    settings.setValue("app/wizard_done", true);

    if(!skipped)
    {
        settings.setValue("app/app_data", _appDataDir);
        settings.setValue("tarsnap/version", _tarsnapVersion);
    }
    settings.sync();

    accept();
}
<|endoftext|>


<commit_before><commit_msg>Progress<commit_after><|endoftext|>


<commit_before>/*
 * connection_pool.cpp
 *
 *  Created on: 11 июля 2015 г.
 *     @author: zmij
 */

#include <tip/db/pg/detail/connection_pool.hpp>
#include <tip/db/pg/detail/basic_connection.hpp>
#include <tip/db/pg/transaction.hpp>
#include <tip/db/pg/common.hpp>
#include <tip/db/pg/error.hpp>

#include <tip/db/pg/log.hpp>

#include <stdexcept>
#include <algorithm>
#include <boost/bind.hpp>

namespace tip {
namespace db {
namespace pg {
namespace detail {

namespace {
/** Local logging facility */
using namespace tip::log;

const std::string LOG_CATEGORY = "PGPOOL";
logger::event_severity DEFAULT_SEVERITY = logger::TRACE;
local
local_log(logger::event_severity s = DEFAULT_SEVERITY)
{
	return local(LOG_CATEGORY, s);
}

}  // namespace
// For more convenient changing severity, eg local_log(logger::WARNING)
using tip::log::logger;

connection_pool::connection_pool(io_service_ptr service,
		size_t pool_size,
		connection_options const& co,
		client_options_type const& params)
	: service_(service), pool_size_(pool_size),
	  co_(co), params_(params), closed_(false)
{
	if (pool_size_ == 0)
		throw error::connection_error("Database connection pool size cannot be zero");

	if (co_.uri.empty())
		throw error::connection_error("No URI in database connection string");

	if (co_.database.empty())
		throw error::connection_error("No database name in database connection string");

	if (co_.user.empty())
		throw error::connection_error("No user name in database connection string");
	local_log() << "Connection pool max size " << pool_size;
}

connection_pool::~connection_pool()
{
	local_log(logger::DEBUG) << "*** connection_pool::~connection_pool()";
}

connection_pool::connection_pool_ptr
connection_pool::create(io_service_ptr service,
		size_t pool_size,
		connection_options const& co,
		client_options_type const& params)
{
	connection_pool_ptr pool(new connection_pool( service, pool_size, co, params ));
	pool->create_new_connection();
	return pool;
}

void
connection_pool::create_new_connection()
{
	if (closed_)
		return;
	{
		auto local = local_log(logger::INFO);
		local << "Create new "
				<< (util::CLEAR) << (util::RED | util::BRIGHT)
				<< alias()
				<< logger::severity_color()
				<< " connection";
	}
	connection_ptr conn = basic_connection::create(service_, co_, params_, {
			boost::bind(&connection_pool::connection_ready, shared_from_this(), _1),
			boost::bind(&connection_pool::connection_terminated, shared_from_this(), _1),
			boost::bind(&connection_pool::connection_error, shared_from_this(), _1, _2),
	});

	connections_.push_back(conn);
	{
		auto local = local_log();
		local
			<< (util::CLEAR) << (util::RED | util::BRIGHT)
			<< alias()
			<< logger::severity_color()
			<< " pool size " << connections_.size();
	}
}

void
connection_pool::connection_ready(connection_ptr c)
{
	{
		auto local = local_log();
		local << "Connection "
				<< (util::CLEAR) << (util::RED | util::BRIGHT)
				<< alias()
				<< logger::severity_color()
				<< " ready";
	}
	lock_type lock(mutex_);

	if (!queue_.empty()) {
		request_callbacks req = queue_.front();
		queue_.pop();
		local_log()
				<< (util::CLEAR) << (util::RED | util::BRIGHT)
				<< alias()
				<< logger::severity_color()
				<< " queue size " << queue_.size() << " (dequeue)";
		c->begin({req.first, req.second});
	} else {
		local_log()
				<< (util::CLEAR) << (util::RED | util::BRIGHT)
				<< alias()
				<< logger::severity_color()
				<< " queue size " << queue_.size();
		if (closed_) {
			close_connections();
		} else {
			ready_connections_.push(c);
		}
	}
}

void
connection_pool::connection_terminated(connection_ptr c)
{
	{
		auto local = local_log(logger::INFO);
		local << "Connection "
				<< (util::CLEAR) << (util::RED | util::BRIGHT)
				<< alias()
				<< logger::severity_color()
				<< " gracefully terminated";
	}
	{
		lock_type lock(mutex_);
		auto f = std::find(connections_.begin(), connections_.end(), c);
		if (f != connections_.end()) {
			connections_.erase(f);
		}

		if (connections_.empty() && closed_ && closed_callback_) {
			closed_callback_();
		}
	}

	{
		auto local = local_log();
		local
			<< (util::CLEAR) << (util::RED | util::BRIGHT)
			<< alias()
			<< logger::severity_color()
			<< " pool size " << connections_.size();
	}
}

void
connection_pool::connection_error(connection_ptr c, error::connection_error const& ec)
{
	local_log(logger::ERROR) << "Connection " << alias() << " error: "
			<< ec.what();
	lock_type lock(mutex_);
	local_log() << "Erase connection from the connection pool";
	auto f = std::find(connections_.begin(), connections_.end(), c);
	if (f != connections_.end()) {
		connections_.erase(f);
	}
	while (!queue_.empty()) {
		request_callbacks req = queue_.front();
		queue_.pop();
		req.second(ec);
	}
}

void
connection_pool::get_connection(transaction_callback const& conn_cb,
		error_callback const& err)
{
	lock_type lock(mutex_);
	if (closed_) {
		err( error::connection_error("Connection pool is closed") );
		return;
	}
	if (!ready_connections_.empty()) {
		local_log() << "Connection to "
				<< (util::CLEAR) << (util::RED | util::BRIGHT)
				<< alias()
				<< logger::severity_color()
				<< " is ready";
		connection_ptr conn = ready_connections_.front();
		ready_connections_.pop();
		conn->begin({conn_cb, err});
	} else {
		local_log()
				<< (util::CLEAR) << (util::RED | util::BRIGHT)
				<< alias()
				<< logger::severity_color()
				<< " queue size " << queue_.size() + 1  << " (enqueue)";;
		if (!closed_ && connections_.size() < pool_size_) {
			create_new_connection();
		}
		queue_.emplace(conn_cb, err);
	}
}

void
connection_pool::close(simple_callback close_cb)
{
	lock_type lock(mutex_);
	closed_ = true;
	closed_callback_ = close_cb;

	if (queue_.empty()) {
		close_connections();
	} else {
		local_log() << "Wait for outstanding tasks to finish";
	}
}

void
connection_pool::close_connections() {
	local_log() << "Close connection pool "
			<< (util::CLEAR) << (util::RED | util::BRIGHT)
			<< alias()
			<< logger::severity_color();
	connections_container copy = connections_;
	for (auto c : copy) {
		c->terminate();
	}
}

} /* namespace detail */
} /* namespace pg */
} /* namespace db */
} /* namespace tip */
<commit_msg>Call shutdown callback immediately when there are no connections<commit_after>/*
 * connection_pool.cpp
 *
 *  Created on: 11 июля 2015 г.
 *     @author: zmij
 */

#include <tip/db/pg/detail/connection_pool.hpp>
#include <tip/db/pg/detail/basic_connection.hpp>
#include <tip/db/pg/transaction.hpp>
#include <tip/db/pg/common.hpp>
#include <tip/db/pg/error.hpp>

#include <tip/db/pg/log.hpp>

#include <stdexcept>
#include <algorithm>
#include <boost/bind.hpp>

namespace tip {
namespace db {
namespace pg {
namespace detail {

namespace {
/** Local logging facility */
using namespace tip::log;

const std::string LOG_CATEGORY = "PGPOOL";
logger::event_severity DEFAULT_SEVERITY = logger::TRACE;
local
local_log(logger::event_severity s = DEFAULT_SEVERITY)
{
	return local(LOG_CATEGORY, s);
}

}  // namespace
// For more convenient changing severity, eg local_log(logger::WARNING)
using tip::log::logger;

connection_pool::connection_pool(io_service_ptr service,
		size_t pool_size,
		connection_options const& co,
		client_options_type const& params)
	: service_(service), pool_size_(pool_size),
	  co_(co), params_(params), closed_(false)
{
	if (pool_size_ == 0)
		throw error::connection_error("Database connection pool size cannot be zero");

	if (co_.uri.empty())
		throw error::connection_error("No URI in database connection string");

	if (co_.database.empty())
		throw error::connection_error("No database name in database connection string");

	if (co_.user.empty())
		throw error::connection_error("No user name in database connection string");
	local_log() << "Connection pool max size " << pool_size;
}

connection_pool::~connection_pool()
{
	local_log(logger::DEBUG) << "*** connection_pool::~connection_pool()";
}

connection_pool::connection_pool_ptr
connection_pool::create(io_service_ptr service,
		size_t pool_size,
		connection_options const& co,
		client_options_type const& params)
{
	connection_pool_ptr pool(new connection_pool( service, pool_size, co, params ));
	pool->create_new_connection();
	return pool;
}

void
connection_pool::create_new_connection()
{
	if (closed_)
		return;
	{
		auto local = local_log(logger::INFO);
		local << "Create new "
				<< (util::CLEAR) << (util::RED | util::BRIGHT)
				<< alias()
				<< logger::severity_color()
				<< " connection";
	}
	connection_ptr conn = basic_connection::create(service_, co_, params_, {
			boost::bind(&connection_pool::connection_ready, shared_from_this(), _1),
			boost::bind(&connection_pool::connection_terminated, shared_from_this(), _1),
			boost::bind(&connection_pool::connection_error, shared_from_this(), _1, _2),
	});

	connections_.push_back(conn);
	{
		auto local = local_log();
		local
			<< (util::CLEAR) << (util::RED | util::BRIGHT)
			<< alias()
			<< logger::severity_color()
			<< " pool size " << connections_.size();
	}
}

void
connection_pool::connection_ready(connection_ptr c)
{
	{
		auto local = local_log();
		local << "Connection "
				<< (util::CLEAR) << (util::RED | util::BRIGHT)
				<< alias()
				<< logger::severity_color()
				<< " ready";
	}
	lock_type lock(mutex_);

	if (!queue_.empty()) {
		request_callbacks req = queue_.front();
		queue_.pop();
		local_log()
				<< (util::CLEAR) << (util::RED | util::BRIGHT)
				<< alias()
				<< logger::severity_color()
				<< " queue size " << queue_.size() << " (dequeue)";
		c->begin({req.first, req.second});
	} else {
		local_log()
				<< (util::CLEAR) << (util::RED | util::BRIGHT)
				<< alias()
				<< logger::severity_color()
				<< " queue size " << queue_.size();
		if (closed_) {
			close_connections();
		} else {
			ready_connections_.push(c);
		}
	}
}

void
connection_pool::connection_terminated(connection_ptr c)
{
	{
		auto local = local_log(logger::INFO);
		local << "Connection "
				<< (util::CLEAR) << (util::RED | util::BRIGHT)
				<< alias()
				<< logger::severity_color()
				<< " gracefully terminated";
	}
	{
		lock_type lock(mutex_);
		auto f = std::find(connections_.begin(), connections_.end(), c);
		if (f != connections_.end()) {
			connections_.erase(f);
		}

		if (connections_.empty() && closed_ && closed_callback_) {
			closed_callback_();
		}
	}

	{
		auto local = local_log();
		local
			<< (util::CLEAR) << (util::RED | util::BRIGHT)
			<< alias()
			<< logger::severity_color()
			<< " pool size " << connections_.size();
	}
}

void
connection_pool::connection_error(connection_ptr c, error::connection_error const& ec)
{
	local_log(logger::ERROR) << "Connection " << alias() << " error: "
			<< ec.what();
	lock_type lock(mutex_);
	local_log() << "Erase connection from the connection pool";
	auto f = std::find(connections_.begin(), connections_.end(), c);
	if (f != connections_.end()) {
		connections_.erase(f);
	}
	while (!queue_.empty()) {
		request_callbacks req = queue_.front();
		queue_.pop();
		req.second(ec);
	}
}

void
connection_pool::get_connection(transaction_callback const& conn_cb,
		error_callback const& err)
{
	lock_type lock(mutex_);
	if (closed_) {
		err( error::connection_error("Connection pool is closed") );
		return;
	}
	if (!ready_connections_.empty()) {
		local_log() << "Connection to "
				<< (util::CLEAR) << (util::RED | util::BRIGHT)
				<< alias()
				<< logger::severity_color()
				<< " is ready";
		connection_ptr conn = ready_connections_.front();
		ready_connections_.pop();
		conn->begin({conn_cb, err});
	} else {
		local_log()
				<< (util::CLEAR) << (util::RED | util::BRIGHT)
				<< alias()
				<< logger::severity_color()
				<< " queue size " << queue_.size() + 1  << " (enqueue)";;
		if (!closed_ && connections_.size() < pool_size_) {
			create_new_connection();
		}
		queue_.emplace(conn_cb, err);
	}
}

void
connection_pool::close(simple_callback close_cb)
{
	lock_type lock(mutex_);
	closed_ = true;
	closed_callback_ = close_cb;

	if (queue_.empty()) {
		close_connections();
	} else {
		local_log() << "Wait for outstanding tasks to finish";
	}
}

void
connection_pool::close_connections() {
	local_log() << "Close connection pool "
			<< (util::CLEAR) << (util::RED | util::BRIGHT)
			<< alias()
			<< logger::severity_color();
	if (connections_.size() > 0) {
		connections_container copy = connections_;
		for ( auto c : copy ) {
			c->terminate();
		}
	} else if (closed_callback_) {
		closed_callback_();
	}
}

} /* namespace detail */
} /* namespace pg */
} /* namespace db */
} /* namespace tip */
<|endoftext|>