Tulip  5.0.0
Large graphs analysis and drawing
TulipItemEditorCreators.cxx
1 /*
2  *
3  * This file is part of Tulip (www.tulip-software.org)
4  *
5  * Authors: David Auber and the Tulip development Team
6  * from LaBRI, University of Bordeaux
7  *
8  * Tulip is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU Lesser General Public License
10  * as published by the Free Software Foundation, either version 3
11  * of the License, or (at your option) any later version.
12  *
13  * Tulip is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
16  * See the GNU General Public License for more details.
17  *
18  */
19 #include <sstream>
20 #include <climits>
21 #include <cfloat>
22 
23 #include <QSet>
24 #include <QLineEdit>
25 #include <QTextEdit>
26 #include <QComboBox>
27 #include <QPainter>
28 #include <QDoubleSpinBox>
29 
30 #include <tulip/ForEach.h>
31 #include <tulip/DataSet.h>
32 #include <tulip/VectorEditor.h>
33 #include <tulip/GraphPropertiesModel.h>
34 #include <tulip/TlpQtTools.h>
35 #include <tulip/TulipMetaTypes.h>
36 #include <tulip/ScientificDoubleSpinBox.h>
37 
38 
39 namespace tlp {
40 
41 template<typename T>
42 QWidget* NumberEditorCreator<T>::createWidget(QWidget* parent) const {
43  QDoubleSpinBox *dsb = NULL;
44 
45  // emulate a QSpinBox for integer types
46  if (typeid(T).name() == typeid(tlp::IntegerType).name() ||
47  typeid(T).name() == typeid(tlp::UnsignedIntegerType).name() ||
48  typeid(T).name() == typeid(tlp::LongType).name()) {
49  dsb = new QDoubleSpinBox(parent);
50  dsb->setDecimals(0);
51  // otherwise for floating point number types
52  }
53  else {
54  // use a dedicated QDoubleSpinBox supporting scientific notation
55  dsb = new tlp::ScientificDoubleSpinBox(parent);
56  // force the use of dot character for decimal separator
57  dsb->setLocale(QLocale(QLocale::C));
58  }
59 
60  // set correct range of values according to type
61  if (typeid(T).name() == typeid(tlp::IntegerType).name()) {
62  dsb->setRange(-INT_MAX, INT_MAX);
63  }
64  else if (typeid(T).name() == typeid(tlp::UnsignedIntegerType).name()) {
65  dsb->setRange(0, UINT_MAX);
66  }
67  else if (typeid(T).name() == typeid(tlp::LongType).name()) {
68  dsb->setRange(-LONG_MAX, LONG_MAX);
69  }
70  else if (typeid(T).name() == typeid(tlp::FloatType).name()) {
71  dsb->setRange(-FLT_MAX, FLT_MAX);
72  }
73  else {
74  dsb->setRange(-DBL_MAX, DBL_MAX);
75  }
76 
77  return dsb;
78 }
79 
80 template<typename T>
81 void NumberEditorCreator<T>::setEditorData(QWidget* editor, const QVariant& data, bool, tlp::Graph*) {
82  static_cast<QDoubleSpinBox*>(editor)->setValue(data.value<typename T::RealType>());
83 }
84 
85 template<typename T>
86 QVariant NumberEditorCreator<T>::editorData(QWidget* editor, tlp::Graph*) {
87  QVariant result;
88  result.setValue(static_cast<typename T::RealType>(static_cast<QDoubleSpinBox*>(editor)->value()));
89  return result;
90 }
91 
92 template<typename T>
93 QWidget* LineEditEditorCreator<T>::createWidget(QWidget *parent) const {
94  return new QLineEdit(parent);
95 }
96 
97 template<typename T>
98 void LineEditEditorCreator<T>::setEditorData(QWidget* editor, const QVariant &data, bool, tlp::Graph*) {
99  typename T::RealType val = data.value<typename T::RealType>();
100  static_cast<QLineEdit*>(editor)->setText(tlpStringToQString(T::toString(val)));
101  static_cast<QLineEdit*>(editor)->selectAll();
102 }
103 
104 template<typename T>
105 QVariant LineEditEditorCreator<T>::editorData(QWidget* editor,tlp::Graph*) {
106  std::string strVal = QStringToTlpString(static_cast<QLineEdit*>(editor)->text());
107  QVariant result;
108  typename T::RealType val;
109 
110  if (T::fromString(val,strVal))
111  result.setValue<typename T::RealType>(val);
112 
113  return result;
114 }
115 
116 template<typename T>
117 QWidget* MultiLinesEditEditorCreator<T>::createWidget(QWidget *parent) const {
118  QTextEdit *edit = new QTextEdit(parent);
119  edit->setFocusPolicy(Qt::StrongFocus);
120  edit->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
121  edit->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
122  return edit;
123 }
124 
125 template<typename T>
126 void MultiLinesEditEditorCreator<T>::setEditorData(QWidget* editor, const QVariant &data,bool,tlp::Graph*) {
127  typename T::RealType val = data.value<typename T::RealType>();
128  static_cast<QTextEdit*>(editor)->setPlainText(tlpStringToQString(T::toString(val)));
129  static_cast<QTextEdit*>(editor)->selectAll();
130 }
131 
132 template<typename T>
133 QVariant MultiLinesEditEditorCreator<T>::editorData(QWidget* editor,tlp::Graph*) {
134  std::string strVal = QStringToTlpString(static_cast<QTextEdit*>(editor)->toPlainText());
135  QVariant result;
136  typename T::RealType val;
137 
138  if (T::fromString(val,strVal))
139  result.setValue<typename T::RealType>(val);
140 
141  return result;
142 }
143 
144 template<typename T>
145 QSize MultiLinesEditEditorCreator<T>::sizeHint(const QStyleOptionViewItem & option, const QModelIndex &index) const {
146  QVariant data = index.model()->data(index);
147  typename T::RealType val = data.value<typename T::RealType>();
148  QString valS = tlpStringToQString(T::toString(val));
149  QStringList lines = valS.split(QLatin1Char('\n'));
150  QFontMetrics fontMetrics(option.font);
151  int height = 0;
152  int width = 0;
153 
154  for (int i = 0 ; i < lines.count() ; ++i) {
155  QRect textBB = fontMetrics.boundingRect(lines.at(i));
156  height += fontMetrics.boundingRect("|").height();
157  width = std::max(width, textBB.width());
158  }
159 
160  // restrict column width in case of really large string to display
161  width = std::min(width, 500);
162 
163  return QSize(width+15, height+5);
164 }
165 
166 template<typename T>
167 bool MultiLinesEditEditorCreator<T>::paint(QPainter* painter, const QStyleOptionViewItem &option, const QVariant &data) const {
168  TulipItemEditorCreator::paint(painter,option,data);
169  QRect rect = option.rect;
170  typename T::RealType val = data.value<typename T::RealType>();
171  QString valS = tlpStringToQString(T::toString(val));
172  QStringList lines = valS.split(QLatin1Char('\n'));
173 
174  if (option.state.testFlag(QStyle::State_Selected) && option.showDecorationSelected) {
175  painter->setPen(option.palette.highlightedText().color());
176  painter->setBrush(option.palette.highlightedText());
177  }
178  else {
179  painter->setPen(option.palette.text().color());
180  painter->setBrush(option.palette.text());
181  }
182 
183  for (int i = 0 ; i < lines.count() ; ++i) {
184  painter->drawText(rect.x(), rect.y() + i * rect.height()/lines.count(), rect.width(), rect.height()/lines.count(),Qt::AlignLeft | Qt::AlignVCenter, lines.at(i));
185  }
186 
187  return true;
188 }
189 
190 template<typename PROPTYPE>
191 QWidget* PropertyEditorCreator<PROPTYPE>::createWidget(QWidget* parent) const {
192  return new QComboBox(parent);
193 }
194 
195 template<typename PROPTYPE>
196 void PropertyEditorCreator<PROPTYPE>::setEditorData(QWidget* w, const QVariant& val,bool isMandatory,tlp::Graph* g) {
197  if (g == NULL) {
198  w->setEnabled(false);
199  return;
200  }
201 
202  PROPTYPE* prop = val.value<PROPTYPE*>();
203  QComboBox* combo = static_cast<QComboBox*>(w);
204  GraphPropertiesModel<PROPTYPE>* model = NULL;
205 
206  if (isMandatory)
207  model = new GraphPropertiesModel<PROPTYPE>(g,false,combo);
208  else
209  model = new GraphPropertiesModel<PROPTYPE>(QObject::trUtf8("Select a property"),g,false,combo);
210 
211  combo->setModel(model);
212  combo->setCurrentIndex(model->rowOf(prop));
213 }
214 
215 template<typename PROPTYPE>
216 QVariant PropertyEditorCreator<PROPTYPE>::editorData(QWidget* w,tlp::Graph* g) {
217  if (g == NULL)
218  return QVariant();
219 
220  QComboBox* combo = static_cast<QComboBox*>(w);
221  GraphPropertiesModel<PROPTYPE>* model = static_cast<GraphPropertiesModel<PROPTYPE> *>(combo->model());
222  QVariant var = model->data(model->index(combo->currentIndex(),0),TulipModel::PropertyRole);
224  PROPTYPE* prop = (PROPTYPE*)(pi);
225  return QVariant::fromValue<PROPTYPE*>(prop);
226 }
227 
228 template<typename PROPTYPE>
229 QString PropertyEditorCreator<PROPTYPE>::displayText(const QVariant& v) const {
230  PROPTYPE *prop = v.value<PROPTYPE*>();
231 
232  if (prop==NULL)
233  return QObject::trUtf8("Select a property");
234 
235  return tlpStringToQString(prop->getName());
236 }
237 
238 template<typename ElementType>
239 QWidget* VectorEditorCreator<ElementType>::createWidget(QWidget*) const {
240  VectorEditor* w = new VectorEditor(NULL);
241  w->setWindowFlags(Qt::Dialog);
242  w->setWindowModality(Qt::ApplicationModal);
243  return w;
244 
245 }
246 
247 template<typename ElementType>
248 void VectorEditorCreator<ElementType>::setEditorData(QWidget* editor, const QVariant& v,bool,tlp::Graph*) {
249  QVector<QVariant> editorData;
250  std::vector<ElementType> vect = v.value<std::vector<ElementType> >();
251 
252  for (size_t i=0; i < vect.size(); ++i) {
253  editorData.push_back(QVariant::fromValue<ElementType>(vect[i]));
254  }
255 
256  static_cast<VectorEditor*>(editor)->setVector(editorData,qMetaTypeId<ElementType>());
257 
258  static_cast<VectorEditor*>(editor)->move(QCursor::pos());
259 }
260 
261 template<typename ElementType>
262 QVariant VectorEditorCreator<ElementType>::editorData(QWidget* editor,tlp::Graph*) {
263  std::vector<ElementType> result;
264  QVector<QVariant> editorData = static_cast<VectorEditor*>(editor)->vector();
265 
266  foreach(QVariant v, editorData)
267  result.push_back(v.value<ElementType>());
268 
269  return QVariant::fromValue<std::vector<ElementType> >(result);
270 }
271 
272 // the template below is only used for displayText method implementation
273 template<typename T>
274 struct DisplayVectorDataType :public DataType {
275  DisplayVectorDataType(void *value) :DataType(value) {}
276  ~DisplayVectorDataType() {
277  }
278  DataType* clone() const {
279  return NULL;
280  }
281 
282  std::string getTypeName() const {
283  return std::string(typeid(std::vector<T>).name());
284  }
285 };
286 
287 
288 template<typename ElementType>
289 QString VectorEditorCreator<ElementType>::displayText(const QVariant &data) const {
290  std::vector<ElementType> v = data.value<std::vector<ElementType> >();
291 
292  if (v.empty())
293  return QString();
294 
295  // use a DataTypeSerializer if any
296  DataTypeSerializer* dts =
297  DataSet::typenameToSerializer(std::string(typeid(v).name()));
298 
299  if (dts) {
300  DisplayVectorDataType<ElementType> dt(&v);
301 
302  std::stringstream sstr;
303  dts->writeData(sstr, &dt);
304 
305  std::string str = sstr.str();
306 
307  QString qstr = tlpStringToQString(str);
308 
309  return truncateText(qstr);
310  }
311 
312  if (v.size() == 1)
313  return QString("1 element");
314 
315  return QString::number(v.size()) + QObject::trUtf8(" elements");
316 }
317 
318 }
Utility class implementing a QDoubleSpinBox supporting scientific notation.
PropertyInterface describes the interface of a graph property.
std::string QStringToTlpString(const QString &toConvert)
Convert a QString to a Tulip UTF-8 encoded std::string.
Definition: TlpQtTools.h:48
static DataTypeSerializer * typenameToSerializer(const std::string &name)
ElementType
Definition: Graph.h:47
QString tlpStringToQString(const std::string &toConvert)
Convert a Tulip UTF-8 encoded std::string to a QString.
Definition: TlpQtTools.h:54