<commit_before>/***********************************************************************
	filename: 	CEGUIMouseCursor.cpp
	created:	21/2/2004
	author:		Paul D Turner

	purpose:	Implements MouseCursor class
*************************************************************************/
/***************************************************************************
 *   Copyright (C) 2004 - 2012 Paul D Turner & The CEGUI Development Team
 *
 *   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 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 "CEGUI/MouseCursor.h"
#include "CEGUI/Exceptions.h"
#include "CEGUI/Logger.h"
#include "CEGUI/System.h"
#include "CEGUI/Renderer.h"
#include "CEGUI/ImageManager.h"
#include "CEGUI/Image.h"
#include "CEGUI/GeometryBuffer.h"
#include "CEGUI/CoordConverter.h"

// Start of CEGUI namespace section
namespace CEGUI
{
/*************************************************************************
	Static Data Definitions
*************************************************************************/
bool MouseCursor::s_initialPositionSet = false;
Vector2f MouseCursor::s_initialPosition(0.0f, 0.0f);

/*************************************************************************
	Event name constants
*************************************************************************/
const String MouseCursor::EventNamespace("MouseCursor");
const String MouseCursor::EventImageChanged("ImageChanged");
const String MouseCursor::EventDefaultImageChanged("DefaultImageChanged");

/*************************************************************************
	constructor
*************************************************************************/
MouseCursor::MouseCursor(void) :
    d_cursorImage(0),
    d_defaultCursorImage(0),
    d_position(0.0f, 0.0f),
    d_visible(true),
    d_geometry(&System::getSingleton().getRenderer()->createGeometryBufferTextured(
               System::getSingleton().getRenderer()->createRenderMaterial(DS_TEXTURED))),
    d_customSize(0.0f, 0.0f),
    d_customOffset(0.0f, 0.0f),
    d_cachedGeometryValid(false)
{
    const Rectf screenArea(Vector2f(0, 0),
                            System::getSingleton().getRenderer()->getDisplaySize());
    d_geometry->setClippingRegion(screenArea);

	// default constraint is to whole screen
	setConstraintArea(&screenArea);

    if (s_initialPositionSet)
        setPosition(s_initialPosition);
    else
    	// mouse defaults to middle of the constrained area
        setPosition(Vector2f(screenArea.getWidth() / 2,
                              screenArea.getHeight() / 2));
}

/*************************************************************************
	Destructor
*************************************************************************/
MouseCursor::~MouseCursor(void)
{
    System::getSingleton().getRenderer()->destroyGeometryBuffer(*d_geometry);
}

/*************************************************************************
	Set the current mouse cursor image
*************************************************************************/
void MouseCursor::setImage(const Image* image)
{
    if (image == d_cursorImage)
        return;

	d_cursorImage = image;
    d_cachedGeometryValid = false;

	MouseCursorEventArgs args(this);
	args.image = image;
	onImageChanged(args);
}

/*************************************************************************
	Set the current mouse cursor image
*************************************************************************/
void MouseCursor::setImage(const String& name)
{
	setImage(&ImageManager::getSingleton().get(name));
}

//----------------------------------------------------------------------------//
void MouseCursor::setDefaultImage(const Image* image)
{
    if (image == d_defaultCursorImage)
        return;

	d_defaultCursorImage = image;
    d_cachedGeometryValid = d_cursorImage != 0;

	MouseCursorEventArgs args(this);
	args.image = image;
	onDefaultImageChanged(args);
}

//----------------------------------------------------------------------------//
void MouseCursor::setDefaultImage(const String& name)
{
	setDefaultImage(&ImageManager::getSingleton().get(name));
}

//----------------------------------------------------------------------------//
const Image* MouseCursor::getDefaultImage() const
{
    return d_defaultCursorImage;
}

/*************************************************************************
	Draw the mouse cursor
*************************************************************************/
void MouseCursor::draw(void) const
{
    if (!d_visible || !d_cursorImage)
        return;

    if (!d_cachedGeometryValid)
        cacheGeometry();

    d_geometry->draw();
}

/*************************************************************************
	Set the current mouse cursor position
*************************************************************************/
void MouseCursor::setPosition(const Vector2f& position)
{
    d_position = position;
	constrainPosition();

    d_geometry->setTranslation(Vector3f(d_position.d_x, d_position.d_y, 0));
}

/*************************************************************************
	Offset the mouse cursor position by the deltas specified in 'offset'.
*************************************************************************/
void MouseCursor::offsetPosition(const Vector2f& offset)
{
	d_position.d_x += offset.d_x;
	d_position.d_y += offset.d_y;
	constrainPosition();

    d_geometry->setTranslation(Vector3f(d_position.d_x, d_position.d_y, 0));
}

/*************************************************************************
	Checks the mouse cursor position is within the current 'constrain'
	Rect and adjusts as required.
*************************************************************************/
void MouseCursor::constrainPosition(void)
{
    Rectf absarea(getConstraintArea());

	if (d_position.d_x >= absarea.d_max.d_x)
		d_position.d_x = absarea.d_max.d_x -1;

	if (d_position.d_y >= absarea.d_max.d_y)
		d_position.d_y = absarea.d_max.d_y -1;

	if (d_position.d_y < absarea.d_min.d_y)
		d_position.d_y = absarea.d_min.d_y;

	if (d_position.d_x < absarea.d_min.d_x)
		d_position.d_x = absarea.d_min.d_x;
}

/*************************************************************************
	Set the area that the mouse cursor is constrained to.
*************************************************************************/
void MouseCursor::setConstraintArea(const Rectf* area)
{
    const Rectf renderer_area(Vector2f(0, 0),
                               System::getSingleton().getRenderer()->getDisplaySize());

	if (!area)
	{
		d_constraints.d_min.d_x = cegui_reldim(renderer_area.d_min.d_x / renderer_area.getWidth());
		d_constraints.d_min.d_y = cegui_reldim(renderer_area.d_min.d_y / renderer_area.getHeight());
		d_constraints.d_max.d_x = cegui_reldim(renderer_area.d_max.d_x / renderer_area.getWidth());
		d_constraints.d_max.d_y = cegui_reldim(renderer_area.d_max.d_y / renderer_area.getHeight());
	}
	else
	{
        Rectf finalArea(area->getIntersection(renderer_area));
		d_constraints.d_min.d_x = cegui_reldim(finalArea.d_min.d_x / renderer_area.getWidth());
		d_constraints.d_min.d_y = cegui_reldim(finalArea.d_min.d_y / renderer_area.getHeight());
		d_constraints.d_max.d_x = cegui_reldim(finalArea.d_max.d_x / renderer_area.getWidth());
		d_constraints.d_max.d_y = cegui_reldim(finalArea.d_max.d_y / renderer_area.getHeight());
	}

	constrainPosition();
}

/*************************************************************************
	Set the area that the mouse cursor is constrained to.
*************************************************************************/
void MouseCursor::setUnifiedConstraintArea(const URect* area)
{
    const Rectf renderer_area(Vector2f(0, 0),
                               System::getSingleton().getRenderer()->getDisplaySize());

	if (area)
	{
        d_constraints = *area;
	}
	else
	{
		d_constraints.d_min.d_x = cegui_reldim(renderer_area.d_min.d_x / renderer_area.getWidth());
		d_constraints.d_min.d_y = cegui_reldim(renderer_area.d_min.d_y / renderer_area.getHeight());
		d_constraints.d_max.d_x = cegui_reldim(renderer_area.d_max.d_x / renderer_area.getWidth());
		d_constraints.d_max.d_y = cegui_reldim(renderer_area.d_max.d_y / renderer_area.getHeight());
	}

	constrainPosition();
}

/*************************************************************************
	Set the area that the mouse cursor is constrained to.
*************************************************************************/
Rectf MouseCursor::getConstraintArea(void) const
{
    return Rectf(CoordConverter::asAbsolute(d_constraints, System::getSingleton().getRenderer()->getDisplaySize()));
}

/*************************************************************************
	Set the area that the mouse cursor is constrained to.
*************************************************************************/
const URect& MouseCursor::getUnifiedConstraintArea(void) const
{
    return d_constraints;
}

/*************************************************************************
	Return the current mouse cursor position in display resolution
	independant values.
*************************************************************************/
Vector2f MouseCursor::getDisplayIndependantPosition(void) const
{
    Sizef dsz(System::getSingleton().getRenderer()->getDisplaySize());

    return Vector2f(d_position.d_x / (dsz.d_width - 1.0f),
                 d_position.d_y / (dsz.d_height - 1.0f));
}

//----------------------------------------------------------------------------//
void MouseCursor::notifyDisplaySizeChanged(const Sizef& new_size)
{
    const Rectf screenArea(Vector2f(0, 0), new_size);
    d_geometry->setClippingRegion(screenArea);

    // invalidate to regenerate geometry at (maybe) new size
    d_cachedGeometryValid = false;
}

//----------------------------------------------------------------------------//
void MouseCursor::setExplicitRenderSize(const Sizef& size)
{
    d_customSize = size;
    d_cachedGeometryValid = false;
}

//----------------------------------------------------------------------------//
const Sizef& MouseCursor::getExplicitRenderSize() const
{
    return d_customSize;
}

//----------------------------------------------------------------------------//
void MouseCursor::cacheGeometry() const
{
    d_cachedGeometryValid = true;
    d_geometry->reset();

    // if no image, nothing more to do.
    if (!d_cursorImage)
        return;

    if (d_customSize.d_width != 0.0f || d_customSize.d_height != 0.0f)
    {
        calculateCustomOffset();
        d_cursorImage->render(*d_geometry, d_customOffset, d_customSize);
    }
    else
    {
        d_cursorImage->render(*d_geometry, Vector2f(0, 0));
    }
}

//----------------------------------------------------------------------------//
void MouseCursor::calculateCustomOffset() const
{
    const Sizef sz(d_cursorImage->getRenderedSize());
    const Vector2f offset(d_cursorImage->getRenderedOffset());

    d_customOffset.d_x =
        d_customSize.d_width / sz.d_width * offset.d_x - offset.d_x;
    d_customOffset.d_y =
        d_customSize.d_height / sz.d_height * offset.d_y - offset.d_y;
}

//----------------------------------------------------------------------------//
void MouseCursor::setInitialMousePosition(const Vector2f& position)
{
    s_initialPosition = position;
    s_initialPositionSet = true;
}

//----------------------------------------------------------------------------//
void MouseCursor::invalidate()
{
    d_cachedGeometryValid = false;
}

//----------------------------------------------------------------------------//
void MouseCursor::onImageChanged(MouseCursorEventArgs& e)
{
    fireEvent(EventImageChanged, e, EventNamespace);
}

//----------------------------------------------------------------------------//
void MouseCursor::onDefaultImageChanged(MouseCursorEventArgs& e)
{
    fireEvent(EventDefaultImageChanged, e, EventNamespace);
}

//----------------------------------------------------------------------------//

} // End of  CEGUI namespace section
<commit_msg>MOD: Changing to the convenience creation function<commit_after>/***********************************************************************
	filename: 	CEGUIMouseCursor.cpp
	created:	21/2/2004
	author:		Paul D Turner

	purpose:	Implements MouseCursor class
*************************************************************************/
/***************************************************************************
 *   Copyright (C) 2004 - 2012 Paul D Turner & The CEGUI Development Team
 *
 *   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 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 "CEGUI/MouseCursor.h"
#include "CEGUI/Exceptions.h"
#include "CEGUI/Logger.h"
#include "CEGUI/System.h"
#include "CEGUI/Renderer.h"
#include "CEGUI/ImageManager.h"
#include "CEGUI/Image.h"
#include "CEGUI/GeometryBuffer.h"
#include "CEGUI/CoordConverter.h"

// Start of CEGUI namespace section
namespace CEGUI
{
/*************************************************************************
	Static Data Definitions
*************************************************************************/
bool MouseCursor::s_initialPositionSet = false;
Vector2f MouseCursor::s_initialPosition(0.0f, 0.0f);

/*************************************************************************
	Event name constants
*************************************************************************/
const String MouseCursor::EventNamespace("MouseCursor");
const String MouseCursor::EventImageChanged("ImageChanged");
const String MouseCursor::EventDefaultImageChanged("DefaultImageChanged");

/*************************************************************************
	constructor
*************************************************************************/
MouseCursor::MouseCursor(void) :
    d_cursorImage(0),
    d_defaultCursorImage(0),
    d_position(0.0f, 0.0f),
    d_visible(true),
    d_geometry(&System::getSingleton().getRenderer()->createGeometryBufferTextured()),
    d_customSize(0.0f, 0.0f),
    d_customOffset(0.0f, 0.0f),
    d_cachedGeometryValid(false)
{
    const Rectf screenArea(Vector2f(0, 0),
                            System::getSingleton().getRenderer()->getDisplaySize());
    d_geometry->setClippingRegion(screenArea);

	// default constraint is to whole screen
	setConstraintArea(&screenArea);

    if (s_initialPositionSet)
        setPosition(s_initialPosition);
    else
    	// mouse defaults to middle of the constrained area
        setPosition(Vector2f(screenArea.getWidth() / 2,
                              screenArea.getHeight() / 2));
}

/*************************************************************************
	Destructor
*************************************************************************/
MouseCursor::~MouseCursor(void)
{
    System::getSingleton().getRenderer()->destroyGeometryBuffer(*d_geometry);
}

/*************************************************************************
	Set the current mouse cursor image
*************************************************************************/
void MouseCursor::setImage(const Image* image)
{
    if (image == d_cursorImage)
        return;

	d_cursorImage = image;
    d_cachedGeometryValid = false;

	MouseCursorEventArgs args(this);
	args.image = image;
	onImageChanged(args);
}

/*************************************************************************
	Set the current mouse cursor image
*************************************************************************/
void MouseCursor::setImage(const String& name)
{
	setImage(&ImageManager::getSingleton().get(name));
}

//----------------------------------------------------------------------------//
void MouseCursor::setDefaultImage(const Image* image)
{
    if (image == d_defaultCursorImage)
        return;

	d_defaultCursorImage = image;
    d_cachedGeometryValid = d_cursorImage != 0;

	MouseCursorEventArgs args(this);
	args.image = image;
	onDefaultImageChanged(args);
}

//----------------------------------------------------------------------------//
void MouseCursor::setDefaultImage(const String& name)
{
	setDefaultImage(&ImageManager::getSingleton().get(name));
}

//----------------------------------------------------------------------------//
const Image* MouseCursor::getDefaultImage() const
{
    return d_defaultCursorImage;
}

/*************************************************************************
	Draw the mouse cursor
*************************************************************************/
void MouseCursor::draw(void) const
{
    if (!d_visible || !d_cursorImage)
        return;

    if (!d_cachedGeometryValid)
        cacheGeometry();

    d_geometry->draw();
}

/*************************************************************************
	Set the current mouse cursor position
*************************************************************************/
void MouseCursor::setPosition(const Vector2f& position)
{
    d_position = position;
	constrainPosition();

    d_geometry->setTranslation(Vector3f(d_position.d_x, d_position.d_y, 0));
}

/*************************************************************************
	Offset the mouse cursor position by the deltas specified in 'offset'.
*************************************************************************/
void MouseCursor::offsetPosition(const Vector2f& offset)
{
	d_position.d_x += offset.d_x;
	d_position.d_y += offset.d_y;
	constrainPosition();

    d_geometry->setTranslation(Vector3f(d_position.d_x, d_position.d_y, 0));
}

/*************************************************************************
	Checks the mouse cursor position is within the current 'constrain'
	Rect and adjusts as required.
*************************************************************************/
void MouseCursor::constrainPosition(void)
{
    Rectf absarea(getConstraintArea());

	if (d_position.d_x >= absarea.d_max.d_x)
		d_position.d_x = absarea.d_max.d_x -1;

	if (d_position.d_y >= absarea.d_max.d_y)
		d_position.d_y = absarea.d_max.d_y -1;

	if (d_position.d_y < absarea.d_min.d_y)
		d_position.d_y = absarea.d_min.d_y;

	if (d_position.d_x < absarea.d_min.d_x)
		d_position.d_x = absarea.d_min.d_x;
}

/*************************************************************************
	Set the area that the mouse cursor is constrained to.
*************************************************************************/
void MouseCursor::setConstraintArea(const Rectf* area)
{
    const Rectf renderer_area(Vector2f(0, 0),
                               System::getSingleton().getRenderer()->getDisplaySize());

	if (!area)
	{
		d_constraints.d_min.d_x = cegui_reldim(renderer_area.d_min.d_x / renderer_area.getWidth());
		d_constraints.d_min.d_y = cegui_reldim(renderer_area.d_min.d_y / renderer_area.getHeight());
		d_constraints.d_max.d_x = cegui_reldim(renderer_area.d_max.d_x / renderer_area.getWidth());
		d_constraints.d_max.d_y = cegui_reldim(renderer_area.d_max.d_y / renderer_area.getHeight());
	}
	else
	{
        Rectf finalArea(area->getIntersection(renderer_area));
		d_constraints.d_min.d_x = cegui_reldim(finalArea.d_min.d_x / renderer_area.getWidth());
		d_constraints.d_min.d_y = cegui_reldim(finalArea.d_min.d_y / renderer_area.getHeight());
		d_constraints.d_max.d_x = cegui_reldim(finalArea.d_max.d_x / renderer_area.getWidth());
		d_constraints.d_max.d_y = cegui_reldim(finalArea.d_max.d_y / renderer_area.getHeight());
	}

	constrainPosition();
}

/*************************************************************************
	Set the area that the mouse cursor is constrained to.
*************************************************************************/
void MouseCursor::setUnifiedConstraintArea(const URect* area)
{
    const Rectf renderer_area(Vector2f(0, 0),
                               System::getSingleton().getRenderer()->getDisplaySize());

	if (area)
	{
        d_constraints = *area;
	}
	else
	{
		d_constraints.d_min.d_x = cegui_reldim(renderer_area.d_min.d_x / renderer_area.getWidth());
		d_constraints.d_min.d_y = cegui_reldim(renderer_area.d_min.d_y / renderer_area.getHeight());
		d_constraints.d_max.d_x = cegui_reldim(renderer_area.d_max.d_x / renderer_area.getWidth());
		d_constraints.d_max.d_y = cegui_reldim(renderer_area.d_max.d_y / renderer_area.getHeight());
	}

	constrainPosition();
}

/*************************************************************************
	Set the area that the mouse cursor is constrained to.
*************************************************************************/
Rectf MouseCursor::getConstraintArea(void) const
{
    return Rectf(CoordConverter::asAbsolute(d_constraints, System::getSingleton().getRenderer()->getDisplaySize()));
}

/*************************************************************************
	Set the area that the mouse cursor is constrained to.
*************************************************************************/
const URect& MouseCursor::getUnifiedConstraintArea(void) const
{
    return d_constraints;
}

/*************************************************************************
	Return the current mouse cursor position in display resolution
	independant values.
*************************************************************************/
Vector2f MouseCursor::getDisplayIndependantPosition(void) const
{
    Sizef dsz(System::getSingleton().getRenderer()->getDisplaySize());

    return Vector2f(d_position.d_x / (dsz.d_width - 1.0f),
                 d_position.d_y / (dsz.d_height - 1.0f));
}

//----------------------------------------------------------------------------//
void MouseCursor::notifyDisplaySizeChanged(const Sizef& new_size)
{
    const Rectf screenArea(Vector2f(0, 0), new_size);
    d_geometry->setClippingRegion(screenArea);

    // invalidate to regenerate geometry at (maybe) new size
    d_cachedGeometryValid = false;
}

//----------------------------------------------------------------------------//
void MouseCursor::setExplicitRenderSize(const Sizef& size)
{
    d_customSize = size;
    d_cachedGeometryValid = false;
}

//----------------------------------------------------------------------------//
const Sizef& MouseCursor::getExplicitRenderSize() const
{
    return d_customSize;
}

//----------------------------------------------------------------------------//
void MouseCursor::cacheGeometry() const
{
    d_cachedGeometryValid = true;
    d_geometry->reset();

    // if no image, nothing more to do.
    if (!d_cursorImage)
        return;

    if (d_customSize.d_width != 0.0f || d_customSize.d_height != 0.0f)
    {
        calculateCustomOffset();
        d_cursorImage->render(*d_geometry, d_customOffset, d_customSize);
    }
    else
    {
        d_cursorImage->render(*d_geometry, Vector2f(0, 0));
    }
}

//----------------------------------------------------------------------------//
void MouseCursor::calculateCustomOffset() const
{
    const Sizef sz(d_cursorImage->getRenderedSize());
    const Vector2f offset(d_cursorImage->getRenderedOffset());

    d_customOffset.d_x =
        d_customSize.d_width / sz.d_width * offset.d_x - offset.d_x;
    d_customOffset.d_y =
        d_customSize.d_height / sz.d_height * offset.d_y - offset.d_y;
}

//----------------------------------------------------------------------------//
void MouseCursor::setInitialMousePosition(const Vector2f& position)
{
    s_initialPosition = position;
    s_initialPositionSet = true;
}

//----------------------------------------------------------------------------//
void MouseCursor::invalidate()
{
    d_cachedGeometryValid = false;
}

//----------------------------------------------------------------------------//
void MouseCursor::onImageChanged(MouseCursorEventArgs& e)
{
    fireEvent(EventImageChanged, e, EventNamespace);
}

//----------------------------------------------------------------------------//
void MouseCursor::onDefaultImageChanged(MouseCursorEventArgs& e)
{
    fireEvent(EventDefaultImageChanged, e, EventNamespace);
}

//----------------------------------------------------------------------------//

} // End of  CEGUI namespace section
<|endoftext|>


<commit_before>/*=========================================================================

  Library:   CTK

  Copyright (c) Kitware Inc.

  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.txt

  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.

=========================================================================*/

// Qt includes
#include <QDebug>
#include <QHBoxLayout>

// CTK includes
#include "ctkCoordinatesWidget.h"
#include "ctkDoubleSpinBox.h"

// STD includes
#include <cmath>

//------------------------------------------------------------------------------
ctkCoordinatesWidget::ctkCoordinatesWidget(QWidget* _parent) :QWidget(_parent)
{
  this->Decimals = 3;
  ctkDoubleSpinBox temp;
  this->DecimalsOption = temp.decimalsOption();
  this->SingleStep = 1.;
  this->Minimum = -100000.;
  this->Maximum = 100000.;
  this->Normalized = false;
  this->Dimension = 0;
  this->Coordinates = 0;

  QHBoxLayout* hboxLayout = new QHBoxLayout(this);
  hboxLayout->setContentsMargins(0, 0, 0, 0);
  this->setLayout(hboxLayout);

  this->setDimension(3);
}

//------------------------------------------------------------------------------
ctkCoordinatesWidget::~ctkCoordinatesWidget()
{
  delete [] this->Coordinates;
}

//------------------------------------------------------------------------------
void ctkCoordinatesWidget::addSpinBox()
{
  ctkDoubleSpinBox* spinBox = new ctkDoubleSpinBox(this);
  spinBox->setDecimals(this->Decimals);
  spinBox->setDecimalsOption(this->DecimalsOption);
  spinBox->setSingleStep(this->SingleStep);
  spinBox->setMinimum(this->Minimum);
  spinBox->setMaximum(this->Maximum);
  connect( spinBox, SIGNAL(valueChanged(double)),
           this, SLOT(updateCoordinate(double)));
  // Same number of decimals within the spinboxes.
  connect( spinBox, SIGNAL(decimalsChanged(int)),
           this, SLOT(setDecimals(int)));
  this->layout()->addWidget(spinBox);
}

//------------------------------------------------------------------------------
void ctkCoordinatesWidget::setDimension(int dim)
{
  if (dim < 1)
    {
    return;
    }
  double* newPos = new double[dim];
  if (dim > this->Dimension)
    {
    memcpy(newPos, this->Coordinates, this->Dimension * sizeof(double));
    for (int i = this->Dimension; i < dim; ++i)
      {
      newPos[i] = 0.;
      this->addSpinBox();
      this->LastUserEditedCoordinates.push_back(i);
      }
    }
  else
    {
    memcpy(newPos, this->Coordinates, dim * sizeof(double));
    for (int i = this->Dimension - 1 ; i >= dim; --i)
      {
      QLayoutItem* item = this->layout()->takeAt(i);
      QWidget* widget = item ? item->widget() : 0;
      delete item;
      delete widget;
      this->LastUserEditedCoordinates.pop_back();
      }
    }
  delete [] this->Coordinates;
  this->Coordinates = newPos;
  this->Dimension = dim;

  this->updateGeometry();

  this->updateCoordinates();
}

//------------------------------------------------------------------------------
int ctkCoordinatesWidget::dimension() const
{
  return this->Dimension;
}

//------------------------------------------------------------------------------
void ctkCoordinatesWidget::setMinimum(double min)
{
  for (int i = 0; this->layout()->itemAt(i); ++i)
    {
    QLayoutItem* item = this->layout()->itemAt(i);
    ctkDoubleSpinBox* spinBox = item ? qobject_cast<ctkDoubleSpinBox*>(
      item->widget()) : 0;
    if (spinBox)
      {
      spinBox->setMinimum(min);
      }
    }
  this->Minimum = min;
}

//------------------------------------------------------------------------------
double ctkCoordinatesWidget::minimum() const
{
  return this->Minimum;
}

//------------------------------------------------------------------------------
void ctkCoordinatesWidget::setMaximum(double max)
{
  for (int i = 0; this->layout()->itemAt(i); ++i)
    {
    QLayoutItem* item = this->layout()->itemAt(i);
    ctkDoubleSpinBox* spinBox = item ? qobject_cast<ctkDoubleSpinBox*>(
      item->widget()) : 0;
    if (spinBox)
      {
      spinBox->setMaximum(max);
      }
    }
  this->Maximum = max;
}

//------------------------------------------------------------------------------
double ctkCoordinatesWidget::maximum() const
{
  return this->Maximum;
}

//------------------------------------------------------------------------------
void ctkCoordinatesWidget::setNormalized(bool normalized)
{
  this->Normalized = normalized;
  if (this->Normalized)
    {
    double* normalizedCoordinates = new double[this->Dimension];
    memcpy(normalizedCoordinates, this->Coordinates, sizeof(double)*this->Dimension);
    ctkCoordinatesWidget::normalize(normalizedCoordinates, this->Dimension);

    this->setMinimum(-1.);
    this->setMaximum(1.);

    this->setCoordinates(normalizedCoordinates);
    delete [] normalizedCoordinates;
    }
}

//------------------------------------------------------------------------------
bool ctkCoordinatesWidget::isNormalized() const
{
  return this->Normalized;
}

//------------------------------------------------------------------------------
void ctkCoordinatesWidget::setDecimals(int newDecimals)
{
  this->Decimals = newDecimals;
  for (int i = 0; this->layout()->itemAt(i); ++i)
    {
    QLayoutItem* item = this->layout()->itemAt(i);
    ctkDoubleSpinBox* spinBox = item ? qobject_cast<ctkDoubleSpinBox*>(
      item->widget()) : 0;
    if (spinBox)
      {
      spinBox->setDecimals(newDecimals);
      }
    }
}

//------------------------------------------------------------------------------
int ctkCoordinatesWidget::decimals() const
{
  return this->Decimals;
}

// --------------------------------------------------------------------------
ctkDoubleSpinBox::DecimalsOptions ctkCoordinatesWidget::decimalsOption()const
{
  return this->DecimalsOption;
}

// --------------------------------------------------------------------------
void ctkCoordinatesWidget
::setDecimalsOption(ctkDoubleSpinBox::DecimalsOptions newDecimalsOption)
{
  for (int i = 0; this->layout()->itemAt(i); ++i)
    {
    QLayoutItem* item = this->layout()->itemAt(i);
    ctkDoubleSpinBox* spinBox = item ? qobject_cast<ctkDoubleSpinBox*>(
      item->widget()) : 0;
    if (spinBox)
      {
      spinBox->setDecimalsOption(newDecimalsOption);
      }
    }
  this->DecimalsOption = newDecimalsOption;
}

//------------------------------------------------------------------------------
void ctkCoordinatesWidget::setSingleStep(double step)
{
  for (int i = 0; this->layout()->itemAt(i); ++i)
    {
    QLayoutItem* item = this->layout()->itemAt(i);
    ctkDoubleSpinBox* spinBox = item ? qobject_cast<ctkDoubleSpinBox*>(
      item->widget()) : 0;
    if (spinBox)
      {
      spinBox->setSingleStep(step);
      }
    }
  this->SingleStep = step;
}

//------------------------------------------------------------------------------
double ctkCoordinatesWidget::singleStep() const
{
  return this->SingleStep;
}

//------------------------------------------------------------------------------
void ctkCoordinatesWidget::setCoordinatesAsString(QString _pos)
{
  QStringList posList = _pos.split(',');
  if (posList.count() != this->Dimension)
    {
    return;
    }
  double* newPos = new double[this->Dimension];
  for (int i = 0; i < this->Dimension; ++i)
    {
    newPos[i] = posList[i].toDouble();
    }
  this->setCoordinates(newPos);
  delete [] newPos;
}

//------------------------------------------------------------------------------
QString ctkCoordinatesWidget::coordinatesAsString()const
{
  QString res;
  for (int i = 0; i < this->Dimension; ++i)
    {
    if (i != 0)
      {
      res += ",";
      }
    res += QString::number(this->Coordinates[i]);
    }
  return res;
}

//------------------------------------------------------------------------------
void ctkCoordinatesWidget::setCoordinates(double* coordinates)
{
  for (int i = 0; i < this->Dimension; ++i)
    {
    this->Coordinates[i] = coordinates[i];
    }
  if (this->Normalized)
    {
    this->normalize(this->Coordinates, this->Dimension);
    }
  bool blocked = this->blockSignals(true);
  for (int i = 0; i < this->Dimension; ++i)
    {
    QLayoutItem* item = this->layout()->itemAt(i);
    ctkDoubleSpinBox* spinBox =
      item ? qobject_cast<ctkDoubleSpinBox*>(item->widget()) : 0;
    if (spinBox)
      {
      // we don't want updateCoordinate() to be called.
      // it could mess with the LastUserEditedCoordinates list.
      bool spinBoxSignalWasBlocked = spinBox->blockSignals(true);
      spinBox->setValue(this->Coordinates[i]);
      spinBox->blockSignals(spinBoxSignalWasBlocked);
      }
    }
  this->blockSignals(blocked);
  this->updateCoordinates();
}

//------------------------------------------------------------------------------
void ctkCoordinatesWidget::setCoordinates(double x, double y, double z, double w)
{
  double* coordinates = new double[this->Dimension];
  if (this->Dimension >= 1)
    {
    coordinates[0] = x;
    }
  if (this->Dimension >= 2)
    {
    coordinates[1] = y;
    }
  if (this->Dimension >= 3)
    {
    coordinates[2] = z;
    }
  if (this->Dimension >= 4)
    {
    coordinates[3] = w;
    }
  for (int i = 4; i < this->Dimension; ++i)
    {
    coordinates[i] = this->Coordinates[i];
    }
  this->setCoordinates(coordinates);
  delete [] coordinates;
}

//------------------------------------------------------------------------------
double const * ctkCoordinatesWidget::coordinates()const
{
  return this->Coordinates;
}

//------------------------------------------------------------------------------
void ctkCoordinatesWidget::updateCoordinate(double coordinate)
{
  int element = -1;
  for (int i = 0; i < this->Dimension; ++i)
    {
    QLayoutItem* item = this->layout()->itemAt(i);
    ctkDoubleSpinBox* spinBox =
      item ? qobject_cast<ctkDoubleSpinBox*>(item->widget()) : 0;
    if ( spinBox && spinBox == this->sender())
      {
      this->Coordinates[i] = coordinate;
      element = i;
      }
    }
  Q_ASSERT(element != -1);
  // Update the last edited history by push first the element.
  for (int i = this->Dimension -1; i > 0; --i)
    {
    if (this->LastUserEditedCoordinates[i] == element)
      {
      this->LastUserEditedCoordinates.swap(i,i-1);
      }
    }
  // What is the oldest coordinate to be edited
  int oldestElement = this->LastUserEditedCoordinates.last();

  if (this->isNormalized())
    {
    // We have to ensure the coordinates are normalized.
    double den = 0.;
    double squaredNorm = this->squaredNorm();
    // Old Values xx + yy + zz = 1
    // New values: x'x' + y'y' + z'z' = 1
    // Say we are changing y into y':
    // x'x' + z'z' = 1 - y'y'
    if (oldestElement != -1 &&
        this->Coordinates[oldestElement] != 0.0 &&
        squaredNorm != 0.0)
      {
      // 1) Normalize only with the oldest user edited value
      // The oldest element is z, that means we try to have
      // x = x' (so that the user doesn't loose the edit he just made on the
      // element (x) he edited before this one (y).
      // Let's pose a the coef to multiply z into z' that keeps the norm to 1
      // xx + z'z' = 1 - y'y' (because x = x')
      // xx + azaz = 1 - y'y' (because z' = az)
      // aa*zz = 1 - y'y' - xx
      // a = sqrt( (1 - y'y' - xx) / zz )
      den = (1. - (squaredNorm -
             this->Coordinates[oldestElement] *
             this->Coordinates[oldestElement])) /
              (this->Coordinates[oldestElement] *
               this->Coordinates[oldestElement]);
      if (den > 0.)
        {
        den = sqrt(den);
        }
      }
    // Maybe 1) failed, then give 2) a chance.
    if (den <= 0)
      {
      oldestElement = -1;
      }
    bool mult = true;
    if (oldestElement == -1)
      {
      // 2) Normalize with all the coordinates
      // Let's pose a the coef to multiply x into x' and z into z' that keeps
      // the norm to 1:
      // axax + azaz = 1 - y'y'
      // aa(xx + zz) = 1 - y'y'
      // a = sqrt( (1 - y'y') / (xx + zz) )
      squaredNorm -= coordinate * coordinate;
      if (squaredNorm != 0.0)
        {
        den = sqrt( (1. - coordinate * coordinate) / squaredNorm);
        }
      else if (this->Dimension > 1)
        {
        mult = false;
        den = sqrt((1. - coordinate*coordinate) / (this->Dimension - 1));
        }
      }
    // Normalize coordinates
    double* normalizedCoordinates = new double[this->Dimension];
    for (int i = 0; i < this->Dimension; ++i)
      {
      if ((i != element && oldestElement == -1) ||
          (i == oldestElement && oldestElement != -1))
        {
        normalizedCoordinates[i] = mult ? this->Coordinates[i] * den : den;
        }
      else
        {
        normalizedCoordinates[i] = this->Coordinates[i];
        }
      }
    this->setCoordinates(normalizedCoordinates);
    delete [] normalizedCoordinates;
    }
  else
    {
    emit coordinatesChanged(this->Coordinates);
    }
}

//------------------------------------------------------------------------------
void ctkCoordinatesWidget::updateCoordinates()
{
  for (int i = 0; i < this->Dimension; ++i)
    {
    QLayoutItem* item = this->layout()->itemAt(i);
    ctkDoubleSpinBox* spinBox =
      item ? qobject_cast<ctkDoubleSpinBox*>(item->widget()) : 0;
    if ( spinBox)
      {
      this->Coordinates[i] = spinBox->value();
      }
    }
  emit coordinatesChanged(this->Coordinates);
}

//------------------------------------------------------------------------------
void ctkCoordinatesWidget::normalize()
{
  double* normalizedCoordinates = new double[this->Dimension];
  memcpy(normalizedCoordinates, this->Coordinates,
         sizeof(double) * this->Dimension);
  ctkCoordinatesWidget::normalize(normalizedCoordinates, this->Dimension);
  this->setCoordinates(normalizedCoordinates);
  delete [] normalizedCoordinates;
}

//------------------------------------------------------------------------------
double ctkCoordinatesWidget::normalize(double* coordinates, int dimension)
{
  double den = ctkCoordinatesWidget::norm( coordinates, dimension );
  if ( den != 0.0 )
    {
    for (int i = 0; i < dimension; ++i)
      {
      coordinates[i] /= den;
      }
    }
  return den;
}

//------------------------------------------------------------------------------
double ctkCoordinatesWidget::norm()const
{
  return ctkCoordinatesWidget::norm(this->Coordinates, this->Dimension);
}

//------------------------------------------------------------------------------
double ctkCoordinatesWidget::norm(double* coordinates, int dimension)
{
  return sqrt(ctkCoordinatesWidget::squaredNorm(coordinates, dimension));
}

//------------------------------------------------------------------------------
double ctkCoordinatesWidget::squaredNorm()const
{
  return ctkCoordinatesWidget::squaredNorm(this->Coordinates, this->Dimension);
}

//------------------------------------------------------------------------------
double ctkCoordinatesWidget::squaredNorm(double* coordinates, int dimension)
{
  double sum = 0.;
  for (int i = 0; i < dimension; ++i)
    {
    sum += coordinates[i] * coordinates[i];
    }
  return sum;
}
<commit_msg>Better support of decimals change in ctkCoordinatesWidget<commit_after>/*=========================================================================

  Library:   CTK

  Copyright (c) Kitware Inc.

  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.txt

  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.

=========================================================================*/

// Qt includes
#include <QDebug>
#include <QHBoxLayout>

// CTK includes
#include "ctkCoordinatesWidget.h"
#include "ctkDoubleSpinBox.h"

// STD includes
#include <cmath>

//------------------------------------------------------------------------------
ctkCoordinatesWidget::ctkCoordinatesWidget(QWidget* _parent) :QWidget(_parent)
{
  this->Decimals = 3;
  ctkDoubleSpinBox temp;
  this->DecimalsOption = temp.decimalsOption();
  this->SingleStep = 1.;
  this->Minimum = -100000.;
  this->Maximum = 100000.;
  this->Normalized = false;
  this->Dimension = 0;
  this->Coordinates = 0;

  QHBoxLayout* hboxLayout = new QHBoxLayout(this);
  hboxLayout->setContentsMargins(0, 0, 0, 0);
  this->setLayout(hboxLayout);

  this->setDimension(3);
}

//------------------------------------------------------------------------------
ctkCoordinatesWidget::~ctkCoordinatesWidget()
{
  delete [] this->Coordinates;
}

//------------------------------------------------------------------------------
void ctkCoordinatesWidget::addSpinBox()
{
  ctkDoubleSpinBox* spinBox = new ctkDoubleSpinBox(this);
  spinBox->setDecimals(this->Decimals);
  spinBox->setDecimalsOption(this->DecimalsOption);
  spinBox->setSingleStep(this->SingleStep);
  spinBox->setMinimum(this->Minimum);
  spinBox->setMaximum(this->Maximum);
  connect( spinBox, SIGNAL(valueChanged(double)),
           this, SLOT(updateCoordinate(double)));
  // Same number of decimals within the spinboxes.
  connect( spinBox, SIGNAL(decimalsChanged(int)),
           this, SLOT(setDecimals(int)));
  this->layout()->addWidget(spinBox);
}

//------------------------------------------------------------------------------
void ctkCoordinatesWidget::setDimension(int dim)
{
  if (dim < 1)
    {
    return;
    }
  double* newPos = new double[dim];
  if (dim > this->Dimension)
    {
    memcpy(newPos, this->Coordinates, this->Dimension * sizeof(double));
    for (int i = this->Dimension; i < dim; ++i)
      {
      newPos[i] = 0.;
      this->addSpinBox();
      this->LastUserEditedCoordinates.push_back(i);
      }
    }
  else
    {
    memcpy(newPos, this->Coordinates, dim * sizeof(double));
    for (int i = this->Dimension - 1 ; i >= dim; --i)
      {
      QLayoutItem* item = this->layout()->takeAt(i);
      QWidget* widget = item ? item->widget() : 0;
      delete item;
      delete widget;
      this->LastUserEditedCoordinates.pop_back();
      }
    }
  delete [] this->Coordinates;
  this->Coordinates = newPos;
  this->Dimension = dim;

  this->updateGeometry();

  this->updateCoordinates();
}

//------------------------------------------------------------------------------
int ctkCoordinatesWidget::dimension() const
{
  return this->Dimension;
}

//------------------------------------------------------------------------------
void ctkCoordinatesWidget::setMinimum(double min)
{
  for (int i = 0; this->layout()->itemAt(i); ++i)
    {
    QLayoutItem* item = this->layout()->itemAt(i);
    ctkDoubleSpinBox* spinBox = item ? qobject_cast<ctkDoubleSpinBox*>(
      item->widget()) : 0;
    if (spinBox)
      {
      spinBox->setMinimum(min);
      }
    }
  this->Minimum = min;
}

//------------------------------------------------------------------------------
double ctkCoordinatesWidget::minimum() const
{
  return this->Minimum;
}

//------------------------------------------------------------------------------
void ctkCoordinatesWidget::setMaximum(double max)
{
  for (int i = 0; this->layout()->itemAt(i); ++i)
    {
    QLayoutItem* item = this->layout()->itemAt(i);
    ctkDoubleSpinBox* spinBox = item ? qobject_cast<ctkDoubleSpinBox*>(
      item->widget()) : 0;
    if (spinBox)
      {
      spinBox->setMaximum(max);
      }
    }
  this->Maximum = max;
}

//------------------------------------------------------------------------------
double ctkCoordinatesWidget::maximum() const
{
  return this->Maximum;
}

//------------------------------------------------------------------------------
void ctkCoordinatesWidget::setNormalized(bool normalized)
{
  this->Normalized = normalized;
  if (this->Normalized)
    {
    double* normalizedCoordinates = new double[this->Dimension];
    memcpy(normalizedCoordinates, this->Coordinates, sizeof(double)*this->Dimension);
    ctkCoordinatesWidget::normalize(normalizedCoordinates, this->Dimension);

    this->setMinimum(-1.);
    this->setMaximum(1.);

    this->setCoordinates(normalizedCoordinates);
    delete [] normalizedCoordinates;
    }
}

//------------------------------------------------------------------------------
bool ctkCoordinatesWidget::isNormalized() const
{
  return this->Normalized;
}

//------------------------------------------------------------------------------
void ctkCoordinatesWidget::setDecimals(int newDecimals)
{
  this->Decimals = newDecimals;
  for (int i = 0; this->layout()->itemAt(i); ++i)
    {
    QLayoutItem* item = this->layout()->itemAt(i);
    ctkDoubleSpinBox* spinBox = item ? qobject_cast<ctkDoubleSpinBox*>(
      item->widget()) : 0;
    if (spinBox)
      {
      spinBox->setDecimals(newDecimals);
      }
    }
}

//------------------------------------------------------------------------------
int ctkCoordinatesWidget::decimals() const
{
  return this->Decimals;
}

// --------------------------------------------------------------------------
ctkDoubleSpinBox::DecimalsOptions ctkCoordinatesWidget::decimalsOption()const
{
  return this->DecimalsOption;
}

// --------------------------------------------------------------------------
void ctkCoordinatesWidget
::setDecimalsOption(ctkDoubleSpinBox::DecimalsOptions newDecimalsOption)
{
  for (int i = 0; this->layout()->itemAt(i); ++i)
    {
    QLayoutItem* item = this->layout()->itemAt(i);
    ctkDoubleSpinBox* spinBox = item ? qobject_cast<ctkDoubleSpinBox*>(
      item->widget()) : 0;
    if (spinBox)
      {
      spinBox->setDecimalsOption(newDecimalsOption);
      }
    }
  this->DecimalsOption = newDecimalsOption;
}

//------------------------------------------------------------------------------
void ctkCoordinatesWidget::setSingleStep(double step)
{
  for (int i = 0; this->layout()->itemAt(i); ++i)
    {
    QLayoutItem* item = this->layout()->itemAt(i);
    ctkDoubleSpinBox* spinBox = item ? qobject_cast<ctkDoubleSpinBox*>(
      item->widget()) : 0;
    if (spinBox)
      {
      spinBox->setSingleStep(step);
      }
    }
  this->SingleStep = step;
}

//------------------------------------------------------------------------------
double ctkCoordinatesWidget::singleStep() const
{
  return this->SingleStep;
}

//------------------------------------------------------------------------------
void ctkCoordinatesWidget::setCoordinatesAsString(QString _pos)
{
  QStringList posList = _pos.split(',');
  if (posList.count() != this->Dimension)
    {
    return;
    }
  double* newPos = new double[this->Dimension];
  for (int i = 0; i < this->Dimension; ++i)
    {
    newPos[i] = posList[i].toDouble();
    }
  this->setCoordinates(newPos);
  delete [] newPos;
}

//------------------------------------------------------------------------------
QString ctkCoordinatesWidget::coordinatesAsString()const
{
  QString res;
  for (int i = 0; i < this->Dimension; ++i)
    {
    if (i != 0)
      {
      res += ",";
      }
    res += QString::number(this->Coordinates[i]);
    }
  return res;
}

//------------------------------------------------------------------------------
void ctkCoordinatesWidget::setCoordinates(double* coordinates)
{
  for (int i = 0; i < this->Dimension; ++i)
    {
    this->Coordinates[i] = coordinates[i];
    }
  if (this->Normalized)
    {
    this->normalize(this->Coordinates, this->Dimension);
    }
  bool valuesModified = false;
  int maxDecimals = 0;
  bool blocked = this->blockSignals(true);
  for (int i = 0; i < this->Dimension; ++i)
    {
    QLayoutItem* item = this->layout()->itemAt(i);
    ctkDoubleSpinBox* spinBox =
      item ? qobject_cast<ctkDoubleSpinBox*>(item->widget()) : 0;
    if (spinBox)
      {
      // we don't want updateCoordinate() to be called.
      // it could mess with the LastUserEditedCoordinates list.
      if (spinBox->displayedValue() != this->Coordinates[i])
        {
        bool spinBoxSignalWasBlocked = spinBox->blockSignals(true);
        spinBox->setValue(this->Coordinates[i]);
        spinBox->blockSignals(spinBoxSignalWasBlocked);
        valuesModified = true;
        }
      maxDecimals = qMax(maxDecimals, spinBox->decimals());
      }
    }
  this->blockSignals(blocked);
  if (valuesModified)
    {
    this->setDecimals(maxDecimals);
    this->updateCoordinates();
    }
}

//------------------------------------------------------------------------------
void ctkCoordinatesWidget::setCoordinates(double x, double y, double z, double w)
{
  double* coordinates = new double[this->Dimension];
  if (this->Dimension >= 1)
    {
    coordinates[0] = x;
    }
  if (this->Dimension >= 2)
    {
    coordinates[1] = y;
    }
  if (this->Dimension >= 3)
    {
    coordinates[2] = z;
    }
  if (this->Dimension >= 4)
    {
    coordinates[3] = w;
    }
  for (int i = 4; i < this->Dimension; ++i)
    {
    coordinates[i] = this->Coordinates[i];
    }
  this->setCoordinates(coordinates);
  delete [] coordinates;
}

//------------------------------------------------------------------------------
double const * ctkCoordinatesWidget::coordinates()const
{
  return this->Coordinates;
}

//------------------------------------------------------------------------------
void ctkCoordinatesWidget::updateCoordinate(double coordinate)
{
  int element = -1;
  for (int i = 0; i < this->Dimension; ++i)
    {
    QLayoutItem* item = this->layout()->itemAt(i);
    ctkDoubleSpinBox* spinBox =
      item ? qobject_cast<ctkDoubleSpinBox*>(item->widget()) : 0;
    if ( spinBox && spinBox == this->sender())
      {
      this->Coordinates[i] = coordinate;
      element = i;
      }
    }
  Q_ASSERT(element != -1);
  // Update the last edited history by push first the element.
  for (int i = this->Dimension -1; i > 0; --i)
    {
    if (this->LastUserEditedCoordinates[i] == element)
      {
      this->LastUserEditedCoordinates.swap(i,i-1);
      }
    }
  // What is the oldest coordinate to be edited
  int oldestElement = this->LastUserEditedCoordinates.last();

  if (this->isNormalized())
    {
    // We have to ensure the coordinates are normalized.
    double den = 0.;
    double squaredNorm = this->squaredNorm();
    // Old Values xx + yy + zz = 1
    // New values: x'x' + y'y' + z'z' = 1
    // Say we are changing y into y':
    // x'x' + z'z' = 1 - y'y'
    if (oldestElement != -1 &&
        this->Coordinates[oldestElement] != 0.0 &&
        squaredNorm != 0.0)
      {
      // 1) Normalize only with the oldest user edited value
      // The oldest element is z, that means we try to have
      // x = x' (so that the user doesn't loose the edit he just made on the
      // element (x) he edited before this one (y).
      // Let's pose a the coef to multiply z into z' that keeps the norm to 1
      // xx + z'z' = 1 - y'y' (because x = x')
      // xx + azaz = 1 - y'y' (because z' = az)
      // aa*zz = 1 - y'y' - xx
      // a = sqrt( (1 - y'y' - xx) / zz )
      den = (1. - (squaredNorm -
             this->Coordinates[oldestElement] *
             this->Coordinates[oldestElement])) /
              (this->Coordinates[oldestElement] *
               this->Coordinates[oldestElement]);
      if (den > 0.)
        {
        den = sqrt(den);
        }
      }
    // Maybe 1) failed, then give 2) a chance.
    if (den <= 0)
      {
      oldestElement = -1;
      }
    bool mult = true;
    if (oldestElement == -1)
      {
      // 2) Normalize with all the coordinates
      // Let's pose a the coef to multiply x into x' and z into z' that keeps
      // the norm to 1:
      // axax + azaz = 1 - y'y'
      // aa(xx + zz) = 1 - y'y'
      // a = sqrt( (1 - y'y') / (xx + zz) )
      squaredNorm -= coordinate * coordinate;
      if (squaredNorm != 0.0)
        {
        den = sqrt( (1. - coordinate * coordinate) / squaredNorm);
        }
      else if (this->Dimension > 1)
        {
        mult = false;
        den = sqrt((1. - coordinate*coordinate) / (this->Dimension - 1));
        }
      }
    // Normalize coordinates
    double* normalizedCoordinates = new double[this->Dimension];
    for (int i = 0; i < this->Dimension; ++i)
      {
      if ((i != element && oldestElement == -1) ||
          (i == oldestElement && oldestElement != -1))
        {
        normalizedCoordinates[i] = mult ? this->Coordinates[i] * den : den;
        }
      else
        {
        normalizedCoordinates[i] = this->Coordinates[i];
        }
      }
    this->setCoordinates(normalizedCoordinates);
    delete [] normalizedCoordinates;
    }
  else
    {
    emit coordinatesChanged(this->Coordinates);
    }
}

//------------------------------------------------------------------------------
void ctkCoordinatesWidget::updateCoordinates()
{
  for (int i = 0; i < this->Dimension; ++i)
    {
    QLayoutItem* item = this->layout()->itemAt(i);
    ctkDoubleSpinBox* spinBox =
      item ? qobject_cast<ctkDoubleSpinBox*>(item->widget()) : 0;
    if ( spinBox)
      {
      this->Coordinates[i] = spinBox->value();
      }
    }
  emit coordinatesChanged(this->Coordinates);
}

//------------------------------------------------------------------------------
void ctkCoordinatesWidget::normalize()
{
  double* normalizedCoordinates = new double[this->Dimension];
  memcpy(normalizedCoordinates, this->Coordinates,
         sizeof(double) * this->Dimension);
  ctkCoordinatesWidget::normalize(normalizedCoordinates, this->Dimension);
  this->setCoordinates(normalizedCoordinates);
  delete [] normalizedCoordinates;
}

//------------------------------------------------------------------------------
double ctkCoordinatesWidget::normalize(double* coordinates, int dimension)
{
  double den = ctkCoordinatesWidget::norm( coordinates, dimension );
  if ( den != 0.0 )
    {
    for (int i = 0; i < dimension; ++i)
      {
      coordinates[i] /= den;
      }
    }
  return den;
}

//------------------------------------------------------------------------------
double ctkCoordinatesWidget::norm()const
{
  return ctkCoordinatesWidget::norm(this->Coordinates, this->Dimension);
}

//------------------------------------------------------------------------------
double ctkCoordinatesWidget::norm(double* coordinates, int dimension)
{
  return sqrt(ctkCoordinatesWidget::squaredNorm(coordinates, dimension));
}

//------------------------------------------------------------------------------
double ctkCoordinatesWidget::squaredNorm()const
{
  return ctkCoordinatesWidget::squaredNorm(this->Coordinates, this->Dimension);
}

//------------------------------------------------------------------------------
double ctkCoordinatesWidget::squaredNorm(double* coordinates, int dimension)
{
  double sum = 0.;
  for (int i = 0; i < dimension; ++i)
    {
    sum += coordinates[i] * coordinates[i];
    }
  return sum;
}
<|endoftext|>


<commit_before>/**************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** No Commercial Usage
**
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions
** contained in the Technology Preview License Agreement accompanying
** this package.
**
** GNU Lesser General Public License Usage
**
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, 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.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
**
**************************************************************************/

#include "qtsingleapplication.h"

#include <extensionsystem/pluginmanager.h>
#include <extensionsystem/pluginspec.h>
#include <extensionsystem/iplugin.h>

#include <QtCore/QDir>
#include <QtCore/QUrl>
#include <QtCore/QTextStream>
#include <QtCore/QFileInfo>
#include <QtCore/QDebug>
#include <QtCore/QTimer>
#include <QtCore/QLibraryInfo>
#include <QtCore/QTranslator>
#include <QtCore/QSettings>
#include <QtCore/QVariant>
#include <QtCore/QThreadPool>

#include <QtNetwork/QNetworkProxyFactory>

#include <QtGui/QMessageBox>
#include <QtGui/QApplication>
#include <QtGui/QMainWindow>

#ifdef ENABLE_QT_BREAKPAD
#include <qtsystemexceptionhandler.h>
#endif

enum { OptionIndent = 4, DescriptionIndent = 34 };

static const char *appNameC = "Qt Creator";
static const char *corePluginNameC = "Core";
static const char *fixedOptionsC =
" [OPTION]... [FILE]...\n"
"Options:\n"
"    -help                         Display this help\n"
"    -version                      Display program version\n"
"    -client                       Attempt to connect to already running instance\n"
"    -settingspath <path>          Override the default path where user settings are stored.\n";

static const char *HELP_OPTION1 = "-h";
static const char *HELP_OPTION2 = "-help";
static const char *HELP_OPTION3 = "/h";
static const char *HELP_OPTION4 = "--help";
static const char *VERSION_OPTION = "-version";
static const char *CLIENT_OPTION = "-client";
static const char *SETTINGS_OPTION = "-settingspath";

typedef QList<ExtensionSystem::PluginSpec *> PluginSpecSet;

// Helpers for displaying messages. Note that there is no console on Windows.
#ifdef Q_OS_WIN
// Format as
 HTML
static inline void toHtml(QString &t)
{
    t.replace(QLatin1Char('&'), QLatin1String("&"));
    t.replace(QLatin1Char('<'), QLatin1String("<"));
    t.replace(QLatin1Char('>'), QLatin1String(">"));
    t.insert(0, QLatin1String("
"));
    t.append(QLatin1String("
"));
}

static void displayHelpText(QString t) // No console on Windows.
{
    toHtml(t);
    QMessageBox::information(0, QLatin1String(appNameC), t);
}

static void displayError(const QString &t) // No console on Windows.
{
    QMessageBox::critical(0, QLatin1String(appNameC), t);
}

#else

static void displayHelpText(const QString &t)
{
    qWarning("%s", qPrintable(t));
}

static void displayError(const QString &t)
{
    qCritical("%s", qPrintable(t));
}

#endif

static void printVersion(const ExtensionSystem::PluginSpec *coreplugin,
                         const ExtensionSystem::PluginManager &pm)
{
    QString version;
    QTextStream str(&version);
    str << '\n' << appNameC << ' ' << coreplugin->version()<< " based on Qt " << qVersion() << "\n\n";
    pm.formatPluginVersions(str);
    str << '\n' << coreplugin->copyright() << '\n';
    displayHelpText(version);
}

static void printHelp(const QString &a0, const ExtensionSystem::PluginManager &pm)
{
    QString help;
    QTextStream str(&help);
    str << "Usage: " << a0  << fixedOptionsC;
    ExtensionSystem::PluginManager::formatOptions(str, OptionIndent, DescriptionIndent);
    pm.formatPluginOptions(str,  OptionIndent, DescriptionIndent);
    displayHelpText(help);
}

static inline QString msgCoreLoadFailure(const QString &why)
{
    return QCoreApplication::translate("Application", "Failed to load core: %1").arg(why);
}

static inline QString msgSendArgumentFailed()
{
    return QCoreApplication::translate("Application", "Unable to send command line arguments to the already running instance. It appears to be not responding.");
}

static inline QStringList getPluginPaths()
{
    QStringList rc;
    // Figure out root:  Up one from 'bin'
    QDir rootDir = QApplication::applicationDirPath();
    rootDir.cdUp();
    const QString rootDirPath = rootDir.canonicalPath();
    // 1) "plugins" (Win/Linux)
    QString pluginPath = rootDirPath;
    pluginPath += QLatin1Char('/');
    pluginPath += QLatin1String(IDE_LIBRARY_BASENAME);
    pluginPath += QLatin1Char('/');
    pluginPath += QLatin1String("qtcreator");
    pluginPath += QLatin1Char('/');
    pluginPath += QLatin1String("plugins");
    rc.push_back(pluginPath);
    // 2) "PlugIns" (OS X)
    pluginPath = rootDirPath;
    pluginPath += QLatin1Char('/');
    pluginPath += QLatin1String("PlugIns");
    rc.push_back(pluginPath);
    return rc;
}

#ifdef Q_OS_MAC
#  define SHARE_PATH "/../Resources"
#else
#  define SHARE_PATH "/../share/qtcreator"
#endif

int main(int argc, char **argv)
{
#ifdef Q_OS_MAC
    // increase the number of file that can be opened in Qt Creator.
    struct rlimit rl;
    getrlimit(RLIMIT_NOFILE, &rl);

    rl.rlim_cur = qMin((rlim_t)OPEN_MAX, rl.rlim_max);
    setrlimit(RLIMIT_NOFILE, &rl);
#endif

    SharedTools::QtSingleApplication app((QLatin1String(appNameC)), argc, argv);

    const int threadCount = QThreadPool::globalInstance()->maxThreadCount();
    QThreadPool::globalInstance()->setMaxThreadCount(qMax(4, 2 * threadCount));

#ifdef ENABLE_QT_BREAKPAD
    QtSystemExceptionHandler systemExceptionHandler;
#endif

    QTranslator translator;
    QTranslator qtTranslator;
    QString locale = QLocale::system().name();

    // Manually determine -settingspath command line option
    // We can't use the regular way of the plugin manager, because that needs to parse pluginspecs
    // but the settings path can influence which plugins are enabled
    QString settingsPath;
    QStringList arguments = app.arguments(); /* adapted arguments list is passed to plugin manager later */
    QMutableStringListIterator it(arguments);
    while (it.hasNext()) {
        const QString &arg = it.next();
        if (arg == QLatin1String(SETTINGS_OPTION)) {
            it.remove();
            if (it.hasNext()) {
                settingsPath = QDir::fromNativeSeparators(it.next());
                it.remove();
            }
        }
    }
    if (!settingsPath.isEmpty())
        QSettings::setPath(QSettings::IniFormat, QSettings::UserScope, settingsPath);

    // Must be done before any QSettings class is created
    QSettings::setPath(QSettings::IniFormat, QSettings::SystemScope,
            QCoreApplication::applicationDirPath()+QLatin1String(SHARE_PATH));
    // plugin manager takes control of this settings object
    QSettings *settings = new QSettings(QSettings::IniFormat, QSettings::UserScope,
                                 QLatin1String("Nokia"), QLatin1String("QtCreator"));

    ExtensionSystem::PluginManager pluginManager;
    pluginManager.setFileExtension(QLatin1String("pluginspec"));
    pluginManager.setSettings(settings);

    locale = settings->value("General/OverrideLanguage", locale).toString();
    const QString &creatorTrPath = QCoreApplication::applicationDirPath()
                        + QLatin1String(SHARE_PATH "/translations");
    if (translator.load(QLatin1String("qtcreator_") + locale, creatorTrPath)) {
        const QString &qtTrPath = QLibraryInfo::location(QLibraryInfo::TranslationsPath);
        const QString &qtTrFile = QLatin1String("qt_") + locale;
        // Binary installer puts Qt tr files into creatorTrPath
        if (qtTranslator.load(qtTrFile, qtTrPath) || qtTranslator.load(qtTrFile, creatorTrPath)) {
            app.installTranslator(&translator);
            app.installTranslator(&qtTranslator);
            app.setProperty("qtc_locale", locale);
        } else {
            translator.load(QString()); // unload()
        }
    }

    // Make sure we honor the system's proxy settings
#if defined(Q_OS_UNIX) && !defined(Q_OS_MAC)
    QUrl proxyUrl(QString::fromLatin1(qgetenv("http_proxy")));
    if (proxyUrl.isValid()) {
        QNetworkProxy proxy(QNetworkProxy::HttpProxy, proxyUrl.host(),
                            proxyUrl.port(), proxyUrl.userName(), proxyUrl.password());
        QNetworkProxy::setApplicationProxy(proxy);
    }
#else
    QNetworkProxyFactory::setUseSystemConfiguration(true);
#endif
    // Load
    const QStringList pluginPaths = getPluginPaths();
    pluginManager.setPluginPaths(pluginPaths);

    QMap<QString, QString> foundAppOptions;
    if (arguments.size() > 1) {
        QMap<QString, bool> appOptions;
        appOptions.insert(QLatin1String(HELP_OPTION1), false);
        appOptions.insert(QLatin1String(HELP_OPTION2), false);
        appOptions.insert(QLatin1String(HELP_OPTION3), false);
        appOptions.insert(QLatin1String(HELP_OPTION4), false);
        appOptions.insert(QLatin1String(VERSION_OPTION), false);
        appOptions.insert(QLatin1String(CLIENT_OPTION), false);
        QString errorMessage;
        if (!pluginManager.parseOptions(arguments,
                                        appOptions,
                                        &foundAppOptions,
                                        &errorMessage)) {
            displayError(errorMessage);
            printHelp(QFileInfo(app.applicationFilePath()).baseName(), pluginManager);
            return -1;
        }
    }

    const PluginSpecSet plugins = pluginManager.plugins();
    ExtensionSystem::PluginSpec *coreplugin = 0;
    foreach (ExtensionSystem::PluginSpec *spec, plugins) {
        if (spec->name() == QLatin1String(corePluginNameC)) {
            coreplugin = spec;
            break;
        }
    }
    if (!coreplugin) {
        QString nativePaths = QDir::toNativeSeparators(pluginPaths.join(QLatin1String(",")));
        const QString reason = QCoreApplication::translate("Application", "Could not find 'Core.pluginspec' in %1").arg(nativePaths);
        displayError(msgCoreLoadFailure(reason));
        return 1;
    }
    if (coreplugin->hasError()) {
        displayError(msgCoreLoadFailure(coreplugin->errorString()));
        return 1;
    }
    if (foundAppOptions.contains(QLatin1String(VERSION_OPTION))) {
        printVersion(coreplugin, pluginManager);
        return 0;
    }
    if (foundAppOptions.contains(QLatin1String(HELP_OPTION1))
            || foundAppOptions.contains(QLatin1String(HELP_OPTION2))
            || foundAppOptions.contains(QLatin1String(HELP_OPTION3))
            || foundAppOptions.contains(QLatin1String(HELP_OPTION4))) {
        printHelp(QFileInfo(app.applicationFilePath()).baseName(), pluginManager);
        return 0;
    }

    const bool isFirstInstance = !app.isRunning();
    if (!isFirstInstance && foundAppOptions.contains(QLatin1String(CLIENT_OPTION))) {
        if (!app.sendMessage(pluginManager.serializedArguments())) {
            displayError(msgSendArgumentFailed());
            return -1;
        }
        return 0;
    }

    pluginManager.loadPlugins();
    if (coreplugin->hasError()) {
        displayError(msgCoreLoadFailure(coreplugin->errorString()));
        return 1;
    }
    {
        QStringList errors;
        foreach (ExtensionSystem::PluginSpec *p, pluginManager.plugins())
            // only show errors on startup if plugin is enabled.
            if (p->hasError() && p->isEnabled() && !p->isDisabledIndirectly())
                errors.append(p->name() + "\n" + p->errorString());
        if (!errors.isEmpty())
            QMessageBox::warning(0,
                QCoreApplication::translate("Application", "Qt Creator - Plugin loader messages"),
                errors.join(QString::fromLatin1("\n\n")));
    }

    if (isFirstInstance) {
        // Set up lock and remote arguments for the first instance only.
        // Silently fallback to unconnected instances for any subsequent
        // instances.
        app.initialize();
        QObject::connect(&app, SIGNAL(messageReceived(QString)),
                         &pluginManager, SLOT(remoteArguments(QString)));
    }
    QObject::connect(&app, SIGNAL(fileOpenRequest(QString)), coreplugin->plugin(), SLOT(fileOpenRequest(QString)));

    // shutdown plugin manager on the exit
    QObject::connect(&app, SIGNAL(aboutToQuit()), &pluginManager, SLOT(shutdown()));

#ifdef WITH_TESTS
    // Do this after the event loop has started
    if(pluginManager.runningTests())
        QTimer::singleShot(100, &pluginManager, SLOT(startTests()));
#endif

    return app.exec();
}

<commit_msg>App: Ask the user if creator -client can't send a message<commit_after>/**************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** No Commercial Usage
**
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions
** contained in the Technology Preview License Agreement accompanying
** this package.
**
** GNU Lesser General Public License Usage
**
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, 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.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
**
**************************************************************************/

#include "qtsingleapplication.h"

#include <extensionsystem/pluginmanager.h>
#include <extensionsystem/pluginspec.h>
#include <extensionsystem/iplugin.h>

#include <QtCore/QDir>
#include <QtCore/QUrl>
#include <QtCore/QTextStream>
#include <QtCore/QFileInfo>
#include <QtCore/QDebug>
#include <QtCore/QTimer>
#include <QtCore/QLibraryInfo>
#include <QtCore/QTranslator>
#include <QtCore/QSettings>
#include <QtCore/QVariant>
#include <QtCore/QThreadPool>

#include <QtNetwork/QNetworkProxyFactory>

#include <QtGui/QMessageBox>
#include <QtGui/QApplication>
#include <QtGui/QMainWindow>

#ifdef ENABLE_QT_BREAKPAD
#include <qtsystemexceptionhandler.h>
#endif

enum { OptionIndent = 4, DescriptionIndent = 34 };

static const char *appNameC = "Qt Creator";
static const char *corePluginNameC = "Core";
static const char *fixedOptionsC =
" [OPTION]... [FILE]...\n"
"Options:\n"
"    -help                         Display this help\n"
"    -version                      Display program version\n"
"    -client                       Attempt to connect to already running instance\n"
"    -settingspath <path>          Override the default path where user settings are stored.\n";

static const char *HELP_OPTION1 = "-h";
static const char *HELP_OPTION2 = "-help";
static const char *HELP_OPTION3 = "/h";
static const char *HELP_OPTION4 = "--help";
static const char *VERSION_OPTION = "-version";
static const char *CLIENT_OPTION = "-client";
static const char *SETTINGS_OPTION = "-settingspath";

typedef QList<ExtensionSystem::PluginSpec *> PluginSpecSet;

// Helpers for displaying messages. Note that there is no console on Windows.
#ifdef Q_OS_WIN
// Format as
 HTML
static inline void toHtml(QString &t)
{
    t.replace(QLatin1Char('&'), QLatin1String("&"));
    t.replace(QLatin1Char('<'), QLatin1String("<"));
    t.replace(QLatin1Char('>'), QLatin1String(">"));
    t.insert(0, QLatin1String("
"));
    t.append(QLatin1String("
"));
}

static void displayHelpText(QString t) // No console on Windows.
{
    toHtml(t);
    QMessageBox::information(0, QLatin1String(appNameC), t);
}

static void displayError(const QString &t) // No console on Windows.
{
    QMessageBox::critical(0, QLatin1String(appNameC), t);
}

#else

static void displayHelpText(const QString &t)
{
    qWarning("%s", qPrintable(t));
}

static void displayError(const QString &t)
{
    qCritical("%s", qPrintable(t));
}

#endif

static void printVersion(const ExtensionSystem::PluginSpec *coreplugin,
                         const ExtensionSystem::PluginManager &pm)
{
    QString version;
    QTextStream str(&version);
    str << '\n' << appNameC << ' ' << coreplugin->version()<< " based on Qt " << qVersion() << "\n\n";
    pm.formatPluginVersions(str);
    str << '\n' << coreplugin->copyright() << '\n';
    displayHelpText(version);
}

static void printHelp(const QString &a0, const ExtensionSystem::PluginManager &pm)
{
    QString help;
    QTextStream str(&help);
    str << "Usage: " << a0  << fixedOptionsC;
    ExtensionSystem::PluginManager::formatOptions(str, OptionIndent, DescriptionIndent);
    pm.formatPluginOptions(str,  OptionIndent, DescriptionIndent);
    displayHelpText(help);
}

static inline QString msgCoreLoadFailure(const QString &why)
{
    return QCoreApplication::translate("Application", "Failed to load core: %1").arg(why);
}

static inline int askMsgSendFailed()
{
    return QMessageBox::question(0, QApplication::translate("Application","Could not send message"),
                                 QCoreApplication::translate("Application", "Unable to send command line arguments to the already running instance."
                                                             "It appears to be not responding. Do you want to start a new instance of Creator?"),
                                 QMessageBox::Yes | QMessageBox::No | QMessageBox::Retry,
                                 QMessageBox::Retry);
}

static inline QStringList getPluginPaths()
{
    QStringList rc;
    // Figure out root:  Up one from 'bin'
    QDir rootDir = QApplication::applicationDirPath();
    rootDir.cdUp();
    const QString rootDirPath = rootDir.canonicalPath();
    // 1) "plugins" (Win/Linux)
    QString pluginPath = rootDirPath;
    pluginPath += QLatin1Char('/');
    pluginPath += QLatin1String(IDE_LIBRARY_BASENAME);
    pluginPath += QLatin1Char('/');
    pluginPath += QLatin1String("qtcreator");
    pluginPath += QLatin1Char('/');
    pluginPath += QLatin1String("plugins");
    rc.push_back(pluginPath);
    // 2) "PlugIns" (OS X)
    pluginPath = rootDirPath;
    pluginPath += QLatin1Char('/');
    pluginPath += QLatin1String("PlugIns");
    rc.push_back(pluginPath);
    return rc;
}

#ifdef Q_OS_MAC
#  define SHARE_PATH "/../Resources"
#else
#  define SHARE_PATH "/../share/qtcreator"
#endif

int main(int argc, char **argv)
{
#ifdef Q_OS_MAC
    // increase the number of file that can be opened in Qt Creator.
    struct rlimit rl;
    getrlimit(RLIMIT_NOFILE, &rl);

    rl.rlim_cur = qMin((rlim_t)OPEN_MAX, rl.rlim_max);
    setrlimit(RLIMIT_NOFILE, &rl);
#endif

    SharedTools::QtSingleApplication app((QLatin1String(appNameC)), argc, argv);

    const int threadCount = QThreadPool::globalInstance()->maxThreadCount();
    QThreadPool::globalInstance()->setMaxThreadCount(qMax(4, 2 * threadCount));

#ifdef ENABLE_QT_BREAKPAD
    QtSystemExceptionHandler systemExceptionHandler;
#endif

    QTranslator translator;
    QTranslator qtTranslator;
    QString locale = QLocale::system().name();

    // Manually determine -settingspath command line option
    // We can't use the regular way of the plugin manager, because that needs to parse pluginspecs
    // but the settings path can influence which plugins are enabled
    QString settingsPath;
    QStringList arguments = app.arguments(); /* adapted arguments list is passed to plugin manager later */
    QMutableStringListIterator it(arguments);
    while (it.hasNext()) {
        const QString &arg = it.next();
        if (arg == QLatin1String(SETTINGS_OPTION)) {
            it.remove();
            if (it.hasNext()) {
                settingsPath = QDir::fromNativeSeparators(it.next());
                it.remove();
            }
        }
    }
    if (!settingsPath.isEmpty())
        QSettings::setPath(QSettings::IniFormat, QSettings::UserScope, settingsPath);

    // Must be done before any QSettings class is created
    QSettings::setPath(QSettings::IniFormat, QSettings::SystemScope,
            QCoreApplication::applicationDirPath()+QLatin1String(SHARE_PATH));
    // plugin manager takes control of this settings object
    QSettings *settings = new QSettings(QSettings::IniFormat, QSettings::UserScope,
                                 QLatin1String("Nokia"), QLatin1String("QtCreator"));

    ExtensionSystem::PluginManager pluginManager;
    pluginManager.setFileExtension(QLatin1String("pluginspec"));
    pluginManager.setSettings(settings);

    locale = settings->value("General/OverrideLanguage", locale).toString();
    const QString &creatorTrPath = QCoreApplication::applicationDirPath()
                        + QLatin1String(SHARE_PATH "/translations");
    if (translator.load(QLatin1String("qtcreator_") + locale, creatorTrPath)) {
        const QString &qtTrPath = QLibraryInfo::location(QLibraryInfo::TranslationsPath);
        const QString &qtTrFile = QLatin1String("qt_") + locale;
        // Binary installer puts Qt tr files into creatorTrPath
        if (qtTranslator.load(qtTrFile, qtTrPath) || qtTranslator.load(qtTrFile, creatorTrPath)) {
            app.installTranslator(&translator);
            app.installTranslator(&qtTranslator);
            app.setProperty("qtc_locale", locale);
        } else {
            translator.load(QString()); // unload()
        }
    }

    // Make sure we honor the system's proxy settings
#if defined(Q_OS_UNIX) && !defined(Q_OS_MAC)
    QUrl proxyUrl(QString::fromLatin1(qgetenv("http_proxy")));
    if (proxyUrl.isValid()) {
        QNetworkProxy proxy(QNetworkProxy::HttpProxy, proxyUrl.host(),
                            proxyUrl.port(), proxyUrl.userName(), proxyUrl.password());
        QNetworkProxy::setApplicationProxy(proxy);
    }
#else
    QNetworkProxyFactory::setUseSystemConfiguration(true);
#endif
    // Load
    const QStringList pluginPaths = getPluginPaths();
    pluginManager.setPluginPaths(pluginPaths);

    QMap<QString, QString> foundAppOptions;
    if (arguments.size() > 1) {
        QMap<QString, bool> appOptions;
        appOptions.insert(QLatin1String(HELP_OPTION1), false);
        appOptions.insert(QLatin1String(HELP_OPTION2), false);
        appOptions.insert(QLatin1String(HELP_OPTION3), false);
        appOptions.insert(QLatin1String(HELP_OPTION4), false);
        appOptions.insert(QLatin1String(VERSION_OPTION), false);
        appOptions.insert(QLatin1String(CLIENT_OPTION), false);
        QString errorMessage;
        if (!pluginManager.parseOptions(arguments,
                                        appOptions,
                                        &foundAppOptions,
                                        &errorMessage)) {
            displayError(errorMessage);
            printHelp(QFileInfo(app.applicationFilePath()).baseName(), pluginManager);
            return -1;
        }
    }

    const PluginSpecSet plugins = pluginManager.plugins();
    ExtensionSystem::PluginSpec *coreplugin = 0;
    foreach (ExtensionSystem::PluginSpec *spec, plugins) {
        if (spec->name() == QLatin1String(corePluginNameC)) {
            coreplugin = spec;
            break;
        }
    }
    if (!coreplugin) {
        QString nativePaths = QDir::toNativeSeparators(pluginPaths.join(QLatin1String(",")));
        const QString reason = QCoreApplication::translate("Application", "Could not find 'Core.pluginspec' in %1").arg(nativePaths);
        displayError(msgCoreLoadFailure(reason));
        return 1;
    }
    if (coreplugin->hasError()) {
        displayError(msgCoreLoadFailure(coreplugin->errorString()));
        return 1;
    }
    if (foundAppOptions.contains(QLatin1String(VERSION_OPTION))) {
        printVersion(coreplugin, pluginManager);
        return 0;
    }
    if (foundAppOptions.contains(QLatin1String(HELP_OPTION1))
            || foundAppOptions.contains(QLatin1String(HELP_OPTION2))
            || foundAppOptions.contains(QLatin1String(HELP_OPTION3))
            || foundAppOptions.contains(QLatin1String(HELP_OPTION4))) {
        printHelp(QFileInfo(app.applicationFilePath()).baseName(), pluginManager);
        return 0;
    }

    const bool isFirstInstance = !app.isRunning();
    if (!isFirstInstance && foundAppOptions.contains(QLatin1String(CLIENT_OPTION))) {
        if (app.sendMessage(pluginManager.serializedArguments()))
            return 0;

        // Message could not be send, maybe it was in the process of quitting
        if (app.isRunning()) {
            // Nah app is still running, ask the user
            int button = askMsgSendFailed();
            while(button == QMessageBox::Retry) {
                if (app.sendMessage(pluginManager.serializedArguments()))
                    return 0;
                if (!app.isRunning()) // App quit while we were trying so start a new creator
                    button = QMessageBox::Yes;
                else
                    button = askMsgSendFailed();
            }
            if (button == QMessageBox::No)
                return -1;
        }
    }

    pluginManager.loadPlugins();
    if (coreplugin->hasError()) {
        displayError(msgCoreLoadFailure(coreplugin->errorString()));
        return 1;
    }
    {
        QStringList errors;
        foreach (ExtensionSystem::PluginSpec *p, pluginManager.plugins())
            // only show errors on startup if plugin is enabled.
            if (p->hasError() && p->isEnabled() && !p->isDisabledIndirectly())
                errors.append(p->name() + "\n" + p->errorString());
        if (!errors.isEmpty())
            QMessageBox::warning(0,
                QCoreApplication::translate("Application", "Qt Creator - Plugin loader messages"),
                errors.join(QString::fromLatin1("\n\n")));
    }

    if (isFirstInstance) {
        // Set up lock and remote arguments for the first instance only.
        // Silently fallback to unconnected instances for any subsequent
        // instances.
        app.initialize();
        QObject::connect(&app, SIGNAL(messageReceived(QString)),
                         &pluginManager, SLOT(remoteArguments(QString)));
    }
    QObject::connect(&app, SIGNAL(fileOpenRequest(QString)), coreplugin->plugin(), SLOT(fileOpenRequest(QString)));

    // shutdown plugin manager on the exit
    QObject::connect(&app, SIGNAL(aboutToQuit()), &pluginManager, SLOT(shutdown()));

#ifdef WITH_TESTS
    // Do this after the event loop has started
    if(pluginManager.runningTests())
        QTimer::singleShot(100, &pluginManager, SLOT(startTests()));
#endif

    return app.exec();
}

<|endoftext|>


<commit_before><commit_msg>ui/gfx: Add unittests for RemoveWindowsStyleAccelerators() function.<commit_after><|endoftext|>


<commit_before>#include "surfacerenderer.h"

#include <QOpenGLFunctions>

SurfaceRenderer::SurfaceRenderer(QOpenGLContext *context, QWindow *surface)
    : m_context(context)
    , m_surface(surface)
{
    const char *textureVertexProgram =
            "uniform highp mat4 matrix;\n"
            "attribute highp vec3 vertexCoordEntry;\n"
            "attribute highp vec2 textureCoordEntry;\n"
            "varying highp vec2 textureCoord;\n"
            "void main() {\n"
            "   textureCoord = textureCoordEntry;\n"
            "   gl_Position = matrix * vec4(vertexCoordEntry, 1);\n"
            "}\n";

    const char *textureFragmentProgram =
            "uniform sampler2D texture;\n"
            "varying highp vec2 textureCoord;\n"
            "void main() {\n"
            "   gl_FragColor = texture2D(texture, textureCoord);\n"
            "}\n";

    m_context->makeCurrent(m_surface);

    //Enable transparent windows
    glEnable(GL_BLEND);
    glBlendFunc (GL_ONE,GL_ONE_MINUS_SRC_ALPHA);

    //May need to manually set context here
    m_shaderProgram = new QGLShaderProgram();

    m_shaderProgram->addShaderFromSourceCode(QGLShader::Vertex, textureVertexProgram);
    m_shaderProgram->addShaderFromSourceCode(QGLShader::Fragment, textureFragmentProgram);
    m_shaderProgram->link();
    m_shaderProgram->bind();

    m_vertexCoordEntry = m_shaderProgram->attributeLocation("vertexCoordEntry");
    m_textureCoordEntry = m_shaderProgram->attributeLocation("textureCoordEntry");
    m_matrixLocation = m_shaderProgram->uniformLocation("matrix");

}

void SurfaceRenderer::drawImage(const QImage &image, const QRectF &geometry)
{
    if (image.isNull())
        return;
    drawTexture(textureFromImage(image), geometry);
}

void SurfaceRenderer::drawTexture(int textureId, const QRectF &geometry, int depth)
{
    GLfloat zValue = depth / 1000.0f;
    //Set Texture and Vertex coordinates
    GLfloat textureCoordinates[] = { 0, 0,
                                     1, 0,
                                     1, 1,
                                     0, 1
                                   };

    GLfloat vertexCoordinates[] = { geometry.left(), geometry.top(), zValue,
                                    geometry.right(), geometry.top(), zValue,
                                    geometry.right(), geometry.bottom(), zValue,
                                    geometry.left(), geometry.bottom(), zValue
                                  };

    //Set matrix to transfrom geometry values into gl coordinate space.
    m_transformMatrix.setToIdentity();
    m_transformMatrix.scale( 2.0f / m_surface->geometry().width(), 2.0f / m_surface->geometry().height());
    m_transformMatrix.translate(-m_surface->geometry().width() / 2.0f, -m_surface->geometry().height() / 2.0f);

    m_shaderProgram->bind();

    //attach the data!
    m_context->functions()->glEnableVertexAttribArray(m_vertexCoordEntry);
    m_context->functions()->glEnableVertexAttribArray(m_textureCoordEntry);

    m_context->functions()->glVertexAttribPointer(m_vertexCoordEntry, 3, GL_FLOAT, GL_FALSE, 0, vertexCoordinates);
    m_context->functions()->glVertexAttribPointer(m_textureCoordEntry, 2, GL_FLOAT, GL_FALSE, 0, textureCoordinates);
    m_shaderProgram->setUniformValue(m_matrixLocation, m_transformMatrix);

    glBindTexture(GL_TEXTURE_2D, textureId);

    glDrawArrays(GL_TRIANGLE_FAN, 0, 4);

    glBindTexture(GL_TEXTURE_2D, 0);

    m_context->functions()->glDisableVertexAttribArray(m_vertexCoordEntry);
    m_context->functions()->glDisableVertexAttribArray(m_textureCoordEntry);
    m_shaderProgram->release();
}

GLuint SurfaceRenderer::textureFromImage(const QImage &image)
{
    //TODO: Replace this line
    QImage convertedImage = QGLWidget::convertToGLFormat(image);

    GLuint textureId;
    //Copy QImage data to Texture
    glGenTextures(1, &textureId);
    glBindTexture(GL_TEXTURE_2D, textureId);
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, convertedImage.width(), convertedImage.height(), 0, GL_RGBA, GL_UNSIGNED_BYTE, convertedImage.constBits());

    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);

    return textureId;
}
<commit_msg>Fix mirrored Y coordinates in qwindow-compositor.<commit_after>#include "surfacerenderer.h"

#include <QOpenGLFunctions>

SurfaceRenderer::SurfaceRenderer(QOpenGLContext *context, QWindow *surface)
    : m_context(context)
    , m_surface(surface)
{
    const char *textureVertexProgram =
            "uniform highp mat4 matrix;\n"
            "attribute highp vec3 vertexCoordEntry;\n"
            "attribute highp vec2 textureCoordEntry;\n"
            "varying highp vec2 textureCoord;\n"
            "void main() {\n"
            "   textureCoord = textureCoordEntry;\n"
            "   gl_Position = matrix * vec4(vertexCoordEntry, 1);\n"
            "}\n";

    const char *textureFragmentProgram =
            "uniform sampler2D texture;\n"
            "varying highp vec2 textureCoord;\n"
            "void main() {\n"
            "   gl_FragColor = texture2D(texture, textureCoord);\n"
            "}\n";

    m_context->makeCurrent(m_surface);

    //Enable transparent windows
    glEnable(GL_BLEND);
    glBlendFunc (GL_ONE,GL_ONE_MINUS_SRC_ALPHA);

    //May need to manually set context here
    m_shaderProgram = new QGLShaderProgram();

    m_shaderProgram->addShaderFromSourceCode(QGLShader::Vertex, textureVertexProgram);
    m_shaderProgram->addShaderFromSourceCode(QGLShader::Fragment, textureFragmentProgram);
    m_shaderProgram->link();
    m_shaderProgram->bind();

    m_vertexCoordEntry = m_shaderProgram->attributeLocation("vertexCoordEntry");
    m_textureCoordEntry = m_shaderProgram->attributeLocation("textureCoordEntry");
    m_matrixLocation = m_shaderProgram->uniformLocation("matrix");

}

void SurfaceRenderer::drawImage(const QImage &image, const QRectF &geometry)
{
    if (image.isNull())
        return;
    drawTexture(textureFromImage(image), geometry);
}

void SurfaceRenderer::drawTexture(int textureId, const QRectF &geometry, int depth)
{
    GLfloat zValue = depth / 1000.0f;
    //Set Texture and Vertex coordinates
    GLfloat textureCoordinates[] = { 0, 1,
                                     1, 1,
                                     1, 0,
                                     0, 0
                                   };

    GLfloat vertexCoordinates[] = { geometry.left(), geometry.top(), zValue,
                                    geometry.right(), geometry.top(), zValue,
                                    geometry.right(), geometry.bottom(), zValue,
                                    geometry.left(), geometry.bottom(), zValue
                                  };

    //Set matrix to transfrom geometry values into gl coordinate space.
    m_transformMatrix.setToIdentity();
    m_transformMatrix.scale( 2.0f / m_surface->geometry().width(), -2.0f / m_surface->geometry().height());
    m_transformMatrix.translate(-m_surface->geometry().width() / 2.0f, -m_surface->geometry().height() / 2.0f);

    m_shaderProgram->bind();

    //attach the data!
    m_context->functions()->glEnableVertexAttribArray(m_vertexCoordEntry);
    m_context->functions()->glEnableVertexAttribArray(m_textureCoordEntry);

    m_context->functions()->glVertexAttribPointer(m_vertexCoordEntry, 3, GL_FLOAT, GL_FALSE, 0, vertexCoordinates);
    m_context->functions()->glVertexAttribPointer(m_textureCoordEntry, 2, GL_FLOAT, GL_FALSE, 0, textureCoordinates);
    m_shaderProgram->setUniformValue(m_matrixLocation, m_transformMatrix);

    glBindTexture(GL_TEXTURE_2D, textureId);

    glDrawArrays(GL_TRIANGLE_FAN, 0, 4);

    glBindTexture(GL_TEXTURE_2D, 0);

    m_context->functions()->glDisableVertexAttribArray(m_vertexCoordEntry);
    m_context->functions()->glDisableVertexAttribArray(m_textureCoordEntry);
    m_shaderProgram->release();
}

GLuint SurfaceRenderer::textureFromImage(const QImage &image)
{
    //TODO: Replace this line
    QImage convertedImage = QGLWidget::convertToGLFormat(image);

    GLuint textureId;
    //Copy QImage data to Texture
    glGenTextures(1, &textureId);
    glBindTexture(GL_TEXTURE_2D, textureId);
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, convertedImage.width(), convertedImage.height(), 0, GL_RGBA, GL_UNSIGNED_BYTE, convertedImage.constBits());

    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);

    return textureId;
}
<|endoftext|>