BornAgain  1.19.0
Simulate and fit neutron and x-ray scattering at grazing incidence
ConnectableView.cpp
Go to the documentation of this file.
1 // ************************************************************************************************
2 //
3 // BornAgain: simulate and fit reflection and scattering
4 //
5 //! @file GUI/coregui/Views/SampleDesigner/ConnectableView.cpp
6 //! @brief Implements class ConnectableView
7 //!
8 //! @homepage http://www.bornagainproject.org
9 //! @license GNU General Public License v3 or higher (see COPYING)
10 //! @copyright Forschungszentrum Jülich GmbH 2018
11 //! @authors Scientific Computing Group at MLZ (see CITATION, AUTHORS)
12 //
13 // ************************************************************************************************
14 
21 #include <QObject>
22 #include <QPainter>
23 #include <QStyleOptionGraphicsItem>
24 #include <iostream>
25 
26 ConnectableView::ConnectableView(QGraphicsItem* parent, QRectF rect)
27  : IView(parent)
28  , m_name("Unnamed")
29  , m_color(Qt::gray)
30  , m_rect(rect)
31  , m_roundpar(0)
32  , m_label_vspace(0)
33 {
34  setFlag(QGraphicsItem::ItemIsMovable, true);
35  setFlag(QGraphicsItem::ItemIsSelectable, true);
36  setFlag(QGraphicsItem::ItemSendsGeometryChanges);
37  m_label_vspace = StyleUtils::SizeOfLetterM().height() * 2.5;
38  m_roundpar = StyleUtils::SizeOfLetterM().height() / 3.0;
39 }
40 
41 void ConnectableView::paint(QPainter* painter, const QStyleOptionGraphicsItem* option,
42  QWidget* widget)
43 {
44  Q_UNUSED(widget);
45 
46  painter->setPen(Qt::gray);
47  if (option->state & (QStyle::State_Selected | QStyle::State_HasFocus)) {
48  painter->setPen(Qt::DashLine);
49  }
50 
52  painter->drawRoundedRect(getRectangle(), m_roundpar, m_roundpar);
53 
54  if (m_label.isEmpty())
55  return;
56 
57  painter->setPen(Qt::black);
58  double width = getRectangle().width() * 0.9;
59  double yoffset = StyleUtils::SizeOfLetterM().height() / 2; // space above the label
60  double height = m_label_vspace - yoffset;
61  QFont serifFont("Monospace", DesignerHelper::getLabelFontSize(), QFont::Normal);
62  painter->setFont(serifFont);
63  QRectF textRect(getRectangle().x() + (getRectangle().width() - width) / 2.,
64  getRectangle().y() + yoffset, width, height);
65  painter->drawText(textRect, Qt::AlignCenter, m_label);
66 }
67 
70  NodeEditorPort::EPortType port_type)
71 {
72  NodeEditorPort* port = new NodeEditorPort(this, name, direction, port_type);
73  if (direction == NodeEditorPort::INPUT) {
74  m_input_ports.append(port);
75  } else if (direction == NodeEditorPort::OUTPUT) {
76  m_output_ports.append(port);
77  } else {
78  throw GUIHelpers::Error("ConnectableView::addPort() -> Unknown port type");
79  }
81  return port;
82 }
83 
84 void ConnectableView::setLabel(const QString& name)
85 {
86  m_label = name;
88 }
89 
91 {
92  ASSERT(other);
93 
94  if (port_number >= m_input_ports.size())
95  throw GUIHelpers::Error("ConnectableView::connectInputPort() -> Wrong input port number");
96 
97  if (other->getOutputPorts().size() != 1)
98  throw GUIHelpers::Error("ConnectableView::connectInputPort() -> Wrong output port number");
99 
100  if (port_number < 0)
101  return;
102 
103  NodeEditorPort* input = m_input_ports.at(port_number);
104  NodeEditorPort* output = other->getOutputPorts().at(0);
105 
106  if (!input->isConnected(output)) {
107  NodeEditorConnection* conn = new NodeEditorConnection(0, scene());
108  conn->setPort2(input);
109  conn->setPort1(output);
110  conn->updatePath();
111  }
112 }
113 
115 {
116  return m_input_ports.indexOf(port);
117 }
118 
119 // calculation of y-pos for ports
121 {
122  if (!getNumberOfPorts())
123  return;
124 
125  // without main label ports can be placed over all rectangle vertical space
126  double hspace = getRectangle().height();
127  if (!getLabel().isEmpty())
128  hspace -= m_label_vspace;
129 
130  double nintervals =
131  getNumberOfPorts() + 2; // one spare interval for margin between input/output ports
132 
133  double dy = hspace / double(nintervals);
134  double ypos = getRectangle().height() - hspace + dy;
135 
136  if (getNumberOfPorts() == 1) {
137  // if total number of ports is 1, place it in the middle
138  ypos = getRectangle().height() - hspace + hspace / 2;
139  }
140  int nOutPorts = getNumberOfOutputPorts();
141  int nport(0);
142  for (QGraphicsItem* item : childItems()) {
143  NodeEditorPort* port = dynamic_cast<NodeEditorPort*>(item);
144  if (!port)
145  continue;
146  if (port->isOutput()) {
147  port->setPos(getRectangle().width(), ypos);
148  } else {
149  if (nport == nOutPorts && nOutPorts != 0)
150  ypos += dy; // additional margin between output and input ports
151  port->setPos(0.0, ypos);
152  }
153  ypos += dy;
154  nport++;
155  }
156 }
157 
159 {
160  return m_input_ports.size() + m_output_ports.size();
161 }
162 
164 {
165  return m_output_ports.size();
166 }
167 
169 {
170  return m_input_ports.size();
171 }
172 
174 {
177 }
178 
179 QString ConnectableView::hyphenate(const QString& name) const
180 {
181  QRegExp capital_letter("[A-Z]");
182  QRegExp number("[0-9]");
183  int next_capital = capital_letter.indexIn(name, 1);
184  int next_number = number.indexIn(name, 1);
185  if (next_capital > 0 && next_capital < name.size() - 2) {
186  int first_split_index =
187  (next_number > 0 && next_number < next_capital) ? next_number : next_capital;
188  QString result = name.left(first_split_index) + QString("\n")
189  + name.right(name.size() - first_split_index);
190  return result;
191  }
192  return name;
193 }
#define ASSERT(condition)
Definition: Assert.h:31
Defines class ConnectableView.
Defines class DesignerHelper.
Defines class GUIHelpers functions.
Defines class NodeEditorConnection.
Defines class SessionItem.
DefinesStyleUtils namespace.
view of ISampleNode's with rectangular shape and node functionality
virtual QString getLabel() const
QString hyphenate(const QString &name) const
ConnectableView(QGraphicsItem *parent=0, QRectF rect={0, 0, 50, 50})
QList< NodeEditorPort * > getOutputPorts()
void connectInputPort(ConnectableView *other, int port_number)
connects input port with given index with output port of other view
int getInputPortIndex(NodeEditorPort *port)
virtual void update_appearance()
updates visual appearance of the item (color, icons, size etc)
virtual int getNumberOfPorts()
virtual void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
virtual void setLabel(const QString &name)
virtual int getNumberOfOutputPorts()
virtual void setPortCoordinates()
virtual QRectF getRectangle() const
virtual int getNumberOfInputPorts()
QList< NodeEditorPort * > m_input_ports
virtual NodeEditorPort * addPort(const QString &name, NodeEditorPort::EPortDirection direction, NodeEditorPort::EPortType port_type)
adds port to view
QList< NodeEditorPort * > m_output_ports
static QGradient getDecorationGradient(const QColor &color, const QRectF &rect)
static int getLabelFontSize()
parent class for graphic representation of all ISampleNode's
Definition: IView.h:25
virtual void update_appearance()
updates visual appearance of the item (color, icons, size etc)
Definition: IView.cpp:70
SessionItem * m_item
Definition: IView.h:51
void setPort2(NodeEditorPort *p)
void setPort1(NodeEditorPort *p)
bool isConnected(NodeEditorPort *)
EPortType
type of ports, same type can be connected together
EPortDirection
port direction
QString displayName() const
Get display name of item, append index if ambigue.
QString const & name(EShape k)
Definition: particles.cpp:21
QSize SizeOfLetterM(const QWidget *widget=nullptr)
Returns size of largest letter of default system font.
Definition: StyleUtils.cpp:110