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.

1203 lines
35KB

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