tilde~
Puredata Qt-based GUI
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Pages
UIInstance.h
Go to the documentation of this file.
1 // (c) 2017 Alex Nadzharov
2 // License: GPL3
3 
4 #ifndef CM_UIInstance_H
5 #define CM_UIInstance_H
6 
7 #include <QLineEdit>
8 #include <QMainWindow>
9 #include <QtGui>
10 
11 #include "Port.h"
12 
13 #include "UIObject.h"
14 #include "UIBox.h"
15 
16 #include "OOPDHeaders.h"
17 
18 #include <QGraphicsView>
19 
20 #include "PatchWindowController.h"
21 #include "PatchWindow.h"
22 
23 #include "Preferences.h"
24 #include "PropertyList.h"
25 
26 #include "UIObjectData.h"
27 
28 namespace tilde {
29 
33 class UIInstance : public UIBox {
34 
35  Q_OBJECT
36 
37 private:
38  OPInstance* _opInstance;
39  OPClass* _opClass;
40 
41  // todo move?
42  t_outlet* _out1;
43 
44  bool _hasType; //temp
45  QString _className;
46 
47 public:
48  explicit UIInstance(); //UIObject* parent = 0);
49  //~UIInstance();
50 
51  static UIObject* createObject(QString objectData, t_canvas* pdCanvas, QGraphicsView* parent = 0)
52  {return 0;} /*
53  {
54  //TODO fix all constructors
55  //t_canvas* pd_Canvas;
56 
57  //temporary fix
58  if (objectData == "")
59  objectData = "pdclass";
60 
61  UIInstance* b = new UIInstance(); //(UIObject*)parent);
62  //b->setCanvas((void*)parent);
63 
64  QStringList list = QString(objectData).split(" ");
65 
66  const char* obj_name = objectData.toStdString().c_str();
67  QString data1 = b->properties()->extractFromPdFileString(obj_name); //test
68 
69  // todo cleanup
70  //const char* obj_name2 = data1.c_str();
71 
72  // fix size changes
73  b->setObjectData(data1);
74  b->autoResize();
75 
76  qDebug() << QString(data1) << "data1";
77 
78  t_object* new_obj = 0;
79  int in_c = 1, out_c = 0;
80 
81  b->setHelpName("pdinstance-help.pd");
82 
83  if (!pdCanvas) {
84  qDebug("bad pd canvas instance");
85  b->setErrorBox(true);
86  } else {
87  //new_obj = cmp_create_object(pdCanvas, "pdinstance", 0, 0);
88  }
89 
90  if (new_obj) {
91  //in_c = cmp_get_inlet_count(new_obj);
92  out_c = cmp_get_outlet_count(new_obj);
93 
94  //b->setPdObject(new_obj);
95 
96  cmp_connectUI((t_pd*)new_obj, (void*)b, &UIInstance::updateUI);
97 
98  } else {
99  qDebug("Error: no pd object");
100  b->setErrorBox(true);
101  in_c = 1;
102  out_c = 0;
103  }
104 
105  for (int i = 0; i < in_c; i++)
106  b->addInlet();
107  for (int i = 0; i < out_c; i++)
108  b->addOutlet();
109 
110  // typed
111  if (list.size() > 1) {
112  std::string typeName = list.at(1).toStdString();
113  //weird
114  AtomList msg(gensym("settype"));
115  msg.append(gensym(typeName.c_str()));
116 
117  b->msgSetType(msg);
118  }
119 
120  connect(b, &UIInstance::updateUISignal, b, &UIInstance::updateUISlot);
121 
122  return (UIObject*)b;
123  };
124  */
125 
129  //void paintEvent(QPaintEvent*)
130  virtual void paint(QPainter* p, const QStyleOptionGraphicsItem*, QWidget*)
131 
132  {
133  QBrush brush(bgColor());
134  p->setBrush(brush);
135  p->drawRect(boundingRect());
136  p->setBrush(QBrush());
137 
138  //QPainter p(viewport());
139  p->setRenderHint(QPainter::HighQualityAntialiasing, true);
140  p->scale(scale(), scale());
141 
142  QColor c1 = (_opInstance) ? QColor(0, 192, 255) : QColor(255, 0, 0);
143  p->setPen(QPen(c1, 1, Qt::SolidLine, Qt::SquareCap, Qt::BevelJoin));
144  p->drawRect(0, 1, width(), height() - 2);
145 
146  //remove this later
147 // if (subpatchWindow()) {
148 // p->setPen(QPen(QColor(192, 192, 192), 1, Qt::SolidLine, Qt::SquareCap, Qt::BevelJoin));
149 // p->drawRect(0, 2, width(), height() - 4);
150 // }
151 
152  QColor rectColor = (errorBox()) ? QColor(255, 0, 0) : properties()->get("BorderColor")->asQColor(); //QColor(128, 128, 128);
153  p->setPen(QPen(rectColor, 1, (errorBox()) ? Qt::DashLine : Qt::SolidLine, Qt::SquareCap, Qt::BevelJoin));
154  p->drawRect(0, 0, width(), height());
155  QTextOption* op = new QTextOption;
156  op->setAlignment(Qt::AlignLeft);
157  p->setPen(QPen(QColor(0, 0, 0), 2, Qt::SolidLine, Qt::SquareCap, Qt::BevelJoin));
158 
159  if (isSelected()) {
160  p->setPen(QPen(QColor(0, 192, 255), 1, (errorBox()) ? Qt::DashLine : Qt::SolidLine, Qt::SquareCap, Qt::BevelJoin));
161  p->drawRect(0, 0, width(), height());
162  }
163 
164  // -----------
165 
166  //XPD-TODO
167  /*
168 
169  if (_hasType) {
170 
171  p->setFont(QFont(PREF_QSTRING("Font"), properties()->get("FontSize")->asFontSize(), 0, false));
172  p->drawText(2, 3, width() - 2, 20 - 3, Qt::AlignCenter, "<" + _className + ">", 0);
173 
174  int y = 20;
175  p->setPen(QPen(QColor(192, 192, 192), 1, Qt::SolidLine, Qt::SquareCap, Qt::BevelJoin));
176  p->drawLine(0, y, width(), y);
177 
178  for (size_t i = 0; i < _opClass->getPropertyList().size(); i++) {
179  p->setPen(QPen(QColor(0, 0, 0), 2, Qt::SolidLine, Qt::SquareCap, Qt::BevelJoin));
180  p->drawText(2, 3 + y, width() - 2, 20 - 3, Qt::AlignCenter, "•" + QString(_opClass->getPropertyList().at(i).asString().c_str()), 0);
181 
182  y += 20;
183  }
184 
185  p->setPen(QPen(QColor(192, 192, 192), 1, Qt::SolidLine, Qt::SquareCap, Qt::BevelJoin));
186  p->drawLine(0, y, width(), y);
187 
188  for (size_t i = 0; i < _opClass->getMethodList().size(); i++) {
189  p->setPen(QPen(QColor(0, 0, 0), 2, Qt::SolidLine, Qt::SquareCap, Qt::BevelJoin));
190  p->drawText(2, 3 + y, width() - 2, 20 - 3, Qt::AlignCenter, QString(_opClass->getMethodList().at(i).asString().c_str()), 0);
191 
192  y += 20;
193  }
194 
195  } else {
196 
197  p->setFont(QFont(PREF_QSTRING("Font"), properties()->get("FontSize")->asFontSize(), 0, false));
198  p->drawText(2, 3, width() - 2, height() - 3, 0, objectData()->toQString(), 0);
199  }
200 
201  */
202  }
203 
208  void mousePressEvent(QGraphicsSceneMouseEvent* ev)
209  {
210  //context menu
211  if (ev->button() == Qt::RightButton) {
212 
213  if (scene()
214  && !scene()->views().isEmpty()
215  && scene()->views().first()
216  && scene()->views().first()->viewport()) {
217 
218  QGraphicsView* v = scene()->views().first();
219  QPoint pos = v->viewport()->mapToGlobal(ev->pos().toPoint());
220 
221  // TODO
222  showPopupMenu(pos + this->pos().toPoint());
223  ev->accept();
224  }
225 
226  return;
227  }
228 
229  //open canvas for subpatch
230  if (getEditMode() != em_Unlocked) {
231  if (subpatchController()) {
232  subpatchController()->mainWindow()->show();
233  }
234  }
235 
236  //window opening. Fix
237  if (getEditMode() != em_Unlocked) {
238  if (_opInstance)
239  _opInstance->showWindow();
240  }
241 
242  if ((getEditMode() == em_Unlocked) && isSelected()) {
243  // editor_->setText(QString(_objectDataModel.objectData()));
244  // editor_->show();
245 
246  emit signalEditObject(this);
247  return;
248  }
249 
250  emit selectBox(this, ev);
251  dragOffset = ev->pos().toPoint();
252  }
253 
257  void mouseReleaseEvent(QGraphicsSceneMouseEvent*)
258  {
259  update();
260  }
261 
266  void mouseMoveEvent(QGraphicsSceneMouseEvent* event)
267  {
268  if (event->buttons() & Qt::LeftButton) {
269  emit moveBox(this, event);
270  }
271  event->ignore();
272 
273  if ((getEditMode() != em_Unlocked) && (subpatchController())) {
274  setCursor(QCursor(Qt::PointingHandCursor));
275  } else {
276  setCursor(QCursor(Qt::ArrowCursor));
277  }
278  }
279 
280  void setPdMessage(QString message)
281  {
282  fromQString(message);
283  autoResize();
284 
285  QFont myFont(PREF_QSTRING("Font"), 11);
286  QFontMetrics fm(myFont);
287  int new_w = fm.width(QString(objectData()->toQString())) + 10;
288  new_w = (new_w < 25) ? 25 : new_w;
289  setWidth(new_w);
290  //editor_->setFixedWidth(width() - 5);
291 
292  //todo: del object and create new + patchcords
293 
294  //
295  setInletsPos();
296  setOutletsPos();
297  }
298 
299  // ---------------------------------------------
300 
301  void msgNew(PdArguments msg)
302  {
303  //XPD-TODO
304  /*
305  qDebug() << "new instance";
306 
307  _opClass = OOPD::inst()->classByName(msg.at(1).asString());
308 
309  if (!_opClass) {
310  // TODO
312  /* TODO * / //cmp_post(msg.at(1).asString());
313  return;
314  }
315 
316  _opInstance = new OPInstance(_opClass);
317  /* TODO * / //cmp_post("new instance");
318 
319  // TODO-PD_OBJECT
320 // if (pdObject()) {
321 // _out1 = cmp_get_outlet((t_object*)pdObject(), 0);
322 
323 // if (_out1)
324 // _opInstance->addInstanceOut(_out1);
325 // else
326 // /* TODO * / //cmp_post("instance pd object outlet error");
327 // }
328 
329  //cmp_get_inlet/outlet
330  _opInstance->addInstanceOut(0);
331  */
332  }
333 
334  //
335 
336  void setInletsPos();
337  void setOutletsPos();
338 
339  //
340  void typedInlets()
341  {
342  addInlet();
343  }
344 
345  void msgFree(PdArguments)
346  {
347  //XPD-TODO
348  /*
349  if (_opInstance) {
350  // TODO-PD_OBJECT
351 // if (pdObject()) {
352 // t_outlet* out1 = cmp_get_outlet((t_object*)pdObject(), 0);
353 // if (out1)
354 
355 // _opInstance->freeInstanceOut(out1);
356 // else
357 // /* TODO * / //cmp_post("instance pd object outlet error");
358 // }
359 
360  _opInstance->freeInstanceOut(0);
361  //delete _opInstance;
362  _opInstance->release();
363  }
364 
365  _opInstance = 0;
366  /* TODO * / //cmp_post("free instance");
367  */
368  }
369 
370  void msgSetObject(PdArguments msg)
371  {
372  //XPD-TODO
373  /*
374  /* TODO * / //cmp_post("pdobject");
375 
376  if (msg.size() < 2) {
377  /* TODO * / //cmp_post("setobject: needs pdobject pointer");
378  return;
379  }
380 
381  qDebug() << "symbol: " << msg.at(1).asSymbol()->s_name;
382 
383  _opInstance = OPInstance::fromObjectSymbol(msg.at(1).asSymbol());
384 
385  _opInstance->retain();
386 
387  qDebug() << "instance: " << _opInstance;
388 
389  update();
390  */
391  }
392 
393  void msgGetObject(PdArguments)
394  {
395  //XPD-TODO
396  /*
397  t_symbol* s = _opInstance->getObjectSymbol();
398 
399  if (_out1) {
400  AtomList list1;
401  list1.append(gensym("pdobject"));
402  list1.append(s);
403 
404  list1.output(_out1);
405 
406  } else {
407  /* TODO * / //cmp_post("instance outlet error!");
408  }
409  */
410  }
411 
412  void msgSetType(PdArguments msg)
413  {
414  //XPD-TODO
415  /*
416  if (msg.size() < 2) {
417  _hasType = false;
418  _opInstance = 0;
419  _opClass = 0;
420  setHeight(20);
421  update();
422  return;
423  } else {
424  _opClass = OOPD::inst()->classByName(msg.at(1).asString());
425  // not working:
426  //_opClass = OOPD::inst()->classBySymbol(msg.at(1).asSymbol());
427 
428  //setObjectSizeMode(os_Free);
429 
430  objectData()->setObjectSize(os_Free,40,20);
431 
432  //resize
433  if (_opClass) {
434  AtomList list;
435  list = _opClass->getMethodList();
436  list.append(_opClass->getPropertyList());
437 
438  setHeight(20 * (list.size() + 1));
439 
440  // inlets and outlets
441  for (size_t i = 0; i < _opClass->getPropertyList().size(); i++) {
442  // TODO-PD_OBJECT
443 // cmp_sendstring((t_pd*)pdObject(), "__newin");
444 // cmp_sendstring((t_pd*)pdObject(), "__newout");
445 // addInlet();
446 // addOutlet();
447  }
448 
449  for (size_t i = 0; i < _opClass->getMethodList().size(); i++) {
450  // TODO-PD_OBJECT
451 // cmp_sendstring((t_pd*)pdObject(), "__newin");
452 // cmp_sendstring((t_pd*)pdObject(), "__newout");
453 // addInlet();
454 // addOutlet();
455  }
456 
457  _hasType = true;
458 
459  // ports position
460  setInletsPos();
461  setOutletsPos();
462 
463  _className = msg.at(1).asString().c_str();
464 
465  } else {
466  /* TODO * / //cmp_post("class not found!");
467  /* TODO * / //cmp_post(msg.at(1).asString().c_str());
468  setHeight(20);
469  }
470 
471  update();
472 
473  }
474  */
475  }
476 
477  // ---------------------------------------------
478 
479  static void updateUI(void* uiobj, PdArguments msg)
480  {
481  //XPD-TODO
482  /*
483 
484  // message handling here - probably move somewhere else?
485 
486  if (msg.size() < 1)
487  return;
488  if (!msg.at(0).isSymbol())
489  return;
490 
491  UIInstance* x = ((UIInstance*)uiobj);
492  // =========
493  // methods
494  if (x->_opInstance) {
495  x->_opInstance->callMethod(msg);
496  //return;
497  }
498 
499  // ===========
500 
501  if ((msg.at(0).asString() == "new") && (msg.size() > 1)) {
502  x->msgNew(msg);
503  }
504 
505  if (msg.at(0).asString() == "free") {
506  x->msgFree(msg);
507  }
508 
509  if (msg.at(0).asString() == "pdobject") {
510  x->msgSetObject(msg);
511  }
512 
513  if (msg.at(0).asString() == "getobject") {
514  x->msgGetObject(msg);
515  }
516 
517  if (msg.at(0).asString() == "settype") {
518  x->msgSetType(msg);
519  }
520 
521  // properties
522  QString qmsg = msg.at(0).asString().c_str();
523 
524  if (qmsg.at(0) == "@") {
525  qmsg.remove(0, 1);
526 
527  if (qmsg.at(qmsg.size() - 1) == "?") {
528  if (x->_opInstance) {
529  qmsg.remove(qmsg.size() - 1, 1);
530  t_symbol* propertyName = gensym(qmsg.toStdString().c_str());
531  // getter
532  //AtomList list = x->_opInstance->getAtomListProperty(propertyName);
533 
534  x->_opInstance->callGetter(propertyName);
535 
536  // if (x->_out1) {
537  // list.output(x->_out1);
538  // } else {
539  // /* TODO * / //cmp_post("bad pdobject outlet pointer");
540  //}
541  }
542  } else {
543  if (x->_opInstance) {
544  // setter
545 
546  AtomList list1 = msg;
547  list1.remove(0);
548  t_symbol* propertyName = gensym(qmsg.toStdString().c_str());
549 
550  qDebug() << "Property name: " << propertyName->s_name;
551  //x->_opInstance->setAtomListProperty(propertyName, list1);
552  x->_opInstance->callSetter(propertyName, list1);
553  }
554  }
555  }
556 
557  emit((UIInstance*)uiobj)->updateUISignal();
558  */
559  }
560 
561 signals:
562 
563  void
564  mouseMoved();
565  void rightClicked();
566 
567 signals:
568  void updateUISignal();
569 
570 private slots:
571  void updateUISlot()
572  {
573  update();
574  }
575 };
576 }
577 
578 #endif // CM_UIInstance_H
#define t_canvas
Definition: m_pd.h:205
Definition: CommonTypes.h:14
#define PREF_QSTRING(x)
Definition: Preferences.h:17
Definition: oop_common.h:352
#define t_outlet
Definition: m_pd.h:189
Definition: oop_common.h:81