Collection of tools useful for audio production
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1202 lines
35KB

  1. /*
  2. * Patchbay Canvas engine using QGraphicsView/Scene
  3. * Copyright (C) 2010-2012 Filipe Coelho <falktx@gmail.com>
  4. *
  5. * This program is free software; you can redistribute it and/or modify
  6. * it under the terms of the GNU General Public License as published by
  7. * the Free Software Foundation; either version 2 of the License, or
  8. * any later version.
  9. *
  10. * This program is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. * GNU General Public License for more details.
  14. *
  15. * For a full copy of the GNU General Public License see the COPYING file
  16. */
  17. #include "patchcanvas.h"
  18. #include <QtCore/QSettings>
  19. #include <QtCore/QTimer>
  20. #include <QtGui/QAction>
  21. #include "canvasfadeanimation.h"
  22. #include "canvasline.h"
  23. #include "canvasbezierline.h"
  24. #include "canvasport.h"
  25. #include "canvasbox.h"
  26. CanvasObject::CanvasObject(QObject* parent) : QObject(parent) {}
  27. void CanvasObject::AnimationIdle()
  28. {
  29. PatchCanvas::CanvasFadeAnimation* animation = (PatchCanvas::CanvasFadeAnimation*)sender();
  30. if (animation)
  31. PatchCanvas::CanvasRemoveAnimation(animation);
  32. }
  33. void CanvasObject::AnimationHide()
  34. {
  35. PatchCanvas::CanvasFadeAnimation* animation = (PatchCanvas::CanvasFadeAnimation*)sender();
  36. if (animation)
  37. {
  38. if (animation->item())
  39. animation->item()->hide();
  40. PatchCanvas::CanvasRemoveAnimation(animation);
  41. }
  42. }
  43. void CanvasObject::AnimationDestroy()
  44. {
  45. PatchCanvas::CanvasFadeAnimation* animation = (PatchCanvas::CanvasFadeAnimation*)sender();
  46. if (animation)
  47. {
  48. if (animation->item())
  49. PatchCanvas::CanvasRemoveItemFX(animation->item());
  50. PatchCanvas::CanvasRemoveAnimation(animation);
  51. }
  52. }
  53. void CanvasObject::CanvasPostponedGroups()
  54. {
  55. PatchCanvas::CanvasPostponedGroups();
  56. }
  57. void CanvasObject::PortContextMenuDisconnect()
  58. {
  59. bool ok;
  60. int connection_id = ((QAction*)sender())->data().toInt(&ok);
  61. if (ok)
  62. PatchCanvas::CanvasCallback(PatchCanvas::ACTION_PORTS_DISCONNECT, connection_id, 0, "");
  63. }
  64. START_NAMESPACE_PATCHCANVAS
  65. /* contructor and destructor */
  66. Canvas::Canvas()
  67. {
  68. qobject = 0;
  69. settings = 0;
  70. theme = 0;
  71. initiated = false;
  72. }
  73. Canvas::~Canvas()
  74. {
  75. if (qobject)
  76. delete qobject;
  77. if (settings)
  78. delete settings;
  79. if (theme)
  80. delete theme;
  81. }
  82. /* Global objects */
  83. Canvas canvas;
  84. options_t options = {
  85. /* theme_name */ getDefaultThemeName(),
  86. /* auto_hide_groups */ false,
  87. /* use_bezier_lines */ true,
  88. /* antialiasing */ ANTIALIASING_SMALL,
  89. /* eyecandy */ EYECANDY_SMALL
  90. };
  91. features_t features = {
  92. /* group_info */ false,
  93. /* group_rename */ false,
  94. /* port_info */ false,
  95. /* port_rename */ false,
  96. /* handle_group_pos */ false
  97. };
  98. /* Internal functions */
  99. const char* bool2str(bool check)
  100. {
  101. return check ? "true" : "false";
  102. }
  103. const char* port_mode2str(PortMode port_mode)
  104. {
  105. if (port_mode == PORT_MODE_NULL)
  106. return "PORT_MODE_NULL";
  107. else if (port_mode == PORT_MODE_INPUT)
  108. return "PORT_MODE_INPUT";
  109. else if (port_mode == PORT_MODE_OUTPUT)
  110. return "PORT_MODE_OUTPUT";
  111. else
  112. return "PORT_MODE_???";
  113. }
  114. const char* port_type2str(PortType port_type)
  115. {
  116. if (port_type == PORT_TYPE_NULL)
  117. return "PORT_TYPE_NULL";
  118. else if (port_type == PORT_TYPE_AUDIO_JACK)
  119. return "PORT_TYPE_AUDIO_JACK";
  120. else if (port_type == PORT_TYPE_MIDI_JACK)
  121. return "PORT_TYPE_MIDI_JACK";
  122. else if (port_type == PORT_TYPE_MIDI_A2J)
  123. return "PORT_TYPE_MIDI_A2J";
  124. else if (port_type == PORT_TYPE_MIDI_ALSA)
  125. return "PORT_TYPE_MIDI_ALSA";
  126. else
  127. return "PORT_TYPE_???";
  128. }
  129. const char* icon2str(Icon icon)
  130. {
  131. if (icon == ICON_HARDWARE)
  132. return "ICON_HARDWARE";
  133. else if (ICON_APPLICATION)
  134. return "ICON_APPLICATION";
  135. else if (ICON_LADISH_ROOM)
  136. return "ICON_LADISH_ROOM";
  137. else
  138. return "ICON_???";
  139. }
  140. const char* split2str(SplitOption split)
  141. {
  142. if (split == SPLIT_UNDEF)
  143. return "SPLIT_UNDEF";
  144. else if (split == SPLIT_NO)
  145. return "SPLIT_NO";
  146. else if (split == SPLIT_YES)
  147. return "SPLIT_YES";
  148. else
  149. return "SPLIT_???";
  150. }
  151. /* PatchCanvas API */
  152. void setOptions(options_t* new_options)
  153. {
  154. if (canvas.initiated) return;
  155. options.theme_name = new_options->theme_name;
  156. options.auto_hide_groups = new_options->auto_hide_groups;
  157. options.use_bezier_lines = new_options->use_bezier_lines;
  158. options.antialiasing = new_options->antialiasing;
  159. options.eyecandy = new_options->eyecandy;
  160. }
  161. void setFeatures(features_t* new_features)
  162. {
  163. if (canvas.initiated) return;
  164. features.group_info = new_features->group_info;
  165. features.group_rename = new_features->group_rename;
  166. features.port_info = new_features->port_info;
  167. features.port_rename = new_features->port_rename;
  168. features.handle_group_pos = new_features->handle_group_pos;
  169. }
  170. void init(PatchScene* scene, Callback callback, bool debug)
  171. {
  172. if (debug)
  173. qDebug("PatchCanvas::init(%p, %p, %s)", scene, callback, bool2str(debug));
  174. if (canvas.initiated)
  175. {
  176. qCritical("PatchCanvas::init() - already initiated");
  177. return;
  178. }
  179. if (!callback)
  180. {
  181. qFatal("PatchCanvas::init() - fatal error: callback not set");
  182. return;
  183. }
  184. canvas.scene = scene;
  185. canvas.callback = callback;
  186. canvas.debug = debug;
  187. canvas.last_z_value = 0;
  188. canvas.last_connection_id = 0;
  189. canvas.initial_pos = QPointF(0, 0);
  190. canvas.size_rect = QRectF();
  191. if (!canvas.qobject) canvas.qobject = new CanvasObject();
  192. if (!canvas.settings) canvas.settings = new QSettings(PATCHCANVAS_ORGANISATION_NAME, "PatchCanvas");
  193. if (canvas.theme)
  194. {
  195. delete canvas.theme;
  196. canvas.theme = 0;
  197. }
  198. for (int i=0; i<Theme::THEME_MAX; i++)
  199. {
  200. QString this_theme_name = getThemeName(static_cast<Theme::List>(i));
  201. if (this_theme_name == options.theme_name)
  202. {
  203. canvas.theme = new Theme(static_cast<Theme::List>(i));
  204. break;
  205. }
  206. }
  207. if (!canvas.theme)
  208. canvas.theme = new Theme(getDefaultTheme());
  209. canvas.scene->updateTheme();
  210. canvas.initiated = true;
  211. }
  212. void clear()
  213. {
  214. if (canvas.debug)
  215. qDebug("PatchCanvas::clear()");
  216. QList<int> group_list_ids;
  217. QList<int> port_list_ids;
  218. QList<int> connection_list_ids;
  219. foreach (const group_dict_t& group, canvas.group_list)
  220. group_list_ids.append(group.group_id);
  221. foreach (const port_dict_t& port, canvas.port_list)
  222. port_list_ids.append(port.port_id);
  223. foreach (const connection_dict_t& connection, canvas.connection_list)
  224. connection_list_ids.append(connection.connection_id);
  225. foreach (const int& idx, connection_list_ids)
  226. disconnectPorts(idx);
  227. foreach (const int& idx, port_list_ids)
  228. removePort(idx);
  229. foreach (const int& idx, group_list_ids)
  230. removeGroup(idx);
  231. canvas.last_z_value = 0;
  232. canvas.last_connection_id = 0;
  233. canvas.group_list.clear();
  234. canvas.port_list.clear();
  235. canvas.connection_list.clear();
  236. canvas.initiated = false;
  237. }
  238. void setInitialPos(int x, int y)
  239. {
  240. if (canvas.debug)
  241. qDebug("PatchCanvas::setInitialPos(%i, %i)", x, y);
  242. canvas.initial_pos.setX(x);
  243. canvas.initial_pos.setY(y);
  244. }
  245. void setCanvasSize(int x, int y, int width, int height)
  246. {
  247. if (canvas.debug)
  248. qDebug("PatchCanvas::setCanvasSize(%i, %i, %i, %i)", x, y, width, height);
  249. canvas.size_rect.setX(x);
  250. canvas.size_rect.setY(y);
  251. canvas.size_rect.setWidth(width);
  252. canvas.size_rect.setHeight(height);
  253. }
  254. void addGroup(int group_id, QString group_name, SplitOption split, Icon icon)
  255. {
  256. if (canvas.debug)
  257. qDebug("PatchCanvas::addGroup(%i, %s, %s, %s)", group_id, group_name.toUtf8().constData(), split2str(split), icon2str(icon));
  258. foreach (const group_dict_t& group, canvas.group_list)
  259. {
  260. if (group.group_id == group_id)
  261. {
  262. qWarning("PatchCanvas::addGroup(%i, %s, %s, %s) - group already exists", group_id, group_name.toUtf8().constData(), split2str(split), icon2str(icon));
  263. return;
  264. }
  265. }
  266. if (split == SPLIT_UNDEF && features.handle_group_pos)
  267. split = static_cast<SplitOption>(canvas.settings->value(QString("CanvasPositions/%1_SPLIT").arg(group_name), split).toInt());
  268. CanvasBox* group_box = new CanvasBox(group_id, group_name, icon);
  269. group_dict_t group_dict;
  270. group_dict.group_id = group_id;
  271. group_dict.group_name = group_name;
  272. group_dict.split = (split == SPLIT_YES);
  273. group_dict.icon = icon;
  274. group_dict.widgets[0] = group_box;
  275. group_dict.widgets[1] = 0;
  276. if (split == SPLIT_YES)
  277. {
  278. group_box->setSplit(true, PORT_MODE_OUTPUT);
  279. if (features.handle_group_pos)
  280. group_box->setPos(canvas.settings->value(QString("CanvasPositions/%1_OUTPUT").arg(group_name), CanvasGetNewGroupPos()).toPointF());
  281. else
  282. group_box->setPos(CanvasGetNewGroupPos());
  283. CanvasBox* group_sbox = new CanvasBox(group_id, group_name, icon);
  284. group_sbox->setSplit(true, PORT_MODE_INPUT);
  285. group_dict.widgets[1] = group_sbox;
  286. if (features.handle_group_pos)
  287. group_sbox->setPos(canvas.settings->value(QString("CanvasPositions/%1_INPUT").arg(group_name), CanvasGetNewGroupPos(true)).toPointF());
  288. else
  289. group_sbox->setPos(CanvasGetNewGroupPos(true));
  290. canvas.last_z_value += 1;
  291. group_sbox->setZValue(canvas.last_z_value);
  292. if (options.auto_hide_groups == false && options.eyecandy == EYECANDY_FULL)
  293. CanvasItemFX(group_sbox, true);
  294. }
  295. else
  296. {
  297. group_box->setSplit(false);
  298. if (features.handle_group_pos)
  299. group_box->setPos(canvas.settings->value(QString("CanvasPositions/%1").arg(group_name), CanvasGetNewGroupPos()).toPointF());
  300. else
  301. {
  302. // Special ladish fake-split groups
  303. bool horizontal = (icon == ICON_HARDWARE || icon == ICON_LADISH_ROOM);
  304. group_box->setPos(CanvasGetNewGroupPos(horizontal));
  305. }
  306. }
  307. canvas.last_z_value += 1;
  308. group_box->setZValue(canvas.last_z_value);
  309. canvas.group_list.append(group_dict);
  310. if (options.auto_hide_groups == false && options.eyecandy == EYECANDY_FULL)
  311. CanvasItemFX(group_box, true);
  312. QTimer::singleShot(0, canvas.scene, SLOT(update()));
  313. }
  314. void removeGroup(int group_id)
  315. {
  316. if (canvas.debug)
  317. qDebug("PatchCanvas::removeGroup(%i)", group_id);
  318. foreach2 (const group_dict_t& group, canvas.group_list)
  319. if (group.group_id == group_id)
  320. {
  321. CanvasBox* item = group.widgets[0];
  322. QString group_name = group.group_name;
  323. if (group.split)
  324. {
  325. CanvasBox* s_item = group.widgets[1];
  326. if (features.handle_group_pos)
  327. {
  328. canvas.settings->setValue(QString("CanvasPositions/%1_OUTPUT").arg(group_name), item->pos());
  329. canvas.settings->setValue(QString("CanvasPositions/%1_INPUT").arg(group_name), s_item->pos());
  330. canvas.settings->setValue(QString("CanvasPositions/%1_SPLIT").arg(group_name), SPLIT_YES);
  331. }
  332. if (options.eyecandy == EYECANDY_FULL)
  333. {
  334. CanvasItemFX(s_item, false, true);
  335. }
  336. else
  337. {
  338. s_item->removeIconFromScene();
  339. canvas.scene->removeItem(s_item);
  340. delete s_item;
  341. }
  342. }
  343. else
  344. {
  345. if (features.handle_group_pos)
  346. {
  347. canvas.settings->setValue(QString("CanvasPositions/%1").arg(group_name), item->pos());
  348. canvas.settings->setValue(QString("CanvasPositions/%1_SPLIT").arg(group_name), SPLIT_NO);
  349. }
  350. }
  351. if (options.eyecandy == EYECANDY_FULL)
  352. {
  353. CanvasItemFX(item, false, true);
  354. }
  355. else
  356. {
  357. item->removeIconFromScene();
  358. canvas.scene->removeItem(item);
  359. delete item;
  360. }
  361. canvas.group_list.takeAt(i);
  362. QTimer::singleShot(0, canvas.scene, SLOT(update()));
  363. return;
  364. }
  365. }
  366. qCritical("PatchCanvas::removeGroup(%i) - unable to find group to remove", group_id);
  367. }
  368. void renameGroup(int group_id, QString new_group_name)
  369. {
  370. if (canvas.debug)
  371. qDebug("PatchCanvas::renameGroup(%i, %s)", group_id, new_group_name.toUtf8().constData());
  372. foreach2 (group_dict_t& group, canvas.group_list)
  373. if (group.group_id == group_id)
  374. {
  375. group.group_name = new_group_name;
  376. group.widgets[0]->setGroupName(new_group_name);
  377. if (group.split && group.widgets[1])
  378. group.widgets[1]->setGroupName(new_group_name);
  379. QTimer::singleShot(0, canvas.scene, SLOT(update()));
  380. return;
  381. }
  382. }
  383. qCritical("PatchCanvas::renameGroup(%i, %s) - unable to find group to rename", group_id, new_group_name.toUtf8().constData());
  384. }
  385. void splitGroup(int group_id)
  386. {
  387. if (canvas.debug)
  388. qDebug("PatchCanvas::splitGroup(%i)", group_id);
  389. CanvasBox* item = 0;
  390. QString group_name;
  391. Icon group_icon = ICON_APPLICATION;
  392. QList<port_dict_t> ports_data;
  393. QList<connection_dict_t> conns_data;
  394. // Step 1 - Store all Item data
  395. foreach (const group_dict_t& group, canvas.group_list)
  396. {
  397. if (group.group_id == group_id)
  398. {
  399. if (group.split)
  400. {
  401. qCritical("PatchCanvas::splitGroup(%i) - group is already splitted", group_id);
  402. return;
  403. }
  404. item = group.widgets[0];
  405. group_name = group.group_name;
  406. group_icon = group.icon;
  407. break;
  408. }
  409. }
  410. if (!item)
  411. {
  412. qCritical("PatchCanvas::splitGroup(%i) - unable to find group to split", group_id);
  413. return;
  414. }
  415. QList<int> port_list_ids = QList<int>(item->getPortList());
  416. foreach (const port_dict_t& port, canvas.port_list)
  417. {
  418. if (port_list_ids.contains(port.port_id))
  419. {
  420. port_dict_t port_dict;
  421. port_dict.group_id = port.group_id;
  422. port_dict.port_id = port.port_id;
  423. port_dict.port_name = port.port_name;
  424. port_dict.port_mode = port.port_mode;
  425. port_dict.port_type = port.port_type;
  426. port_dict.widget = 0;
  427. ports_data.append(port_dict);
  428. }
  429. }
  430. foreach (const connection_dict_t& connection, canvas.connection_list)
  431. {
  432. if (port_list_ids.contains(connection.port_out_id) || port_list_ids.contains(connection.port_in_id))
  433. {
  434. connection_dict_t connection_dict;
  435. connection_dict.connection_id = connection.connection_id;
  436. connection_dict.port_in_id = connection.port_in_id;
  437. connection_dict.port_out_id = connection.port_out_id;
  438. connection_dict.widget = 0;
  439. conns_data.append(connection_dict);
  440. }
  441. }
  442. // Step 2 - Remove Item and Children
  443. foreach (const connection_dict_t& conn, conns_data)
  444. disconnectPorts(conn.connection_id);
  445. foreach (const int& port_id, port_list_ids)
  446. removePort(port_id);
  447. removeGroup(group_id);
  448. // Step 3 - Re-create Item, now splitted
  449. addGroup(group_id, group_name, SPLIT_YES, group_icon);
  450. foreach (const port_dict_t& port, ports_data)
  451. addPort(group_id, port.port_id, port.port_name, port.port_mode, port.port_type);
  452. foreach (const connection_dict_t& conn, conns_data)
  453. connectPorts(conn.connection_id, conn.port_out_id, conn.port_in_id);
  454. QTimer::singleShot(0, canvas.scene, SLOT(update()));
  455. }
  456. void joinGroup(int group_id)
  457. {
  458. if (canvas.debug)
  459. qDebug("PatchCanvas::joinGroup(%i)", group_id);
  460. CanvasBox* item = 0;
  461. CanvasBox* s_item = 0;
  462. QString group_name;
  463. Icon group_icon = ICON_APPLICATION;
  464. QList<port_dict_t> ports_data;
  465. QList<connection_dict_t> conns_data;
  466. // Step 1 - Store all Item data
  467. foreach (const group_dict_t& group, canvas.group_list)
  468. {
  469. if (group.group_id == group_id)
  470. {
  471. if (group.split == false)
  472. {
  473. qCritical("PatchCanvas::joinGroup(%i) - group is not splitted", group_id);
  474. return;
  475. }
  476. item = group.widgets[0];
  477. s_item = group.widgets[1];
  478. group_name = group.group_name;
  479. group_icon = group.icon;
  480. break;
  481. }
  482. }
  483. if (!item || !s_item)
  484. {
  485. qCritical("PatchCanvas::joinGroup(%i) - Unable to find groups to join", group_id);
  486. return;
  487. }
  488. QList<int> port_list_ids = QList<int>(item->getPortList());
  489. QList<int> port_list_idss = s_item->getPortList();
  490. foreach (const int& port_id, port_list_idss)
  491. {
  492. if (port_list_ids.contains(port_id) == false)
  493. port_list_ids.append(port_id);
  494. }
  495. foreach (const port_dict_t& port, canvas.port_list)
  496. {
  497. if (port_list_ids.contains(port.port_id))
  498. {
  499. port_dict_t port_dict;
  500. port_dict.group_id = port.group_id;
  501. port_dict.port_id = port.port_id;
  502. port_dict.port_name = port.port_name;
  503. port_dict.port_mode = port.port_mode;
  504. port_dict.port_type = port.port_type;
  505. port_dict.widget = 0;
  506. ports_data.append(port_dict);
  507. }
  508. }
  509. foreach (const connection_dict_t& connection, canvas.connection_list)
  510. {
  511. if (port_list_ids.contains(connection.port_out_id) || port_list_ids.contains(connection.port_in_id))
  512. {
  513. connection_dict_t connection_dict;
  514. connection_dict.connection_id = connection.connection_id;
  515. connection_dict.port_in_id = connection.port_in_id;
  516. connection_dict.port_out_id = connection.port_out_id;
  517. connection_dict.widget = 0;
  518. conns_data.append(connection_dict);
  519. }
  520. }
  521. // Step 2 - Remove Item and Children
  522. foreach (const connection_dict_t& conn, conns_data)
  523. disconnectPorts(conn.connection_id);
  524. foreach (const int& port_id, port_list_ids)
  525. removePort(port_id);
  526. removeGroup(group_id);
  527. // Step 3 - Re-create Item, now together
  528. addGroup(group_id, group_name, SPLIT_NO, group_icon);
  529. foreach (const port_dict_t& port, ports_data)
  530. addPort(group_id, port.port_id, port.port_name, port.port_mode, port.port_type);
  531. foreach (const connection_dict_t& conn, conns_data)
  532. connectPorts(conn.connection_id, conn.port_out_id, conn.port_in_id);
  533. QTimer::singleShot(0, canvas.scene, SLOT(update()));
  534. }
  535. QPointF getGroupPos(int group_id, PortMode port_mode)
  536. {
  537. if (canvas.debug)
  538. qDebug("PatchCanvas::getGroupPos(%i, %s)", group_id, port_mode2str(port_mode));
  539. foreach (const group_dict_t& group, canvas.group_list)
  540. {
  541. if (group.group_id == group_id)
  542. {
  543. if (group.split)
  544. {
  545. if (port_mode == PORT_MODE_OUTPUT)
  546. return group.widgets[0]->pos();
  547. else if (port_mode == PORT_MODE_INPUT)
  548. return group.widgets[1]->pos();
  549. else
  550. return QPointF(0, 0);
  551. }
  552. else
  553. return group.widgets[0]->pos();
  554. }
  555. }
  556. qCritical("PatchCanvas::getGroupPos(%i, %s) - unable to find group", group_id, port_mode2str(port_mode));
  557. return QPointF(0,0);
  558. }
  559. void setGroupPos(int group_id, int group_pos_x, int group_pos_y)
  560. {
  561. setGroupPos(group_id, group_pos_x, group_pos_y, group_pos_x, group_pos_y);
  562. }
  563. void setGroupPos(int group_id, int group_pos_x, int group_pos_y, int group_pos_xs, int group_pos_ys)
  564. {
  565. if (canvas.debug)
  566. qDebug("PatchCanvas::setGroupPos(%i, %i, %i, %i, %i)", group_id, group_pos_x, group_pos_y, group_pos_xs, group_pos_ys);
  567. foreach (const group_dict_t& group, canvas.group_list)
  568. {
  569. if (group.group_id == group_id)
  570. {
  571. group.widgets[0]->setPos(group_pos_x, group_pos_y);
  572. if (group.split && group.widgets[1])
  573. {
  574. group.widgets[1]->setPos(group_pos_xs, group_pos_ys);
  575. }
  576. QTimer::singleShot(0, canvas.scene, SLOT(update()));
  577. return;
  578. }
  579. }
  580. qCritical("PatchCanvas::setGroupPos(%i, %i, %i, %i, %i) - unable to find group to reposition", group_id, group_pos_x, group_pos_y, group_pos_xs, group_pos_ys);
  581. }
  582. void setGroupIcon(int group_id, Icon icon)
  583. {
  584. if (canvas.debug)
  585. qDebug("PatchCanvas::setGroupIcon(%i, %s)", group_id, icon2str(icon));
  586. foreach2 (group_dict_t& group, canvas.group_list)
  587. if (group.group_id == group_id)
  588. {
  589. group.icon = icon;
  590. group.widgets[0]->setIcon(icon);
  591. if (group.split && group.widgets[1])
  592. group.widgets[1]->setIcon(icon);
  593. QTimer::singleShot(0, canvas.scene, SLOT(update()));
  594. return;
  595. }
  596. }
  597. qCritical("PatchCanvas::setGroupIcon(%i, %s) - unable to find group to change icon", group_id, icon2str(icon));
  598. }
  599. void addPort(int group_id, int port_id, QString port_name, PortMode port_mode, PortType port_type)
  600. {
  601. if (canvas.debug)
  602. qDebug("PatchCanvas::addPort(%i, %i, %s, %s, %s)", group_id, port_id, port_name.toUtf8().constData(), port_mode2str(port_mode), port_type2str(port_type));
  603. foreach (const port_dict_t& port, canvas.port_list)
  604. {
  605. if (port.group_id == group_id and port.port_id == port_id)
  606. {
  607. qWarning("PatchCanvas::addPort(%i, %i, %s, %s, %s) - port already exists" , group_id, port_id, port_name.toUtf8().constData(), port_mode2str(port_mode), port_type2str(port_type));
  608. return;
  609. }
  610. }
  611. CanvasBox* box_widget = 0;
  612. CanvasPort* port_widget = 0;
  613. foreach (const group_dict_t& group, canvas.group_list)
  614. {
  615. if (group.group_id == group_id)
  616. {
  617. int n;
  618. if (group.split && group.widgets[0]->getSplittedMode() != port_mode && group.widgets[1])
  619. n = 1;
  620. else
  621. n = 0;
  622. box_widget = group.widgets[n];
  623. port_widget = box_widget->addPortFromGroup(port_id, port_name, port_mode, port_type);
  624. break;
  625. }
  626. }
  627. if (!box_widget || !port_widget)
  628. {
  629. qCritical("PatchCanvas::addPort(%i, %i, %s, %s, %s) - unable to find parent group", group_id, port_id, port_name.toUtf8().constData(), port_mode2str(port_mode), port_type2str(port_type));
  630. return;
  631. }
  632. if (options.eyecandy == EYECANDY_FULL)
  633. CanvasItemFX(port_widget, true);
  634. port_dict_t port_dict;
  635. port_dict.group_id = group_id;
  636. port_dict.port_id = port_id;
  637. port_dict.port_name = port_name;
  638. port_dict.port_mode = port_mode;
  639. port_dict.port_type = port_type;
  640. port_dict.widget = port_widget;
  641. canvas.port_list.append(port_dict);
  642. box_widget->updatePositions();
  643. QTimer::singleShot(0, canvas.scene, SLOT(update()));
  644. }
  645. void removePort(int port_id)
  646. {
  647. if (canvas.debug)
  648. qDebug("PatchCanvas::removePort(%i)", port_id);
  649. foreach2 (const port_dict_t& port, canvas.port_list)
  650. if (port.port_id == port_id)
  651. {
  652. CanvasPort* item = port.widget;
  653. ((CanvasBox*)item->parentItem())->removePortFromGroup(port_id);
  654. canvas.scene->removeItem(item);
  655. delete item;
  656. canvas.port_list.takeAt(i);
  657. QTimer::singleShot(0, canvas.scene, SLOT(update()));
  658. return;
  659. }
  660. }
  661. qCritical("PatchCanvas::removePort(%i) - unable to find port to remove", port_id);
  662. }
  663. void renamePort(int port_id, QString new_port_name)
  664. {
  665. if (canvas.debug)
  666. qDebug("PatchCanvas::renamePort(%i, %s)", port_id, new_port_name.toUtf8().constData());
  667. foreach2 (port_dict_t& port, canvas.port_list)
  668. if (port.port_id == port_id)
  669. {
  670. port.port_name = new_port_name;
  671. port.widget->setPortName(new_port_name);
  672. ((CanvasBox*)port.widget->parentItem())->updatePositions();
  673. QTimer::singleShot(0, canvas.scene, SLOT(update()));
  674. return;
  675. }
  676. }
  677. qCritical("PatchCanvas::renamePort(%i, %s) - unable to find port to rename", port_id, new_port_name.toUtf8().constData());
  678. }
  679. void connectPorts(int connection_id, int port_out_id, int port_in_id)
  680. {
  681. if (canvas.debug)
  682. qDebug("PatchCanvas::connectPorts(%i, %i, %i)", connection_id, port_out_id, port_in_id);
  683. CanvasPort* port_out = 0;
  684. CanvasPort* port_in = 0;
  685. CanvasBox* port_out_parent = 0;
  686. CanvasBox* port_in_parent = 0;
  687. foreach (const port_dict_t& port, canvas.port_list)
  688. {
  689. if (port.port_id == port_out_id)
  690. {
  691. port_out = port.widget;
  692. port_out_parent = (CanvasBox*)port_out->parentItem();
  693. }
  694. else if (port.port_id == port_in_id)
  695. {
  696. port_in = port.widget;
  697. port_in_parent = (CanvasBox*)port_in->parentItem();
  698. }
  699. }
  700. if (!port_out || !port_in)
  701. {
  702. qCritical("PatchCanvas::connectPorts(%i, %i, %i) - Unable to find ports to connect", connection_id, port_out_id, port_in_id);
  703. return;
  704. }
  705. connection_dict_t connection_dict;
  706. connection_dict.connection_id = connection_id;
  707. connection_dict.port_out_id = port_out_id;
  708. connection_dict.port_in_id = port_in_id;
  709. if (options.use_bezier_lines)
  710. connection_dict.widget = new CanvasBezierLine(port_out, port_in, 0);
  711. else
  712. connection_dict.widget = new CanvasLine(port_out, port_in, 0);
  713. port_out_parent->addLineFromGroup(connection_dict.widget, connection_id);
  714. port_in_parent->addLineFromGroup(connection_dict.widget, connection_id);
  715. canvas.last_z_value += 1;
  716. port_out_parent->setZValue(canvas.last_z_value);
  717. port_in_parent->setZValue(canvas.last_z_value);
  718. canvas.last_z_value += 1;
  719. connection_dict.widget->setZValue(canvas.last_z_value);
  720. canvas.connection_list.append(connection_dict);
  721. if (options.eyecandy == EYECANDY_FULL)
  722. {
  723. QGraphicsItem* item = (options.use_bezier_lines) ? (QGraphicsItem*)(CanvasBezierLine*)connection_dict.widget : (QGraphicsItem*)(CanvasLine*)connection_dict.widget;
  724. CanvasItemFX(item, true);
  725. }
  726. QTimer::singleShot(0, canvas.scene, SLOT(update()));
  727. }
  728. void disconnectPorts(int connection_id)
  729. {
  730. if (canvas.debug)
  731. qDebug("PatchCanvas::disconnectPorts(%i)", connection_id);
  732. int port_1_id, port_2_id;
  733. AbstractCanvasLine* line = 0;
  734. QGraphicsItem* item1 = 0;
  735. QGraphicsItem* item2 = 0;
  736. foreach2 (const connection_dict_t& connection, canvas.connection_list)
  737. if (connection.connection_id == connection_id)
  738. {
  739. port_1_id = connection.port_out_id;
  740. port_2_id = connection.port_in_id;
  741. line = connection.widget;
  742. canvas.connection_list.takeAt(i);
  743. break;
  744. }
  745. }
  746. if (!line)
  747. {
  748. qCritical("PatchCanvas::disconnectPorts(%i) - unable to find connection ports", connection_id);
  749. return;
  750. }
  751. foreach (const port_dict_t& port, canvas.port_list)
  752. {
  753. if (port.port_id == port_1_id)
  754. {
  755. item1 = port.widget;
  756. break;
  757. }
  758. }
  759. if (!item1)
  760. {
  761. qCritical("PatchCanvas::disconnectPorts(%i) - unable to find output port", connection_id);
  762. return;
  763. }
  764. foreach (const port_dict_t& port, canvas.port_list)
  765. {
  766. if (port.port_id == port_2_id)
  767. {
  768. item2 = port.widget;
  769. break;
  770. }
  771. }
  772. if (!item2)
  773. {
  774. qCritical("PatchCanvas::disconnectPorts(%i) - unable to find input port", connection_id);
  775. return;
  776. }
  777. ((CanvasBox*)item1->parentItem())->removeLineFromGroup(connection_id);
  778. ((CanvasBox*)item2->parentItem())->removeLineFromGroup(connection_id);
  779. if (options.eyecandy == EYECANDY_FULL)
  780. {
  781. QGraphicsItem* item = (options.use_bezier_lines) ? (QGraphicsItem*)(CanvasBezierLine*)line : (QGraphicsItem*)(CanvasLine*)line;
  782. CanvasItemFX(item, false, true);
  783. }
  784. else
  785. line->deleteFromScene();
  786. QTimer::singleShot(0, canvas.scene, SLOT(update()));
  787. }
  788. void arrange()
  789. {
  790. if (canvas.debug)
  791. qDebug("PatchCanvas::Arrange()");
  792. }
  793. void updateZValues()
  794. {
  795. if (canvas.debug)
  796. qDebug("PatchCanvas::updateZValues()");
  797. foreach (const group_dict_t& group, canvas.group_list)
  798. {
  799. group.widgets[0]->resetLinesZValue();
  800. if (group.split and group.widgets[1])
  801. group.widgets[1]->resetLinesZValue();
  802. }
  803. }
  804. /* Extra Internal functions */
  805. QString CanvasGetGroupName(int group_id)
  806. {
  807. if (canvas.debug)
  808. qDebug("PatchCanvas::CanvasGetGroupName(%i)", group_id);
  809. foreach (const group_dict_t& group, canvas.group_list)
  810. {
  811. if (group.group_id == group_id)
  812. return group.group_name;
  813. }
  814. qCritical("PatchCanvas::CanvasGetGroupName(%i) - unable to find group", group_id);
  815. return "";
  816. }
  817. int CanvasGetGroupPortCount(int group_id)
  818. {
  819. if (canvas.debug)
  820. qDebug("PatchCanvas::CanvasGetGroupPortCount(%i)", group_id);
  821. int port_count = 0;
  822. foreach (const port_dict_t& port, canvas.port_list)
  823. {
  824. if (port.group_id == group_id)
  825. port_count += 1;
  826. }
  827. return port_count;
  828. }
  829. QPointF CanvasGetNewGroupPos(bool horizontal)
  830. {
  831. if (canvas.debug)
  832. qDebug("PatchCanvas::CanvasGetNewGroupPos(%s)", bool2str(horizontal));
  833. QPointF new_pos(canvas.initial_pos.x(), canvas.initial_pos.y());
  834. QList<QGraphicsItem*> items = canvas.scene->items();
  835. bool break_loop = false;
  836. while (break_loop == false)
  837. {
  838. bool break_for = false;
  839. for (int i=0; i < items.count(); i++)
  840. {
  841. QGraphicsItem* item = items[i];
  842. if (item && item->type() == CanvasBoxType)
  843. {
  844. if (item->sceneBoundingRect().contains(new_pos))
  845. {
  846. if (horizontal)
  847. new_pos += QPointF(item->boundingRect().width()+15, 0);
  848. else
  849. new_pos += QPointF(0, item->boundingRect().height()+15);
  850. break;
  851. }
  852. }
  853. if (i >= items.count()-1 && break_for == false)
  854. break_loop = true;
  855. }
  856. }
  857. return new_pos;
  858. }
  859. QString CanvasGetFullPortName(int port_id)
  860. {
  861. if (canvas.debug)
  862. qDebug("PatchCanvas::CanvasGetFullPortName(%i)", port_id);
  863. foreach (const port_dict_t& port, canvas.port_list)
  864. {
  865. if (port.port_id == port_id)
  866. {
  867. int group_id = port.group_id;
  868. foreach (const group_dict_t& group, canvas.group_list)
  869. {
  870. if (group.group_id == group_id)
  871. return group.group_name + ":" + port.port_name;
  872. }
  873. break;
  874. }
  875. }
  876. qCritical("PatchCanvas::CanvasGetFullPortName(%i) - unable to find port", port_id);
  877. return "";
  878. }
  879. QList<int> CanvasGetPortConnectionList(int port_id)
  880. {
  881. if (canvas.debug)
  882. qDebug("PatchCanvas::CanvasGetPortConnectionList(%i)", port_id);
  883. QList<int> port_con_list;
  884. foreach (const connection_dict_t& connection, canvas.connection_list)
  885. {
  886. if (connection.port_out_id == port_id || connection.port_in_id == port_id)
  887. port_con_list.append(connection.connection_id);
  888. }
  889. return port_con_list;
  890. }
  891. int CanvasGetConnectedPort(int connection_id, int port_id)
  892. {
  893. if (canvas.debug)
  894. qDebug("PatchCanvas::CanvasGetConnectedPort(%i, %i)", connection_id, port_id);
  895. foreach (const connection_dict_t& connection, canvas.connection_list)
  896. {
  897. if (connection.connection_id == connection_id)
  898. {
  899. if (connection.port_out_id == port_id)
  900. return connection.port_in_id;
  901. else
  902. return connection.port_out_id;
  903. }
  904. }
  905. qCritical("PatchCanvas::CanvasGetConnectedPort(%i, %i) - unable to find connection", connection_id, port_id);
  906. return 0;
  907. }
  908. void CanvasRemoveAnimation(CanvasFadeAnimation* f_animation)
  909. {
  910. if (canvas.debug)
  911. qDebug("PatchCanvas::CanvasRemoveAnimation(%p)", f_animation);
  912. foreach2 (const animation_dict_t& animation, canvas.animation_list)
  913. if (animation.animation == f_animation)
  914. {
  915. delete animation.animation;
  916. canvas.animation_list.takeAt(i);
  917. break;
  918. }
  919. }
  920. }
  921. void CanvasPostponedGroups()
  922. {
  923. if (canvas.debug)
  924. qDebug("PatchCanvas::CanvasPostponedGroups()");
  925. }
  926. void CanvasCallback(CallbackAction action, int value1, int value2, QString value_str)
  927. {
  928. if (canvas.debug)
  929. qDebug("PatchCanvas::CanvasCallback(%i, %i, %i, %s)", action, value1, value2, value_str.toStdString().data());
  930. canvas.callback(action, value1, value2, value_str);
  931. }
  932. void CanvasItemFX(QGraphicsItem* item, bool show, bool destroy)
  933. {
  934. if (canvas.debug)
  935. qDebug("PatchCanvas::CanvasItemFX(%p, %s, %s)", item, bool2str(show), bool2str(destroy));
  936. // Check if item already has an animationItemFX
  937. foreach2 (const animation_dict_t& animation, canvas.animation_list)
  938. if (animation.item == item)
  939. {
  940. if (animation.animation)
  941. {
  942. animation.animation->stop();
  943. delete animation.animation;
  944. }
  945. canvas.animation_list.takeAt(i);
  946. break;
  947. }
  948. }
  949. CanvasFadeAnimation* animation = new CanvasFadeAnimation(item, show);
  950. animation->setDuration(show ? 750 : 500);
  951. animation_dict_t animation_dict;
  952. animation_dict.animation = animation;
  953. animation_dict.item = item;
  954. canvas.animation_list.append(animation_dict);
  955. if (show)
  956. {
  957. QObject::connect(animation, SIGNAL(finished()), canvas.qobject, SLOT(AnimationIdle()));
  958. }
  959. else
  960. {
  961. if (destroy)
  962. QObject::connect(animation, SIGNAL(finished()), canvas.qobject, SLOT(AnimationDestroy()));
  963. else
  964. QObject::connect(animation, SIGNAL(finished()), canvas.qobject, SLOT(AnimationHide()));
  965. }
  966. animation->start();
  967. }
  968. void CanvasRemoveItemFX(QGraphicsItem* item)
  969. {
  970. if (canvas.debug)
  971. qDebug("PatchCanvas::CanvasRemoveItemFX(%p)", item);
  972. switch (item->type())
  973. {
  974. case CanvasBoxType:
  975. {
  976. CanvasBox* box = (CanvasBox*)item;
  977. box->removeIconFromScene();
  978. canvas.scene->removeItem(box);
  979. delete box;
  980. }
  981. case CanvasPortType:
  982. {
  983. CanvasPort* port = (CanvasPort*)item;
  984. canvas.scene->removeItem(port);
  985. delete port;
  986. }
  987. case CanvasLineType:
  988. case CanvasBezierLineType:
  989. {
  990. AbstractCanvasLine* line = (AbstractCanvasLine*)item;
  991. line->deleteFromScene();
  992. }
  993. default:
  994. break;
  995. }
  996. }
  997. END_NAMESPACE_PATCHCANVAS