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

/**
 * @file piecewise_jerk_fallback_speed.cc
 **/

#include "modules/planning/tasks/optimizers/piecewise_jerk_speed/piecewise_jerk_speed_optimizer.h"

#include <memory>
#include <string>
#include <tuple>
#include <utility>
#include <vector>

#include "modules/common/proto/pnc_point.pb.h"

#include "modules/common/vehicle_state/vehicle_state_provider.h"
#include "modules/planning/common/planning_gflags.h"
#include "modules/planning/common/st_graph_data.h"
#include "modules/planning/math/piecewise_jerk/path_time_qp_problem.h"

namespace apollo {
namespace planning {

using apollo::common::ErrorCode;
using apollo::common::Status;
using apollo::common::TrajectoryPoint;

PiecewiseJerkSpeedOptimizer::PiecewiseJerkSpeedOptimizer(
    const TaskConfig& config)
    : SpeedOptimizer(config) {
  SetName("PiecewiseJerkSpeedOptimizer");
  CHECK(config_.has_piecewise_jerk_speed_config());
}

Status PiecewiseJerkSpeedOptimizer::Process(
    const SLBoundary& adc_sl_boundary, const PathData& path_data,
    const TrajectoryPoint& init_point, const ReferenceLine& reference_line,
    const SpeedData& reference_speed_data, PathDecision* const path_decision,
    SpeedData* const speed_data) {
  if (reference_line_info_->ReachedDestination()) {
    return Status::OK();
  }

  if (path_data.discretized_path().empty()) {
    std::string msg("Empty path data");
    AERROR << msg;
    return Status(ErrorCode::PLANNING_ERROR, msg);
  }

  for (const auto* obstacle : path_decision->obstacles().Items()) {
    DCHECK(obstacle->HasLongitudinalDecision());
  }
  StGraphData& st_graph_data = *reference_line_info_->mutable_st_graph_data();

  const auto& veh_param =
      common::VehicleConfigHelper::GetConfig().vehicle_param();

  std::array<double, 3> init_s = {0.0, st_graph_data.init_point().v(),
                                  st_graph_data.init_point().a()};
  double delta_t = 0.1;
  std::array<double, 5> w = {1.0, 100.0, 10.0, 30.0, 0.0};
  double total_length = st_graph_data.path_length_by_conf();
  double total_time = st_graph_data.total_time_by_conf();
  int num_of_knots = static_cast<int>(total_time / delta_t) + 1;
  // Start a PathTimeQpProblem
  std::unique_ptr<PathTimeQpProblem> path_time_qp(new PathTimeQpProblem());
  path_time_qp->InitProblem(num_of_knots, delta_t, w, init_s);

  path_time_qp->SetZeroOrderBounds(0.0, total_length);
  path_time_qp->SetFirstOrderBounds(0.0, FLAGS_planning_upper_speed_limit);
  path_time_qp->SetSecondOrderBounds(veh_param.max_deceleration(),
                                     veh_param.max_acceleration());
  path_time_qp->SetThirdOrderBound(FLAGS_longitudinal_jerk_bound);
  // TODO(Hongyi): tune the params and move to a config
  path_time_qp->SetFirstOrderBounds(0.0, 10.0);
  path_time_qp->SetSecondOrderBounds(-4.4, 2.0);
  path_time_qp->SetDesireDerivative(10.0);  // default speed to be 10.0

  // Update STBoundary
  std::vector<std::tuple<double, double, double>> x_bounds;
  for (int i = 0; i < num_of_knots; ++i) {
    double curr_t = i * delta_t;
    double s_lower_bound = 0.0;
    double s_upper_bound = total_length;
    for (const STBoundary* boundary : st_graph_data.st_boundaries()) {
      double s_lower = 0.0;
      double s_upper = 0.0;
      if (!boundary->GetUnblockSRange(curr_t, &s_upper, &s_lower)) {
        continue;
      }
      switch (boundary->boundary_type()) {
        case STBoundary::BoundaryType::STOP:
        case STBoundary::BoundaryType::YIELD:
          s_upper_bound = std::fmin(s_upper_bound, s_upper);
          break;
        case STBoundary::BoundaryType::FOLLOW:
          // TODO(Hongyi): unify follow buffer on decision side
          s_upper_bound = std::fmin(s_upper_bound, s_upper - 8.0);
          break;
        case STBoundary::BoundaryType::OVERTAKE:
          s_lower_bound = std::fmax(s_lower_bound, s_lower);
          break;
        default:
          break;
      }
    }
    x_bounds.emplace_back(curr_t, s_lower_bound, std::fmax(s_upper_bound, 0.0));
  }
  path_time_qp->SetVariableBounds(x_bounds);

  // Sovle the problem
  if (!path_time_qp->Optimize()) {
    std::string msg("Piecewise jerk speed optimizer failed!");
    AERROR << msg;
    return Status(ErrorCode::PLANNING_ERROR, msg);
  }

  // Extract output
  const std::vector<double>& s = path_time_qp->x();
  const std::vector<double>& ds = path_time_qp->x_derivative();
  const std::vector<double>& dds = path_time_qp->x_second_order_derivative();
  for (int i = 0; i < num_of_knots; ++i) {
    ADEBUG << "For t[" << i * delta_t << "], s = " << s[i] << ", v = " << ds[i]
           << ", a = " << dds[i];
  }
  speed_data->clear();
  speed_data->AppendSpeedPoint(s[0], 0.0, ds[0], dds[0], 0.0);
  for (int i = 1; i < num_of_knots; ++i) {
    // Avoid the very last points when already stopped
    if (ds[i] <= 0.0) {
      break;
    }
    speed_data->AppendSpeedPoint(s[i], delta_t * i, ds[i], dds[i],
                                 (dds[i] - dds[i - 1]) / delta_t);
  }
  RecordDebugInfo(*speed_data, st_graph_data.mutable_st_graph_debug());
  return Status::OK();
}

}  // namespace planning
}  // namespace apollo
<commit_msg>Planning: add SpeedBoundary and ref_s for piecewise_jerk_speed optimizer<commit_after>/******************************************************************************
 * Copyright 2019 The Apollo Authors. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *****************************************************************************/

/**
 * @file piecewise_jerk_fallback_speed.cc
 **/

#include "modules/planning/tasks/optimizers/piecewise_jerk_speed/piecewise_jerk_speed_optimizer.h"

#include <memory>
#include <string>
#include <tuple>
#include <utility>
#include <vector>

#include "modules/common/proto/pnc_point.pb.h"

#include "modules/common/vehicle_state/vehicle_state_provider.h"
#include "modules/planning/common/planning_gflags.h"
#include "modules/planning/common/st_graph_data.h"
#include "modules/planning/math/piecewise_jerk/path_time_qp_problem.h"

namespace apollo {
namespace planning {

using apollo::common::ErrorCode;
using apollo::common::SpeedPoint;
using apollo::common::Status;
using apollo::common::TrajectoryPoint;

PiecewiseJerkSpeedOptimizer::PiecewiseJerkSpeedOptimizer(
    const TaskConfig& config)
    : SpeedOptimizer(config) {
  SetName("PiecewiseJerkSpeedOptimizer");
  CHECK(config_.has_piecewise_jerk_speed_config());
}

Status PiecewiseJerkSpeedOptimizer::Process(
    const SLBoundary& adc_sl_boundary, const PathData& path_data,
    const TrajectoryPoint& init_point, const ReferenceLine& reference_line,
    const SpeedData& reference_speed_data, PathDecision* const path_decision,
    SpeedData* const speed_data) {
  if (reference_line_info_->ReachedDestination()) {
    return Status::OK();
  }

  if (path_data.discretized_path().empty()) {
    std::string msg("Empty path data");
    AERROR << msg;
    return Status(ErrorCode::PLANNING_ERROR, msg);
  }

  for (const auto* obstacle : path_decision->obstacles().Items()) {
    DCHECK(obstacle->HasLongitudinalDecision());
  }
  StGraphData& st_graph_data = *reference_line_info_->mutable_st_graph_data();

  const auto& veh_param =
      common::VehicleConfigHelper::GetConfig().vehicle_param();

  std::array<double, 3> init_s = {0.0, st_graph_data.init_point().v(),
                                  st_graph_data.init_point().a()};
  double delta_t = 0.1;
  std::array<double, 5> w = {1.0, 100.0, 10.0, 30.0, 0.0};
  double total_length = st_graph_data.path_length_by_conf();
  double total_time = st_graph_data.total_time_by_conf();
  int num_of_knots = static_cast<int>(total_time / delta_t) + 1;
  // Start a PathTimeQpProblem
  std::unique_ptr<PathTimeQpProblem> path_time_qp(new PathTimeQpProblem());
  path_time_qp->InitProblem(num_of_knots, delta_t, w, init_s);

  path_time_qp->SetZeroOrderBounds(0.0, total_length);
  path_time_qp->SetFirstOrderBounds(0.0, FLAGS_planning_upper_speed_limit);
  path_time_qp->SetSecondOrderBounds(veh_param.max_deceleration(),
                                     veh_param.max_acceleration());
  path_time_qp->SetThirdOrderBound(FLAGS_longitudinal_jerk_bound);
  // TODO(Hongyi): tune the params and move to a config
  path_time_qp->SetSecondOrderBounds(-4.4, 2.0);
  path_time_qp->SetDesireDerivative(10.0);  // default speed to be 10.0

  // Update STBoundary
  std::vector<std::tuple<double, double, double>> x_bounds;
  for (int i = 0; i < num_of_knots; ++i) {
    double curr_t = i * delta_t;
    double s_lower_bound = 0.0;
    double s_upper_bound = total_length;
    for (const STBoundary* boundary : st_graph_data.st_boundaries()) {
      double s_lower = 0.0;
      double s_upper = 0.0;
      if (!boundary->GetUnblockSRange(curr_t, &s_upper, &s_lower)) {
        continue;
      }
      switch (boundary->boundary_type()) {
        case STBoundary::BoundaryType::STOP:
        case STBoundary::BoundaryType::YIELD:
          s_upper_bound = std::fmin(s_upper_bound, s_upper);
          break;
        case STBoundary::BoundaryType::FOLLOW:
          // TODO(Hongyi): unify follow buffer on decision side
          s_upper_bound = std::fmin(s_upper_bound, s_upper - 8.0);
          break;
        case STBoundary::BoundaryType::OVERTAKE:
          s_lower_bound = std::fmax(s_lower_bound, s_lower);
          break;
        default:
          break;
      }
    }
    x_bounds.emplace_back(curr_t, s_lower_bound, std::fmax(s_upper_bound, 0.0));
  }
  path_time_qp->SetVariableBounds(x_bounds);

  // Update SpeedBoundary and ref_s
  std::vector<double> x_ref;
  std::vector<std::tuple<double, double, double>> dx_bounds;
  const SpeedLimit& speed_limit = st_graph_data.speed_limit();
  for (int i = 0; i < num_of_knots; ++i) {
    double curr_t = i * delta_t;
    double v_lower_bound = 0.0;
    double v_upper_bound = FLAGS_planning_upper_speed_limit;
    SpeedPoint sp;
    reference_speed_data.EvaluateByTime(curr_t, &sp);
    v_upper_bound = speed_limit.GetSpeedLimitByS(sp.s());
    x_ref.emplace_back(sp.s());
    dx_bounds.emplace_back(curr_t, v_lower_bound,
                           std::fmax(v_upper_bound, 0.0));
  }
  path_time_qp->SetRefX(x_ref);
  path_time_qp->SetVariableDerivativeBounds(dx_bounds);

  // Sovle the problem
  if (!path_time_qp->Optimize()) {
    std::string msg("Piecewise jerk speed optimizer failed!");
    AERROR << msg;
    return Status(ErrorCode::PLANNING_ERROR, msg);
  }

  // Extract output
  const std::vector<double>& s = path_time_qp->x();
  const std::vector<double>& ds = path_time_qp->x_derivative();
  const std::vector<double>& dds = path_time_qp->x_second_order_derivative();
  for (int i = 0; i < num_of_knots; ++i) {
    ADEBUG << "For t[" << i * delta_t << "], s = " << s[i] << ", v = " << ds[i]
           << ", a = " << dds[i];
  }
  speed_data->clear();
  speed_data->AppendSpeedPoint(s[0], 0.0, ds[0], dds[0], 0.0);
  for (int i = 1; i < num_of_knots; ++i) {
    // Avoid the very last points when already stopped
    if (ds[i] <= 0.0) {
      break;
    }
    speed_data->AppendSpeedPoint(s[i], delta_t * i, ds[i], dds[i],
                                 (dds[i] - dds[i - 1]) / delta_t);
  }
  RecordDebugInfo(*speed_data, st_graph_data.mutable_st_graph_debug());
  return Status::OK();
}

}  // namespace planning
}  // namespace apollo
<|endoftext|>


<commit_before>#include "MainWindow.h"
#include "ui_MainWindow.h"
#include <QTextCursor>
#include <QFileInfo>
#include <QDebug>
#include <QMessageBox>
#include <QCloseEvent>

#include "Widgets/InputWidget.h"
#include "Widgets/HistoryWidget.h"
#include "Managers/HistoryManager.h"
#include "Managers/FileManager.h"
#include "Managers/MarkovRunManager.h"
#include "Managers/SourceCodeManager.h"

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow),
    _has_unsaved_data(true),
    _current_file("")
{
    ui->setupUi(this);

    updateWindowTitle();
    redoAvailable(false);
    undoAvailable(false);
    copyAvailable(false);

    _window = this;

    //Connect MainWindow menu
    connect(ui->actionExit, SIGNAL(triggered()), this, SLOT(close()));
    connect(ui->actionUndo, SIGNAL(triggered()), this, SIGNAL(undo()));
    connect(ui->actionRedo, SIGNAL(triggered()), this, SIGNAL(redo()));
    connect(ui->actionSelect_All, SIGNAL(triggered()), this, SIGNAL(selectAll()));
    connect(ui->actionCopy, SIGNAL(triggered()), this, SIGNAL(copy()));
    connect(ui->actionPaste, SIGNAL(triggered()), this, SIGNAL(paste()));
    connect(ui->actionCut, SIGNAL(triggered()), this, SIGNAL(cut()));
    connect(ui->actionDelete, SIGNAL(triggered()), this, SIGNAL(deleteSelection()));
    connect(ui->actionNew, SIGNAL(triggered()), this, SIGNAL(newFile()));
    connect(ui->actionOpen, SIGNAL(triggered()), this, SIGNAL(open()));
    connect(ui->actionSave, SIGNAL(triggered()), this, SIGNAL(save()));
    connect(ui->actionSave_As, SIGNAL(triggered()), this, SIGNAL(saveAs()));

    //Connect InputWidget and HistoryManager
    HistoryManager* history_manager = HistoryManager::getInstance();

    connect(ui->input, SIGNAL(addToHistory(QString)),
            history_manager, SLOT(addToHistory(QString)));
    connect(history_manager, SIGNAL(wordSelected(QString)),
            ui->input, SLOT(setInput(QString)));

    //Connect HistoryWidget and HistoryManager
    connect(ui->history, SIGNAL(inputWordSelected(QString)),
            history_manager, SIGNAL(wordSelected(QString)));
    connect(ui->history, SIGNAL(removeFromHistory(QString)),
            history_manager, SLOT(removeFromHistory(QString)));
    connect(history_manager, SIGNAL(historyChanged(QVector<QString>)),
            ui->history, SLOT(historyChanged(QVector<QString>)));

    //Connect MainWindows and FileManager
    FileManager* file_manager = FileManager::getInstance();
    connect(this, SIGNAL(newFile()), file_manager, SLOT(newFile()));
    connect(this, SIGNAL(open()), file_manager, SLOT(open()));
    connect(this, SIGNAL(save()), file_manager, SLOT(save()));
    connect(this, SIGNAL(saveAs()), file_manager, SLOT(saveAs()));
    connect(file_manager, SIGNAL(hasUnsavedData(bool)),
            this, SLOT(hasUnsavedData(bool)));
    connect(file_manager, SIGNAL(fileNameChanged(QString)),
            this, SLOT(fileNameChanged(QString)));

    //Connect MainWindows and EditorWindowWidget
    connect(this, SIGNAL(undo()), ui->editorWindow, SLOT(undo()));
    connect(this, SIGNAL(redo()), ui->editorWindow, SLOT(redo()));
    connect(this, SIGNAL(selectAll()), ui->editorWindow, SLOT(selectAll()));
    connect(this, SIGNAL(copy()), ui->editorWindow, SLOT(copy()));
    connect(this, SIGNAL(paste()), ui->editorWindow, SLOT(paste()));
    connect(this, SIGNAL(cut()), ui->editorWindow, SLOT(cut()));
    connect(this, SIGNAL(deleteSelection()),
            ui->editorWindow, SLOT(deleteSelection()));

    connect(ui->editorWindow, SIGNAL(redoAvailable(bool)),
            this, SLOT(redoAvailable(bool)));
    connect(ui->editorWindow, SIGNAL(undoAvailable(bool)),
            this, SLOT(undoAvailable(bool)));
    connect(ui->editorWindow, SIGNAL(copyAvailable(bool)),
            this, SLOT(copyAvailable(bool)));

    //Connect InputWidget and MarkovRunManager
    MarkovRunManager* run_manager = MarkovRunManager::getInstance();

    connect(ui->input, SIGNAL(run(QString)),
            run_manager, SLOT(runWithoutDebug(QString)));
    connect(ui->input, SIGNAL(runWithDebug(QString)),
            run_manager, SLOT(runWithDebug(QString)));
    connect(run_manager, SIGNAL(runWithoutDebugStarted(QString)),
            ui->input, SLOT(runStarted()));
    connect(run_manager, SIGNAL(debugStarted(QString)),
            ui->input, SLOT(runStarted()));
    connect(run_manager, SIGNAL(runWithoutDebugFinishFail(QString,RunError,int)),
            ui->input, SLOT(runFinished()));
    connect(run_manager, SIGNAL(runWithoutDebugFinishSuccess(QString,QString,int)),
            ui->input, SLOT(runFinished()));
    connect(run_manager, SIGNAL(debugFinishFail(QString,RunError,int)),
            ui->input, SLOT(runFinished()));
    connect(run_manager, SIGNAL(debugFinishSuccess(QString,QString,int)),
            ui->input, SLOT(runFinished()));
    connect(run_manager, SIGNAL(canRunSourceCode(bool)),
            ui->input, SLOT(canRunAlgorithm(bool)));

    //Connect SourceCodeManager and EditorWindowWidget
    SourceCodeManager* source_manager = SourceCodeManager::getInstance();
    connect(source_manager, SIGNAL(newSourceCodeWasLoaded(QString)),
            ui->editorWindow, SLOT(newSourceCode(QString)));
    connect(ui->editorWindow, SIGNAL(sourceCodeChanged(QString)),
            source_manager, SLOT(setSourceCode(QString)));

    //Connect InputWidget and FileManager
    connect(ui->input, SIGNAL(save()), file_manager, SLOT(save()));

    //Connect MarkovRunManager and EditorWindowWidget
    connect(ui->editorWindow, SIGNAL(canRun(bool)),
            run_manager, SLOT(setCanRunSourceCode(bool)));
    connect(ui->editorWindow, SIGNAL(markovAlgorithmChanged(MarkovAlgorithm)),
            run_manager, SLOT(setAlgorithm(MarkovAlgorithm)));

    //Read file to open from command line
    QStringList arguments = QCoreApplication::arguments();
    if(arguments.size() >= 2)
    {
        QString file_name = arguments.at(1);
        FileManager::getInstance()->openFile(file_name);
    }
    else
    {
        source_manager->setNewSourceCodeFromFile(tr("//Alphabet\nT = {}\n\n//Rules\n//a -> b"));
    }

}

void MainWindow::updateWindowTitle()
{
    QString file = _current_file;
    if(file == "")
        file = tr("Untitiled");

    QFileInfo fileInfo(file);
    QString filename(fileInfo.fileName());

    QString saved="";
    if(_has_unsaved_data)
        saved = "*";

    QString title = tr("%1%2 - Yad Studio").arg(filename, saved);
    this->setWindowTitle(title);
}

void MainWindow::fileNameChanged(QString new_name)
{
    _current_file = new_name;
    updateWindowTitle();
}

void MainWindow::hasUnsavedData(bool has_unsaved_data)
{
    _has_unsaved_data = has_unsaved_data;
    updateWindowTitle();
}

void MainWindow::redoAvailable(bool v)
{
    ui->actionRedo->setEnabled(v);
}

void MainWindow::undoAvailable(bool v)
{
    ui->actionUndo->setEnabled(v);
}

void MainWindow::copyAvailable(bool v)
{
    ui->actionCopy->setEnabled(v);
    ui->actionCut->setEnabled(v);
    ui->actionDelete->setEnabled(v);
}

MainWindow::~MainWindow()
{
    _window = nullptr;
    delete ui;
}

void MainWindow::closeEvent(QCloseEvent * event)
{
    if(FileManager::getInstance()->hasUnsavedData())
    {
        QMessageBox msgBox;
        msgBox.setText(tr("The document has been modified."));
        msgBox.setInformativeText(tr("Do you want to save your changes?"));
        msgBox.setStandardButtons(QMessageBox::Save | QMessageBox::Discard | QMessageBox::Cancel);
        msgBox.setDefaultButton(QMessageBox::Save);
        int ret = msgBox.exec();

        if(ret == QMessageBox::Save)
        {
            FileManager::getInstance()->save();
            QMainWindow::closeEvent(event);
        }
        else if(ret == QMessageBox::Discard)
        {
            QMainWindow::closeEvent(event);
        }
        else
        {
            event->ignore();
        }

    }
    else
    {
        QMainWindow::closeEvent(event);
    }
}

MainWindow* MainWindow::_window = nullptr;
MainWindow* MainWindow::getInstance()
{
    return _window;
}
<commit_msg>close #50 connections<commit_after>#include "MainWindow.h"
#include "ui_MainWindow.h"
#include <QTextCursor>
#include <QFileInfo>
#include <QDebug>
#include <QMessageBox>
#include <QCloseEvent>

#include "Widgets/InputWidget.h"
#include "Widgets/HistoryWidget.h"
#include "Managers/HistoryManager.h"
#include "Managers/FileManager.h"
#include "Managers/MarkovRunManager.h"
#include "Managers/SourceCodeManager.h"

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow),
    _has_unsaved_data(true),
    _current_file("")
{
    ui->setupUi(this);

    updateWindowTitle();
    redoAvailable(false);
    undoAvailable(false);
    copyAvailable(false);

    _window = this;

    //Connect MainWindow menu
    connect(ui->actionExit, SIGNAL(triggered()), this, SLOT(close()));
    connect(ui->actionUndo, SIGNAL(triggered()), this, SIGNAL(undo()));
    connect(ui->actionRedo, SIGNAL(triggered()), this, SIGNAL(redo()));
    connect(ui->actionSelect_All, SIGNAL(triggered()), this, SIGNAL(selectAll()));
    connect(ui->actionCopy, SIGNAL(triggered()), this, SIGNAL(copy()));
    connect(ui->actionPaste, SIGNAL(triggered()), this, SIGNAL(paste()));
    connect(ui->actionCut, SIGNAL(triggered()), this, SIGNAL(cut()));
    connect(ui->actionDelete, SIGNAL(triggered()), this, SIGNAL(deleteSelection()));
    connect(ui->actionNew, SIGNAL(triggered()), this, SIGNAL(newFile()));
    connect(ui->actionOpen, SIGNAL(triggered()), this, SIGNAL(open()));
    connect(ui->actionSave, SIGNAL(triggered()), this, SIGNAL(save()));
    connect(ui->actionSave_As, SIGNAL(triggered()), this, SIGNAL(saveAs()));

    //Connect InputWidget and HistoryManager
    HistoryManager* history_manager = HistoryManager::getInstance();

    connect(ui->input, SIGNAL(addToHistory(QString)),
            history_manager, SLOT(addToHistory(QString)));
    connect(history_manager, SIGNAL(wordSelected(QString)),
            ui->input, SLOT(setInput(QString)));

    //Connect HistoryWidget and HistoryManager
    connect(ui->history, SIGNAL(inputWordSelected(QString)),
            history_manager, SIGNAL(wordSelected(QString)));
    connect(ui->history, SIGNAL(removeFromHistory(QString)),
            history_manager, SLOT(removeFromHistory(QString)));
    connect(history_manager, SIGNAL(historyChanged(QVector<QString>)),
            ui->history, SLOT(historyChanged(QVector<QString>)));

    //Connect MainWindows and FileManager
    FileManager* file_manager = FileManager::getInstance();
    connect(this, SIGNAL(newFile()), file_manager, SLOT(newFile()));
    connect(this, SIGNAL(open()), file_manager, SLOT(open()));
    connect(this, SIGNAL(save()), file_manager, SLOT(save()));
    connect(this, SIGNAL(saveAs()), file_manager, SLOT(saveAs()));
    connect(file_manager, SIGNAL(hasUnsavedData(bool)),
            this, SLOT(hasUnsavedData(bool)));
    connect(file_manager, SIGNAL(fileNameChanged(QString)),
            this, SLOT(fileNameChanged(QString)));

    //Connect MainWindows and EditorWindowWidget
    connect(this, SIGNAL(undo()), ui->editorWindow, SLOT(undo()));
    connect(this, SIGNAL(redo()), ui->editorWindow, SLOT(redo()));
    connect(this, SIGNAL(selectAll()), ui->editorWindow, SLOT(selectAll()));
    connect(this, SIGNAL(copy()), ui->editorWindow, SLOT(copy()));
    connect(this, SIGNAL(paste()), ui->editorWindow, SLOT(paste()));
    connect(this, SIGNAL(cut()), ui->editorWindow, SLOT(cut()));
    connect(this, SIGNAL(deleteSelection()),
            ui->editorWindow, SLOT(deleteSelection()));

    connect(ui->editorWindow, SIGNAL(redoAvailable(bool)),
            this, SLOT(redoAvailable(bool)));
    connect(ui->editorWindow, SIGNAL(undoAvailable(bool)),
            this, SLOT(undoAvailable(bool)));
    connect(ui->editorWindow, SIGNAL(copyAvailable(bool)),
            this, SLOT(copyAvailable(bool)));

    //Connect InputWidget and MarkovRunManager
    MarkovRunManager* run_manager = MarkovRunManager::getInstance();

    connect(ui->input, SIGNAL(run(QString)),
            run_manager, SLOT(runWithoutDebug(QString)));
    connect(ui->input, SIGNAL(runWithDebug(QString)),
            run_manager, SLOT(runWithDebug(QString)));
    connect(run_manager, SIGNAL(runWithoutDebugStarted(QString)),
            ui->input, SLOT(runStarted()));
    connect(run_manager, SIGNAL(debugStarted(QString)),
            ui->input, SLOT(runStarted()));
    connect(run_manager, SIGNAL(runWithoutDebugFinishFail(QString,RunError,int)),
            ui->input, SLOT(runFinished()));
    connect(run_manager, SIGNAL(runWithoutDebugFinishSuccess(QString,QString,int)),
            ui->input, SLOT(runFinished()));
    connect(run_manager, SIGNAL(debugFinishFail(QString,RunError,int)),
            ui->input, SLOT(runFinished()));
    connect(run_manager, SIGNAL(debugFinishSuccess(QString,QString,int)),
            ui->input, SLOT(runFinished()));
    connect(run_manager, SIGNAL(canRunSourceCode(bool)),
            ui->input, SLOT(canRunAlgorithm(bool)));

    //Connect SourceCodeManager and EditorWindowWidget
    SourceCodeManager* source_manager = SourceCodeManager::getInstance();
    connect(source_manager, SIGNAL(newSourceCodeWasLoaded(QString)),
            ui->editorWindow, SLOT(newSourceCode(QString)));
    connect(ui->editorWindow, SIGNAL(sourceCodeChanged(QString)),
            source_manager, SLOT(setSourceCode(QString)));

    //Connect InputWidget and FileManager
    connect(ui->input, SIGNAL(save()), file_manager, SLOT(save()));

    //Connect MarkovRunManager and EditorWindowWidget
    connect(ui->editorWindow, SIGNAL(canRun(bool)),
            run_manager, SLOT(setCanRunSourceCode(bool)));
    connect(ui->editorWindow, SIGNAL(markovAlgorithmChanged(MarkovAlgorithm)),
            run_manager, SLOT(setAlgorithm(MarkovAlgorithm)));

    //Connect SourceCodeManager and FileManager
    connect(file_manager, SIGNAL(newSourceCodeLoaded(QString)),
            source_manager, SLOT(setNewSourceCodeFromFile(QString)));
    connect(source_manager, SIGNAL(sourceCodeChanged(QString)),
            file_manager, SLOT(sourceCodeChanged()));

    //Read file to open from command line
    QStringList arguments = QCoreApplication::arguments();
    if(arguments.size() >= 2)
    {
        QString file_name = arguments.at(1);
        FileManager::getInstance()->openFile(file_name);
    }
    else
    {
        source_manager->setNewSourceCodeFromFile(tr("//Alphabet\nT = {}\n\n//Rules\n//a -> b"));
    }

}

void MainWindow::updateWindowTitle()
{
    QString file = _current_file;
    if(file == "")
        file = tr("Untitiled");

    QFileInfo fileInfo(file);
    QString filename(fileInfo.fileName());

    QString saved="";
    if(_has_unsaved_data)
        saved = "*";

    QString title = tr("%1%2 - Yad Studio").arg(filename, saved);
    this->setWindowTitle(title);
}

void MainWindow::fileNameChanged(QString new_name)
{
    _current_file = new_name;
    updateWindowTitle();
}

void MainWindow::hasUnsavedData(bool has_unsaved_data)
{
    _has_unsaved_data = has_unsaved_data;
    updateWindowTitle();
}

void MainWindow::redoAvailable(bool v)
{
    ui->actionRedo->setEnabled(v);
}

void MainWindow::undoAvailable(bool v)
{
    ui->actionUndo->setEnabled(v);
}

void MainWindow::copyAvailable(bool v)
{
    ui->actionCopy->setEnabled(v);
    ui->actionCut->setEnabled(v);
    ui->actionDelete->setEnabled(v);
}

MainWindow::~MainWindow()
{
    _window = nullptr;
    delete ui;
}

void MainWindow::closeEvent(QCloseEvent * event)
{
    if(FileManager::getInstance()->hasUnsavedData())
    {
        QMessageBox msgBox;
        msgBox.setText(tr("The document has been modified."));
        msgBox.setInformativeText(tr("Do you want to save your changes?"));
        msgBox.setStandardButtons(QMessageBox::Save | QMessageBox::Discard | QMessageBox::Cancel);
        msgBox.setDefaultButton(QMessageBox::Save);
        int ret = msgBox.exec();

        if(ret == QMessageBox::Save)
        {
            FileManager::getInstance()->save();
            QMainWindow::closeEvent(event);
        }
        else if(ret == QMessageBox::Discard)
        {
            QMainWindow::closeEvent(event);
        }
        else
        {
            event->ignore();
        }

    }
    else
    {
        QMainWindow::closeEvent(event);
    }
}

MainWindow* MainWindow::_window = nullptr;
MainWindow* MainWindow::getInstance()
{
    return _window;
}
<|endoftext|>


<commit_before>/*
 * Software License Agreement (BSD License)
 *
 *  Point Cloud Library (PCL) - www.pointclouds.org
 *  Copyright (c) 2010-2012, Willow Garage, Inc.
 *  Copyright (c) 2012-, Open Perception, Inc.
 *
 *  All rights reserved.
 *
 *  Redistribution and use in source and binary forms, with or without
 *  modification, are permitted provided that the following conditions
 *  are met:
 *
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *   * Redistributions in binary form must reproduce the above
 *     copyright notice, this list of conditions and the following
 *     disclaimer in the documentation and/or other materials provided
 *     with the distribution.
 *   * Neither the name of the copyright holder(s) nor the names of its
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 *  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 *  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 *  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 *  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 *  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 *  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 *  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 *  POSSIBILITY OF SUCH DAMAGE.
 *
 *
 */
#ifndef PCL_REGISTRATION_IMPL_CORRESPONDENCE_ESTIMATION_NORMAL_SHOOTING_H_
#define PCL_REGISTRATION_IMPL_CORRESPONDENCE_ESTIMATION_NORMAL_SHOOTING_H_

#include <pcl/registration/correspondence_estimation_normal_shooting.h>

///////////////////////////////////////////////////////////////////////////////////////////
template <typename PointSource, typename PointTarget, typename NormalT> void
pcl::registration::CorrespondenceEstimationNormalShooting<PointSource, PointTarget, NormalT>::determineCorrespondences (
    pcl::Correspondences &correspondences, float max_distance)
{
  if (!target_)
  {
    PCL_WARN ("[pcl::%s::compute] No input target dataset was given!\n", getClassName ().c_str ());
    return;
  }

  if (!initCompute ())
    return;

  typedef typename pcl::traits::fieldList<PointTarget>::type FieldListTarget;

  correspondences.resize (indices_->size ());

  std::vector<int> nn_indices (k_);
  std::vector<float> nn_dists (k_);

  float min_dist = std::numeric_limits<float>::max ();
  int min_index = 0;

  // Set the internal point representation of choice
  if (point_representation_)
    tree_->setPointRepresentation (point_representation_);

  // If the target indices have been given via setIndicesTarget
  if (target_indices_)
    tree_->setInputCloud (target_, target_indices_);
  else
    tree_->setInputCloud (target_);

  pcl::Correspondence corr;
  unsigned int nr_valid_correspondences = 0;

  // Check if the template types are the same. If true, avoid a copy.
  // Both point types MUST be registered using the POINT_CLOUD_REGISTER_POINT_STRUCT macro!
  if (isSamePointType<PointSource, PointTarget> ())
  {
    // Iterate over the input set of source indices
    for (size_t i = 0; i < indices_->size (); ++i)
    {
      if (!tree_->nearestKSearch (input_->points[(*indices_)[i]], k_, nn_indices, nn_dists))
        continue;

      // Among the K nearest neighbours find the one with minimum perpendicular distance to the normal
      min_dist = std::numeric_limits<float>::max ();
      PointTarget pt;

      for (size_t j = 0; j < nn_indices.size (); j++)
      {
        // computing the distance between a point and a line in 3d.
        // Reference - http://mathworld.wolfram.com/Point-LineDistance3-Dimensional.html
        pt.x = target_->points[nn_indices[j]].x - input_->points[(*indices_)[i]].x;
        pt.y = target_->points[nn_indices[j]].y - input_->points[(*indices_)[i]].y;
        pt.z = target_->points[nn_indices[j]].z - input_->points[(*indices_)[i]].z;

        NormalT &normal = source_normals_->points[(*indices_)[i]].normal;
        Eigen::Vector3d N (normal.normal_x, normal.normal_y, normal.normal_z);
        Eigen::Vector3d V (pt.x, pt.y, pt.z);
        Eigen::Vector3d C = N.cross (V);

        // Check if we have a better correspondence
        float dist = C.dot (C);
        if (dist < min_dist)
        {
          min_dist = dist;
          min_index = nn_indices[j];
        }
      }
      if (min_dist > max_distance)
        continue;
      corr.index_query = i;
      corr.index_match = min_index;
      corr.distance = min_dist;
      correspondences[nr_valid_correspondences++] = corr;
    }
  }
  else
  {
    PointTarget pt;

    // Iterate over the input set of source indices
    for (size_t i = 0; i < indices_->size (); ++i)
    {
      if (!tree_->nearestKSearch (input_->points[(*indices_)[i]], k_, nn_indices, nn_dists))
        continue;

      // Among the K nearest neighbours find the one with minimum perpendicular distance to the normal
      min_dist = std::numeric_limits<float>::max ();
      for (size_t j = 0; j < nn_indices.size (); j++)
      {
        PointSource pt_src;
        // Copy the source data to a target PointTarget format so we can search in the tree
        pcl::for_each_type <FieldListTarget> (pcl::NdConcatenateFunctor <PointSource, PointTarget> (
            input_->points[(*indices_)[i]],
            pt_src));

        // computing the distance between a point and a line in 3d.
        // Reference - http://mathworld.wolfram.com/Point-LineDistance3-Dimensional.html
        pt.x = target_->points[nn_indices[j]].x - pt_src.x;
        pt.y = target_->points[nn_indices[j]].y - pt_src.y;
        pt.z = target_->points[nn_indices[j]].z - pt_src.z;

        NormalT &normal = source_normals_->points[(*indices_)[i]].normal;
        Eigen::Vector3d N (normal.normal_x, normal.normal_y, normal.normal_z);
        Eigen::Vector3d V (pt.x, pt.y, pt.z);
        Eigen::Vector3d C = N.cross (V);

        // Check if we have a better correspondence
        float dist = C.dot (C);
        if (dist < min_dist)
        {
          min_dist = dist;
          min_index = nn_indices[j];
        }
      }
      if (min_dist > max_distance)
        continue;
      corr.index_query = i;
      corr.index_match = min_index;
      corr.distance = min_dist;
      correspondences[nr_valid_correspondences++] = corr;
    }
  }
  correspondences.resize (nr_valid_correspondences);
  deinitCompute ();
}

#endif    // PCL_REGISTRATION_IMPL_CORRESPONDENCE_ESTIMATION_NORMAL_SHOOTING_H_
<commit_msg>fixed the data accessor<commit_after>/*
 * Software License Agreement (BSD License)
 *
 *  Point Cloud Library (PCL) - www.pointclouds.org
 *  Copyright (c) 2010-2012, Willow Garage, Inc.
 *  Copyright (c) 2012-, Open Perception, Inc.
 *
 *  All rights reserved.
 *
 *  Redistribution and use in source and binary forms, with or without
 *  modification, are permitted provided that the following conditions
 *  are met:
 *
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *   * Redistributions in binary form must reproduce the above
 *     copyright notice, this list of conditions and the following
 *     disclaimer in the documentation and/or other materials provided
 *     with the distribution.
 *   * Neither the name of the copyright holder(s) nor the names of its
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 *  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 *  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 *  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 *  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 *  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 *  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 *  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 *  POSSIBILITY OF SUCH DAMAGE.
 *
 *
 */
#ifndef PCL_REGISTRATION_IMPL_CORRESPONDENCE_ESTIMATION_NORMAL_SHOOTING_H_
#define PCL_REGISTRATION_IMPL_CORRESPONDENCE_ESTIMATION_NORMAL_SHOOTING_H_

#include <pcl/registration/correspondence_estimation_normal_shooting.h>

///////////////////////////////////////////////////////////////////////////////////////////
template <typename PointSource, typename PointTarget, typename NormalT> void
pcl::registration::CorrespondenceEstimationNormalShooting<PointSource, PointTarget, NormalT>::determineCorrespondences (
    pcl::Correspondences &correspondences, float max_distance)
{
  if (!target_)
  {
    PCL_WARN ("[pcl::%s::compute] No input target dataset was given!\n", getClassName ().c_str ());
    return;
  }

  if (!initCompute ())
    return;

  typedef typename pcl::traits::fieldList<PointTarget>::type FieldListTarget;

  correspondences.resize (indices_->size ());

  std::vector<int> nn_indices (k_);
  std::vector<float> nn_dists (k_);

  float min_dist = std::numeric_limits<float>::max ();
  int min_index = 0;

  // Set the internal point representation of choice
  if (point_representation_)
    tree_->setPointRepresentation (point_representation_);

  // If the target indices have been given via setIndicesTarget
  if (target_indices_)
    tree_->setInputCloud (target_, target_indices_);
  else
    tree_->setInputCloud (target_);

  pcl::Correspondence corr;
  unsigned int nr_valid_correspondences = 0;

  // Check if the template types are the same. If true, avoid a copy.
  // Both point types MUST be registered using the POINT_CLOUD_REGISTER_POINT_STRUCT macro!
  if (isSamePointType<PointSource, PointTarget> ())
  {
    // Iterate over the input set of source indices
    for (size_t i = 0; i < indices_->size (); ++i)
    {
      if (!tree_->nearestKSearch (input_->points[(*indices_)[i]], k_, nn_indices, nn_dists))
        continue;

      // Among the K nearest neighbours find the one with minimum perpendicular distance to the normal
      min_dist = std::numeric_limits<float>::max ();
      PointTarget pt;

      for (size_t j = 0; j < nn_indices.size (); j++)
      {
        // computing the distance between a point and a line in 3d.
        // Reference - http://mathworld.wolfram.com/Point-LineDistance3-Dimensional.html
        pt.x = target_->points[nn_indices[j]].x - input_->points[(*indices_)[i]].x;
        pt.y = target_->points[nn_indices[j]].y - input_->points[(*indices_)[i]].y;
        pt.z = target_->points[nn_indices[j]].z - input_->points[(*indices_)[i]].z;

        NormalT &normal = source_normals_->points[(*indices_)[i]];
        Eigen::Vector3d N (normal.normal_x, normal.normal_y, normal.normal_z);
        Eigen::Vector3d V (pt.x, pt.y, pt.z);
        Eigen::Vector3d C = N.cross (V);

        // Check if we have a better correspondence
        float dist = C.dot (C);
        if (dist < min_dist)
        {
          min_dist = dist;
          min_index = nn_indices[j];
        }
      }
      if (min_dist > max_distance)
        continue;
      corr.index_query = i;
      corr.index_match = min_index;
      corr.distance = min_dist;
      correspondences[nr_valid_correspondences++] = corr;
    }
  }
  else
  {
    PointTarget pt;

    // Iterate over the input set of source indices
    for (size_t i = 0; i < indices_->size (); ++i)
    {
      if (!tree_->nearestKSearch (input_->points[(*indices_)[i]], k_, nn_indices, nn_dists))
        continue;

      // Among the K nearest neighbours find the one with minimum perpendicular distance to the normal
      min_dist = std::numeric_limits<float>::max ();
      for (size_t j = 0; j < nn_indices.size (); j++)
      {
        PointSource pt_src;
        // Copy the source data to a target PointTarget format so we can search in the tree
        pcl::for_each_type <FieldListTarget> (pcl::NdConcatenateFunctor <PointSource, PointTarget> (
            input_->points[(*indices_)[i]],
            pt_src));

        // computing the distance between a point and a line in 3d.
        // Reference - http://mathworld.wolfram.com/Point-LineDistance3-Dimensional.html
        pt.x = target_->points[nn_indices[j]].x - pt_src.x;
        pt.y = target_->points[nn_indices[j]].y - pt_src.y;
        pt.z = target_->points[nn_indices[j]].z - pt_src.z;

        NormalT &normal = source_normals_->points[(*indices_)[i]];
        Eigen::Vector3d N (normal.normal_x, normal.normal_y, normal.normal_z);
        Eigen::Vector3d V (pt.x, pt.y, pt.z);
        Eigen::Vector3d C = N.cross (V);

        // Check if we have a better correspondence
        float dist = C.dot (C);
        if (dist < min_dist)
        {
          min_dist = dist;
          min_index = nn_indices[j];
        }
      }
      if (min_dist > max_distance)
        continue;
      corr.index_query = i;
      corr.index_match = min_index;
      corr.distance = min_dist;
      correspondences[nr_valid_correspondences++] = corr;
    }
  }
  correspondences.resize (nr_valid_correspondences);
  deinitCompute ();
}

#endif    // PCL_REGISTRATION_IMPL_CORRESPONDENCE_ESTIMATION_NORMAL_SHOOTING_H_
<|endoftext|>


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

#include "dbg_builtin_collection.h"

#include <algorithm>
#include <array>
#include <cstdint>
#include <iostream>

#include "class_names.h"
#include "dbg_array.h"
#include "dbg_breakpoint.h"
#include "i_cor_debug_helper.h"
#include "i_dbg_object_factory.h"
#include "i_eval_coordinator.h"
#include "variable_wrapper.h"

using google::cloud::diagnostics::debug::Variable;
using std::min;
using std::shared_ptr;
using std::string;
using std::unique_ptr;
using std::vector;

namespace google_cloud_debugger {

const string DbgBuiltinCollection::kListItemsFieldName = "_items";
const string DbgBuiltinCollection::kListSizeFieldName = "_size";
const string DbgBuiltinCollection::kHashSetSlotsFieldName = "_slots";
const string DbgBuiltinCollection::kHashSetCountFieldName = "_count";
const string DbgBuiltinCollection::kHashSetLastIndexFieldName = "_lastIndex";
const string DbgBuiltinCollection::kDictionaryCountFieldName = "count";
const string DbgBuiltinCollection::kDictionaryItemsFieldName = "entries";
const string DbgBuiltinCollection::kDictionaryKeyFieldName = "key";
const string DbgBuiltinCollection::kHashSetAndDictValueFieldName = "value";
const string DbgBuiltinCollection::kHashSetAndDictHashCodeFieldName =
    "hashCode";
const string DbgBuiltinCollection::kCountProtoFieldName = "Count";

HRESULT DbgBuiltinCollection::ProcessClassMembersHelper(
    ICorDebugValue *debug_value, ICorDebugClass *debug_class,
    IMetaDataImport *metadata_import) {
  HRESULT hr;
  CComPtr<ICorDebugObjectValue> debug_obj_value;
  hr = debug_value->QueryInterface(__uuidof(ICorDebugObjectValue),
                                   reinterpret_cast<void **>(&debug_obj_value));
  if (FAILED(hr)) {
    WriteError("Failed to cast ICorDebugValue to ICorDebugObjValue.");
    return hr;
  }

  // This is a list.
  if (kListClassName.compare(class_name_) == 0) {
    class_type_ = ClassType::LIST;
    hr = ProcessCollectionType(debug_obj_value, debug_class, metadata_import,
                               kListSizeFieldName, kListItemsFieldName);
    if (SUCCEEDED(hr)) {
      // Makes sure we don't grab more items than we need (this can happen
      // because if a list size is 2, the underlying items_ array can have 4
      // items).
      if (count_ < DbgBreakpoint::GetMaximumCollectionSize()) {
        (reinterpret_cast<DbgArray *>(collection_items_.get()))
            ->SetMaxArrayItemsToRetrieve(count_);
      }
    }
    return hr;
  }

  // This is a hash set.
  if (kHashSetClassName.compare(class_name_) == 0) {
    class_type_ = ClassType::SET;
    hr = ProcessCollectionType(debug_obj_value, debug_class, metadata_import,
                               kHashSetCountFieldName, kHashSetSlotsFieldName);
    if (SUCCEEDED(hr)) {
      // For hash set, we also needs the _lastIndex field, which tells us
      // the last valid index in the collection_items_ array. See comments
      // on hashset_last_index_ for more details.
      unique_ptr<DbgObject> last_index;

      // Extracts out the last index of the hash set.
      hr = ExtractField(debug_obj_value, debug_class, metadata_import,
                        kHashSetLastIndexFieldName, &last_index);
      if (FAILED(hr)) {
        WriteError(
            "Failed to find field that represents the last index of the hash "
            "set.");
        return hr;
      }

      hashset_last_index_ =
          reinterpret_cast<DbgPrimitive<int32_t> *>(last_index.get())
              ->GetValue();
    }
    return hr;
  }

  // This is a dictionary.
  if (kDictionaryClassName.compare(class_name_) == 0) {
    class_type_ = ClassType::DICTIONARY;
    return ProcessCollectionType(debug_obj_value, debug_class, metadata_import,
                                 kDictionaryCountFieldName,
                                 kDictionaryItemsFieldName);
  }

  return E_NOTIMPL;
}

HRESULT DbgBuiltinCollection::ProcessCollectionType(
    ICorDebugObjectValue *debug_obj_value, ICorDebugClass *debug_class,
    IMetaDataImport *metadata_import, const std::string &count_field,
    const std::string &entries_field) {
  HRESULT hr;
  // DbgObject representing the int that counts the size of the collection.
  unique_ptr<DbgObject> collection_size;

  // Extracts out the size of the collection.
  hr = ExtractField(debug_obj_value, debug_class, metadata_import, count_field,
                    &collection_size);
  if (FAILED(hr)) {
    WriteError(
        "Failed to find field that represents the size of the collection.");
    return hr;
  }
  count_ = reinterpret_cast<DbgPrimitive<int32_t> *>(collection_size.get())
               ->GetValue();

  // Extracts out the array that contains items in the collection.
  hr = ExtractField(debug_obj_value, debug_class, metadata_import,
                    entries_field, &collection_items_);
  if (FAILED(hr)) {
    WriteError("Failed to get the items of the collection.");
    return hr;
  }

  return hr;
}

HRESULT DbgBuiltinCollection::PopulateMembers(
    Variable *variable_proto, vector<VariableWrapper> *members,
    IEvalCoordinator *eval_coordinator) {
  if (!members) {
    return E_INVALIDARG;
  }

  if (!eval_coordinator) {
    WriteError("No Eval Coordinator, cannot do evaluation of properties.");
    return E_INVALIDARG;
  }

  if (FAILED(initialize_hr_)) {
    return initialize_hr_;
  }

  if (GetIsNull()) {
    return S_OK;
  }

  if (GetCreationDepth() <= 0) {
    WriteError("Object Inspection Depth Limit reached.");
    return E_FAIL;
  }

  HRESULT hr = ProcessClassMembers();
  if (FAILED(hr)) {
    return hr;
  }

  // Sets the Count property of the collection.
  Variable *list_count = variable_proto->add_members();
  list_count->set_name(kCountProtoFieldName);
  list_count->set_value(std::to_string(count_));
  list_count->set_type(kInt32ClassName);

  if (class_type_ == ClassType::LIST && collection_items_) {
    return collection_items_->PopulateMembers(variable_proto, members,
                                              eval_coordinator);
  }

  if ((class_type_ == ClassType::SET || class_type_ == ClassType::DICTIONARY) &&
      collection_items_) {
    return PopulateHashSetOrDictionary(variable_proto, members,
                                       eval_coordinator);
  }

  WriteError("Unknown collection.");

  return E_NOTIMPL;
}

HRESULT DbgBuiltinCollection::PopulateHashSetOrDictionary(
    google::cloud::diagnostics::debug::Variable *variable_proto,
    vector<VariableWrapper> *members, IEvalCoordinator *eval_coordinator) {
  // Start fetching items from the hash set or dictionary.
  HRESULT hr;
  int32_t index = 0;
  int32_t max_items_to_fetch =
      min(count_, DbgBreakpoint::GetMaximumCollectionSize());
  int32_t items_fetched_so_far = 0;
  // Casts the collection_items_ to an array.
  DbgArray *slots_array = reinterpret_cast<DbgArray *>(collection_items_.get());
  // We get items from the _items array. If this is a hash set, we have to make
  // sure we don't go beyond the hashset_last_index_ because items at this point
  // onwards will either be invalid or out of bound of the array.
  // If this is a dictionary, we just have to make sure we go until count_.
  // We will only get items in the array that has hashCode greater or equal to
  // 0.
  int32_t max_index =
      (class_type_ == ClassType::SET) ? hashset_last_index_ : count_;

  for (int32_t index = 0; index < max_index; ++index) {
    // Extracts out the item from the array.
    CComPtr<ICorDebugValue> array_item;
    hr = slots_array->GetArrayItem(index, &array_item);
    if (FAILED(hr)) {
      WriteError("Failed to get hash set item at index " +
                 std::to_string(index));
      return hr;
    }

    // Now creates a DbgObject that represents the Slot object from the
    // array_item we got above. Each Slot has the form struct Slot { int
    // hashCode; T value; int next; }
    // If this is a dictionary, then we will have Entry object with
    // the form Entry { int hashCode; TKey key; TValue value; int next; }
    // So a dictionary entry is essentially the same as a set slot except
    // that the dictionary entry has a key.
    unique_ptr<DbgObject> slot_item_obj;
    hr = object_factory_->CreateDbgObject(array_item, GetCreationDepth(),
                                          &slot_item_obj, GetErrorStream());
    if (FAILED(hr)) {
      WriteError("Failed to create DbgObject for item at index " +
                 std::to_string(index));
      return hr;
    }

    // Casts the DbgObject to a class.
    DbgClass *slot_item = reinterpret_cast<DbgClass *>(slot_item_obj.get());
    // Try to find the hashCode field of the struct.
    shared_ptr<DbgObject> hash_code_obj = nullptr;
    hr = slot_item->GetNonStaticField(kHashSetAndDictHashCodeFieldName,
                                      &hash_code_obj);
    if (FAILED(hr)) {
      WriteError("Failed to evaluate hash code for item at index " +
                 std::to_string(index));
      return hr;
    }

    // Since hashCode is an int, we cast it to a DbgPrimitive<int32_t>.
    DbgPrimitive<int32_t> *hash_code_primitive_obj =
        reinterpret_cast<DbgPrimitive<int32_t> *>(hash_code_obj.get());
    int32_t hash_code_value = hash_code_primitive_obj->GetValue();
    // Now the hashCode of the struct is actually processed in such a way that
    // they can only be greater than or equal to 0. If they are -1, then this
    // means this is not a valid item (probably removed), so we continue to the
    // next index. This is true for both hash set and dictionary.
    if (hash_code_value == -1) {
      continue;
    }

    // Gets the underlying DbgObject that represents value field.
    shared_ptr<DbgObject> value_obj = nullptr;
    hr =
        slot_item->GetNonStaticField(kHashSetAndDictValueFieldName, &value_obj);
    if (FAILED(hr)) {
      WriteError("Failed to evaluate the value of item at index " +
                 std::to_string(index));
      return hr;
    }

    shared_ptr<DbgObject> key_obj = nullptr;
    // If this is a dictionary, we have to find the key field of the struct.
    if (class_type_ == ClassType::DICTIONARY) {
      hr = slot_item->GetNonStaticField(kDictionaryKeyFieldName, &key_obj);
      if (FAILED(hr)) {
        WriteError("Failed to evaluate the value of the key at index " +
                   std::to_string(index));
        return hr;
      }
    }

    // Now creates a member that represents this item.
    Variable *item_proto = variable_proto->add_members();
    item_proto->set_name("[" + std::to_string(items_fetched_so_far) + "]");

    // For hash set, just display item as [index]: value.
    if (class_type_ == ClassType::SET) {
      // We don't have to worry about errors since PopulateVariableValue
      // will automatically sets error in item_proto.
      members->push_back(VariableWrapper(item_proto, value_obj));
    } else {
      // For dictionary, we also display the key. So an item would be
      // [index]: { "key": Key, "value": Value }
      Variable *key_proto = item_proto->add_members();
      key_proto->set_name(kDictionaryKeyFieldName);
      members->push_back(VariableWrapper(key_proto, key_obj));

      Variable *value_proto = item_proto->add_members();
      value_proto->set_name(kHashSetAndDictValueFieldName);
      members->push_back(VariableWrapper(value_proto, value_obj));
    }

    items_fetched_so_far++;
    if (items_fetched_so_far >= max_items_to_fetch) {
      break;
    }
  }
  return S_OK;
}

}  // namespace google_cloud_debugger
<commit_msg>Fix compilation error<commit_after>// Copyright 2017 Google Inc. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include "dbg_builtin_collection.h"

#include <algorithm>
#include <array>
#include <cstdint>
#include <iostream>

#include "class_names.h"
#include "dbg_array.h"
#include "dbg_breakpoint.h"
#include "i_cor_debug_helper.h"
#include "i_dbg_object_factory.h"
#include "i_eval_coordinator.h"
#include "variable_wrapper.h"

using google::cloud::diagnostics::debug::Variable;
using std::min;
using std::shared_ptr;
using std::string;
using std::unique_ptr;
using std::vector;

namespace google_cloud_debugger {

const string DbgBuiltinCollection::kListItemsFieldName = "_items";
const string DbgBuiltinCollection::kListSizeFieldName = "_size";
const string DbgBuiltinCollection::kHashSetSlotsFieldName = "_slots";
const string DbgBuiltinCollection::kHashSetCountFieldName = "_count";
const string DbgBuiltinCollection::kHashSetLastIndexFieldName = "_lastIndex";
const string DbgBuiltinCollection::kDictionaryCountFieldName = "count";
const string DbgBuiltinCollection::kDictionaryItemsFieldName = "entries";
const string DbgBuiltinCollection::kDictionaryKeyFieldName = "key";
const string DbgBuiltinCollection::kHashSetAndDictValueFieldName = "value";
const string DbgBuiltinCollection::kHashSetAndDictHashCodeFieldName =
    "hashCode";
const string DbgBuiltinCollection::kCountProtoFieldName = "Count";

HRESULT DbgBuiltinCollection::ProcessClassMembersHelper(
    ICorDebugValue *debug_value, ICorDebugClass *debug_class,
    IMetaDataImport *metadata_import) {
  HRESULT hr;
  CComPtr<ICorDebugObjectValue> debug_obj_value;
  hr = debug_value->QueryInterface(__uuidof(ICorDebugObjectValue),
                                   reinterpret_cast<void **>(&debug_obj_value));
  if (FAILED(hr)) {
    WriteError("Failed to cast ICorDebugValue to ICorDebugObjValue.");
    return hr;
  }

  // This is a list.
  if (kListClassName.compare(class_name_) == 0) {
    class_type_ = ClassType::LIST;
    hr = ProcessCollectionType(debug_obj_value, debug_class, metadata_import,
                               kListSizeFieldName, kListItemsFieldName);
    if (SUCCEEDED(hr)) {
      // Makes sure we don't grab more items than we need (this can happen
      // because if a list size is 2, the underlying items_ array can have 4
      // items).
      if (count_ < DbgBreakpoint::GetMaximumCollectionSize()) {
        (reinterpret_cast<DbgArray *>(collection_items_.get()))
            ->SetMaxArrayItemsToRetrieve(count_);
      }
    }
    return hr;
  }

  // This is a hash set.
  if (kHashSetClassName.compare(class_name_) == 0) {
    class_type_ = ClassType::SET;
    hr = ProcessCollectionType(debug_obj_value, debug_class, metadata_import,
                               kHashSetCountFieldName, kHashSetSlotsFieldName);
    if (SUCCEEDED(hr)) {
      // For hash set, we also needs the _lastIndex field, which tells us
      // the last valid index in the collection_items_ array. See comments
      // on hashset_last_index_ for more details.
      unique_ptr<DbgObject> last_index;

      // Extracts out the last index of the hash set.
      hr = ExtractField(debug_obj_value, debug_class, metadata_import,
                        kHashSetLastIndexFieldName, &last_index);
      if (FAILED(hr)) {
        WriteError(
            "Failed to find field that represents the last index of the hash "
            "set.");
        return hr;
      }

      hashset_last_index_ =
          reinterpret_cast<DbgPrimitive<int32_t> *>(last_index.get())
              ->GetValue();
    }
    return hr;
  }

  // This is a dictionary.
  if (kDictionaryClassName.compare(class_name_) == 0) {
    class_type_ = ClassType::DICTIONARY;
    return ProcessCollectionType(debug_obj_value, debug_class, metadata_import,
                                 kDictionaryCountFieldName,
                                 kDictionaryItemsFieldName);
  }

  return E_NOTIMPL;
}

HRESULT DbgBuiltinCollection::ProcessCollectionType(
    ICorDebugObjectValue *debug_obj_value, ICorDebugClass *debug_class,
    IMetaDataImport *metadata_import, const std::string &count_field,
    const std::string &entries_field) {
  HRESULT hr;
  // DbgObject representing the int that counts the size of the collection.
  unique_ptr<DbgObject> collection_size;

  // Extracts out the size of the collection.
  hr = ExtractField(debug_obj_value, debug_class, metadata_import, count_field,
                    &collection_size);
  if (FAILED(hr)) {
    WriteError(
        "Failed to find field that represents the size of the collection.");
    return hr;
  }
  count_ = reinterpret_cast<DbgPrimitive<int32_t> *>(collection_size.get())
               ->GetValue();

  // Extracts out the array that contains items in the collection.
  hr = ExtractField(debug_obj_value, debug_class, metadata_import,
                    entries_field, &collection_items_);
  if (FAILED(hr)) {
    WriteError("Failed to get the items of the collection.");
    return hr;
  }

  return hr;
}

HRESULT DbgBuiltinCollection::PopulateMembers(
    Variable *variable_proto, vector<VariableWrapper> *members,
    IEvalCoordinator *eval_coordinator) {
  if (!members) {
    return E_INVALIDARG;
  }

  if (!eval_coordinator) {
    WriteError("No Eval Coordinator, cannot do evaluation of properties.");
    return E_INVALIDARG;
  }

  if (FAILED(initialize_hr_)) {
    return initialize_hr_;
  }

  if (GetIsNull()) {
    return S_OK;
  }

  if (GetCreationDepth() <= 0) {
    WriteError("Object Inspection Depth Limit reached.");
    return E_FAIL;
  }

  HRESULT hr = ProcessClassMembers();
  if (FAILED(hr)) {
    return hr;
  }

  // Sets the Count property of the collection.
  Variable *list_count = variable_proto->add_members();
  list_count->set_name(kCountProtoFieldName);
  list_count->set_value(std::to_string(count_));
  list_count->set_type(kInt32ClassName);

  if (class_type_ == ClassType::LIST && collection_items_) {
    return collection_items_->PopulateMembers(variable_proto, members,
                                              eval_coordinator);
  }

  if ((class_type_ == ClassType::SET || class_type_ == ClassType::DICTIONARY) &&
      collection_items_) {
    return PopulateHashSetOrDictionary(variable_proto, members,
                                       eval_coordinator);
  }

  WriteError("Unknown collection.");

  return E_NOTIMPL;
}

HRESULT DbgBuiltinCollection::PopulateHashSetOrDictionary(
    google::cloud::diagnostics::debug::Variable *variable_proto,
    vector<VariableWrapper> *members, IEvalCoordinator *eval_coordinator) {
  // Start fetching items from the hash set or dictionary.
  HRESULT hr;
  int32_t index = 0;
  int32_t current_max_size = DbgBreakpoint::GetMaximumCollectionSize();
  int32_t max_items_to_fetch = min(count_, current_max_size);
  int32_t items_fetched_so_far = 0;
  // Casts the collection_items_ to an array.
  DbgArray *slots_array = reinterpret_cast<DbgArray *>(collection_items_.get());
  // We get items from the _items array. If this is a hash set, we have to make
  // sure we don't go beyond the hashset_last_index_ because items at this point
  // onwards will either be invalid or out of bound of the array.
  // If this is a dictionary, we just have to make sure we go until count_.
  // We will only get items in the array that has hashCode greater or equal to
  // 0.
  int32_t max_index =
      (class_type_ == ClassType::SET) ? hashset_last_index_ : count_;

  for (int32_t index = 0; index < max_index; ++index) {
    // Extracts out the item from the array.
    CComPtr<ICorDebugValue> array_item;
    hr = slots_array->GetArrayItem(index, &array_item);
    if (FAILED(hr)) {
      WriteError("Failed to get hash set item at index " +
                 std::to_string(index));
      return hr;
    }

    // Now creates a DbgObject that represents the Slot object from the
    // array_item we got above. Each Slot has the form struct Slot { int
    // hashCode; T value; int next; }
    // If this is a dictionary, then we will have Entry object with
    // the form Entry { int hashCode; TKey key; TValue value; int next; }
    // So a dictionary entry is essentially the same as a set slot except
    // that the dictionary entry has a key.
    unique_ptr<DbgObject> slot_item_obj;
    hr = object_factory_->CreateDbgObject(array_item, GetCreationDepth(),
                                          &slot_item_obj, GetErrorStream());
    if (FAILED(hr)) {
      WriteError("Failed to create DbgObject for item at index " +
                 std::to_string(index));
      return hr;
    }

    // Casts the DbgObject to a class.
    DbgClass *slot_item = reinterpret_cast<DbgClass *>(slot_item_obj.get());
    // Try to find the hashCode field of the struct.
    shared_ptr<DbgObject> hash_code_obj = nullptr;
    hr = slot_item->GetNonStaticField(kHashSetAndDictHashCodeFieldName,
                                      &hash_code_obj);
    if (FAILED(hr)) {
      WriteError("Failed to evaluate hash code for item at index " +
                 std::to_string(index));
      return hr;
    }

    // Since hashCode is an int, we cast it to a DbgPrimitive<int32_t>.
    DbgPrimitive<int32_t> *hash_code_primitive_obj =
        reinterpret_cast<DbgPrimitive<int32_t> *>(hash_code_obj.get());
    int32_t hash_code_value = hash_code_primitive_obj->GetValue();
    // Now the hashCode of the struct is actually processed in such a way that
    // they can only be greater than or equal to 0. If they are -1, then this
    // means this is not a valid item (probably removed), so we continue to the
    // next index. This is true for both hash set and dictionary.
    if (hash_code_value == -1) {
      continue;
    }

    // Gets the underlying DbgObject that represents value field.
    shared_ptr<DbgObject> value_obj = nullptr;
    hr =
        slot_item->GetNonStaticField(kHashSetAndDictValueFieldName, &value_obj);
    if (FAILED(hr)) {
      WriteError("Failed to evaluate the value of item at index " +
                 std::to_string(index));
      return hr;
    }

    shared_ptr<DbgObject> key_obj = nullptr;
    // If this is a dictionary, we have to find the key field of the struct.
    if (class_type_ == ClassType::DICTIONARY) {
      hr = slot_item->GetNonStaticField(kDictionaryKeyFieldName, &key_obj);
      if (FAILED(hr)) {
        WriteError("Failed to evaluate the value of the key at index " +
                   std::to_string(index));
        return hr;
      }
    }

    // Now creates a member that represents this item.
    Variable *item_proto = variable_proto->add_members();
    item_proto->set_name("[" + std::to_string(items_fetched_so_far) + "]");

    // For hash set, just display item as [index]: value.
    if (class_type_ == ClassType::SET) {
      // We don't have to worry about errors since PopulateVariableValue
      // will automatically sets error in item_proto.
      members->push_back(VariableWrapper(item_proto, value_obj));
    } else {
      // For dictionary, we also display the key. So an item would be
      // [index]: { "key": Key, "value": Value }
      Variable *key_proto = item_proto->add_members();
      key_proto->set_name(kDictionaryKeyFieldName);
      members->push_back(VariableWrapper(key_proto, key_obj));

      Variable *value_proto = item_proto->add_members();
      value_proto->set_name(kHashSetAndDictValueFieldName);
      members->push_back(VariableWrapper(value_proto, value_obj));
    }

    items_fetched_so_far++;
    if (items_fetched_so_far >= max_items_to_fetch) {
      break;
    }
  }
  return S_OK;
}

}  // namespace google_cloud_debugger
<|endoftext|>


<commit_before> /*
  * jabberresource.cpp
  *
  * Copyright (c) 2005-2006 by Michaël Larouche <larouche@kde.org>
  * Copyright (c) 2004 by Till Gerken <till@tantalo.net>
  *
  * Kopete    (c) 2001-2006 by the Kopete developers  <kopete-devel@kde.org>
  *
  * *************************************************************************
  * *                                                                       *
  * * This program is free software; you can redistribute it and/or modify  *
  * * it under the terms of the GNU General Public License as published by  *
  * * the Free Software Foundation; either version 2 of the License, or     *
  * * (at your option) any later version.                                   *
  * *                                                                       *
  * *************************************************************************
  */

#include "jabberresource.h"

// Qt includes
#include <qtimer.h>

// KDE includes
#include <kdebug.h>

// libiris includes
#include <im.h>
#include <xmpp_tasks.h>

// Kopete includes
#include "jabberprotocol.h"
#include "jabberaccount.h"
#include "jabbercapabilitiesmanager.h"

class JabberResource::Private
{
public:
	Private( JabberAccount *t_account, const XMPP::Jid &t_jid, const XMPP::Resource &t_resource )
	 : account(t_account), jid(t_jid), resource(t_resource), capsEnabled(false)
	{
		// Make sure the resource is always set.
		jid.setResource(resource.name());
	}

	JabberAccount *account;
	XMPP::Jid jid;
	XMPP::Resource resource;

	QString clientName, clientSystem;
	XMPP::Features supportedFeatures;
	bool capsEnabled;
};

JabberResource::JabberResource ( JabberAccount *account, const XMPP::Jid &jid, const XMPP::Resource &resource )
	: d( new Private(account, jid, resource) )
{
	d->capsEnabled = account->protocol()->capabilitiesManager()->capabilitiesEnabled(jid);

	if ( account->isConnected () )
	{
		QTimer::singleShot ( account->client()->getPenaltyTime () * 1000, this, SLOT ( slotGetTimedClientVersion () ) );
		if(!d->capsEnabled)
		{
			QTimer::singleShot ( account->client()->getPenaltyTime () * 1000, this, SLOT ( slotGetDiscoCapabilties () ) );
		}
	}
}

JabberResource::~JabberResource ()
{
	delete d;
}

const XMPP::Jid &JabberResource::jid () const
{
	return d->jid;
}

const XMPP::Resource &JabberResource::resource () const
{
	return d->resource;
}

void JabberResource::setResource ( const XMPP::Resource &resource )
{
	d->resource = resource;

	// Check if the caps are now available.
	d->capsEnabled = d->account->protocol()->capabilitiesManager()->capabilitiesEnabled(d->jid);

	emit updated( this );
}

const QString &JabberResource::clientName () const
{
	return d->clientName;
}

const QString &JabberResource::clientSystem () const
{
	return d->clientSystem;
}

XMPP::Features JabberResource::features() const
{
	if(d->capsEnabled)
	{
		return d->account->protocol()->capabilitiesManager()->features(d->jid);
	}
	else
	{
		return d->supportedFeatures;
	}
}

void JabberResource::slotGetTimedClientVersion ()
{
	if ( d->account->isConnected () )
	{
		kDebug ( JABBER_DEBUG_GLOBAL ) << "Requesting client version for " << d->jid.full ();

		// request client version
		XMPP::JT_ClientVersion *task = new XMPP::JT_ClientVersion ( d->account->client()->rootTask () );
		// signal to ourselves when the vCard data arrived
		QObject::connect ( task, SIGNAL ( finished () ), this, SLOT ( slotGotClientVersion () ) );
		task->get ( d->jid );
		task->go ( true );
	}
}

void JabberResource::slotGotClientVersion ()
{
	XMPP::JT_ClientVersion *clientVersion = (XMPP::JT_ClientVersion *) sender ();

	if ( clientVersion->success () )
	{
		d->clientName = clientVersion->name () + ' ' + clientVersion->version ();
		d->clientSystem = clientVersion->os ();

		emit updated ( this );
	}
}

void JabberResource:: slotGetDiscoCapabilties ()
{
	if ( d->account->isConnected () )
	{
		kDebug ( JABBER_DEBUG_GLOBAL ) << "Requesting Client Features for " << d->jid.full ();

		XMPP:: JT_DiscoInfo *task = new XMPP::JT_DiscoInfo ( d->account->client()->rootTask () );
		// Retrive features when service discovery is done.
		QObject::connect ( task, SIGNAL ( finished () ), this, SLOT (slotGotDiscoCapabilities () ) );
		task->get ( d->jid);
		task->go ( true );
	}
}

void JabberResource::slotGotDiscoCapabilities ()
{
	XMPP::JT_DiscoInfo *discoInfo = (XMPP::JT_DiscoInfo *) sender ();

	if ( discoInfo->success () )
	{
		d->supportedFeatures = discoInfo->item().features();

		emit updated ( this );
	}
}

#include "jabberresource.moc"
<commit_msg>Disable version discovery because it just flood the server.<commit_after> /*
  * jabberresource.cpp
  *
  * Copyright (c) 2005-2006 by Michaël Larouche <larouche@kde.org>
  * Copyright (c) 2004 by Till Gerken <till@tantalo.net>
  *
  * Kopete    (c) 2001-2006 by the Kopete developers  <kopete-devel@kde.org>
  *
  * *************************************************************************
  * *                                                                       *
  * * This program is free software; you can redistribute it and/or modify  *
  * * it under the terms of the GNU General Public License as published by  *
  * * the Free Software Foundation; either version 2 of the License, or     *
  * * (at your option) any later version.                                   *
  * *                                                                       *
  * *************************************************************************
  */

#include "jabberresource.h"

// Qt includes
#include <qtimer.h>

// KDE includes
#include <kdebug.h>

// libiris includes
#include <im.h>
#include <xmpp_tasks.h>

// Kopete includes
#include "jabberprotocol.h"
#include "jabberaccount.h"
#include "jabbercapabilitiesmanager.h"

class JabberResource::Private
{
public:
	Private( JabberAccount *t_account, const XMPP::Jid &t_jid, const XMPP::Resource &t_resource )
	 : account(t_account), jid(t_jid), resource(t_resource), capsEnabled(false)
	{
		// Make sure the resource is always set.
		jid.setResource(resource.name());
	}

	JabberAccount *account;
	XMPP::Jid jid;
	XMPP::Resource resource;

	QString clientName, clientSystem;
	XMPP::Features supportedFeatures;
	bool capsEnabled;
};

JabberResource::JabberResource ( JabberAccount *account, const XMPP::Jid &jid, const XMPP::Resource &resource )
	: d( new Private(account, jid, resource) )
{
	d->capsEnabled = account->protocol()->capabilitiesManager()->capabilitiesEnabled(jid);

	if ( account->isConnected () )
	{
#if 0  //disabled because that flood the server, specially bad with the irc gateway
		QTimer::singleShot ( account->client()->getPenaltyTime () * 1000, this, SLOT ( slotGetTimedClientVersion () ) );
#endif
		if(!d->capsEnabled)
		{
			QTimer::singleShot ( account->client()->getPenaltyTime () * 1000, this, SLOT ( slotGetDiscoCapabilties () ) );
		}
	}
}

JabberResource::~JabberResource ()
{
	delete d;
}

const XMPP::Jid &JabberResource::jid () const
{
	return d->jid;
}

const XMPP::Resource &JabberResource::resource () const
{
	return d->resource;
}

void JabberResource::setResource ( const XMPP::Resource &resource )
{
	d->resource = resource;

	// Check if the caps are now available.
	d->capsEnabled = d->account->protocol()->capabilitiesManager()->capabilitiesEnabled(d->jid);

	emit updated( this );
}

const QString &JabberResource::clientName () const
{
	return d->clientName;
}

const QString &JabberResource::clientSystem () const
{
	return d->clientSystem;
}

XMPP::Features JabberResource::features() const
{
	if(d->capsEnabled)
	{
		return d->account->protocol()->capabilitiesManager()->features(d->jid);
	}
	else
	{
		return d->supportedFeatures;
	}
}

void JabberResource::slotGetTimedClientVersion ()
{
	if ( d->account->isConnected () )
	{
		kDebug ( JABBER_DEBUG_GLOBAL ) << "Requesting client version for " << d->jid.full ();

		// request client version
		XMPP::JT_ClientVersion *task = new XMPP::JT_ClientVersion ( d->account->client()->rootTask () );
		// signal to ourselves when the vCard data arrived
		QObject::connect ( task, SIGNAL ( finished () ), this, SLOT ( slotGotClientVersion () ) );
		task->get ( d->jid );
		task->go ( true );
	}
}

void JabberResource::slotGotClientVersion ()
{
	XMPP::JT_ClientVersion *clientVersion = (XMPP::JT_ClientVersion *) sender ();

	if ( clientVersion->success () )
	{
		d->clientName = clientVersion->name () + ' ' + clientVersion->version ();
		d->clientSystem = clientVersion->os ();

		emit updated ( this );
	}
}

void JabberResource:: slotGetDiscoCapabilties ()
{
	if ( d->account->isConnected () )
	{
		kDebug ( JABBER_DEBUG_GLOBAL ) << "Requesting Client Features for " << d->jid.full ();

		XMPP:: JT_DiscoInfo *task = new XMPP::JT_DiscoInfo ( d->account->client()->rootTask () );
		// Retrive features when service discovery is done.
		QObject::connect ( task, SIGNAL ( finished () ), this, SLOT (slotGotDiscoCapabilities () ) );
		task->get ( d->jid);
		task->go ( true );
	}
}

void JabberResource::slotGotDiscoCapabilities ()
{
	XMPP::JT_DiscoInfo *discoInfo = (XMPP::JT_DiscoInfo *) sender ();

	if ( discoInfo->success () )
	{
		d->supportedFeatures = discoInfo->item().features();

		emit updated ( this );
	}
}

#include "jabberresource.moc"
<|endoftext|>


<commit_before><commit_msg>added CSC,SEC,CSCH,SECH to testFunctionLists<commit_after><|endoftext|>