<commit_before>/*************************************************************************/
/*  view_panner.cpp                                                      */
/*************************************************************************/
/*                       This file is part of:                           */
/*                           GODOT ENGINE                                */
/*                      https://godotengine.org                          */
/*************************************************************************/
/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur.                 */
/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md).   */
/*                                                                       */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the       */
/* "Software"), to deal in the Software without restriction, including   */
/* without limitation the rights to use, copy, modify, merge, publish,   */
/* distribute, sublicense, and/or sell copies of the Software, and to    */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions:                                             */
/*                                                                       */
/* The above copyright notice and this permission notice shall be        */
/* included in all copies or substantial portions of the Software.       */
/*                                                                       */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,       */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF    */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY  */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,  */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE     */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                */
/*************************************************************************/

#include "view_panner.h"

#include "core/input/input.h"
#include "core/input/shortcut.h"
#include "core/os/keyboard.h"

bool ViewPanner::gui_input(const Ref<InputEvent> &p_event, Rect2 p_canvas_rect) {
	Ref<InputEventMouseButton> mb = p_event;
	if (mb.is_valid()) {
		Vector2i scroll_vec = Vector2((mb->get_button_index() == MouseButton::WHEEL_RIGHT) - (mb->get_button_index() == MouseButton::WHEEL_LEFT), (mb->get_button_index() == MouseButton::WHEEL_DOWN) - (mb->get_button_index() == MouseButton::WHEEL_UP));
		if (scroll_vec != Vector2()) {
			if (control_scheme == SCROLL_PANS) {
				if (mb->is_ctrl_pressed()) {
					scroll_vec.y *= mb->get_factor();
					callback_helper(zoom_callback, varray(scroll_vec, mb->get_position(), mb->is_alt_pressed()));
					return true;
				} else {
					Vector2 panning;
					if (mb->is_shift_pressed()) {
						panning.x += mb->get_factor() * scroll_vec.y;
						panning.y += mb->get_factor() * scroll_vec.x;
					} else {
						panning.y += mb->get_factor() * scroll_vec.y;
						panning.x += mb->get_factor() * scroll_vec.x;
					}
					callback_helper(scroll_callback, varray(panning, mb->is_alt_pressed()));
					return true;
				}
			} else {
				if (mb->is_ctrl_pressed()) {
					Vector2 panning;
					if (mb->is_shift_pressed()) {
						panning.x += mb->get_factor() * scroll_vec.y;
						panning.y += mb->get_factor() * scroll_vec.x;
					} else {
						panning.y += mb->get_factor() * scroll_vec.y;
						panning.x += mb->get_factor() * scroll_vec.x;
					}
					callback_helper(scroll_callback, varray(panning, mb->is_alt_pressed()));
					return true;
				} else if (!mb->is_shift_pressed()) {
					scroll_vec.y *= mb->get_factor();
					callback_helper(zoom_callback, varray(scroll_vec, mb->get_position(), mb->is_alt_pressed()));
					return true;
				}
			}
		}

		// Alt is not used for button presses, so ignore it.
		if (mb->is_alt_pressed()) {
			return false;
		}

		bool is_drag_event = mb->get_button_index() == MouseButton::MIDDLE ||
				(enable_rmb && mb->get_button_index() == MouseButton::RIGHT) ||
				(!simple_panning_enabled && mb->get_button_index() == MouseButton::LEFT && is_panning()) ||
				(force_drag && mb->get_button_index() == MouseButton::LEFT);

		if (is_drag_event) {
			if (mb->is_pressed()) {
				is_dragging = true;
			} else {
				is_dragging = false;
			}
			return mb->get_button_index() != MouseButton::LEFT || mb->is_pressed(); // Don't consume LMB release events (it fixes some selection problems).
		}
	}

	Ref<InputEventMouseMotion> mm = p_event;
	if (mm.is_valid()) {
		if (is_dragging) {
			if (p_canvas_rect != Rect2()) {
				callback_helper(pan_callback, varray(Input::get_singleton()->warp_mouse_motion(mm, p_canvas_rect)));
			} else {
				callback_helper(pan_callback, varray(mm->get_relative()));
			}
			return true;
		}
	}

	Ref<InputEventKey> k = p_event;
	if (k.is_valid()) {
		if (pan_view_shortcut.is_valid() && pan_view_shortcut->matches_event(k)) {
			pan_key_pressed = k->is_pressed();
			if (simple_panning_enabled || (Input::get_singleton()->get_mouse_button_mask() & MouseButton::LEFT) != MouseButton::NONE) {
				is_dragging = pan_key_pressed;
			}
			return true;
		}
	}

	return false;
}

void ViewPanner::release_pan_key() {
	pan_key_pressed = false;
	is_dragging = false;
}

void ViewPanner::callback_helper(Callable p_callback, Vector<Variant> p_args) {
	const Variant **argptr = (const Variant **)alloca(sizeof(Variant *) * p_args.size());
	for (int i = 0; i < p_args.size(); i++) {
		argptr[i] = &p_args[i];
	}

	Variant result;
	Callable::CallError ce;
	p_callback.call(argptr, p_args.size(), result, ce);
}

void ViewPanner::set_callbacks(Callable p_scroll_callback, Callable p_pan_callback, Callable p_zoom_callback) {
	scroll_callback = p_scroll_callback;
	pan_callback = p_pan_callback;
	zoom_callback = p_zoom_callback;
}

void ViewPanner::set_control_scheme(ControlScheme p_scheme) {
	control_scheme = p_scheme;
}

void ViewPanner::set_enable_rmb(bool p_enable) {
	enable_rmb = p_enable;
}

void ViewPanner::set_pan_shortcut(Ref<Shortcut> p_shortcut) {
	pan_view_shortcut = p_shortcut;
	pan_key_pressed = false;
}

void ViewPanner::set_simple_panning_enabled(bool p_enabled) {
	simple_panning_enabled = p_enabled;
}

void ViewPanner::setup(ControlScheme p_scheme, Ref<Shortcut> p_shortcut, bool p_simple_panning) {
	set_control_scheme(p_scheme);
	set_pan_shortcut(p_shortcut);
	set_simple_panning_enabled(p_simple_panning);
}

bool ViewPanner::is_panning() const {
	return is_dragging || pan_key_pressed;
}

void ViewPanner::set_force_drag(bool p_force) {
	force_drag = p_force;
}

ViewPanner::ViewPanner() {
	Array inputs;
	inputs.append(InputEventKey::create_reference(Key::SPACE));

	pan_view_shortcut.instantiate();
	pan_view_shortcut->set_events(inputs);
}
<commit_msg>Fix that slow mouse wheel scroll has no zoom effect on 2D editor<commit_after>/*************************************************************************/
/*  view_panner.cpp                                                      */
/*************************************************************************/
/*                       This file is part of:                           */
/*                           GODOT ENGINE                                */
/*                      https://godotengine.org                          */
/*************************************************************************/
/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur.                 */
/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md).   */
/*                                                                       */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the       */
/* "Software"), to deal in the Software without restriction, including   */
/* without limitation the rights to use, copy, modify, merge, publish,   */
/* distribute, sublicense, and/or sell copies of the Software, and to    */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions:                                             */
/*                                                                       */
/* The above copyright notice and this permission notice shall be        */
/* included in all copies or substantial portions of the Software.       */
/*                                                                       */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,       */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF    */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY  */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,  */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE     */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                */
/*************************************************************************/

#include "view_panner.h"

#include "core/input/input.h"
#include "core/input/shortcut.h"
#include "core/os/keyboard.h"

bool ViewPanner::gui_input(const Ref<InputEvent> &p_event, Rect2 p_canvas_rect) {
	Ref<InputEventMouseButton> mb = p_event;
	if (mb.is_valid()) {
		Vector2 scroll_vec = Vector2((mb->get_button_index() == MouseButton::WHEEL_RIGHT) - (mb->get_button_index() == MouseButton::WHEEL_LEFT), (mb->get_button_index() == MouseButton::WHEEL_DOWN) - (mb->get_button_index() == MouseButton::WHEEL_UP));
		if (scroll_vec != Vector2()) {
			if (control_scheme == SCROLL_PANS) {
				if (mb->is_ctrl_pressed()) {
					scroll_vec.y *= mb->get_factor();
					callback_helper(zoom_callback, varray(scroll_vec, mb->get_position(), mb->is_alt_pressed()));
					return true;
				} else {
					Vector2 panning;
					if (mb->is_shift_pressed()) {
						panning.x += mb->get_factor() * scroll_vec.y;
						panning.y += mb->get_factor() * scroll_vec.x;
					} else {
						panning.y += mb->get_factor() * scroll_vec.y;
						panning.x += mb->get_factor() * scroll_vec.x;
					}
					callback_helper(scroll_callback, varray(panning, mb->is_alt_pressed()));
					return true;
				}
			} else {
				if (mb->is_ctrl_pressed()) {
					Vector2 panning;
					if (mb->is_shift_pressed()) {
						panning.x += mb->get_factor() * scroll_vec.y;
						panning.y += mb->get_factor() * scroll_vec.x;
					} else {
						panning.y += mb->get_factor() * scroll_vec.y;
						panning.x += mb->get_factor() * scroll_vec.x;
					}
					callback_helper(scroll_callback, varray(panning, mb->is_alt_pressed()));
					return true;
				} else if (!mb->is_shift_pressed()) {
					scroll_vec.y *= mb->get_factor();
					callback_helper(zoom_callback, varray(scroll_vec, mb->get_position(), mb->is_alt_pressed()));
					return true;
				}
			}
		}

		// Alt is not used for button presses, so ignore it.
		if (mb->is_alt_pressed()) {
			return false;
		}

		bool is_drag_event = mb->get_button_index() == MouseButton::MIDDLE ||
				(enable_rmb && mb->get_button_index() == MouseButton::RIGHT) ||
				(!simple_panning_enabled && mb->get_button_index() == MouseButton::LEFT && is_panning()) ||
				(force_drag && mb->get_button_index() == MouseButton::LEFT);

		if (is_drag_event) {
			if (mb->is_pressed()) {
				is_dragging = true;
			} else {
				is_dragging = false;
			}
			return mb->get_button_index() != MouseButton::LEFT || mb->is_pressed(); // Don't consume LMB release events (it fixes some selection problems).
		}
	}

	Ref<InputEventMouseMotion> mm = p_event;
	if (mm.is_valid()) {
		if (is_dragging) {
			if (p_canvas_rect != Rect2()) {
				callback_helper(pan_callback, varray(Input::get_singleton()->warp_mouse_motion(mm, p_canvas_rect)));
			} else {
				callback_helper(pan_callback, varray(mm->get_relative()));
			}
			return true;
		}
	}

	Ref<InputEventKey> k = p_event;
	if (k.is_valid()) {
		if (pan_view_shortcut.is_valid() && pan_view_shortcut->matches_event(k)) {
			pan_key_pressed = k->is_pressed();
			if (simple_panning_enabled || (Input::get_singleton()->get_mouse_button_mask() & MouseButton::LEFT) != MouseButton::NONE) {
				is_dragging = pan_key_pressed;
			}
			return true;
		}
	}

	return false;
}

void ViewPanner::release_pan_key() {
	pan_key_pressed = false;
	is_dragging = false;
}

void ViewPanner::callback_helper(Callable p_callback, Vector<Variant> p_args) {
	const Variant **argptr = (const Variant **)alloca(sizeof(Variant *) * p_args.size());
	for (int i = 0; i < p_args.size(); i++) {
		argptr[i] = &p_args[i];
	}

	Variant result;
	Callable::CallError ce;
	p_callback.call(argptr, p_args.size(), result, ce);
}

void ViewPanner::set_callbacks(Callable p_scroll_callback, Callable p_pan_callback, Callable p_zoom_callback) {
	scroll_callback = p_scroll_callback;
	pan_callback = p_pan_callback;
	zoom_callback = p_zoom_callback;
}

void ViewPanner::set_control_scheme(ControlScheme p_scheme) {
	control_scheme = p_scheme;
}

void ViewPanner::set_enable_rmb(bool p_enable) {
	enable_rmb = p_enable;
}

void ViewPanner::set_pan_shortcut(Ref<Shortcut> p_shortcut) {
	pan_view_shortcut = p_shortcut;
	pan_key_pressed = false;
}

void ViewPanner::set_simple_panning_enabled(bool p_enabled) {
	simple_panning_enabled = p_enabled;
}

void ViewPanner::setup(ControlScheme p_scheme, Ref<Shortcut> p_shortcut, bool p_simple_panning) {
	set_control_scheme(p_scheme);
	set_pan_shortcut(p_shortcut);
	set_simple_panning_enabled(p_simple_panning);
}

bool ViewPanner::is_panning() const {
	return is_dragging || pan_key_pressed;
}

void ViewPanner::set_force_drag(bool p_force) {
	force_drag = p_force;
}

ViewPanner::ViewPanner() {
	Array inputs;
	inputs.append(InputEventKey::create_reference(Key::SPACE));

	pan_view_shortcut.instantiate();
	pan_view_shortcut->set_events(inputs);
}
<|endoftext|>


<commit_before>/* Begin CVS Header
   $Source: /Volumes/Home/Users/shoops/cvs/copasi_dev/copasi/steadystate/CSteadyStateTask.cpp,v $
   $Revision: 1.62 $
   $Name:  $
   $Author: shoops $
   $Date: 2006/04/27 01:31:49 $
   End CVS Header */

// Copyright  2005 by Pedro Mendes, Virginia Tech Intellectual
// Properties, Inc. and EML Research, gGmbH.
// All rights reserved.

/**
 * CSteadyStateTask class.
 *
 * This class implements a steady state task which is comprised of a
 * of a problem and a method. Additionally calls to the reporting
 * methods are done when initialized.
 *
 * Created for Copasi by Stefan Hoops 2002
 */

#include "copasi.h"

#include "CSteadyStateTask.h"
#include "CSteadyStateProblem.h"
#include "CSteadyStateMethod.h"
#include "model/CModel.h"
#include "model/CState.h"
#include "model/CMetabNameInterface.h"
#include "report/CKeyFactory.h"
#include "report/CReport.h"

#define XXXX_Reporting

CSteadyStateTask::CSteadyStateTask(const CCopasiContainer * pParent):
    CCopasiTask(CCopasiTask::steadyState, pParent),
    mpSteadyState(NULL),
    mJacobian(),
    mJacobianX(),
    mEigenValues("Eigenvalues of Jacobian", this),
    mEigenValuesX("Eigenvalues of reduced system Jacobian", this)
{
  mpProblem = new CSteadyStateProblem(this);
  mpMethod =
    CSteadyStateMethod::createSteadyStateMethod(CCopasiMethod::Newton);
  this->add(mpMethod, true);
  //mpMethod->setObjectParent(this);
  //((CSteadyStateMethod *) mpMethod)->setProblem((CSteadyStateProblem *) mpProblem);
}

CSteadyStateTask::CSteadyStateTask(const CSteadyStateTask & src,
                                   const CCopasiContainer * pParent):
    CCopasiTask(src, pParent),
    mpSteadyState(src.mpSteadyState),
    mJacobian(src.mJacobian),
    mJacobianX(src.mJacobianX),
    mEigenValues(src.mEigenValues, this),
    mEigenValuesX(src.mEigenValuesX, this)
{
  mpProblem =
    new CSteadyStateProblem(* (CSteadyStateProblem *) src.mpProblem, this);
  mpMethod =
    CSteadyStateMethod::createSteadyStateMethod(src.mpMethod->getSubType());
  this->add(mpMethod, true);
  //mpMethod->setObjectParent(this);
  //((CSteadyStateMethod *) mpMethod)->setProblem((CSteadyStateProblem *) mpProblem);
}

CSteadyStateTask::~CSteadyStateTask()
{
  pdelete(mpSteadyState);
}

void CSteadyStateTask::cleanup()
{}

void CSteadyStateTask::print(std::ostream * ostream) const {(*ostream) << (*this);}

void CSteadyStateTask::load(CReadConfig & configBuffer)
{
  configBuffer.getVariable("SteadyState", "bool", &mScheduled,
                           CReadConfig::LOOP);

  ((CSteadyStateProblem *) mpProblem)->load(configBuffer);

  ((CSteadyStateMethod *) mpMethod)->load(configBuffer);
}

//CState * CSteadyStateTask::getState()
//{return mpSteadyState;}

const CState * CSteadyStateTask::getState() const
  {return mpSteadyState;}

const CMatrix< C_FLOAT64 > & CSteadyStateTask::getJacobian() const
  {return mJacobian;}
const CMatrix< C_FLOAT64 > & CSteadyStateTask::getJacobianReduced() const
  {return mJacobianX;}

const CEigen & CSteadyStateTask::getEigenValues() const
  {
    return mEigenValues;
  }
const CEigen & CSteadyStateTask::getEigenValuesReduced() const
  {
    return mEigenValuesX;
  }

bool CSteadyStateTask::initialize(const OutputFlag & of,
                                  std::ostream * pOstream)
{
  assert(mpProblem && mpMethod);

  if (!mpMethod->isValidProblem(mpProblem)) return false;

  bool success = true;

  success &= CCopasiTask::initialize(of, pOstream);

  //init states
  if (!mpProblem->getModel()) return false;

  pdelete(mpSteadyState);
  mpSteadyState = new CState(mpProblem->getModel()->getInitialState());

  mCalculateReducedSystem = (mpProblem->getModel()->getNumDependentMetabs() != 0);

  //init jacobians
  unsigned C_INT32 size = mpSteadyState->getNumIndependent();
  mJacobianX.resize(size, size);
  size += mpSteadyState->getNumDependent();
  mJacobian.resize(size, size);

  CSteadyStateProblem* pProblem =
    dynamic_cast<CSteadyStateProblem *>(mpProblem);
  assert(pProblem);

  success &= pProblem->initialize();

  CSteadyStateMethod* pMethod =
    dynamic_cast<CSteadyStateMethod *>(mpMethod);
  assert(pMethod);

  success &= pMethod->initialize(pProblem);

  return success;
}

bool CSteadyStateTask::process(const bool & useInitialValues)
{
  if (useInitialValues)
    {
      mpProblem->getModel()->applyInitialValues();
    }

  *mpSteadyState = mpProblem->getModel()->getState();

  CSteadyStateMethod* pMethod =
    dynamic_cast<CSteadyStateMethod *>(mpMethod);
  assert(pMethod);

  output(COutputInterface::BEFORE);

  mResult = pMethod->process(mpSteadyState,
                             mJacobian,
                             mJacobianX,
                             mEigenValues,
                             mEigenValuesX,
                             mpCallBack);

  output(COutputInterface::AFTER);

  return (mResult != CSteadyStateMethod::notFound);
}

bool CSteadyStateTask::restore()
{
  bool success = CCopasiTask::restore();

  if (mUpdateModel)
    {
      CModel * pModel = mpProblem->getModel();

      pModel->setState(*mpSteadyState);
      pModel->applyAssignments();
      pModel->setInitialState(pModel->getState());
    }

  return success;
}

std::ostream &operator<<(std::ostream &os, const CSteadyStateTask &A)
{
  switch (A.getResult())
    {
    case CSteadyStateMethod::found:
      os << "A steady state with given resolution was found." << std::endl;
      break;

    case CSteadyStateMethod::notFound:
      os << "No steady state with given resolution was found!" << std::endl;
      os << "(below are the last unsuccessful trial values)" << std::endl;
      break;

    case CSteadyStateMethod::foundEquilibrium:
      os << "An equilibrium steady state (zero fluxes) was found." << std::endl;
      break;

    case CSteadyStateMethod::foundNegative:
      os << "An invalid steady state (negative concentrations) was found." << std::endl;
    }

  os << std::endl;

  // Update all necessary values.
  CState * pState = const_cast<CState *>(A.getState());
  if (!pState) return os;
  CModel * pModel = A.mpProblem->getModel();
  if (!pModel) return os;

  pModel->setState(*pState);
  pModel->applyAssignments();
  pModel->refreshRates();
  pModel->setTransitionTimes();

  // Metabolite Info: Name, Concentration, Concentration Rate, Particle Number, Particle Rate, Transition Time
  const CCopasiVector<CMetab> & Metabolites = pModel->getMetabolites();
  const CMetab * pMetab;

  unsigned C_INT32 i, imax = Metabolites.size();

  os << "Metabolite" << "\t";
  os << "Concentration (" << pModel->getConcentrationUnitName() << ")" << "\t";
  os << "Concentration Rate (" << pModel->getConcentrationRateUnitName() << ")" << "\t";
  os << "Particle Number" << "\t";
  os << "Particle Number Rate (1/" << pModel->getTimeUnitName() << ")" << "\t";
  os << "Transition Time (" << pModel->getTimeUnitName() << ")" << std::endl;

  for (i = 0; i < imax; ++i)
    {
      pMetab = Metabolites[i];
      os << CMetabNameInterface::getDisplayName(pModel, *pMetab) << "\t";
      os << pMetab->getConcentration() << "\t";
      os << pMetab->getConcentrationRate() << "\t";
      os << pMetab->getValue() << "\t";
      os << pMetab->getRate() << "\t";
      os << pMetab->getTransitionTime() << std::endl;
    }
  os << std::endl;

  // Reaction Info: Name, Flux, Particle Flux
  const CCopasiVector<CReaction>& Reactions = pModel->getReactions();
  const CReaction * pReaction;

  imax = Reactions.size();

  os << "Reaction" << "\t";
  os << "Flux (" << pModel->getQuantityRateUnitName() << ")" << "\t";
  os << "Particle Flux (1/" << pModel->getTimeUnitName() << ")" << std::endl;

  for (i = 0; i < imax; ++i)
    {
      pReaction = Reactions[i];
      os << pReaction->getObjectName() << "\t";
      os << pReaction->getFlux() << "\t";
      os << pReaction->getParticleFlux() << std::endl;
    }
  os << std::endl;

  // if Jacobian Requested
  //    Jacobian
  //    Jacobian Reduced System
  if (static_cast<CSteadyStateProblem *>(A.mpProblem)->isJacobianRequested())
    {
      os << "Jacobian of the Complete System" << std::endl;
      os << A.mJacobian << std::endl;
      if (static_cast<CSteadyStateProblem *>(A.mpProblem)->isStabilityAnalysisRequested())
        {
          os << "Eigenvalues\treal\timaginary" << std::endl;
          imax = A.mEigenValues.getR().size();
          for (i = 0; i < imax; i++)
            os << "\t" << A.mEigenValues.getR()[i] << "\t" << A.mEigenValues.getI()[i] << std::endl;
          os << std::endl;
        }

      os << "Jacobian of the Reduced System" << std::endl;
      os << A.mJacobianX << std::endl;
      if (static_cast<CSteadyStateProblem *>(A.mpProblem)->isStabilityAnalysisRequested())
        {
          os << "Eigenvalues\treal\timaginary" << std::endl;
          imax = A.mEigenValuesX.getR().size();
          for (i = 0; i < imax; i++)
            os << "\t" << A.mEigenValuesX.getR()[i] << "\t" << A.mEigenValuesX.getI()[i] << std::endl;
          os << std::endl;
        }
    }
  // if Stability Analysis Requested
  //    Stability Analysis Reduced System

  if (static_cast<CSteadyStateProblem *>(A.mpProblem)->isStabilityAnalysisRequested())
    {
      os << "Stability Analysis of the Reduced System" << std::endl;
      os << A.mEigenValuesX << std::endl;
    }

  return os;
}
<commit_msg>Fixed Bug 694. Steady-state calculation may never update the initial time as this calculation is only valid for autonomous models.<commit_after>/* Begin CVS Header
   $Source: /Volumes/Home/Users/shoops/cvs/copasi_dev/copasi/steadystate/CSteadyStateTask.cpp,v $
   $Revision: 1.63 $
   $Name:  $
   $Author: shoops $
   $Date: 2006/11/03 19:49:49 $
   End CVS Header */

// Copyright  2005 by Pedro Mendes, Virginia Tech Intellectual
// Properties, Inc. and EML Research, gGmbH.
// All rights reserved.

/**
 * CSteadyStateTask class.
 *
 * This class implements a steady state task which is comprised of a
 * of a problem and a method. Additionally calls to the reporting
 * methods are done when initialized.
 *
 * Created for Copasi by Stefan Hoops 2002
 */

#include "copasi.h"

#include "CSteadyStateTask.h"
#include "CSteadyStateProblem.h"
#include "CSteadyStateMethod.h"
#include "model/CModel.h"
#include "model/CState.h"
#include "model/CMetabNameInterface.h"
#include "report/CKeyFactory.h"
#include "report/CReport.h"

#define XXXX_Reporting

CSteadyStateTask::CSteadyStateTask(const CCopasiContainer * pParent):
    CCopasiTask(CCopasiTask::steadyState, pParent),
    mpSteadyState(NULL),
    mJacobian(),
    mJacobianX(),
    mEigenValues("Eigenvalues of Jacobian", this),
    mEigenValuesX("Eigenvalues of reduced system Jacobian", this)
{
  mpProblem = new CSteadyStateProblem(this);
  mpMethod =
    CSteadyStateMethod::createSteadyStateMethod(CCopasiMethod::Newton);
  this->add(mpMethod, true);
  //mpMethod->setObjectParent(this);
  //((CSteadyStateMethod *) mpMethod)->setProblem((CSteadyStateProblem *) mpProblem);
}

CSteadyStateTask::CSteadyStateTask(const CSteadyStateTask & src,
                                   const CCopasiContainer * pParent):
    CCopasiTask(src, pParent),
    mpSteadyState(src.mpSteadyState),
    mJacobian(src.mJacobian),
    mJacobianX(src.mJacobianX),
    mEigenValues(src.mEigenValues, this),
    mEigenValuesX(src.mEigenValuesX, this)
{
  mpProblem =
    new CSteadyStateProblem(* (CSteadyStateProblem *) src.mpProblem, this);
  mpMethod =
    CSteadyStateMethod::createSteadyStateMethod(src.mpMethod->getSubType());
  this->add(mpMethod, true);
  //mpMethod->setObjectParent(this);
  //((CSteadyStateMethod *) mpMethod)->setProblem((CSteadyStateProblem *) mpProblem);
}

CSteadyStateTask::~CSteadyStateTask()
{
  pdelete(mpSteadyState);
}

void CSteadyStateTask::cleanup()
{}

void CSteadyStateTask::print(std::ostream * ostream) const {(*ostream) << (*this);}

void CSteadyStateTask::load(CReadConfig & configBuffer)
{
  configBuffer.getVariable("SteadyState", "bool", &mScheduled,
                           CReadConfig::LOOP);

  ((CSteadyStateProblem *) mpProblem)->load(configBuffer);

  ((CSteadyStateMethod *) mpMethod)->load(configBuffer);
}

//CState * CSteadyStateTask::getState()
//{return mpSteadyState;}

const CState * CSteadyStateTask::getState() const
  {return mpSteadyState;}

const CMatrix< C_FLOAT64 > & CSteadyStateTask::getJacobian() const
  {return mJacobian;}
const CMatrix< C_FLOAT64 > & CSteadyStateTask::getJacobianReduced() const
  {return mJacobianX;}

const CEigen & CSteadyStateTask::getEigenValues() const
  {
    return mEigenValues;
  }
const CEigen & CSteadyStateTask::getEigenValuesReduced() const
  {
    return mEigenValuesX;
  }

bool CSteadyStateTask::initialize(const OutputFlag & of,
                                  std::ostream * pOstream)
{
  assert(mpProblem && mpMethod);

  if (!mpMethod->isValidProblem(mpProblem)) return false;

  bool success = true;

  success &= CCopasiTask::initialize(of, pOstream);

  //init states
  if (!mpProblem->getModel()) return false;

  pdelete(mpSteadyState);
  mpSteadyState = new CState(mpProblem->getModel()->getInitialState());

  mCalculateReducedSystem = (mpProblem->getModel()->getNumDependentMetabs() != 0);

  //init jacobians
  unsigned C_INT32 size = mpSteadyState->getNumIndependent();
  mJacobianX.resize(size, size);
  size += mpSteadyState->getNumDependent();
  mJacobian.resize(size, size);

  CSteadyStateProblem* pProblem =
    dynamic_cast<CSteadyStateProblem *>(mpProblem);
  assert(pProblem);

  success &= pProblem->initialize();

  CSteadyStateMethod* pMethod =
    dynamic_cast<CSteadyStateMethod *>(mpMethod);
  assert(pMethod);

  success &= pMethod->initialize(pProblem);

  return success;
}

bool CSteadyStateTask::process(const bool & useInitialValues)
{
  if (useInitialValues)
    {
      mpProblem->getModel()->applyInitialValues();
    }

  *mpSteadyState = mpProblem->getModel()->getState();

  // A steady-state makes only sense in an autonomous model,
  // i.e., the time of the steady-state must not be changed
  // during simulation.
  C_FLOAT64 InitialTime = mpSteadyState->getTime();

  CSteadyStateMethod* pMethod =
    dynamic_cast<CSteadyStateMethod *>(mpMethod);
  assert(pMethod);

  output(COutputInterface::BEFORE);

  mResult = pMethod->process(mpSteadyState,
                             mJacobian,
                             mJacobianX,
                             mEigenValues,
                             mEigenValuesX,
                             mpCallBack);

  // Reset the time.
  mpSteadyState->setTime(InitialTime);

  output(COutputInterface::AFTER);

  return (mResult != CSteadyStateMethod::notFound);
}

bool CSteadyStateTask::restore()
{
  bool success = CCopasiTask::restore();

  if (mUpdateModel)
    {
      CModel * pModel = mpProblem->getModel();

      pModel->setState(*mpSteadyState);
      pModel->applyAssignments();
      pModel->setInitialState(pModel->getState());
    }

  return success;
}

std::ostream &operator<<(std::ostream &os, const CSteadyStateTask &A)
{
  switch (A.getResult())
    {
    case CSteadyStateMethod::found:
      os << "A steady state with given resolution was found." << std::endl;
      break;

    case CSteadyStateMethod::notFound:
      os << "No steady state with given resolution was found!" << std::endl;
      os << "(below are the last unsuccessful trial values)" << std::endl;
      break;

    case CSteadyStateMethod::foundEquilibrium:
      os << "An equilibrium steady state (zero fluxes) was found." << std::endl;
      break;

    case CSteadyStateMethod::foundNegative:
      os << "An invalid steady state (negative concentrations) was found." << std::endl;
    }

  os << std::endl;

  // Update all necessary values.
  CState * pState = const_cast<CState *>(A.getState());
  if (!pState) return os;
  CModel * pModel = A.mpProblem->getModel();
  if (!pModel) return os;

  pModel->setState(*pState);
  pModel->applyAssignments();
  pModel->refreshRates();
  pModel->setTransitionTimes();

  // Metabolite Info: Name, Concentration, Concentration Rate, Particle Number, Particle Rate, Transition Time
  const CCopasiVector<CMetab> & Metabolites = pModel->getMetabolites();
  const CMetab * pMetab;

  unsigned C_INT32 i, imax = Metabolites.size();

  os << "Metabolite" << "\t";
  os << "Concentration (" << pModel->getConcentrationUnitName() << ")" << "\t";
  os << "Concentration Rate (" << pModel->getConcentrationRateUnitName() << ")" << "\t";
  os << "Particle Number" << "\t";
  os << "Particle Number Rate (1/" << pModel->getTimeUnitName() << ")" << "\t";
  os << "Transition Time (" << pModel->getTimeUnitName() << ")" << std::endl;

  for (i = 0; i < imax; ++i)
    {
      pMetab = Metabolites[i];
      os << CMetabNameInterface::getDisplayName(pModel, *pMetab) << "\t";
      os << pMetab->getConcentration() << "\t";
      os << pMetab->getConcentrationRate() << "\t";
      os << pMetab->getValue() << "\t";
      os << pMetab->getRate() << "\t";
      os << pMetab->getTransitionTime() << std::endl;
    }
  os << std::endl;

  // Reaction Info: Name, Flux, Particle Flux
  const CCopasiVector<CReaction>& Reactions = pModel->getReactions();
  const CReaction * pReaction;

  imax = Reactions.size();

  os << "Reaction" << "\t";
  os << "Flux (" << pModel->getQuantityRateUnitName() << ")" << "\t";
  os << "Particle Flux (1/" << pModel->getTimeUnitName() << ")" << std::endl;

  for (i = 0; i < imax; ++i)
    {
      pReaction = Reactions[i];
      os << pReaction->getObjectName() << "\t";
      os << pReaction->getFlux() << "\t";
      os << pReaction->getParticleFlux() << std::endl;
    }
  os << std::endl;

  // if Jacobian Requested
  //    Jacobian
  //    Jacobian Reduced System
  if (static_cast<CSteadyStateProblem *>(A.mpProblem)->isJacobianRequested())
    {
      os << "Jacobian of the Complete System" << std::endl;
      os << A.mJacobian << std::endl;
      if (static_cast<CSteadyStateProblem *>(A.mpProblem)->isStabilityAnalysisRequested())
        {
          os << "Eigenvalues\treal\timaginary" << std::endl;
          imax = A.mEigenValues.getR().size();
          for (i = 0; i < imax; i++)
            os << "\t" << A.mEigenValues.getR()[i] << "\t" << A.mEigenValues.getI()[i] << std::endl;
          os << std::endl;
        }

      os << "Jacobian of the Reduced System" << std::endl;
      os << A.mJacobianX << std::endl;
      if (static_cast<CSteadyStateProblem *>(A.mpProblem)->isStabilityAnalysisRequested())
        {
          os << "Eigenvalues\treal\timaginary" << std::endl;
          imax = A.mEigenValuesX.getR().size();
          for (i = 0; i < imax; i++)
            os << "\t" << A.mEigenValuesX.getR()[i] << "\t" << A.mEigenValuesX.getI()[i] << std::endl;
          os << std::endl;
        }
    }
  // if Stability Analysis Requested
  //    Stability Analysis Reduced System

  if (static_cast<CSteadyStateProblem *>(A.mpProblem)->isStabilityAnalysisRequested())
    {
      os << "Stability Analysis of the Reduced System" << std::endl;
      os << A.mEigenValuesX << std::endl;
    }

  return os;
}
<|endoftext|>


<commit_before>/****************************************************************************
**
** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/
**
** This file is part of the QtQml module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** GNU Lesser General Public License Usage
** This file may be used under the terms of the GNU Lesser General Public
** License version 2.1 as published by the Free Software Foundation and
** appearing in the file LICENSE.LGPL included in the packaging of this
** file. Please review the following information to ensure the GNU Lesser
** General Public License version 2.1 requirements will be met:
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU General
** Public License version 3.0 as published by the Free Software Foundation
** and appearing in the file LICENSE.GPL included in the packaging of this
** file. Please review the following information to ensure the GNU General
** Public License version 3.0 requirements will be met:
** http://www.gnu.org/copyleft/gpl.html.
**
** Other Usage
** Alternatively, this file may be used in accordance with the terms and
** conditions contained in a signed written agreement between you and Nokia.
**
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/

#include <qnamespace.h>
#include "qqmlaccessible.h"

#ifndef QT_NO_ACCESSIBILITY

QT_BEGIN_NAMESPACE

QString Q_GUI_EXPORT qTextBeforeOffsetFromString(int offset, QAccessible2::BoundaryType boundaryType,
        int *startOffset, int *endOffset, const QString& text);
QString Q_GUI_EXPORT qTextAtOffsetFromString(int offset, QAccessible2::BoundaryType boundaryType,
        int *startOffset, int *endOffset, const QString& text);
QString Q_GUI_EXPORT qTextAfterOffsetFromString(int offset, QAccessible2::BoundaryType boundaryType,
        int *startOffset, int *endOffset, const QString& text);

QQmlAccessible::QQmlAccessible(QObject *object)
    :QAccessibleObject(object)
{
}

void *QQmlAccessible::interface_cast(QAccessible::InterfaceType t)
{
    if (t == QAccessible::ActionInterface)
        return static_cast<QAccessibleActionInterface*>(this);
    return QAccessibleObject::interface_cast(t);
}

QQmlAccessible::~QQmlAccessible()
{
}

QAccessibleInterface *QQmlAccessible::childAt(int x, int y) const
{
    // Note that this function will disregard stacking order.
    // (QAccessibleQuickView::childAt() does this correctly and more efficient)

    // If the item clips its children, we can return early if the coordinate is outside its rect
    if (clipsChildren()) {
        if (!rect().contains(x, y))
            return 0;
    }

    for (int i = childCount() - 1; i >= 0; --i) {
        QAccessibleInterface *childIface = child(i);
        if (childIface && !childIface->state().invisible) {
            if (childIface->rect().contains(x, y))
                return childIface;
        }
        delete childIface;
    }
    return 0;
}

QAccessible::State QQmlAccessible::state() const
{
    QAccessible::State state;

    //QRect viewRect(QPoint(0, 0), m_implementation->size());
    //QRect itemRect(m_item->scenePos().toPoint(), m_item->boundingRect().size().toSize());

    QRect viewRect_ = viewRect();
    QRect itemRect = rect();

   // qDebug() << "viewRect" << viewRect << "itemRect" << itemRect;
    // error case:
    if (viewRect_.isNull() || itemRect.isNull()) {
        state.invisible = true;
    }

    if (!viewRect_.intersects(itemRect)) {
        state.offscreen = true;
        // state.invisible = true; // no set at this point to ease development
    }

    if (!object()->property("visible").toBool() || qFuzzyIsNull(object()->property("opacity").toDouble())) {
        state.invisible = true;
    }

    if ((role() == QAccessible::CheckBox || role() == QAccessible::RadioButton) && object()->property("checked").toBool()) {
        state.checked = true;
    }

    if (role() == QAccessible::EditableText)
        state.focusable = true;

    //qDebug() << "state?" << m_item->property("state").toString() << m_item->property("status").toString() << m_item->property("visible").toString();

    return state;
}

QStringList QQmlAccessible::actionNames() const
{
    QStringList actions;
    switch (role()) {
    case QAccessible::PushButton:
        actions << QAccessibleActionInterface::pressAction();
        break;
    case QAccessible::RadioButton:
    case QAccessible::CheckBox:
        actions << QAccessibleActionInterface::checkAction()
                << QAccessibleActionInterface::uncheckAction()
                << QAccessibleActionInterface::pressAction();
        break;
    case QAccessible::Slider:
    case QAccessible::SpinBox:
    case QAccessible::ScrollBar:
        actions << QAccessibleActionInterface::increaseAction()
                << QAccessibleActionInterface::decreaseAction();
        break;
    default:
        break;
    }
    return actions;
}

void QQmlAccessible::doAction(const QString &actionName)
{
    // Look for and call the accessible[actionName]Action() function on the item.
    // This allows for overriding the default action handling.
    const QByteArray functionName = "accessible" + actionName.toLatin1() + "Action()";
    if (object()->metaObject()->indexOfMethod(functionName) != -1) {
        QMetaObject::invokeMethod(object(), functionName, Q_ARG(QString, actionName));
        return;
    }

    // Role-specific default action handling follows. Items are excepted to provide
    // properties according to role conventions. These will then be read and/or updated
    // by the accessibility system.
    //   Checkable roles   : checked
    //   Value-based roles : (via the value interface: value, minimumValue, maximumValue), stepSize
    switch (role()) {
    case QAccessible::RadioButton:
    case QAccessible::CheckBox: {
        QVariant checked = object()->property("checked");
        if (checked.isValid()) {
            if (actionName == QAccessibleActionInterface::pressAction()) {
                object()->setProperty("checked",  QVariant(!checked.toBool()));
            } else if (actionName == QAccessibleActionInterface::checkAction()) {
                object()->setProperty("checked",  QVariant(true));
            } else if (actionName == QAccessibleActionInterface::uncheckAction()) {
                object()->setProperty("checked",  QVariant(false));
            }
        }
        break;
    }
    case QAccessible::Slider:
    case QAccessible::SpinBox:
    case QAccessible::Dial:
    case QAccessible::ScrollBar: {
        if (actionName != QAccessibleActionInterface::increaseAction() &&
            actionName != QAccessibleActionInterface::decreaseAction())
            break;

        // Update the value using QAccessibleValueInterface, respecting
        // the minimum and maximum value (if set). Also check for and
        // use the "stepSize" property on the item
        if (QAccessibleValueInterface *valueIface = valueInterface()) {
            QVariant valueV = valueIface->currentValue();
            qreal newValue = valueV.toInt();

            QVariant stepSizeV = object()->property("stepSize");
            qreal stepSize = stepSizeV.isValid() ? stepSizeV.toReal() : qreal(1.0);
            if (actionName == QAccessibleActionInterface::increaseAction()) {
                newValue += stepSize;
            } else {
                newValue -= stepSize;
            }

            QVariant minimumValueV = valueIface->minimumValue();
            if (minimumValueV.isValid()) {
                newValue = qMax(newValue, minimumValueV.toReal());
            }
            QVariant maximumValueV = valueIface->maximumValue();
            if (maximumValueV.isValid()) {
                newValue = qMin(newValue, maximumValueV.toReal());
            }

            valueIface->setCurrentValue(QVariant(newValue));
        }
        break;
    }
    default:
        break;
    }
}

QStringList QQmlAccessible::keyBindingsForAction(const QString &actionName) const
{
    Q_UNUSED(actionName)
    return QStringList();
}

QT_END_NAMESPACE

#endif // QT_NO_ACCESSIBILITY
<commit_msg>Fix doAction with custom functions.<commit_after>/****************************************************************************
**
** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/
**
** This file is part of the QtQml module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** GNU Lesser General Public License Usage
** This file may be used under the terms of the GNU Lesser General Public
** License version 2.1 as published by the Free Software Foundation and
** appearing in the file LICENSE.LGPL included in the packaging of this
** file. Please review the following information to ensure the GNU Lesser
** General Public License version 2.1 requirements will be met:
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU General
** Public License version 3.0 as published by the Free Software Foundation
** and appearing in the file LICENSE.GPL included in the packaging of this
** file. Please review the following information to ensure the GNU General
** Public License version 3.0 requirements will be met:
** http://www.gnu.org/copyleft/gpl.html.
**
** Other Usage
** Alternatively, this file may be used in accordance with the terms and
** conditions contained in a signed written agreement between you and Nokia.
**
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/

#include <qnamespace.h>
#include "qqmlaccessible.h"

#ifndef QT_NO_ACCESSIBILITY

QT_BEGIN_NAMESPACE

QString Q_GUI_EXPORT qTextBeforeOffsetFromString(int offset, QAccessible2::BoundaryType boundaryType,
        int *startOffset, int *endOffset, const QString& text);
QString Q_GUI_EXPORT qTextAtOffsetFromString(int offset, QAccessible2::BoundaryType boundaryType,
        int *startOffset, int *endOffset, const QString& text);
QString Q_GUI_EXPORT qTextAfterOffsetFromString(int offset, QAccessible2::BoundaryType boundaryType,
        int *startOffset, int *endOffset, const QString& text);

QQmlAccessible::QQmlAccessible(QObject *object)
    :QAccessibleObject(object)
{
}

void *QQmlAccessible::interface_cast(QAccessible::InterfaceType t)
{
    if (t == QAccessible::ActionInterface)
        return static_cast<QAccessibleActionInterface*>(this);
    return QAccessibleObject::interface_cast(t);
}

QQmlAccessible::~QQmlAccessible()
{
}

QAccessibleInterface *QQmlAccessible::childAt(int x, int y) const
{
    // Note that this function will disregard stacking order.
    // (QAccessibleQuickView::childAt() does this correctly and more efficient)

    // If the item clips its children, we can return early if the coordinate is outside its rect
    if (clipsChildren()) {
        if (!rect().contains(x, y))
            return 0;
    }

    for (int i = childCount() - 1; i >= 0; --i) {
        QAccessibleInterface *childIface = child(i);
        if (childIface && !childIface->state().invisible) {
            if (childIface->rect().contains(x, y))
                return childIface;
        }
        delete childIface;
    }
    return 0;
}

QAccessible::State QQmlAccessible::state() const
{
    QAccessible::State state;

    //QRect viewRect(QPoint(0, 0), m_implementation->size());
    //QRect itemRect(m_item->scenePos().toPoint(), m_item->boundingRect().size().toSize());

    QRect viewRect_ = viewRect();
    QRect itemRect = rect();

   // qDebug() << "viewRect" << viewRect << "itemRect" << itemRect;
    // error case:
    if (viewRect_.isNull() || itemRect.isNull()) {
        state.invisible = true;
    }

    if (!viewRect_.intersects(itemRect)) {
        state.offscreen = true;
        // state.invisible = true; // no set at this point to ease development
    }

    if (!object()->property("visible").toBool() || qFuzzyIsNull(object()->property("opacity").toDouble())) {
        state.invisible = true;
    }

    if ((role() == QAccessible::CheckBox || role() == QAccessible::RadioButton) && object()->property("checked").toBool()) {
        state.checked = true;
    }

    if (role() == QAccessible::EditableText)
        state.focusable = true;

    //qDebug() << "state?" << m_item->property("state").toString() << m_item->property("status").toString() << m_item->property("visible").toString();

    return state;
}

QStringList QQmlAccessible::actionNames() const
{
    QStringList actions;
    switch (role()) {
    case QAccessible::PushButton:
        actions << QAccessibleActionInterface::pressAction();
        break;
    case QAccessible::RadioButton:
    case QAccessible::CheckBox:
        actions << QAccessibleActionInterface::checkAction()
                << QAccessibleActionInterface::uncheckAction()
                << QAccessibleActionInterface::pressAction();
        break;
    case QAccessible::Slider:
    case QAccessible::SpinBox:
    case QAccessible::ScrollBar:
        actions << QAccessibleActionInterface::increaseAction()
                << QAccessibleActionInterface::decreaseAction();
        break;
    default:
        break;
    }
    return actions;
}

void QQmlAccessible::doAction(const QString &actionName)
{
    // Look for and call the accessible[actionName]Action() function on the item.
    // This allows for overriding the default action handling.
    const QByteArray functionName = "accessible" + actionName.toLatin1() + "Action";
    if (object()->metaObject()->indexOfMethod(functionName + "()") != -1) {
        QMetaObject::invokeMethod(object(), functionName);
        return;
    }

    // Role-specific default action handling follows. Items are excepted to provide
    // properties according to role conventions. These will then be read and/or updated
    // by the accessibility system.
    //   Checkable roles   : checked
    //   Value-based roles : (via the value interface: value, minimumValue, maximumValue), stepSize
    switch (role()) {
    case QAccessible::RadioButton:
    case QAccessible::CheckBox: {
        QVariant checked = object()->property("checked");
        if (checked.isValid()) {
            if (actionName == QAccessibleActionInterface::pressAction()) {
                object()->setProperty("checked",  QVariant(!checked.toBool()));
            } else if (actionName == QAccessibleActionInterface::checkAction()) {
                object()->setProperty("checked",  QVariant(true));
            } else if (actionName == QAccessibleActionInterface::uncheckAction()) {
                object()->setProperty("checked",  QVariant(false));
            }
        }
        break;
    }
    case QAccessible::Slider:
    case QAccessible::SpinBox:
    case QAccessible::Dial:
    case QAccessible::ScrollBar: {
        if (actionName != QAccessibleActionInterface::increaseAction() &&
            actionName != QAccessibleActionInterface::decreaseAction())
            break;

        // Update the value using QAccessibleValueInterface, respecting
        // the minimum and maximum value (if set). Also check for and
        // use the "stepSize" property on the item
        if (QAccessibleValueInterface *valueIface = valueInterface()) {
            QVariant valueV = valueIface->currentValue();
            qreal newValue = valueV.toInt();

            QVariant stepSizeV = object()->property("stepSize");
            qreal stepSize = stepSizeV.isValid() ? stepSizeV.toReal() : qreal(1.0);
            if (actionName == QAccessibleActionInterface::increaseAction()) {
                newValue += stepSize;
            } else {
                newValue -= stepSize;
            }

            QVariant minimumValueV = valueIface->minimumValue();
            if (minimumValueV.isValid()) {
                newValue = qMax(newValue, minimumValueV.toReal());
            }
            QVariant maximumValueV = valueIface->maximumValue();
            if (maximumValueV.isValid()) {
                newValue = qMin(newValue, maximumValueV.toReal());
            }

            valueIface->setCurrentValue(QVariant(newValue));
        }
        break;
    }
    default:
        break;
    }
}

QStringList QQmlAccessible::keyBindingsForAction(const QString &actionName) const
{
    Q_UNUSED(actionName)
    return QStringList();
}

QT_END_NAMESPACE

#endif // QT_NO_ACCESSIBILITY
<|endoftext|>


<commit_before>/*
 * Copyright (C) 2015  LINK/2012 <dma_2012@hotmail.com>
 * Licensed under the MIT License, see LICENSE at top level directory.
 *
 */
#include <stdinc.hpp>
#include "../data_traits.hpp"
using namespace modloader;
using std::set;
using std::string;

namespace datalib
{
    template<>
    struct data_info<udata<modelname>> : data_info<modelname>
    {
        static const bool ignore = true;
    };
}

// Traits for pedgrp.dat and cargrp.dat
struct xxxgrp_traits : public data_traits
{
    static const bool has_sections      = false;
    static const bool per_line_section  = false;

    //
    using key_type   = std::pair<int, size_t>; // grpindex, model_hash
    using value_type = data_slice<either<set<modelname>, udata<modelname>>>;

    key_type key_from_value(const value_type&)
    {
        return std::make_pair(grpindex++, 0);
    }

    template<typename StoreType, typename TData>
    static bool setbyline(StoreType& store, TData& data, const gta3::section_info* section, const std::string& line)
    {
        if(gvm.IsVC())
        {
            // VC uses '//' at the end of the line.
            // The game doesn't even reach the point of reading this char (it only reads 16 tokens),
            // but our method to avoid it is erasing.
            size_t comment_pos = line.find("//");
            if(comment_pos != line.npos)
            {
                std::string fixed_line = line;
                fixed_line.erase(comment_pos);
                return data_traits::setbyline(store, data, section, fixed_line);
            }
        }
        return data_traits::setbyline(store, data, section, line);
    }

    // Before the merging process transform the set of models into individual models in each key of the container
    // This allows merging of individual entries in a group not just the entire group container itself
    template<class StoreType>
    static bool premerge(StoreType& store)
    {
        StoreType::container_type newcontainer;

        // Builds the new container, which contains a single model instead of the set of models
        std::for_each(store.container().begin(), store.container().end(), [&](StoreType::pair_type& pair)
        {
            auto& set = *get<std::set<modelname>>(&pair.second.get<0>());
            for(auto& model : set)
            {
                newcontainer.emplace(
                    key_type(pair.first.first, hash_model(model)),
                    value_type(make_udata<modelname>(model)));
            }
        });

        store.container() = std::move(newcontainer);
        return true;
    }

    // Now, before writing the content to the merged file we should reverse the transformation we did in premerge.
    // So this time we should take each model with the same group in the key and put in a set
    template<class StoreType, class MergedList, class FuncDoWrite>
    static bool prewrite(MergedList list, FuncDoWrite dowrite)
    {
        std::map<key_type, value_type> grp_content;

        std::for_each(list.begin(), list.end(), [&](MergedList::value_type& pair)
        {
            auto& model = get(*get<udata<modelname>>(&pair.second.get().get<0>()));
            auto key = key_type(pair.first.get().first, 0);

            // If the key still doesn't exist, make it to be have it's mapped type to be a set of models
            if(grp_content.count(key) == 0)
            {
                grp_content.emplace(key, value_type(set<modelname>()));
            }

            get<set<modelname>>(&grp_content[key].get<0>())->emplace(model);
        });

        list.clear();
        for(auto& x : grp_content)
           list.emplace_back(std::cref(x.first), std::ref(x.second));

        return dowrite(list);
    }

    public: // traits data

        int grpindex = 0;   // Line index we are going tho for groups

        template<class Archive>
        void serialize(Archive& archive)
        { archive(this->grpindex); }
};

struct cargrp_traits : public xxxgrp_traits
{
    struct dtraits : modloader::dtraits::OpenFile
    {
        static const char* what()       { return "car groups"; }
        static const char* datafile()   { return "cargrp.dat"; }
    };

    using detour_type = modloader::OpenFileDetour<0x5BD1BB, dtraits>;
};

struct pedgrp_traits : public xxxgrp_traits
{
    struct dtraits : modloader::dtraits::OpenFile
    {
        static const char* what()       { return "ped groups"; }
        static const char* datafile()   { return "pedgrp.dat"; }
    };

    using detour_type = modloader::OpenFileDetour<0x5BCFFB, dtraits>;
};

template<class Traits>
using xxxgrp_store = gta3::data_store<Traits, std::map<
                        typename Traits::key_type, typename Traits::value_type
                        >>;

template<class Traits>
static void initialise(DataPlugin* plugin_ptr, std::function<void()> refresher)
{
    using store_type = xxxgrp_store<Traits>;
    plugin_ptr->AddMerger<store_type>(Traits::dtraits::datafile(), true, false, false, reinstall_since_load, refresher);
}

static auto xinit = initializer([](DataPlugin* plugin_ptr)
{
    if(true)       initialise<pedgrp_traits>(plugin_ptr, gdir_refresh(injector::cstd<void()>::call<0x5BCFE0>));
    if(gvm.IsSA()) initialise<cargrp_traits>(plugin_ptr, gdir_refresh(injector::cstd<void()>::call<0x5BD1A0>));
});
<commit_msg>Fix pedgrp merger for III/VC<commit_after>/*
 * Copyright (C) 2015  LINK/2012 <dma_2012@hotmail.com>
 * Licensed under the MIT License, see LICENSE at top level directory.
 *
 */
#include <stdinc.hpp>
#include "../data_traits.hpp"
using namespace modloader;
using std::set;
using std::vector;
using std::string;

namespace datalib
{
    template<>
    struct data_info<udata<modelname>> : data_info<modelname>
    {
        static const bool ignore = true;
    };
}

// Traits for pedgrp.dat and cargrp.dat
struct xxxgrp_traits : public data_traits
{
    static const bool has_sections      = false;
    static const bool per_line_section  = false;

    //
    using key_type   = std::pair<int, size_t>; // grpindex, model_hash
    using value_type = data_slice<either<vector<modelname>, udata<modelname>>>;

    key_type key_from_value(const value_type&)
    {
        return std::make_pair(grpindex++, 0);
    }

    template<typename StoreType, typename TData>
    static bool setbyline(StoreType& store, TData& data, const gta3::section_info* section, const std::string& line)
    {
        if(gvm.IsVC())
        {
            // VC uses '//' at the end of the line.
            // The game doesn't even reach the point of reading this char (it only reads 16 tokens),
            // but our method to avoid it is erasing.
            size_t comment_pos = line.find("//");
            if(comment_pos != line.npos)
            {
                std::string fixed_line = line;
                fixed_line.erase(comment_pos);
                return data_traits::setbyline(store, data, section, fixed_line);
            }
        }
        return data_traits::setbyline(store, data, section, line);
    }

    // (SA-only, III/VC grps aren't variable length)
    // Before the merging process transform the set of models into individual models in each key of the container
    // This allows merging of individual entries in a group not just the entire group container itself
    template<class StoreType>
    static bool premerge(StoreType& store)
    {
        if(gvm.IsSA())
        {
            StoreType::container_type newcontainer;

            // Builds the new container, which contains a single model instead of the set of models
            std::for_each(store.container().begin(), store.container().end(), [&](StoreType::pair_type& pair)
            {
                auto& vec = *get<std::vector<modelname>>(&pair.second.get<0>());
                for(auto& model : vec)
                {
                    // the key will make the vector unique, no need to do a find.
                    newcontainer.emplace(
                        key_type(pair.first.first, hash_model(model)),
                        value_type(make_udata<modelname>(model)));
                }
            });

            store.container() = std::move(newcontainer);
        }
        return true;
    }

    // (SA-only, III/VC grps aren't variable length)
    // Now, before writing the content to the merged file we should reverse the transformation we did in premerge.
    // So this time we should take each model with the same group in the key and put in a set
    template<class StoreType, class MergedList, class FuncDoWrite>
    static bool prewrite(MergedList list, FuncDoWrite dowrite)
    {
        if(gvm.IsSA())
        {
            std::map<key_type, value_type> grp_content;

            std::for_each(list.begin(), list.end(), [&](MergedList::value_type& pair)
            {
                auto& model = get(*get<udata<modelname>>(&pair.second.get().get<0>()));
                auto key = key_type(pair.first.get().first, 0);

                // If the key still doesn't exist, make it to be have it's mapped type to be a set of models
                if(grp_content.count(key) == 0)
                {
                    grp_content.emplace(key, value_type(vector<modelname>()));
                }

                get<vector<modelname>>(&grp_content[key].get<0>())->emplace_back(model);
            });

            list.clear();
            for(auto& x : grp_content)
               list.emplace_back(std::cref(x.first), std::ref(x.second));
        }
        return dowrite(list);
    }

    public: // traits data

        int grpindex = 0;   // Line index we are going tho for groups

        template<class Archive>
        void serialize(Archive& archive)
        { archive(this->grpindex); }
};

struct cargrp_traits : public xxxgrp_traits
{
    struct dtraits : modloader::dtraits::OpenFile
    {
        static const char* what()       { return "car groups"; }
        static const char* datafile()   { return "cargrp.dat"; }
    };

    using detour_type = modloader::OpenFileDetour<0x5BD1BB, dtraits>;
};

struct pedgrp_traits : public xxxgrp_traits
{
    struct dtraits : modloader::dtraits::OpenFile
    {
        static const char* what()       { return "ped groups"; }
        static const char* datafile()   { return "pedgrp.dat"; }
    };

    using detour_type = modloader::OpenFileDetour<0x5BCFFB, dtraits>;
};

template<class Traits>
using xxxgrp_store = gta3::data_store<Traits, std::map<
                        typename Traits::key_type, typename Traits::value_type
                        >>;

template<class Traits>
static void initialise(DataPlugin* plugin_ptr, std::function<void()> refresher)
{
    using store_type = xxxgrp_store<Traits>;
    plugin_ptr->AddMerger<store_type>(Traits::dtraits::datafile(), true, false, false, reinstall_since_load, refresher);
}

static auto xinit = initializer([](DataPlugin* plugin_ptr)
{
    if(true)       initialise<pedgrp_traits>(plugin_ptr, gdir_refresh(injector::cstd<void()>::call<0x5BCFE0>));
    if(gvm.IsSA()) initialise<cargrp_traits>(plugin_ptr, gdir_refresh(injector::cstd<void()>::call<0x5BD1A0>));
});
<|endoftext|>


<commit_before>/**
 * The Seeks proxy and plugin framework are part of the SEEKS project.
 * Copyright (C) 2010 Emmanuel Benazera, juban@free.fr
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as
 * published by the Free Software Foundation, either version 3 of the
 * License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

#include "img_search_snippet.h"
#include "websearch.h"
#include "query_context.h"
#include "img_query_context.h"
#include "miscutil.h"
#include "mem_utils.h"
#include "encode.h"
#include "urlmatch.h"
#include <assert.h>

#if defined(PROTOBUF) && defined(TC)
#include "query_capture_configuration.h"
#endif

using sp::miscutil;
using sp::encode;
using sp::urlmatch;

namespace seeks_plugins
{

  img_search_snippet::img_search_snippet()
      :search_snippet()
#ifdef FEATURE_OPENCV2
      ,_surf_keypoints(NULL),_surf_descriptors(NULL),_surf_storage(NULL)
#endif
      , _cached_image(NULL)
  {
    _doc_type = IMAGE;
  }

  img_search_snippet::img_search_snippet(const short &rank)
      :search_snippet(rank)
#ifdef FEATURE_OPENCV2
      ,_surf_keypoints(NULL),_surf_descriptors(NULL)
#endif
      , _cached_image(NULL)
  {
    _doc_type = IMAGE;
#ifdef FEATURE_OPENCV2
    _surf_storage = cvCreateMemStorage(0);
#endif
  }

  img_search_snippet::~img_search_snippet()
  {
    if (_cached_image)
      delete _cached_image;

#ifdef FEATURE_OPENCV2
    if (_surf_keypoints)
      cvClearSeq(_surf_keypoints);
    if (_surf_descriptors)
      cvClearSeq(_surf_descriptors);
    if (_surf_storage)
      cvReleaseMemStorage(&_surf_storage);
#endif
  }

  std::string img_search_snippet::to_html_with_highlight(std::vector<std::string> &words,
      const std::string &base_url_str,
      const hash_map<const char*,const char*,hash<const char*>,eqstr> *parameters)
  {
    // check for URL redirection for capture & personalization of results.
    bool prs = true;
    const char *pers = miscutil::lookup(parameters,"prs");
    if (!pers)
      prs = websearch::_wconfig->_personalization;
    else
      {
        if (strcasecmp(pers,"on") == 0)
          prs = true;
        else if (strcasecmp(pers,"off") == 0)
          prs = false;
        else prs = websearch::_wconfig->_personalization;
      }

    std::string url = _url;

#if defined(PROTOBUF) && defined(TC)
    if (prs && websearch::_qc_plugin && websearch::_qc_plugin_activated
        && query_capture_configuration::_config
        && query_capture_configuration::_config->_mode_intercept == "redirect")
      {
        char *url_enc = encode::url_encode(url.c_str());
        url = base_url_str + "/qc_redir?q=" + _qc->_url_enc_query + "&url=" + std::string(url_enc);
        free(url_enc);
      }
#endif

    std::string se_icon = "_url_enc_query + "&page=1&expansion=1&action=expand&engines=seeng\"> ";
    std::string html_content = "
";

    html_content += "

";

    const char *title_enc = encode::html_encode(_title.c_str());
    html_content += title_enc;
    free_const(title_enc);

    if (_img_engine.to_ulong()&SE_GOOGLE_IMG)
      {
        std::string ggle_se_icon = se_icon;
        miscutil::replace_in_string(ggle_se_icon,"icon","search_engine_google");
        miscutil::replace_in_string(ggle_se_icon,"setitle","Google");
        miscutil::replace_in_string(ggle_se_icon,"seeng","google");
        html_content += ggle_se_icon;
      }
    if (_img_engine.to_ulong()&SE_BING_IMG)
      {
        std::string bing_se_icon = se_icon;
        miscutil::replace_in_string(bing_se_icon,"icon","search_engine_bing");
        miscutil::replace_in_string(bing_se_icon,"setitle","Bing");
        miscutil::replace_in_string(bing_se_icon,"seeng","bing");
        html_content += bing_se_icon;
      }
    if (_img_engine.to_ulong()&SE_FLICKR)
      {
        std::string flickr_se_icon = se_icon;
        miscutil::replace_in_string(flickr_se_icon,"icon","search_engine_flickr");
        miscutil::replace_in_string(flickr_se_icon,"setitle","Flickr");
        miscutil::replace_in_string(flickr_se_icon,"seeng","flickr");
        html_content += flickr_se_icon;
      }
    if (_img_engine.to_ulong()&SE_WCOMMONS)
      {
        std::string wcommons_se_icon = se_icon;
        miscutil::replace_in_string(wcommons_se_icon,"icon","search_engine_wcommons");
        miscutil::replace_in_string(wcommons_se_icon,"setitle","Wikimedia Commons");
        miscutil::replace_in_string(wcommons_se_icon,"seeng","wcommons");
        html_content += wcommons_se_icon;
      }
    if (_img_engine.to_ulong()&SE_YAHOO_IMG)
      {
        std::string yahoo_se_icon = se_icon;
        miscutil::replace_in_string(yahoo_se_icon,"icon","search_engine_yahoo");
        miscutil::replace_in_string(yahoo_se_icon,"setitle","yahoo");
        miscutil::replace_in_string(yahoo_se_icon,"seeng","yahoo");
        html_content += yahoo_se_icon;
      }

    // XXX: personalization icon kind of look ugly with image snippets...
    /* if (_personalized)
      {
         html_content += "
";
      }
    else */
    html_content += "

";
    const char *cite_enc = NULL;
    if (!_cite.empty())
      {
        std::string cite_host;
        std::string cite_path;
        urlmatch::parse_url_host_and_path(_cite,cite_host,cite_path);
        cite_enc = encode::html_encode(cite_host.c_str());
      }
    else
      {
        std::string cite_host;
        std::string cite_path;
        urlmatch::parse_url_host_and_path(_url,cite_host,cite_path);
        cite_enc = encode::html_encode(cite_host.c_str());
      }
    std::string cite_enc_str = std::string(cite_enc);
    if (cite_enc_str.size()>4 && cite_enc_str.substr(0,4)=="www.") //TODO: tolower.
      cite_enc_str = cite_enc_str.substr(4);
    free_const(cite_enc);
    html_content += "";
    html_content += cite_enc_str;
    html_content += "
";

    if (!_cached.empty())
      {
        char *enc_cached = encode::html_encode(_cached.c_str());
        miscutil::chomp(enc_cached);
        html_content += "Cached";
        free_const(enc_cached);
      }

#ifdef FEATURE_OPENCV2
    if (!_sim_back)
      {
        set_similarity_link(parameters);
        html_content += "<a class=\"search_cache\" href=\"";
      }
    else
      {
        set_back_similarity_link(parameters);
        html_content += "Similar";
    else html_content += "\">Back";
#endif
    html_content += "
\n";
    return html_content;
  }

  std::string img_search_snippet::to_json(const bool &thumbs,
                                          const std::vector<std::string> &query_words)
  {
    std::string json_str;
    json_str += "{";
    json_str += "\"id\":" + miscutil::to_string(_id) + ",";
    std::string title = _title;
    miscutil::replace_in_string(title,"\"","\\\"");
    json_str += "\"title\":\"" + title + "\",";
    std::string url = _url;
    miscutil::replace_in_string(url,"\"","\\\"");
    json_str += "\"url\":\"" + url + "\",";
    std::string summary = _summary_noenc;
    miscutil::replace_in_string(summary,"\"","\\\"");
    json_str += "\"summary\":\"" + summary + "\",";
    json_str += "\"seeks_meta\":" + miscutil::to_string(_meta_rank) + ",";
    json_str += "\"seeks_score\":" + miscutil::to_string(_seeks_rank) + ",";
    double rank = _rank / static_cast<double>(_img_engine.count());
    json_str += "\"rank\":" + miscutil::to_string(rank) + ",";
    json_str += "\"cite\":\"";
    if (!_cite.empty())
      {
        std::string cite_host;
        std::string cite_path;
        urlmatch::parse_url_host_and_path(_cite,cite_host,cite_path);
        json_str += cite_host + "\",";
      }
    else
      {
        std::string cite_host;
        std::string cite_path;
        urlmatch::parse_url_host_and_path(_url,cite_host,cite_path);
        json_str += cite_host + "\",";
      }
    if (!_cached.empty())
      {
        std::string cached = _cached;
        miscutil::replace_in_string(cached,"\"","\\\"");
        json_str += "\"cached\":\"" + _cached + "\","; // XXX: cached might be malformed without preprocessing.
      }
    json_str += "\"engines\":[";
    std::string json_str_eng = "";
    if (_img_engine.to_ulong()&SE_GOOGLE_IMG)
      json_str_eng += "\"google\"";
    if (_img_engine.to_ulong()&SE_BING_IMG)
      {
        if (!json_str_eng.empty())
          json_str_eng += ",";
        json_str_eng += "\"bing\"";
      }
    if (_img_engine.to_ulong()&SE_FLICKR)
      {
        if (!json_str_eng.empty())
          json_str_eng += ",";
        json_str_eng += "\"flickr\"";
      }
    if (_img_engine.to_ulong()&SE_WCOMMONS)
      {
        if (!json_str_eng.empty())
          json_str_eng += ",";
        json_str_eng += "\"wcommons\"";
      }
    if (_img_engine.to_ulong()&SE_YAHOO_IMG)
      {
        if (!json_str_eng.empty())
          json_str_eng += ",";
        json_str_eng += "\"yahoo\"";
      }
    json_str += json_str_eng + "]";
    json_str += ",\"type\":\"" + get_doc_type_str() + "\"";
    json_str += ",\"personalized\":\"";
    if (_personalized)
      json_str += "yes";
    else json_str += "no";
    json_str += "\"";
    if (!_date.empty())
      json_str += ",\"date\":\"" + _date + "\"";
    json_str += "}";
    return json_str;
  }

  bool img_search_snippet::is_se_enabled(const hash_map<const char*,const char*,hash<const char*>,eqstr> *parameters)
  {
    std::bitset<IMG_NSEs> se_enabled;
    img_query_context::fillup_img_engines(parameters,se_enabled);
    std::bitset<IMG_NSEs> band = _img_engine & se_enabled;
    return (band.count() != 0);
  }

  void img_search_snippet::set_similarity_link(const hash_map<const char*,const char*,hash<const char*>,eqstr> *parameters)
  {
    const char *engines = miscutil::lookup(parameters,"engines");
    std::string sfsearch = "on";
    if (!static_cast<img_query_context*>(_qc)->_safesearch)
      sfsearch = "off";
    _sim_link = "/search_img?q=" + _qc->_url_enc_query
                + "&page=1&expansion=" + miscutil::to_string(_qc->_page_expansion)
                + "&action=similarity&safesearch=" + sfsearch
                + "&id=" + miscutil::to_string(_id) + "&engines=";
    if (engines)
      _sim_link += std::string(engines);
    _sim_back = false;
  }

  void img_search_snippet::set_back_similarity_link(const hash_map<const char*,const char*,hash<const char*>,eqstr> *parameters)
  {
    const char *engines = miscutil::lookup(parameters,"engines");
    std::string sfsearch = "on";
    if (!static_cast<img_query_context*>(_qc)->_safesearch)
      sfsearch = "off";
    _sim_link = "/search_img?q=" + _qc->_url_enc_query
                + "&page=1&expansion=" + miscutil::to_string(_qc->_page_expansion)
                + "&action=expand&safesearch=" + sfsearch + "&engines=";
    if (engines)
      _sim_link += std::string(engines);
    _sim_back = true;
  }

  void img_search_snippet::merge_img_snippets(img_search_snippet *s1,
      const img_search_snippet *s2)
  {
    search_snippet::merge_snippets(s1,s2);

    std::bitset<IMG_NSEs> setest = s1->_img_engine;
    setest &= s2->_img_engine;
    if (setest.count()>0)
      return;
    s1->_img_engine |= s2->_img_engine;

    if (!s1->_cached_image && s2->_cached_image)
      s1->_cached_image = new std::string(*s2->_cached_image);

    /// seeks rank.
    s1->_seeks_rank = s1->_img_engine.count();

    // XXX: hack, on English queries, Bing & Yahoo are the same engine,
    // therefore the rank must be tweaked accordingly in this special case.
    if (s1->_qc->_auto_lang == "en"
        && (s1->_img_engine.to_ulong()&SE_YAHOO_IMG)
        && (s1->_img_engine.to_ulong()&SE_BING_IMG))
      s1->_seeks_rank--;
  }

} /* end of namespace. */
<commit_msg>fixed search engines icon URL rendering bug in image statuc UI<commit_after>/**
 * The Seeks proxy and plugin framework are part of the SEEKS project.
 * Copyright (C) 2010 Emmanuel Benazera, juban@free.fr
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as
 * published by the Free Software Foundation, either version 3 of the
 * License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

#include "img_search_snippet.h"
#include "websearch.h"
#include "query_context.h"
#include "img_query_context.h"
#include "miscutil.h"
#include "mem_utils.h"
#include "encode.h"
#include "urlmatch.h"
#include <assert.h>

#if defined(PROTOBUF) && defined(TC)
#include "query_capture_configuration.h"
#endif

using sp::miscutil;
using sp::encode;
using sp::urlmatch;

namespace seeks_plugins
{

  img_search_snippet::img_search_snippet()
      :search_snippet()
#ifdef FEATURE_OPENCV2
      ,_surf_keypoints(NULL),_surf_descriptors(NULL),_surf_storage(NULL)
#endif
      , _cached_image(NULL)
  {
    _doc_type = IMAGE;
  }

  img_search_snippet::img_search_snippet(const short &rank)
      :search_snippet(rank)
#ifdef FEATURE_OPENCV2
      ,_surf_keypoints(NULL),_surf_descriptors(NULL)
#endif
      , _cached_image(NULL)
  {
    _doc_type = IMAGE;
#ifdef FEATURE_OPENCV2
    _surf_storage = cvCreateMemStorage(0);
#endif
  }

  img_search_snippet::~img_search_snippet()
  {
    if (_cached_image)
      delete _cached_image;

#ifdef FEATURE_OPENCV2
    if (_surf_keypoints)
      cvClearSeq(_surf_keypoints);
    if (_surf_descriptors)
      cvClearSeq(_surf_descriptors);
    if (_surf_storage)
      cvReleaseMemStorage(&_surf_storage);
#endif
  }

  std::string img_search_snippet::to_html_with_highlight(std::vector<std::string> &words,
      const std::string &base_url_str,
      const hash_map<const char*,const char*,hash<const char*>,eqstr> *parameters)
  {
    // check for URL redirection for capture & personalization of results.
    bool prs = true;
    const char *pers = miscutil::lookup(parameters,"prs");
    if (!pers)
      prs = websearch::_wconfig->_personalization;
    else
      {
        if (strcasecmp(pers,"on") == 0)
          prs = true;
        else if (strcasecmp(pers,"off") == 0)
          prs = false;
        else prs = websearch::_wconfig->_personalization;
      }

    std::string url = _url;

#if defined(PROTOBUF) && defined(TC)
    if (prs && websearch::_qc_plugin && websearch::_qc_plugin_activated
        && query_capture_configuration::_config
        && query_capture_configuration::_config->_mode_intercept == "redirect")
      {
        char *url_enc = encode::url_encode(url.c_str());
        url = base_url_str + "/qc_redir?q=" + _qc->_url_enc_query + "&url=" + std::string(url_enc);
        free(url_enc);
      }
#endif

    std::string se_icon = " ";
    std::string html_content = "
";

    html_content += "

";

    const char *title_enc = encode::html_encode(_title.c_str());
    html_content += title_enc;
    free_const(title_enc);

    if (_img_engine.to_ulong()&SE_GOOGLE_IMG)
      {
        std::string ggle_se_icon = se_icon;
        miscutil::replace_in_string(ggle_se_icon,"icon","search_engine_google");
        miscutil::replace_in_string(ggle_se_icon,"setitle","Google");
        miscutil::replace_in_string(ggle_se_icon,"seeng","google");
	miscutil::replace_in_string(ggle_se_icon,"@query@",_qc->_url_enc_query);
	html_content += ggle_se_icon;
      }
    if (_img_engine.to_ulong()&SE_BING_IMG)
      {
        std::string bing_se_icon = se_icon;
        miscutil::replace_in_string(bing_se_icon,"icon","search_engine_bing");
        miscutil::replace_in_string(bing_se_icon,"setitle","Bing");
        miscutil::replace_in_string(bing_se_icon,"seeng","bing");
	miscutil::replace_in_string(bing_se_icon,"@query@",_qc->_url_enc_query);
	html_content += bing_se_icon;
      }
    if (_img_engine.to_ulong()&SE_FLICKR)
      {
        std::string flickr_se_icon = se_icon;
        miscutil::replace_in_string(flickr_se_icon,"icon","search_engine_flickr");
        miscutil::replace_in_string(flickr_se_icon,"setitle","Flickr");
        miscutil::replace_in_string(flickr_se_icon,"seeng","flickr");
	miscutil::replace_in_string(flickr_se_icon,"@query@",_qc->_url_enc_query);
	html_content += flickr_se_icon;
      }
    if (_img_engine.to_ulong()&SE_WCOMMONS)
      {
        std::string wcommons_se_icon = se_icon;
        miscutil::replace_in_string(wcommons_se_icon,"icon","search_engine_wcommons");
        miscutil::replace_in_string(wcommons_se_icon,"setitle","Wikimedia Commons");
        miscutil::replace_in_string(wcommons_se_icon,"seeng","wcommons");
	miscutil::replace_in_string(wcommons_se_icon,"@query@",_qc->_url_enc_query);
        html_content += wcommons_se_icon;
      }
    if (_img_engine.to_ulong()&SE_YAHOO_IMG)
      {
        std::string yahoo_se_icon = se_icon;
        miscutil::replace_in_string(yahoo_se_icon,"icon","search_engine_yahoo");
        miscutil::replace_in_string(yahoo_se_icon,"setitle","yahoo");
        miscutil::replace_in_string(yahoo_se_icon,"seeng","yahoo");
	miscutil::replace_in_string(yahoo_se_icon,"@query@",_qc->_url_enc_query);
	html_content += yahoo_se_icon;
      }

    // XXX: personalization icon kind of look ugly with image snippets...
    /* if (_personalized)
      {
         html_content += "
";
      }
    else */
    html_content += "

";
    const char *cite_enc = NULL;
    if (!_cite.empty())
      {
        std::string cite_host;
        std::string cite_path;
        urlmatch::parse_url_host_and_path(_cite,cite_host,cite_path);
        cite_enc = encode::html_encode(cite_host.c_str());
      }
    else
      {
        std::string cite_host;
        std::string cite_path;
        urlmatch::parse_url_host_and_path(_url,cite_host,cite_path);
        cite_enc = encode::html_encode(cite_host.c_str());
      }
    std::string cite_enc_str = std::string(cite_enc);
    if (cite_enc_str.size()>4 && cite_enc_str.substr(0,4)=="www.") //TODO: tolower.
      cite_enc_str = cite_enc_str.substr(4);
    free_const(cite_enc);
    html_content += "";
    html_content += cite_enc_str;
    html_content += "
";

    if (!_cached.empty())
      {
        char *enc_cached = encode::html_encode(_cached.c_str());
        miscutil::chomp(enc_cached);
        html_content += "Cached";
        free_const(enc_cached);
      }

#ifdef FEATURE_OPENCV2
    if (!_sim_back)
      {
        set_similarity_link(parameters);
        html_content += "<a class=\"search_cache\" href=\"";
      }
    else
      {
        set_back_similarity_link(parameters);
        html_content += "Similar";
    else html_content += "\">Back";
#endif
    html_content += "
\n";
    return html_content;
  }

  std::string img_search_snippet::to_json(const bool &thumbs,
                                          const std::vector<std::string> &query_words)
  {
    std::string json_str;
    json_str += "{";
    json_str += "\"id\":" + miscutil::to_string(_id) + ",";
    std::string title = _title;
    miscutil::replace_in_string(title,"\"","\\\"");
    json_str += "\"title\":\"" + title + "\",";
    std::string url = _url;
    miscutil::replace_in_string(url,"\"","\\\"");
    json_str += "\"url\":\"" + url + "\",";
    std::string summary = _summary_noenc;
    miscutil::replace_in_string(summary,"\"","\\\"");
    json_str += "\"summary\":\"" + summary + "\",";
    json_str += "\"seeks_meta\":" + miscutil::to_string(_meta_rank) + ",";
    json_str += "\"seeks_score\":" + miscutil::to_string(_seeks_rank) + ",";
    double rank = _rank / static_cast<double>(_img_engine.count());
    json_str += "\"rank\":" + miscutil::to_string(rank) + ",";
    json_str += "\"cite\":\"";
    if (!_cite.empty())
      {
        std::string cite_host;
        std::string cite_path;
        urlmatch::parse_url_host_and_path(_cite,cite_host,cite_path);
        json_str += cite_host + "\",";
      }
    else
      {
        std::string cite_host;
        std::string cite_path;
        urlmatch::parse_url_host_and_path(_url,cite_host,cite_path);
        json_str += cite_host + "\",";
      }
    if (!_cached.empty())
      {
        std::string cached = _cached;
        miscutil::replace_in_string(cached,"\"","\\\"");
        json_str += "\"cached\":\"" + _cached + "\","; // XXX: cached might be malformed without preprocessing.
      }
    json_str += "\"engines\":[";
    std::string json_str_eng = "";
    if (_img_engine.to_ulong()&SE_GOOGLE_IMG)
      json_str_eng += "\"google\"";
    if (_img_engine.to_ulong()&SE_BING_IMG)
      {
        if (!json_str_eng.empty())
          json_str_eng += ",";
        json_str_eng += "\"bing\"";
      }
    if (_img_engine.to_ulong()&SE_FLICKR)
      {
        if (!json_str_eng.empty())
          json_str_eng += ",";
        json_str_eng += "\"flickr\"";
      }
    if (_img_engine.to_ulong()&SE_WCOMMONS)
      {
        if (!json_str_eng.empty())
          json_str_eng += ",";
        json_str_eng += "\"wcommons\"";
      }
    if (_img_engine.to_ulong()&SE_YAHOO_IMG)
      {
        if (!json_str_eng.empty())
          json_str_eng += ",";
        json_str_eng += "\"yahoo\"";
      }
    json_str += json_str_eng + "]";
    json_str += ",\"type\":\"" + get_doc_type_str() + "\"";
    json_str += ",\"personalized\":\"";
    if (_personalized)
      json_str += "yes";
    else json_str += "no";
    json_str += "\"";
    if (!_date.empty())
      json_str += ",\"date\":\"" + _date + "\"";
    json_str += "}";
    return json_str;
  }

  bool img_search_snippet::is_se_enabled(const hash_map<const char*,const char*,hash<const char*>,eqstr> *parameters)
  {
    std::bitset<IMG_NSEs> se_enabled;
    img_query_context::fillup_img_engines(parameters,se_enabled);
    std::bitset<IMG_NSEs> band = _img_engine & se_enabled;
    return (band.count() != 0);
  }

  void img_search_snippet::set_similarity_link(const hash_map<const char*,const char*,hash<const char*>,eqstr> *parameters)
  {
    const char *engines = miscutil::lookup(parameters,"engines");
    std::string sfsearch = "on";
    if (!static_cast<img_query_context*>(_qc)->_safesearch)
      sfsearch = "off";
    _sim_link = "/search_img?q=" + _qc->_url_enc_query
                + "&page=1&expansion=" + miscutil::to_string(_qc->_page_expansion)
                + "&action=similarity&safesearch=" + sfsearch
                + "&id=" + miscutil::to_string(_id) + "&engines=";
    if (engines)
      _sim_link += std::string(engines);
    _sim_back = false;
  }

  void img_search_snippet::set_back_similarity_link(const hash_map<const char*,const char*,hash<const char*>,eqstr> *parameters)
  {
    const char *engines = miscutil::lookup(parameters,"engines");
    std::string sfsearch = "on";
    if (!static_cast<img_query_context*>(_qc)->_safesearch)
      sfsearch = "off";
    _sim_link = "/search_img?q=" + _qc->_url_enc_query
                + "&page=1&expansion=" + miscutil::to_string(_qc->_page_expansion)
                + "&action=expand&safesearch=" + sfsearch + "&engines=";
    if (engines)
      _sim_link += std::string(engines);
    _sim_back = true;
  }

  void img_search_snippet::merge_img_snippets(img_search_snippet *s1,
      const img_search_snippet *s2)
  {
    search_snippet::merge_snippets(s1,s2);

    std::bitset<IMG_NSEs> setest = s1->_img_engine;
    setest &= s2->_img_engine;
    if (setest.count()>0)
      return;
    s1->_img_engine |= s2->_img_engine;

    if (!s1->_cached_image && s2->_cached_image)
      s1->_cached_image = new std::string(*s2->_cached_image);

    /// seeks rank.
    s1->_seeks_rank = s1->_img_engine.count();

    // XXX: hack, on English queries, Bing & Yahoo are the same engine,
    // therefore the rank must be tweaked accordingly in this special case.
    if (s1->_qc->_auto_lang == "en"
        && (s1->_img_engine.to_ulong()&SE_YAHOO_IMG)
        && (s1->_img_engine.to_ulong()&SE_BING_IMG))
      s1->_seeks_rank--;
  }

} /* end of namespace. */
<|endoftext|>