Go back to Richel Bilderbeek's homepage.

Go back to Richel Bilderbeek's C++ page.

 

 

 

 

 

(C++) QtRoundedRectItem

 

QtQt CreatorLubuntu

 

QtRoundedEditRectItem is a Qt QGraphicsItem class that displays a rounded rectangle.

Technical facts

 

 

 

 

 

 

./CppQtRoundedRectItem/CppQtRoundedRectItem.pri

 

INCLUDEPATH += \
    ../../Classes/CppQtRoundedRectItem

SOURCES += \
    ../../Classes/CppQtRoundedRectItem/qtroundedrectitem.cpp \
    ../../Classes/CppQtRoundedRectItem/qtroundedrectitemdialog.cpp \
    ../../Classes/CppQtRoundedRectItem/qtroundedrectitem_test.cpp

HEADERS  += \
    ../../Classes/CppQtRoundedRectItem/qtroundedrectitem.h \
    ../../Classes/CppQtRoundedRectItem/qtroundedrectitemdialog.h

OTHER_FILES += \
    ../../Classes/CppQtRoundedRectItem/Licence.txt

FORMS += \
    ../../Classes/CppQtRoundedRectItem/qtroundedrectitemdialog.ui

 

 

 

 

 

./CppQtRoundedRectItem/qtroundedrectitem.h

 

//---------------------------------------------------------------------------
/*
QtRoundedRectItem, rectangular-shaped QGraphicsItem
Copyright (C) 2012-2015 Richel Bilderbeek and Claudio Tiecher

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

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program.If not, see <http://www.gnu.org/licenses/>.
*/
//---------------------------------------------------------------------------
//From http://www.richelbilderbeek.nl/CppQtRoundedRectItem.htm
//---------------------------------------------------------------------------
#ifndef QTROUNDEDRECTITEM_H
#define QTROUNDEDRECTITEM_H

#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Weffc++"
#pragma GCC diagnostic ignored "-Wunused-local-typedefs"
#pragma GCC diagnostic ignored "-Wunused-but-set-parameter"
#include <iosfwd>
#include <boost/signals2.hpp>

#include <QGraphicsRectItem>
#include <QPen>
#pragma GCC diagnostic pop

namespace ribi {

///Rounded rectangle item
/*

     _______
  A /       \           ______
   /  _____  \         / _____ \
  |  |B    |  |       | |B    | |
  |  |  C  |  |       | |  C  | |
  |  |_____|  |       | |_____| |
   \         /         \_______/
    \_______/

A: Outer rectangle, includes thickest pen width
B: Inner rectangle, excluded thickest pen width
C: The position if the QtRoundedRectItem
If the rectangle is displayed with a thinner pen, A and B remain at the same relative position

QGraphicsRectItem::rect must be of the form (-0.5*width,-0.5*height,0.5*width,0.5*height)
so that (0.0,0.0) is its origin

Comparison of Qt and this class:

   rect():                 GetOuterRect()

        |                        |
        |                        |
     ---+---                  ---+---
    /   |   \                /   |   \
--+----O----+--          --+----C----+--
    \   |   /                \   |   /
     ---+---                  ---+---
        |                        |
        |                        |


   where rect().center    where GetOuterRect().center
     == QPointF(0.0,0.0)   == GetPos()

   pos():
     (1.2,3.4)


*/
class QtRoundedRectItem : public QGraphicsRectItem
{
  //Q_OBJECT //Cannot make this a QObject???

  public:
  explicit QtRoundedRectItem(QGraphicsItem *parent = 0);

  virtual ~QtRoundedRectItem() noexcept;

  ///Get the pen by which the contour is drawn
  const QPen& GetContourPen() const noexcept { return m_contour_pen; }

  ///Get the pen by which focus is indicated
  const QPen& GetFocusPen() const noexcept { return m_focus_pen; }

  const QPen& GetCurrentPen() const noexcept { return GetIsSelected() ? m_focus_pen : m_contour_pen; }

  bool GetIsSelected() const noexcept { return isSelected() || hasFocus(); }

  QPointF GetCenterPos() const noexcept { return QGraphicsRectItem::pos(); }
  double GetCenterX() const noexcept { return GetCenterPos().x(); }
  double GetCenterY() const noexcept { return GetCenterPos().y(); }

  double GetInnerHeight() const noexcept;

  ///Gets the rectangle within/excluding the pen, use GetRawRect the get the raw QRectF
  QRectF GetInnerRect() const noexcept;
  double GetInnerWidth() const noexcept;

  double GetOuterHeight() const noexcept { return QGraphicsRectItem::rect().height(); }
  ///Gets the rectangle with/including the pen, use GetRawRect the get the raw QRectF
  QRectF GetOuterRect() const noexcept;
  double GetOuterWidth() const noexcept { return QGraphicsRectItem::rect().width(); }


  ///Get the rounded rect corner x radius
  double GetRadiusX() const noexcept{ return m_radius_x; }

  ///Get the rounded rect corner y radius
  double GetRadiusY() const noexcept{ return m_radius_y; }

  ///Obtain the version of this class
  static std::string GetVersion() noexcept;

  ///Obtain the version history of this class
  static std::vector<std::string> GetVersionHistory() noexcept;

  void SetCenterPos(const double x,const double y) noexcept { SetCenterX(x); SetCenterY(y); }
  void SetCenterPos(const QPointF& pos) noexcept { SetCenterPos(pos.x(),pos.y()); }
  void SetCenterX(const double x) noexcept;
  void SetCenterY(const double y) noexcept;

  void SetContourPen(const QPen& pen) noexcept; ///Set the pen by which the contours are normally drawn, default value: QPen(Qt::DashLine)
  void SetFocusPen(const QPen& pen) noexcept; ///Set the pen by which focus is indicated, default value: QPen(Qt::DashLine)

  void SetInnerHeight(const double width) noexcept;
  void SetInnerWidth(const double width) noexcept;

  void SetOuterHeight(const double width) noexcept;
  void SetOuterWidth(const double width) noexcept;

  void SetRadiusX(const double radius_x) noexcept;
  void SetRadiusY(const double radius_y) noexcept;

  mutable boost::signals2::signal<void (QtRoundedRectItem*)> m_signal_contour_pen_changed;
  mutable boost::signals2::signal<void (QtRoundedRectItem*)> m_signal_focus_pen_changed;
  mutable boost::signals2::signal<void (QtRoundedRectItem*)> m_signal_height_changed;
  mutable boost::signals2::signal<void (QtRoundedRectItem*)> m_signal_pos_changed;
  mutable boost::signals2::signal<void (QtRoundedRectItem*)> m_signal_radius_x_changed;
  mutable boost::signals2::signal<void (QtRoundedRectItem*)> m_signal_radius_y_changed;
  mutable boost::signals2::signal<void (QtRoundedRectItem*)> m_signal_width_changed;

  ///Signal emitted when this item has moved
  //mutable boost::signals2::signal<void ()> m_signal_request_scene_update;

protected:

  virtual void dragEnterEvent(QGraphicsSceneDragDropEvent *event) noexcept override;
  virtual void dragLeaveEvent(QGraphicsSceneDragDropEvent *event) noexcept override;
  virtual void dragMoveEvent(QGraphicsSceneDragDropEvent *event) noexcept override;
  virtual void mouseMoveEvent(QGraphicsSceneMouseEvent *event) noexcept override;
  virtual void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) noexcept override;

  private:
  ///The pen by which the contour is drawn
  QPen m_contour_pen;

  ///The pen by which focus is indicated
  QPen m_focus_pen;

  ///The rounded rect corner x radius
  double m_radius_x;

  ///The rounded rect corner y radius
  double m_radius_y;


  ///To make it private, use GetPos instead
  QPointF pos() = delete;
  ///To make it private, use GetRect instead

  QRectF rect() = delete; //#244
  ///To make it private, use SetPos instead
  void setPos(qreal x, qreal y) = delete;
  void setPos(const QPointF&) = delete;
  ///To make it private, use SetRoundedRect instead
  void setRect(const double,const double,const double,const double) = delete;
  void setRect(const QRectF&) = delete;

  #ifndef NDEBUG
  static void Test() noexcept;
  #endif
};

std::ostream& operator<<(std::ostream& os,const QtRoundedRectItem& item) noexcept;

bool operator==(const QtRoundedRectItem& lhs, const QtRoundedRectItem& rhs) noexcept;
bool operator!=(const QtRoundedRectItem& lhs, const QtRoundedRectItem& rhs) noexcept;

} //~namespace ribi

#endif // QTROUNDEDRECTITEM_H

 

 

 

 

 

./CppQtRoundedRectItem/qtroundedrectitem.cpp

 

//---------------------------------------------------------------------------
/*
QtRoundedRectItem, rectangular-shaped QGraphicsItem
Copyright (C) 2012-2015 Richel Bilderbeek and Claudio Tiecher

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

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program.If not, see <http://www.gnu.org/licenses/>.
*/
//---------------------------------------------------------------------------
//From http://www.richelbilderbeek.nl/CppQtRoundedRectItem.htm
//---------------------------------------------------------------------------
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Weffc++"
#pragma GCC diagnostic ignored "-Wunused-but-set-parameter"
#pragma GCC diagnostic ignored "-Wunused-local-typedefs"
#include "qtroundedrectitem.h"

#include <cassert>
#include <QPainter>
#include <QGraphicsScene>
#include <QKeyEvent>

#include "trace.h"
#pragma GCC diagnostic pop

ribi::QtRoundedRectItem::QtRoundedRectItem(QGraphicsItem *parent)
: QGraphicsRectItem(parent),
   m_signal_contour_pen_changed{},
   m_signal_focus_pen_changed{},
   m_signal_height_changed{},
   m_signal_pos_changed{},
   m_signal_radius_x_changed{},
   m_signal_radius_y_changed{},
   m_signal_width_changed{},
   m_contour_pen(QPen(QColor(0,0,0),0.0)),
   m_focus_pen(QPen(QColor(0,0,0),0.0,Qt::DashLine)),
   m_radius_x(4.0),
   m_radius_y(4.0)
{
  #ifndef NDEBUG
  Test();
  #endif

  this->setFlags(
      QGraphicsItem::ItemIsFocusable
    | QGraphicsItem::ItemIsMovable
    | QGraphicsItem::ItemIsSelectable
    );
  this->SetContourPen(QPen(QColor(0,0,0),2.0));
  this->SetFocusPen(QPen(QColor(0,0,0),3.0,Qt::DashLine));
  const double height = 32.0;
  const double width = 64.0;
  this->SetInnerWidth(width);
  this->SetInnerHeight(height);
}

ribi::QtRoundedRectItem::~QtRoundedRectItem() noexcept
{
  //OK
}

void ribi::QtRoundedRectItem::dragEnterEvent(QGraphicsSceneDragDropEvent *) noexcept
{
  this->m_signal_pos_changed(this);
}

void ribi::QtRoundedRectItem::dragLeaveEvent(QGraphicsSceneDragDropEvent *) noexcept
{
  this->m_signal_pos_changed(this);
}

void ribi::QtRoundedRectItem::dragMoveEvent(QGraphicsSceneDragDropEvent *) noexcept
{
  this->m_signal_pos_changed(this);
}

double ribi::QtRoundedRectItem::GetInnerHeight() const noexcept
{
  const double pen_width = GetFocusPen().widthF() > GetContourPen().widthF()
                         ? GetFocusPen().widthF()
                         : GetContourPen().widthF();
  return GetOuterHeight() - (2.0 * pen_width);
}

QRectF ribi::QtRoundedRectItem::GetInnerRect() const noexcept
{
  return QRectF(
    GetCenterX(),
    GetCenterY(),
    GetInnerWidth(),
    GetInnerHeight()
  );
}

double ribi::QtRoundedRectItem::GetInnerWidth() const noexcept
{
  const double pen_width = GetFocusPen().widthF() > GetContourPen().widthF()
                         ? GetFocusPen().widthF()
                         : GetContourPen().widthF();
  return GetOuterWidth() - (2.0 * pen_width);
}


QRectF ribi::QtRoundedRectItem::GetOuterRect() const noexcept
{
  const QRectF r{QGraphicsRectItem::rect()};
  return r.translated(GetCenterX(),GetCenterY());
}


std::string ribi::QtRoundedRectItem::GetVersion() noexcept
{
  return "1.10";
}

std::vector<std::string> ribi::QtRoundedRectItem::GetVersionHistory() noexcept
{
  return {
    "2012-12-13: version 1.0: initial version",
    "2012-12-19: version 1.1: added use of pen, brush and focus-indicating pen",
    "2012-12-22: version 1.2: correctly uses the focus and regular pen, added contour pen",
    "2014-06-14: version 1.3: removed superfluous signal m_signal_item_has_updated",
    "2014-06-14: version 1.4: fixed issue #219",
    "2014-06-16: version 1.5: disallow setRect and setPos (use SetRoundedRect and SetPos instead), cooperation with QtRoundedRectItemDialog",
    "2014-06-22: version 1.6: allow setting the inner and outer rectangle",
    "2014-08-07: version 1.7: renamed IncludingPen member functions to Outer",
    "2014-08-08: version 1.8: removed using with rectangles from interface, as it led to incorrectness and confusion",
    "2014-08-09: version 1.9: increased use of Tdd, fixed bug",
    "2015-02-08: version 1.10: gaining/losing focus for different pen widths work correctly"
  };
}

void ribi::QtRoundedRectItem::mouseMoveEvent(QGraphicsSceneMouseEvent *event) noexcept
{
  QGraphicsRectItem::mouseMoveEvent(event);
  this->update();
  this->scene()->update();
  m_signal_pos_changed(this);
}

void ribi::QtRoundedRectItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *, QWidget *) noexcept
{
  painter->setBrush(brush());

  const QPen thickest_pen = GetContourPen().widthF() > GetFocusPen().widthF()
                         ? GetContourPen()
                         : GetFocusPen();

  if (this->isSelected() || this->hasFocus())
  {
    painter->setPen(m_focus_pen);
    assert(painter->pen() == m_focus_pen);
  }
  else
  {
    painter->setPen(m_contour_pen);
    assert(painter->pen() == m_contour_pen);
  }

  const double w{GetOuterWidth() - (2 * thickest_pen.widthF()) + this->GetCurrentPen().widthF()};
  const double h{GetOuterHeight() - (2 * thickest_pen.widthF()) + this->GetCurrentPen().widthF()};

  painter->drawRoundedRect(
    QRectF(
      -0.5 * w,
      -0.5 * h,
       1.0 * w, //Width
       1.0 * h //Height
    ),
    m_radius_x,m_radius_y
  );
}

void ribi::QtRoundedRectItem::SetCenterX(const double x) noexcept
{
  const bool verbose{false};
  const double current_x = this->GetCenterX();
  if (current_x != x)
  {
    const auto current_pos = this->GetCenterPos();
    QGraphicsRectItem::setPos(
      x,
      current_pos.y()
    );

    if (verbose) { TRACE("Emitting ribi::QtRoundedRectItem::m_signal_pos_changed"); }

    m_signal_pos_changed(this);
    this->update();
  }
}

void ribi::QtRoundedRectItem::SetCenterY(const double y) noexcept
{
  const double current_y = this->GetCenterY();
  if (current_y != y)
  {
    const auto current_pos = this->GetCenterPos();
    QGraphicsRectItem::setPos(
      current_pos.x(),
      y
    );
    this->update();
    m_signal_pos_changed(this);
  }
}

void ribi::QtRoundedRectItem::SetContourPen(const QPen& pen) noexcept
{
  #ifndef NDEBUG
  const double inner_height_before = GetInnerHeight();
  const double inner_width_before = GetInnerWidth();
  #endif
  //if (m_contour_pen.widthF() != pen.widthF())
  if (m_contour_pen != pen)
  {
    const double height = GetInnerHeight();
    const double width = GetInnerWidth();
    m_contour_pen = pen;
    this->SetInnerHeight(height);
    this->SetInnerWidth(width);

    this->update();
    m_signal_contour_pen_changed(this);
  }
  #ifndef NDEBUG
  else
  {
    const double inner_height_after = GetInnerHeight();
    const double inner_width_after = GetInnerWidth();
    assert(std::abs(inner_height_before - inner_height_after) < 0.001);
    assert(std::abs(inner_width_before  - inner_width_after ) < 0.001);
  }
  #endif
  assert(std::abs(pen.widthF() - GetContourPen().widthF()) < 0.01);
}

void ribi::QtRoundedRectItem::SetFocusPen(const QPen& pen) noexcept
{
  #ifndef NDEBUG
  const double inner_height_before = GetInnerHeight();
  const double inner_width_before = GetInnerWidth();
  #endif
  if (m_focus_pen != pen)
  {
    const double height = GetInnerHeight();
    const double width = GetInnerWidth();
    m_focus_pen = pen;
    this->SetInnerHeight(height);
    this->SetInnerWidth(width);

    this->update();
    m_signal_focus_pen_changed(this);
  }
  #ifndef NDEBUG
  else
  {
    const double inner_height_after = GetInnerHeight();
    const double inner_width_after = GetInnerWidth();
    assert(std::abs(inner_height_before - inner_height_after) < 0.001);
    assert(std::abs(inner_width_before  - inner_width_after ) < 0.001);
  }
  #endif

  assert(std::abs(pen.widthF() - GetFocusPen().widthF()) < 0.01);
}

void ribi::QtRoundedRectItem::SetInnerHeight(const double height) noexcept
{
  const double pen_width = GetFocusPen().widthF() > GetContourPen().widthF()
                         ? GetFocusPen().widthF()
                         : GetContourPen().widthF();
  SetOuterHeight(
    height + (2.0 * pen_width)
  );
}

void ribi::QtRoundedRectItem::SetInnerWidth(const double width) noexcept
{
  const double pen_width = GetFocusPen().widthF() > GetContourPen().widthF()
                         ? GetFocusPen().widthF()
                         : GetContourPen().widthF();
  SetOuterWidth(
    width + (2.0 * pen_width)
  );
}


void ribi::QtRoundedRectItem::SetOuterHeight(const double height) noexcept
{
  if (height != GetOuterHeight())
  {
    const auto w = GetOuterWidth();
    const auto h = height;
    QGraphicsRectItem::setRect(
      QRectF(
        QPointF(-0.5 * w,-0.5 * h),
        QPointF( 0.5 * w, 0.5 * h)
      )
    );
    this->update();
    m_signal_height_changed(this);
  }
}

void ribi::QtRoundedRectItem::SetOuterWidth(const double width) noexcept
{
  if (width != GetOuterWidth())
  {
    const auto w = width;
    const auto h = GetOuterHeight();
    QGraphicsRectItem::setRect(
      QRectF(
        QPointF(-0.5 * w,-0.5 * h),
        QPointF( 0.5 * w, 0.5 * h)
      )
    );
    this->update();
    m_signal_width_changed(this);
  }
}

void ribi::QtRoundedRectItem::SetRadiusX(const double radius_x) noexcept
{
  if (m_radius_x != radius_x)
  {
    m_radius_x = radius_x;
    this->update();
    m_signal_radius_x_changed(this);
  }
  assert(radius_x == GetRadiusX());
}

void ribi::QtRoundedRectItem::SetRadiusY(const double radius_y) noexcept
{
  if (m_radius_y != radius_y)
  {
    m_radius_y = radius_y;
    this->update();
    m_signal_radius_y_changed(this);
  }
  assert(radius_y == GetRadiusY());
}

bool ribi::operator==(const QtRoundedRectItem& lhs, const QtRoundedRectItem& rhs) noexcept
{
  return
       lhs.GetContourPen() == rhs.GetContourPen()
    && lhs.GetFocusPen() == rhs.GetFocusPen()
    && lhs.GetRadiusX() == rhs.GetRadiusX()
    && lhs.GetRadiusY() == rhs.GetRadiusY()
    && lhs.GetInnerWidth() == rhs.GetInnerWidth()
    && lhs.GetInnerHeight() == rhs.GetInnerHeight()
  ;
}

bool ribi::operator!=(const QtRoundedRectItem& lhs, const QtRoundedRectItem& rhs) noexcept
{
  return !(lhs == rhs);
}

 

 

 

 

 

./CppQtRoundedRectItem/qtroundedrectitem_test.cpp

 

//---------------------------------------------------------------------------
/*
QtRoundedRectItem, rectangular-shaped QGraphicsItem
Copyright (C) 2012-2015 Richel Bilderbeek

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

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program.If not, see <http://www.gnu.org/licenses/>.
*/
//---------------------------------------------------------------------------
//From http://www.richelbilderbeek.nl/CppQtRoundedRectItem.htm
//---------------------------------------------------------------------------
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Weffc++"
#pragma GCC diagnostic ignored "-Wunused-but-set-parameter"
#pragma GCC diagnostic ignored "-Wunused-local-typedefs"
#include "qtroundedrectitem.h"

#include <QCoreApplication>
#include <QGraphicsSceneMouseEvent>
#include <QGraphicsScene>
#include <QImage>
#include <QPainter>

#include "counter.h"
#include "testtimer.h"
#include "trace.h"
#pragma GCC diagnostic pop

#ifndef NDEBUG
void ribi::QtRoundedRectItem::Test() noexcept
{
  {
    static bool is_tested{false};
    if (is_tested) return;
    is_tested = true;
  }
  const TestTimer test_timer(__func__,__FILE__,1.0);
  const bool verbose{false};
  if (verbose) { TRACE("Construction"); }
  {
    QtRoundedRectItem();
  }
  QtRoundedRectItem i;
  if (verbose) { TRACE("SetOuterX and GetOuterX must be symmetric"); }
  {
    const auto old_x = i.GetCenterX();
    const auto new_x = old_x + 10.0;
    i.SetCenterX(new_x);
    assert(std::abs(i.GetCenterX() - new_x) < 4.0);
  }
  if (verbose) { TRACE("SetOuterY and GetOuterY must be symmetric"); }
  {
    const auto old_y = i.GetCenterY();
    const auto new_y = old_y + 10.0;
    i.SetCenterY(new_y);
    assert(std::abs(i.GetCenterY() - new_y) < 4.0);
  }
  if (verbose) { TRACE("SetOuterPos and GetOuterPos must be symmetric"); }
  {
    const auto old_pos = i.GetCenterPos();
    const auto new_pos = old_pos + QPointF(10.0,10.0);
    i.SetCenterPos(new_pos);
    assert(std::abs(i.GetCenterPos().x() - new_pos.x()) < 2.0);
    assert(std::abs(i.GetCenterPos().y() - new_pos.y()) < 2.0);
  }
  if (verbose) { TRACE("SetOuterWidth and GetOuterWidth must be symmetric"); }
  {
    const auto old_width = i.GetOuterWidth();
    const auto new_width = old_width + 10.0;
    i.SetOuterWidth(new_width);
    assert(std::abs(i.GetOuterWidth() - new_width) < 2.0);
  }
  if (verbose) { TRACE("SetOuterHeight and GetOuterHeight must be symmetric"); }
  {
    const auto old_height = i.GetOuterHeight();
    const auto new_height = old_height + 10.0;
    i.SetOuterHeight(new_height);
    assert(std::abs(i.GetOuterHeight() - new_height) < 2.0);
  }
  if (verbose) { TRACE("SetInnerX and GetInnerX must be symmetric"); }
  {
    const auto old_x = i.GetCenterX();
    const auto new_x = old_x + 10.0;
    i.SetCenterX(new_x);
    assert(std::abs(i.GetCenterX() - new_x) < 2.0);
  }
  if (verbose) { TRACE("SetInnerY and GetInnerY must be symmetric"); }
  {
    const auto old_y = i.GetCenterY();
    const auto new_y = old_y + 10.0;
    i.SetCenterY(new_y);
    assert(std::abs(i.GetCenterY() - new_y) < 2.0);
  }
  if (verbose) { TRACE("SetInnerPos and GetInnerPos must be symmetric"); }
  {
    const auto old_pos = i.GetCenterPos();
    const auto new_pos = old_pos + QPointF(10.0,10.0);
    i.SetCenterPos(new_pos);
    assert(std::abs(i.GetCenterPos().x() - new_pos.x()) < 2.0);
    assert(std::abs(i.GetCenterPos().y() - new_pos.y()) < 2.0);
  }
  if (verbose) { TRACE("SetInnerHeight and GetInnerHeight must be symmetric"); }
  {
    const auto old_height = i.GetInnerHeight();
    const auto new_height = old_height + 10.0;
    i.SetInnerHeight(new_height);
    assert(std::abs(i.GetInnerHeight() - new_height) < 2.0);
  }
  if (verbose) { TRACE("SetInnerWidth and GetInnerWidth must be symmetric"); }
  {
    const auto old_width = i.GetInnerWidth();
    const auto new_width = old_width + 10.0;
    i.SetInnerWidth(new_width);
    //Difference has been measured to be 3.0
    assert(std::abs(i.GetInnerWidth() - new_width) < 4.0);
  }
  if (verbose) { TRACE("SetRadiusX and GetRadiusX must be symmetric"); }
  {
    const auto old_radius_x = i.GetRadiusX();
    const auto new_radius_x = old_radius_x + 10.0;
    i.SetRadiusX(new_radius_x);
    assert(std::abs(i.GetRadiusX() - new_radius_x) < 2.0);
  }
  if (verbose) { TRACE("SetRadiusY and GetRadiusY must be symmetric"); }
  {
    const auto old_radius_y = i.GetRadiusY();
    const auto new_radius_y = old_radius_y + 10.0;
    i.SetRadiusY(new_radius_y);
    assert(std::abs(i.GetRadiusY() - new_radius_y) < 2.0);
  }
  if (verbose) { TRACE("Position must be in GetOuterRect"); }
  {
    assert(i.GetOuterRect().contains(i.GetCenterPos()));
  }
  if (verbose) { TRACE("Position must be in GetInnerRect"); }
  {
    assert(i.GetInnerRect().contains(i.GetCenterPos()));
  }
  if (verbose) { TRACE("After changing the outer width and position, the Position must be in GetOuterRect"); }
  {
    i.SetOuterWidth(3.0);
    i.SetOuterHeight(3.0);
    i.SetCenterX(i.GetCenterX() + 10.0);
    i.SetCenterY(i.GetCenterY() + 10.0);
    assert(i.GetOuterRect().contains(i.GetCenterPos()));
  }
  if (verbose) { TRACE("After changing the inner width and position, the Position must be in GetInnerRect"); }
  {
    i.SetInnerWidth(3.0);
    i.SetInnerHeight(3.0);
    i.SetCenterX(i.GetCenterX() + 10.0);
    i.SetCenterY(i.GetCenterY() + 10.0);
    assert(i.GetInnerRect().contains(i.GetCenterPos()));
  }
  if (verbose) { TRACE("After a drag event, m_signal_pos_changed must be emitted"); }
  {
    //Cannot be tested
    //Counter c{0}; //For receiving the signal
    //i.m_signal_pos_changed.connect(
    //  boost::bind(&ribi::Counter::Inc,&c) //Do not forget the &
    //);
    //const QGraphicsSceneMouseEvent * const event{new QGraphicsSceneMouseEvent};
    //QCoreApplication::sendEvent(&i,event);
    //assert(c.Get() > 0);
  }
  if (verbose) { TRACE("GetInnerRect should not change if width of contour pen changes"); }
  {
    QGraphicsScene scene;
    scene.addItem(&i);
    i.setSelected(false);
    i.clearFocus();
    assert(!i.hasFocus() && !i.isSelected()
      && "Assume no focus, otherwise this test has no use");
    const auto before = i.GetInnerRect();
    const QPen old_pen{i.GetContourPen()};
    QPen new_pen{old_pen};
    new_pen.setWidth((old_pen.width() * 10) + 10);
    i.SetContourPen(new_pen);
    const auto after = i.GetInnerRect();
    assert(before == after);
    scene.removeItem(&i); //Otherwise i gets deleted
  }
  if (verbose) { TRACE("GetInnerRect should not change if width of focus pen changes"); }
  {
    QGraphicsScene scene;
    scene.addItem(&i);
    i.setSelected(false);
    i.clearFocus();
    assert(!i.hasFocus() && !i.isSelected()
      && "Assume no focus, otherwise this test has no use");
    const auto before = i.GetInnerRect();
    const QPen old_pen{i.GetContourPen()};
    QPen new_pen{old_pen};
    new_pen.setWidth((old_pen.width() * 10) + 10);
    i.SetFocusPen(new_pen);
    const auto after = i.GetInnerRect();
    assert(before == after);
    scene.removeItem(&i); //Otherwise i gets deleted
  }
  #ifdef ISSUE_261_GIVE_UP_ON_TESTING_FOCUS
  if (verbose) { TRACE("GetInnerRect should not change if width of focus pen changes and given focus"); }
  {
    QGraphicsScene scene;
    scene.addItem(&i);
    i.setSelected(false);
    i.clearFocus();
    assert(!i.hasFocus() && !i.isSelected()
      && "Assume no focus, otherwise this test has no use");
    const auto before = i.GetInnerRect();
    const QPen old_pen{i.GetContourPen()};
    QPen new_pen{old_pen};
    new_pen.setWidth((old_pen.width() * 10) + 10);

    i.SetFocusPen(new_pen);
    i.setFocus();
    i.setSelected(true);
    // Force repaint
    {
      //Create an image of the item
      QImage image(scene.sceneRect().size().toSize(), QImage::Format_ARGB32);
      // Start all pixels transparent
      image.fill(Qt::transparent);
      QPainter painter(&image);
      scene.render(&painter);
      image.save("tmp_bug244_pre.png");
    }
    assert(i.hasFocus());
    assert(i.isSelected());
    assert(i.hasFocus() && i.isSelected()
      && "Assume focus, otherwise this test has no use");
    const auto after = i.GetInnerRect();
    assert(before == after);
    scene.removeItem(&i); //Otherwise i gets deleted
  }
  if (verbose) { TRACE("Bug #244: Changing pens does not resize the raw QRect"); }
  // The GetInnerRect should always remain the same
  // Test procedure:
  // 1) Set the contour pen to wide
  // 2) Give the item focus
  // Now, the inner rectangle has gotten bigger. This should not be.

  {

    QGraphicsScene scene;
    scene.addItem(&i);

    //Set contour pen to width 20
    {
      auto contour_pen = i.GetContourPen();
      contour_pen.setWidth(20);
      i.SetContourPen(contour_pen);
    }
    //Set focus pen to width 1
    {
      auto focus_pen = i.GetFocusPen();
      focus_pen.setWidth(1);
      i.SetFocusPen(focus_pen);
      assert(i.GetFocusPen().width() == 1);
    }
    assert(i.GetContourPen().width() == 20);
    assert(i.GetCurrentPen().width() == 20);
    assert(i.GetFocusPen().width() == 1);

    //OK: inner width + 2 * contour pen width = outer width
    {
      const auto expected_outer_width
        = i.GetInnerWidth() + (2 * i.GetContourPen().width());
      const auto real_outer_width = i.GetOuterWidth();
      assert(std::abs(expected_outer_width - real_outer_width) < 4
        && "inner_width + 2 * contour_pen_width should be about the outer width"
      );
    }
    //big_rect_width is the outer rectangle of the QItem, as it is drawn
    const auto big_rect_width = i.GetOuterRect().width();
    TRACE("PAY ATTENTION!");
    //Set focus to QtNode
    i.setSelected(true);
    assert(i.GetCurrentPen() == i.GetFocusPen()
      && "Be sure that QtNode has focus now");
    //Paint it to file, to force a redraw
    {
      //Create an image of before
      QImage image(scene.sceneRect().size().toSize(), QImage::Format_ARGB32);
      // Start all pixels transparent
      image.fill(Qt::transparent);
      QPainter painter(&image);
      scene.render(&painter);
      image.save("tmp_bug244.png");
    }

    //ERROR: inner width + 2 * focus pen width != outer width
    {
      const auto expected_outer_width
        = i.GetInnerWidth() + (2 * i.GetFocusPen().width());
      const auto real_outer_width = i.GetOuterWidth();
      assert(std::abs(expected_outer_width - real_outer_width) < 4
        && "inner_width + 2 * focus_pen_width should be about the outer width"
      );
    }
    assert(i.GetContourPen().width() == 20);
    assert(i.GetCurrentPen().width() == 1);
    assert(i.GetFocusPen().width() == 1);

    //small_rect_width is the outer rectangle of the QItem, as it is drawn
    //
    //
    //   v---v   = small_rect_width
    // v-------v = big_rect_width
    //
    // +-------+
    // |       |
    // | +---+ |
    // | | X | |
    // | +---+ |
    // |       |
    // +-------+

    const auto small_rect_width = i.GetInnerRect().width();
    assert(small_rect_width + 4 < big_rect_width);

    scene.removeItem(&i); //Otherwise i gets deleted

    assert(!"Fixed, refactor, then check in");
  }
  assert(1==2);
  #endif // ISSUE_261_GIVE_UP_ON_TESTING_FOCUS
}
#endif

 

 

 

 

 

./CppQtRoundedRectItem/qtroundedrectitemdialog.h

 

//---------------------------------------------------------------------------
/*
QtRoundedRectItem, rectangular-shaped QGraphicsItem
Copyright (C) 2012-2015 Richel Bilderbeek

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

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program.If not, see <http://www.gnu.org/licenses/>.
*/
//---------------------------------------------------------------------------
//From http://www.richelbilderbeek.nl/CppQtRoundedRectItem.htm
//---------------------------------------------------------------------------
#ifndef QTROUNDEDRECTDIALOG_H
#define QTROUNDEDRECTDIALOG_H

#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Weffc++"
#pragma GCC diagnostic ignored "-Wunused-local-typedefs"
#pragma GCC diagnostic ignored "-Wunused-but-set-parameter"
#include <boost/shared_ptr.hpp>
#include "qthideandshowdialog.h"
#pragma GCC diagnostic pop

namespace Ui {
class QtRoundedRectItemDialog;
}

namespace ribi {

struct QtRoundedRectItem;

class QtRoundedRectItemDialog : public QtHideAndShowDialog
{
  Q_OBJECT
    
public:

  explicit QtRoundedRectItemDialog(QWidget *parent = 0);
  QtRoundedRectItemDialog(const QtRoundedRectItemDialog&) = delete;
  QtRoundedRectItemDialog& operator=(const QtRoundedRectItemDialog&) = delete;
  ~QtRoundedRectItemDialog() noexcept;

  void DisableSetSize() noexcept;
  void DoSomethingRandom() noexcept;

  boost::shared_ptr<const QtRoundedRectItem> GetItem() const noexcept;

  static int GetMinimumHeight() noexcept { return 276; }

  ///Read the X value directly from GUI
  double GetUiX() const noexcept;
  ///Read the Y value directly from GUI
  double GetUiY() const noexcept;

  ///Obtain the version of this class
  static std::string GetVersion() noexcept;

  ///Obtain the version history of this class
  static std::vector<std::string> GetVersionHistory() noexcept;

  void SetItem(const boost::shared_ptr<QtRoundedRectItem>& item) noexcept;

  ///Set the X value directly to GUI
  void SetUiX(const double x) noexcept;
  ///Set the Y value directly to GUI
  void SetUiY(const double y) noexcept;


protected:
  void keyPressEvent(QKeyEvent * event);

private slots:

  void on_box_contour_pen_width_valueChanged(double arg1);
  void on_box_focus_pen_width_valueChanged(double arg1);
  void on_box_height_including_pen_valueChanged(double arg1);
  void on_box_height_valueChanged(double arg1);
  void on_box_radius_x_valueChanged(double arg1);
  void on_box_radius_y_valueChanged(double arg1);
  void on_box_width_including_pen_valueChanged(double arg1);
  void on_box_width_valueChanged(double arg1);
  void on_box_x_valueChanged(double arg1);
  void on_box_y_valueChanged(double arg1);

private:
  Ui::QtRoundedRectItemDialog *ui;

  ///The QtRoundedRectItem to work on
  boost::shared_ptr<QtRoundedRectItem> m_item;

  void OnContourPenChanged(QtRoundedRectItem * const qtitem) noexcept;
  void OnFocusPenChanged(QtRoundedRectItem * const qtitem) noexcept;
  void OnPosChanged(QtRoundedRectItem * const qtitem) noexcept;
  void OnRadiusXchanged(QtRoundedRectItem * const qtitem) noexcept;
  void OnRadiusYchanged(QtRoundedRectItem * const qtitem) noexcept;
  void OnWidthChanged(QtRoundedRectItem * const qtitem) noexcept;
  void OnHeightChanged(QtRoundedRectItem * const qtitem) noexcept;

  #ifndef NDEBUG
  static void Test() noexcept;
  #endif
};

} //~namespace ribi

#endif // QTROUNDEDRECTDIALOG_H

 

 

 

 

 

./CppQtRoundedRectItem/qtroundedrectitemdialog.cpp

 

//---------------------------------------------------------------------------
/*
QtRoundedRectItem, rectangular-shaped QGraphicsItem
Copyright (C) 2012-2015 Richel Bilderbeek

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

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program.If not, see <http://www.gnu.org/licenses/>.
*/
//---------------------------------------------------------------------------
//From http://www.richelbilderbeek.nl/CppQtRoundedRectItem.htm
//---------------------------------------------------------------------------
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Weffc++"
#pragma GCC diagnostic ignored "-Wunused-local-typedefs"
#pragma GCC diagnostic ignored "-Wunused-but-set-parameter"
#include "qtroundedrectitemdialog.h"

#include <boost/make_shared.hpp>
#include <boost/lambda/lambda.hpp>

#include <QKeyEvent>

#include "geometry.h"
#include "qtroundedrectitem.h"
#include "testtimer.h"
#include "trace.h"
#include "ui_qtroundedrectitemdialog.h"
#pragma GCC diagnostic pop

ribi::QtRoundedRectItemDialog::QtRoundedRectItemDialog(QWidget *parent) :
    QtHideAndShowDialog(parent),
    ui(new Ui::QtRoundedRectItemDialog),
    m_item()
{
  #ifndef NDEBUG
  Test();
  #endif
  ui->setupUi(this);
}

ribi::QtRoundedRectItemDialog::~QtRoundedRectItemDialog() noexcept
{
  delete ui;
}

void ribi::QtRoundedRectItemDialog::DisableSetSize() noexcept
{
  ui->box_height->setReadOnly(true);
  ui->box_height_including_pen->setReadOnly(true);
  ui->box_width->setReadOnly(true);
  ui->box_width_including_pen->setReadOnly(true);
}

void ribi::QtRoundedRectItemDialog::DoSomethingRandom() noexcept
{
  ui->box_contour_pen_width->setValue(
    ui->box_contour_pen_width->value()
    + static_cast<double>(std::rand() % 3) - 1.0
  );

  ui->box_focus_pen_width->setValue(
    ui->box_focus_pen_width->value()
    + static_cast<double>(std::rand() % 3) - 1.0
  );

  ui->box_height->setValue(
    ui->box_height->value()
    + static_cast<double>(std::rand() % 3) - 1.0
  );

  ui->box_height_including_pen->setValue(
    ui->box_height_including_pen->value()
    + static_cast<double>(std::rand() % 3) - 1.0
  );

  ui->box_radius_x->setValue(
    ui->box_radius_x->value()
    + static_cast<double>(std::rand() % 3) - 1.0
  );

  ui->box_radius_y->setValue(
    ui->box_radius_y->value()
    + static_cast<double>(std::rand() % 3) - 1.0
  );

  ui->box_width->setValue(
    ui->box_width->value()
    + static_cast<double>(std::rand() % 3) - 1.0
  );

  ui->box_width_including_pen->setValue(
    ui->box_width_including_pen->value()
    + static_cast<double>(std::rand() % 3) - 1.0
  );

  ui->box_x->setValue(
    ui->box_x->value()
    + static_cast<double>(std::rand() % 3) - 1.0
  );

  ui->box_y->setValue(
    ui->box_y->value()
    + static_cast<double>(std::rand() % 3) - 1.0
  );
}

boost::shared_ptr<const ribi::QtRoundedRectItem> ribi::QtRoundedRectItemDialog::GetItem() const noexcept
{
  return m_item;
}

double ribi::QtRoundedRectItemDialog::GetUiX() const noexcept
{
  return ui->box_x->value();
}

double ribi::QtRoundedRectItemDialog::GetUiY() const noexcept
{
  return ui->box_y->value();
}

std::string ribi::QtRoundedRectItemDialog::GetVersion() noexcept
{
  return "1.3";
}

std::vector<std::string> ribi::QtRoundedRectItemDialog::GetVersionHistory() noexcept
{
  return {
    "2014-06-15: version 1.0: initial version",
    "2014-06-23: version 1.1: allow cooperation with QtRoundedEditRectItemDialog",
    "2014-07-21: version 1.2: added CheckMe member function, for checking its invariants",
    "2014-08-04: version 1.3: removed CheckMe member function in favor of Tdd"
  };
}

void ribi::QtRoundedRectItemDialog::keyPressEvent(QKeyEvent * event)
{
  if (event->key() == Qt::Key_Escape) { close(); return; }
}

void ribi::QtRoundedRectItemDialog::OnContourPenChanged(QtRoundedRectItem * const qtitem) noexcept
{
  ui->box_contour_pen_width->setValue(qtitem->GetContourPen().widthF());
}

void ribi::QtRoundedRectItemDialog::OnFocusPenChanged(QtRoundedRectItem * const qtitem) noexcept
{
  ui->box_focus_pen_width->setValue(qtitem->GetFocusPen().widthF());
}

void ribi::QtRoundedRectItemDialog::OnPosChanged(QtRoundedRectItem * const qtitem) noexcept
{
  const double new_x = qtitem->GetCenterPos().x();
  const double new_y = qtitem->GetCenterPos().y();
  ui->box_x->setValue(new_x);
  ui->box_y->setValue(new_y);
}

void ribi::QtRoundedRectItemDialog::OnRadiusXchanged(QtRoundedRectItem * const qtitem) noexcept
{
  ui->box_radius_x->setValue(qtitem->GetRadiusX());
}

void ribi::QtRoundedRectItemDialog::OnRadiusYchanged(QtRoundedRectItem * const qtitem) noexcept
{
  ui->box_radius_y->setValue(qtitem->GetRadiusY());
}

void ribi::QtRoundedRectItemDialog::OnWidthChanged(QtRoundedRectItem * const qtitem) noexcept
{
  const double new_width = qtitem->GetInnerWidth();
  ui->box_width->setValue(new_width);
  const double new_width_including_pen = qtitem->GetOuterWidth();
  ui->box_width_including_pen->setValue(new_width_including_pen);
}

void ribi::QtRoundedRectItemDialog::OnHeightChanged(QtRoundedRectItem * const qtitem) noexcept
{
  const double new_height = qtitem->GetInnerHeight();
  ui->box_height->setValue(new_height);
  const double new_height_including_pen = qtitem->GetOuterHeight();
  ui->box_height_including_pen->setValue(new_height_including_pen);
}

void ribi::QtRoundedRectItemDialog::on_box_contour_pen_width_valueChanged(double arg1)
{
  const QPen pen(
    QBrush(qRgb(0,0,0)),
    arg1
  );
  m_item->SetContourPen(pen);
}

void ribi::QtRoundedRectItemDialog::on_box_focus_pen_width_valueChanged(double arg1)
{
  const QPen pen(
    QBrush(qRgb(0,0,0)),
    arg1,
    Qt::DashLine
  );
  m_item->SetFocusPen(pen);
}

void ribi::QtRoundedRectItemDialog::on_box_height_valueChanged(double arg1)
{
  m_item->SetInnerHeight(arg1);
}

void ribi::QtRoundedRectItemDialog::on_box_height_including_pen_valueChanged(double arg1)
{
  m_item->SetOuterHeight(arg1);
}

void ribi::QtRoundedRectItemDialog::on_box_radius_x_valueChanged(double arg1)
{
  m_item->SetRadiusX(arg1);
}

void ribi::QtRoundedRectItemDialog::on_box_radius_y_valueChanged(double arg1)
{
  m_item->SetRadiusY(arg1);
}

void ribi::QtRoundedRectItemDialog::on_box_width_valueChanged(double arg1)
{
  m_item->SetInnerWidth(arg1);
}

void ribi::QtRoundedRectItemDialog::on_box_width_including_pen_valueChanged(double arg1)
{
  m_item->SetOuterWidth(arg1);
}

void ribi::QtRoundedRectItemDialog::on_box_x_valueChanged(double arg1)
{
  m_item->SetCenterPos(arg1,m_item->GetCenterPos().y());
}

void ribi::QtRoundedRectItemDialog::on_box_y_valueChanged(double arg1)
{
  m_item->SetCenterPos(m_item->GetCenterPos().x(),arg1);
}

void ribi::QtRoundedRectItemDialog::SetItem(const boost::shared_ptr<QtRoundedRectItem>& item) noexcept
{
  const bool verbose{false};

  assert(item);
  if (m_item == item)
  {
    //Let the GUI follow
    ui->box_contour_pen_width->setValue(GetItem()->GetContourPen().widthF());
    ui->box_focus_pen_width->setValue(GetItem()->GetFocusPen().widthF());
    ui->box_height->setValue(GetItem()->GetInnerHeight());
    ui->box_height_including_pen->setValue(GetItem()->GetOuterHeight());
    ui->box_radius_x->setValue(GetItem()->GetRadiusX());
    ui->box_radius_y->setValue(GetItem()->GetRadiusY());
    ui->box_width->setValue(GetItem()->GetInnerWidth());
    ui->box_width_including_pen->setValue(GetItem()->GetOuterWidth());
    ui->box_x->setValue(GetItem()->GetCenterX());
    ui->box_y->setValue(GetItem()->GetCenterY());
    return;
  }
  if (verbose)
  {
    std::stringstream s;
    s << "Setting item '" << (*item) << "'\n";
  }

  const auto contour_pen_after = item->GetContourPen();
  const auto focus_pen_after = item->GetFocusPen();
  const auto pos_after = item->GetCenterPos();
  const auto radius_x_after = item->GetRadiusX();
  const auto radius_y_after = item->GetRadiusY();
  const auto width_after = item->GetInnerWidth();
  const auto height_after = item->GetInnerHeight();


  bool contour_pen_changed{true};
  bool focus_pen_changed{true};
  bool pos_changed{true};
  bool radius_x_changed{true};
  bool radius_y_changed{true};
  bool width_changed{true};
  bool height_changed{true};

  if (m_item)
  {
    const auto contour_pen_before = m_item->GetContourPen();
    const auto focus_pen_before = m_item->GetFocusPen();
    const auto pos_before = m_item->GetCenterPos();
    const auto radius_x_before = m_item->GetRadiusX();
    const auto radius_y_before = m_item->GetRadiusY();
    const auto width_before = m_item->GetInnerWidth();
    const auto height_before = m_item->GetInnerHeight();

    contour_pen_changed  = contour_pen_before != contour_pen_after;
    focus_pen_changed  = focus_pen_before != focus_pen_after;
    pos_changed = pos_before != pos_after;
    radius_x_changed = radius_x_before != radius_x_after;
    radius_y_changed = radius_y_before != radius_y_after;
    width_changed = width_before != width_after;
    height_changed = height_before != height_after;


    if (verbose)
    {
      if (contour_pen_changed)
      {
        std::stringstream s;
        s
          << "Contour pen will change from "
          << contour_pen_before
          << " to "
          << contour_pen_after
          << '\n'
        ;
        TRACE(s.str());
      }
      if (focus_pen_changed)
      {
        std::stringstream s;
        s << "FocusPen will change from " << focus_pen_before
          << " to " << focus_pen_after << '\n';
        TRACE(s.str());
      }
      if (pos_changed)
      {
        std::stringstream s;
        s << "Pos will change from '" << pos_before
          << "' to '" << pos_after << "'\n";
        TRACE(s.str());
      }
      if (radius_x_changed)
      {
        std::stringstream s;
        s << "RadiusX will change from " << radius_x_before
          << " to " << radius_x_after << '\n';
        TRACE(s.str());
      }
      if (radius_y_changed)
      {
        std::stringstream s;
        s << "RadiusY will change from " << radius_y_before
          << " to " << radius_y_after << '\n';
        TRACE(s.str());
      }
      if (width_changed)
      {
        std::stringstream s;
        s << "Inner width will change from '" << width_before
          << "' to '" << width_after << "'\n";
        TRACE(s.str());
      }
      if (height_changed)
      {
        std::stringstream s;
        s << "Inner height will change from '" << height_before
          << "' to '" << height_after << "'\n";
        TRACE(s.str());
      }
    }

    //Disconnect m_item
    m_item->m_signal_contour_pen_changed.disconnect(
      boost::bind(&ribi::QtRoundedRectItemDialog::OnContourPenChanged,this,boost::lambda::_1)
    );
    m_item->m_signal_focus_pen_changed.disconnect(
      boost::bind(&ribi::QtRoundedRectItemDialog::OnFocusPenChanged,this,boost::lambda::_1)
    );
    m_item->m_signal_pos_changed.disconnect(
      boost::bind(&ribi::QtRoundedRectItemDialog::OnPosChanged,this,boost::lambda::_1)
    );
    m_item->m_signal_radius_x_changed.disconnect(
      boost::bind(&ribi::QtRoundedRectItemDialog::OnRadiusXchanged,this,boost::lambda::_1)
    );
    m_item->m_signal_radius_y_changed.disconnect(
      boost::bind(&ribi::QtRoundedRectItemDialog::OnRadiusYchanged,this,boost::lambda::_1)
    );
    m_item->m_signal_width_changed.disconnect(
      boost::bind(&ribi::QtRoundedRectItemDialog::OnWidthChanged,this,boost::lambda::_1)
    );
    m_item->m_signal_height_changed.disconnect(
      boost::bind(&ribi::QtRoundedRectItemDialog::OnHeightChanged,this,boost::lambda::_1)
    );
  }

  //Replace m_item by the new one
  m_item = item;


  assert(m_item->GetContourPen() == contour_pen_after);
  assert(m_item->GetFocusPen()   == focus_pen_after  );
  assert(m_item->GetCenterPos()   == pos_after        );
  assert(m_item->GetRadiusX()    == radius_x_after   );
  assert(m_item->GetRadiusY()    == radius_y_after   );
  assert(std::abs(m_item->GetInnerWidth() - width_after) < 1.0);

  m_item->m_signal_contour_pen_changed.connect(
    boost::bind(&ribi::QtRoundedRectItemDialog::OnContourPenChanged,this,boost::lambda::_1)
  );
  m_item->m_signal_focus_pen_changed.connect(
    boost::bind(&ribi::QtRoundedRectItemDialog::OnFocusPenChanged,this,boost::lambda::_1)
  );
  m_item->m_signal_pos_changed.connect(
    boost::bind(&ribi::QtRoundedRectItemDialog::OnPosChanged,this,boost::lambda::_1)
  );
  m_item->m_signal_radius_x_changed.connect(
    boost::bind(&ribi::QtRoundedRectItemDialog::OnRadiusXchanged,this,boost::lambda::_1)
  );
  m_item->m_signal_radius_y_changed.connect(
    boost::bind(&ribi::QtRoundedRectItemDialog::OnRadiusYchanged,this,boost::lambda::_1)
  );
  m_item->m_signal_width_changed.connect(
    boost::bind(&ribi::QtRoundedRectItemDialog::OnWidthChanged,this,boost::lambda::_1)
  );
  m_item->m_signal_height_changed.connect(
    boost::bind(&ribi::QtRoundedRectItemDialog::OnHeightChanged,this,boost::lambda::_1)
  );

  //Emit everything that has changed
  if (contour_pen_changed)
  {
    m_item->m_signal_contour_pen_changed(m_item.get());
  }
  if (focus_pen_changed)
  {
    m_item->m_signal_focus_pen_changed(m_item.get());
  }
  if (pos_changed)
  {
    m_item->m_signal_pos_changed(m_item.get());
  }
  if (radius_x_changed)
  {
    m_item->m_signal_radius_x_changed(m_item.get());
  }
  if (radius_y_changed)
  {
    m_item->m_signal_radius_y_changed(m_item.get());
  }
  if (width_changed)
  {
    m_item->m_signal_width_changed(m_item.get());
  }
  if (height_changed)
  {
    m_item->m_signal_height_changed(m_item.get());
  }
  assert( item ==  m_item);
  assert(*item == *m_item);
}

void ribi::QtRoundedRectItemDialog::SetUiX(const double x) noexcept
{
  this->ui->box_x->setValue(x);
}

void ribi::QtRoundedRectItemDialog::SetUiY(const double y) noexcept
{
  this->ui->box_y->setValue(y);
}

#ifndef NDEBUG
void ribi::QtRoundedRectItemDialog::Test() noexcept
{
  {
    static bool is_tested{false};
    if (is_tested) return;
    is_tested = true;
  }
  QtRoundedRectItem();

  const TestTimer test_timer(__func__,__FILE__,1.0);
  const bool verbose{false};
  QtRoundedRectItemDialog dialog;
  boost::shared_ptr<QtRoundedRectItem> item{new QtRoundedRectItem};
  dialog.SetItem(item);
  //Change all, sorted by UI component name
  if (verbose) { TRACE("Set/Get Contour pen must be symmetric"); }
  {
    dialog.ui->box_contour_pen_width->setValue( item->GetContourPen().widthF() + 10.0 );
    QPen new_pen = item->GetContourPen();
    new_pen.setWidthF(dialog.ui->box_contour_pen_width->value() + 10.0);
    item->SetContourPen(new_pen);
    assert(item->GetContourPen() == new_pen);
  }
  if (verbose) { TRACE("Set/Get Focus pen width must be symmetric"); }
  {
    dialog.ui->box_focus_pen_width->setValue( item->GetFocusPen().widthF() + 10.0);
    QPen new_pen = item->GetFocusPen();
    new_pen.setWidthF(dialog.ui->box_focus_pen_width->value() + 10.0);
    item->SetFocusPen(new_pen);
    assert(item->GetFocusPen() == new_pen);
  }
  if (verbose) { TRACE("Set/Get InnerHeight must be symmetric"); }
  {
    dialog.ui->box_height->setValue(item->GetInnerHeight() + 10.0);
    const auto new_height = dialog.ui->box_height->value() + 10.0;
    item->SetInnerHeight(new_height);
    assert(std::abs(item->GetInnerHeight() - new_height) < 2.0);
  }
  if (verbose) { TRACE("Set/Get OuterHeight must be symmetric"); }
  {
    dialog.ui->box_height_including_pen->setValue(item->GetOuterHeight() + 10.0);
    const auto new_height = dialog.ui->box_height_including_pen->value() + 10.0;
    item->SetOuterHeight(new_height);
    assert(std::abs(item->GetOuterHeight() - new_height) < 2.0);
  }
  if (verbose) { TRACE("Set/Get Radius X must be symmetric"); }
  {
    dialog.ui->box_radius_x->setValue(item->GetRadiusX() + 10.0);
    const auto new_x = dialog.ui->box_radius_x->value() + 10.0;
    item->SetRadiusX(new_x);
    assert(std::abs(item->GetRadiusX() - new_x) < 2.0);
  }
  if (verbose) { TRACE("Set/Get Radius Y must be symmetric"); }
  {
    dialog.ui->box_radius_y->setValue(item->GetRadiusY() + 10.0);
    const auto new_y = dialog.ui->box_radius_y->value() + 10.0;
    item->SetRadiusY(new_y);
    assert(std::abs(item->GetRadiusY() - new_y) < 2.0);
  }
  if (verbose) { TRACE("Set/Get InnerWidth must be symmetric"); }
  {
    const double old_width{item->GetInnerWidth()};
    const double new_width{old_width + 10.0};
    item->SetInnerWidth(new_width);
    assert(std::abs(item->GetInnerWidth() - new_width) < 2.0);
  }
  if (verbose) { TRACE("Set/Get OuterWidth must be symmetric"); }
  {
    dialog.ui->box_width_including_pen->setValue(item->GetOuterWidth() + 10.0);
    const auto new_width = dialog.ui->box_width_including_pen->value() + 10.0;
    item->SetOuterWidth(new_width);
    assert(std::abs(item->GetOuterWidth() - new_width) < 2.0);
  }
  if (verbose) { TRACE("Set/Get X must be symmetric"); }
  {
    dialog.ui->box_x->setValue(item->GetCenterX() + 10.0);
    const auto new_x = dialog.ui->box_x->value() + 10.0;
    item->SetCenterX(new_x);
    assert(std::abs(item->GetCenterX() - new_x) < 2.0);
  }
  if (verbose) { TRACE("Set/Get Y must be symmetric"); }
  {
    dialog.ui->box_y->setValue(item->GetCenterY() + 10.0);
    const auto new_y = dialog.ui->box_y->value() + 10.0;
    item->SetCenterY(new_y);
    assert(std::abs(item->GetCenterY() - new_y) < 2.0);
  }
  if (verbose) { TRACE("SetItem with other item"); }
  {
    boost::shared_ptr<QtRoundedRectItem> new_item{new QtRoundedRectItem};
    dialog.SetItem(new_item);
    assert(dialog.GetItem() == new_item);
  }
  if (verbose) { TRACE("SetItem with original item"); }
  {
    dialog.SetItem(item);
    assert(dialog.GetItem() == item);
  }
  if (verbose) { TRACE("Changing a contour pen does not change the inner height"); }
  {
    assert(!item->GetIsSelected() && "Work with contour pen");
    const double old_height{item->GetInnerHeight()};
    const double new_height{old_height + 10.0};
    item->SetInnerHeight(new_height);
    QPen pen(item->GetContourPen());
    pen.setWidthF(pen.widthF() + 5.0);
    item->SetContourPen(pen);
    assert(std::abs(item->GetInnerHeight() - new_height) < 4.0);
  }
  if (verbose) { TRACE("Changing a contour pen does not change the inner width"); }
  {
    assert(!item->GetIsSelected() && "Work with contour pen");
    const double old_width{item->GetInnerWidth()};
    const double new_width{old_width + 10.0};
    item->SetInnerWidth(new_width);
    QPen pen(item->GetContourPen());
    pen.setWidthF(pen.widthF() + 5.0);
    item->SetContourPen(pen);
    assert(std::abs(item->GetInnerWidth() - new_width) < 4.0);
  }
  if (verbose) { TRACE("Changing a contour pen does change the outer height"); }
  {
    assert(!item->GetIsSelected() && "Work with contour pen");
    const double old_height{item->GetInnerHeight()};
    const double new_height{old_height + 10.0};
    item->SetOuterHeight(new_height);
    QPen pen(item->GetContourPen());
    pen.setWidthF(pen.widthF() + 5.0);
    item->SetContourPen(pen);
    assert(std::abs(item->GetOuterHeight() - new_height) > 4.0);
  }
  if (verbose) { TRACE("Changing a contour pen does change the outer width"); }
  {
    assert(!item->GetIsSelected() && "Work with contour pen");
    const double old_width{item->GetInnerWidth()};
    const double new_width{old_width + 10.0};
    item->SetOuterWidth(new_width);
    QPen pen(item->GetContourPen());
    pen.setWidthF(pen.widthF() + 5.0);
    item->SetContourPen(pen);
    assert(std::abs(item->GetOuterWidth() - new_width) > 4.0);
  }
  if (verbose) { TRACE("Brute-force some random items"); }
  {
    for (int i{0}; i!=10; ++i) { dialog.DoSomethingRandom(); }
  }
}
#endif

 

 

 

 

 

Go back to Richel Bilderbeek's C++ page.

Go back to Richel Bilderbeek's homepage.

 

Valid XHTML 1.0 Strict

This page has been created by the tool CodeToHtml