Browse Source

Add PatchCanvas C++ version, with a test app inside

tags/v0.9.0
falkTX 13 years ago
parent
commit
0802f745e1
33 changed files with 5147 additions and 0 deletions
  1. +47
    -0
      c++/patchcanvas/PatchCanvas.pro
  2. +63
    -0
      c++/patchcanvas/abstractcanvasline.h
  3. +162
    -0
      c++/patchcanvas/canvasbezierline.cpp
  4. +72
    -0
      c++/patchcanvas/canvasbezierline.h
  5. +104
    -0
      c++/patchcanvas/canvasbezierlinemov.cpp
  6. +60
    -0
      c++/patchcanvas/canvasbezierlinemov.h
  7. +680
    -0
      c++/patchcanvas/canvasbox.cpp
  8. +106
    -0
      c++/patchcanvas/canvasbox.h
  9. +46
    -0
      c++/patchcanvas/canvasboxshadow.cpp
  10. +44
    -0
      c++/patchcanvas/canvasboxshadow.h
  11. +71
    -0
      c++/patchcanvas/canvasfadeanimation.cpp
  12. +51
    -0
      c++/patchcanvas/canvasfadeanimation.h
  13. +134
    -0
      c++/patchcanvas/canvasicon.cpp
  14. +52
    -0
      c++/patchcanvas/canvasicon.h
  15. +148
    -0
      c++/patchcanvas/canvasline.cpp
  16. +72
    -0
      c++/patchcanvas/canvasline.h
  17. +94
    -0
      c++/patchcanvas/canvaslinemov.cpp
  18. +60
    -0
      c++/patchcanvas/canvaslinemov.h
  19. +447
    -0
      c++/patchcanvas/canvasport.cpp
  20. +79
    -0
      c++/patchcanvas/canvasport.h
  21. +38
    -0
      c++/patchcanvas/canvasportglow.cpp
  22. +35
    -0
      c++/patchcanvas/canvasportglow.h
  23. +405
    -0
      c++/patchcanvas/canvastestapp.cpp
  24. +50
    -0
      c++/patchcanvas/canvastestapp.h
  25. +95
    -0
      c++/patchcanvas/canvastestapp.ui
  26. +11
    -0
      c++/patchcanvas/main.cpp
  27. +134
    -0
      c++/patchcanvas/patchcanvas-api.h
  28. +178
    -0
      c++/patchcanvas/patchcanvas-theme.cpp
  29. +106
    -0
      c++/patchcanvas/patchcanvas-theme.h
  30. +1020
    -0
      c++/patchcanvas/patchcanvas.cpp
  31. +129
    -0
      c++/patchcanvas/patchcanvas.h
  32. +287
    -0
      c++/patchcanvas/patchscene.cpp
  33. +67
    -0
      c++/patchcanvas/patchscene.h

+ 47
- 0
c++/patchcanvas/PatchCanvas.pro View File

@@ -0,0 +1,47 @@
#-------------------------------------------------
#
# Project created by QtCreator 2011-10-17T21:44:58
#
#-------------------------------------------------

QT = core gui svg opengl
TEMPLATE = app
CONFIG += debug

TARGET = PatchCanvas

SOURCES = main.cpp canvastestapp.cpp \
patchcanvas.cpp \
patchcanvas-theme.cpp \
patchscene.cpp \
canvasbox.cpp \
canvasportglow.cpp \
canvasboxshadow.cpp \
canvasicon.cpp \
canvasfadeanimation.cpp \
canvasline.cpp \
canvasport.cpp \
canvasbezierline.cpp \
canvaslinemov.cpp \
canvasbezierlinemov.cpp

HEADERS = canvastestapp.h \
patchcanvas.h \
patchcanvas-api.h \
patchcanvas-theme.h \
patchscene.h \
abstractcanvasline.h \
canvasline.h \
canvasbezierline.h \
canvaslinemov.h \
canvasbezierlinemov.h \
canvasport.h \
canvasbox.h \
canvasicon.h \
canvasboxshadow.h \
canvasportglow.h \
canvasfadeanimation.h

FORMS = canvastestapp.ui

LIBS = -ljack

+ 63
- 0
c++/patchcanvas/abstractcanvasline.h View File

@@ -0,0 +1,63 @@
/*
* Patchbay Canvas engine using QGraphicsView/Scene
* Copyright (C) 2010-2012 Filipe Coelho <falktx@gmail.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* For a full copy of the GNU General Public License see the COPYING file
*/

#ifndef ABSTRACTCANVASLINE_H
#define ABSTRACTCANVASLINE_H

#include "patchcanvas.h"

START_NAMESPACE_PATCHCANVAS

class AbstractCanvasLine
{
public:
AbstractCanvasLine() {}

virtual void deleteFromScene() = 0;

virtual bool isLocked() const = 0;
virtual void setLocked(bool yesno) = 0;

virtual bool isLineSelected() const = 0;
virtual void setLineSelected(bool yesno) = 0;

virtual void updateLinePos() = 0;

virtual int type() const = 0;

// QGraphicsItem generic calls
virtual void setZValue(qreal z) = 0;
};

class AbstractCanvasLineMov
{
public:
AbstractCanvasLineMov() {}

virtual void deleteFromScene() = 0;

virtual void updateLinePos(QPointF scenePos) = 0;

virtual int type() const = 0;

// QGraphicsItem generic calls
virtual void setZValue(qreal z) = 0;
};

END_NAMESPACE_PATCHCANVAS

#endif // ABSTRACTCANVASLINE_H

+ 162
- 0
c++/patchcanvas/canvasbezierline.cpp View File

@@ -0,0 +1,162 @@
/*
* Patchbay Canvas engine using QGraphicsView/Scene
* Copyright (C) 2010-2012 Filipe Coelho <falktx@gmail.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* For a full copy of the GNU General Public License see the COPYING file
*/

#include "canvasbezierline.h"

#include <QtGui/QPainter>

#include "canvasport.h"
#include "canvasportglow.h"

START_NAMESPACE_PATCHCANVAS

CanvasBezierLine::CanvasBezierLine(CanvasPort* item1_, CanvasPort* item2_, QGraphicsItem* parent) :
QGraphicsPathItem(parent, canvas.scene)
{
item1 = item1_;
item2 = item2_;

m_locked = false;
m_lineSelected = false;

setBrush(QColor(0,0,0,0));
setGraphicsEffect(0);
updateLinePos();
}

CanvasBezierLine::~CanvasBezierLine()
{
setGraphicsEffect(0);
}

void CanvasBezierLine::deleteFromScene()
{
canvas.scene->removeItem(this);
delete this;
}

bool CanvasBezierLine::isLocked() const
{
return m_locked;
}

void CanvasBezierLine::setLocked(bool yesno)
{
m_locked = yesno;
}

bool CanvasBezierLine::isLineSelected() const
{
return m_lineSelected;
}

void CanvasBezierLine::setLineSelected(bool yesno)
{
if (m_locked)
return;

if (options.eyecandy)
{
if (yesno)
setGraphicsEffect(new CanvasPortGlow(item1->getPortType(), toGraphicsObject()));
else
setGraphicsEffect(0);
}

m_lineSelected = yesno;
updateLineGradient();
}

void CanvasBezierLine::updateLinePos()
{
if (item1->getPortMode() == PORT_MODE_OUTPUT)
{
int item1_x = item1->scenePos().x() + item1->getPortWidth()+12;
int item1_y = item1->scenePos().y() + 7.5;

int item2_x = item2->scenePos().x();
int item2_y = item2->scenePos().y()+7.5;

int item1_mid_x = abs(item1_x-item2_x)/2;
int item1_new_x = item1_x+item1_mid_x;

int item2_mid_x = abs(item1_x-item2_x)/2;
int item2_new_x = item2_x-item2_mid_x;

QPainterPath path(QPointF(item1_x, item1_y));
path.cubicTo(item1_new_x, item1_y, item2_new_x, item2_y, item2_x, item2_y);
setPath(path);

m_lineSelected = false;
updateLineGradient();
}
}

int CanvasBezierLine::type() const
{
return CanvasBezierLineType;
}

void CanvasBezierLine::updateLineGradient()
{
short pos1, pos2;
int pos_top = boundingRect().top();
int pos_bot = boundingRect().bottom();

if (item2->scenePos().y() >= item1->scenePos().y())
{
pos1 = 0;
pos2 = 1;
}
else
{
pos1 = 1;
pos2 = 0;
}

PortType port_type1 = item1->getPortType();
PortType port_type2 = item2->getPortType();
QLinearGradient port_gradient(0, pos_top, 0, pos_bot);

if (port_type1 == PORT_TYPE_AUDIO_JACK)
port_gradient.setColorAt(pos1, m_lineSelected ? canvas.theme->line_audio_jack_sel : canvas.theme->line_audio_jack);
else if (port_type1 == PORT_TYPE_MIDI_JACK)
port_gradient.setColorAt(pos1, m_lineSelected ? canvas.theme->line_midi_jack_sel : canvas.theme->line_midi_jack);
else if (port_type1 == PORT_TYPE_MIDI_A2J)
port_gradient.setColorAt(pos1, m_lineSelected ? canvas.theme->line_midi_a2j_sel : canvas.theme->line_midi_a2j);
else if (port_type1 == PORT_TYPE_MIDI_ALSA)
port_gradient.setColorAt(pos1, m_lineSelected ? canvas.theme->line_midi_alsa_sel : canvas.theme->line_midi_alsa);

if (port_type2 == PORT_TYPE_AUDIO_JACK)
port_gradient.setColorAt(pos2, m_lineSelected ? canvas.theme->line_audio_jack_sel : canvas.theme->line_audio_jack);
else if (port_type2 == PORT_TYPE_MIDI_JACK)
port_gradient.setColorAt(pos2, m_lineSelected ? canvas.theme->line_midi_jack_sel : canvas.theme->line_midi_jack);
else if (port_type2 == PORT_TYPE_MIDI_A2J)
port_gradient.setColorAt(pos2, m_lineSelected ? canvas.theme->line_midi_a2j_sel : canvas.theme->line_midi_a2j);
else if (port_type2 == PORT_TYPE_MIDI_ALSA)
port_gradient.setColorAt(pos2, m_lineSelected ? canvas.theme->line_midi_alsa_sel : canvas.theme->line_midi_alsa);

setPen(QPen(port_gradient, 2));
}

void CanvasBezierLine::paint(QPainter* painter, const QStyleOptionGraphicsItem* option, QWidget* widget)
{
painter->setRenderHint(QPainter::Antialiasing, bool(options.antialiasing));
QGraphicsPathItem::paint(painter, option, widget);
}

END_NAMESPACE_PATCHCANVAS

+ 72
- 0
c++/patchcanvas/canvasbezierline.h View File

@@ -0,0 +1,72 @@
/*
* Patchbay Canvas engine using QGraphicsView/Scene
* Copyright (C) 2010-2012 Filipe Coelho <falktx@gmail.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* For a full copy of the GNU General Public License see the COPYING file
*/

#ifndef CANVASBEZIERLINE_H
#define CANVASBEZIERLINE_H

#include <QtGui/QGraphicsPathItem>

#include "abstractcanvasline.h"

class QPainter;

START_NAMESPACE_PATCHCANVAS

class CanvasPort;
class CanvasPortGlow;

class CanvasBezierLine :
public AbstractCanvasLine,
public QGraphicsPathItem
{
public:
CanvasBezierLine(CanvasPort* item1, CanvasPort* item2, QGraphicsItem* parent);
~CanvasBezierLine();

virtual void deleteFromScene();

virtual bool isLocked() const;
virtual void setLocked(bool yesno);

virtual bool isLineSelected() const;
virtual void setLineSelected(bool yesno);

virtual void updateLinePos();

virtual int type() const;

// QGraphicsItem generic calls
virtual void setZValue(qreal z)
{
QGraphicsPathItem::setZValue(z);
}

private:
CanvasPort* item1;
CanvasPort* item2;
CanvasPortGlow* glow;
bool m_locked;
bool m_lineSelected;

void updateLineGradient();

virtual void paint(QPainter* painter, const QStyleOptionGraphicsItem* option, QWidget* widget);
};

END_NAMESPACE_PATCHCANVAS

#endif // CANVASBEZIERLINE_H

+ 104
- 0
c++/patchcanvas/canvasbezierlinemov.cpp View File

@@ -0,0 +1,104 @@
/*
* Patchbay Canvas engine using QGraphicsView/Scene
* Copyright (C) 2010-2012 Filipe Coelho <falktx@gmail.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* For a full copy of the GNU General Public License see the COPYING file
*/

#include "canvasbezierlinemov.h"

#include <QtGui/QPainter>

#include "canvasport.h"

START_NAMESPACE_PATCHCANVAS

CanvasBezierLineMov::CanvasBezierLineMov(PortMode port_mode, PortType port_type, QGraphicsItem* parent) :
QGraphicsPathItem(parent, canvas.scene)
{
m_port_mode = port_mode;
m_port_type = port_type;

// Port position doesn't change while moving around line
p_itemX = scenePos().x();
p_itemY = scenePos().y();
p_width = ((CanvasPort*)parentItem())->getPortWidth();

QPen pen;

if (port_type == PORT_TYPE_AUDIO_JACK)
pen = QPen(canvas.theme->line_audio_jack, 2);
else if (port_type == PORT_TYPE_MIDI_JACK)
pen = QPen(canvas.theme->line_midi_jack, 2);
else if (port_type == PORT_TYPE_MIDI_A2J)
pen = QPen(canvas.theme->line_midi_a2j, 2);
else if (port_type == PORT_TYPE_MIDI_ALSA)
pen = QPen(canvas.theme->line_midi_alsa, 2);
else
{
qWarning("PatchCanvas::CanvasBezierLineMov(%s, %s, %p) - invalid port type", port_mode2str(port_mode), port_type2str(port_type), parent);
pen = QPen(Qt::black);
}

QColor color(0,0,0,0);
setBrush(color);
setPen(pen);
}

void CanvasBezierLineMov::deleteFromScene()
{
canvas.scene->removeItem(this);
delete this;
}

void CanvasBezierLineMov::updateLinePos(QPointF scenePos)
{
int old_x, old_y, mid_x, new_x, final_x, final_y;

if (m_port_mode == PORT_MODE_INPUT)
{
old_x = 0;
old_y = 7.5;
mid_x = abs(scenePos.x()-p_itemX)/2;
new_x = old_x-mid_x;
}
else if (m_port_mode == PORT_MODE_OUTPUT)
{
old_x = p_width+12;
old_y = 7.5;
mid_x = abs(scenePos.x()-(p_itemX+old_x))/2;
new_x = old_x+mid_x;
}
else
return;

final_x = scenePos.x()-p_itemX;
final_y = scenePos.y()-p_itemY;

QPainterPath path(QPointF(old_x, old_y));
path.cubicTo(new_x, old_y, new_x, final_y, final_x, final_y);
setPath(path);
}

int CanvasBezierLineMov::type() const
{
return CanvasBezierLineMovType;
}

void CanvasBezierLineMov::paint(QPainter* painter, const QStyleOptionGraphicsItem* option, QWidget* widget)
{
painter->setRenderHint(QPainter::Antialiasing, bool(options.antialiasing));
QGraphicsPathItem::paint(painter, option, widget);
}

END_NAMESPACE_PATCHCANVAS

+ 60
- 0
c++/patchcanvas/canvasbezierlinemov.h View File

@@ -0,0 +1,60 @@
/*
* Patchbay Canvas engine using QGraphicsView/Scene
* Copyright (C) 2010-2012 Filipe Coelho <falktx@gmail.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* For a full copy of the GNU General Public License see the COPYING file
*/

#ifndef CANVASBEZIERLINEMOV_H
#define CANVASBEZIERLINEMOV_H

#include <QtGui/QGraphicsPathItem>

#include "abstractcanvasline.h"

class QPainter;

START_NAMESPACE_PATCHCANVAS

class CanvasBezierLineMov :
public AbstractCanvasLineMov,
public QGraphicsPathItem
{
public:
CanvasBezierLineMov(PortMode port_mode, PortType port_type, QGraphicsItem* parent);

virtual void deleteFromScene();

virtual void updateLinePos(QPointF scenePos);

virtual int type() const;

// QGraphicsItem generic calls
virtual void setZValue(qreal z)
{
QGraphicsPathItem::setZValue(z);
}

private:
PortMode m_port_mode;
PortType m_port_type;
int p_itemX;
int p_itemY;
int p_width;

virtual void paint(QPainter* painter, const QStyleOptionGraphicsItem* option, QWidget* widget);
};

END_NAMESPACE_PATCHCANVAS

#endif // CANVASBEZIERLINEMOV_H

+ 680
- 0
c++/patchcanvas/canvasbox.cpp View File

@@ -0,0 +1,680 @@
/*
* Patchbay Canvas engine using QGraphicsView/Scene
* Copyright (C) 2010-2012 Filipe Coelho <falktx@gmail.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* For a full copy of the GNU General Public License see the COPYING file
*/

#include "canvasbox.h"

#include <QtCore/QTimer>
#include <QtGui/QCursor>
#include <QtGui/QInputDialog>
#include <QtGui/QMenu>
#include <QtGui/QGraphicsSceneContextMenuEvent>
#include <QtGui/QGraphicsSceneMouseEvent>
#include <QtGui/QPainter>

#include "canvasline.h"
#include "canvasbezierline.h"
#include "canvasport.h"
#include "canvasboxshadow.h"
#include "canvasicon.h"

START_NAMESPACE_PATCHCANVAS

CanvasBox::CanvasBox(int group_id, QString group_name, Icon icon, QGraphicsItem* parent) :
QGraphicsItem(parent, canvas.scene)
{
// Save Variables, useful for later
m_group_id = group_id;
m_group_name = group_name;

// Base Variables
p_width = 50;
p_height = 25;

m_last_pos = QPointF();
m_splitted = false;
m_splitted_mode = PORT_MODE_NULL;

m_cursor_moving = false;
m_forced_split = false;
m_mouse_down = false;

m_port_list_ids.clear();
m_connection_lines.clear();

// Set Font
m_font_name = QFont(canvas.theme->box_font_name, canvas.theme->box_font_size, canvas.theme->box_font_state);
m_font_port = QFont(canvas.theme->port_font_name, canvas.theme->port_font_size, canvas.theme->port_font_state);

// Icon
icon_svg = new CanvasIcon(icon, group_name, this);

// Shadow
if (options.eyecandy)
{
shadow = new CanvasBoxShadow(toGraphicsObject());
shadow->setFakeParent(this);
setGraphicsEffect(shadow);
}
else
shadow = 0;

// Final touches
setFlags(QGraphicsItem::ItemIsMovable|QGraphicsItem::ItemIsSelectable);

// Wait for at least 1 port
if (options.auto_hide_groups)
setVisible(false);

updatePositions();
}

CanvasBox::~CanvasBox()
{
if (shadow)
delete shadow;
delete icon_svg;
}

int CanvasBox::getGroupId()
{
return m_group_id;
}

QString CanvasBox::getGroupName()
{
return m_group_name;
}

bool CanvasBox::isSplitted()
{
return m_splitted;
}

PortMode CanvasBox::getSplittedMode()
{
return m_splitted_mode;
}

int CanvasBox::getPortCount()
{
return m_port_list_ids.count();
}

QList<int> CanvasBox::getPortList()
{
return m_port_list_ids;
}

void CanvasBox::setIcon(Icon icon)
{
icon_svg->setIcon(icon, m_group_name);
}

void CanvasBox::setSplit(bool split, PortMode mode)
{
m_splitted = split;
m_splitted_mode = mode;
}

void CanvasBox::setGroupName(QString group_name)
{
m_group_name = group_name;
updatePositions();
}

CanvasPort* CanvasBox::addPortFromGroup(int port_id, QString port_name, PortMode port_mode, PortType port_type)
{
if (m_port_list_ids.count() == 0)
{
if (options.auto_hide_groups)
setVisible(true);
}

CanvasPort* new_widget = new CanvasPort(port_id, port_name, port_mode, port_type, this);

port_dict_t port_dict;
port_dict.group_id = m_group_id;
port_dict.port_id = port_id;
port_dict.port_name = port_name;
port_dict.port_mode = port_mode;
port_dict.port_type = port_type;
port_dict.widget = new_widget;

m_port_list_ids.append(port_id);

return new_widget;
}

void CanvasBox::removePortFromGroup(int port_id)
{
if (m_port_list_ids.contains(port_id))
{
m_port_list_ids.removeOne(port_id);
}
else
{
qCritical("PatchCanvas::CanvasBox->removePort(%i) - unable to find port to remove", port_id);
return;
}

if (m_port_list_ids.count() > 0)
{
updatePositions();
}
else if (isVisible())
{
if (options.auto_hide_groups)
setVisible(false);
}
}

void CanvasBox::addLineFromGroup(AbstractCanvasLine* line, int connection_id)
{
cb_line_t new_cbline;
new_cbline.line = line;
new_cbline.connection_id = connection_id;
m_connection_lines.append(new_cbline);
}

void CanvasBox::removeLineFromGroup(int connection_id)
{
foreach2 (const cb_line_t& connection, m_connection_lines)
if (connection.connection_id == connection_id)
{
m_connection_lines.takeAt(i);
return;
}
}

qCritical("PatchCanvas::CanvasBox->removeLineFromGroup(%i) - unable to find line to remove", connection_id);
}

void CanvasBox::checkItemPos()
{
if (canvas.size_rect.isNull() == false)
{
QPointF pos = scenePos();
if (canvas.size_rect.contains(pos) == false || canvas.size_rect.contains(pos+QPointF(p_width, p_height)) == false)
{
if (pos.x() < canvas.size_rect.x())
setPos(canvas.size_rect.x(), pos.y());
else if (pos.x()+p_width > canvas.size_rect.width())
setPos(canvas.size_rect.width()-p_width, pos.y());

pos = scenePos();
if (pos.y() < canvas.size_rect.y())
setPos(pos.x(), canvas.size_rect.y());
else if (pos.y()+p_height > canvas.size_rect.height())
setPos(pos.x(), canvas.size_rect.height()-p_height);
}
}
}

void CanvasBox::removeIconFromScene()
{
canvas.scene->removeItem(icon_svg);
}

void CanvasBox::updatePositions()
{
prepareGeometryChange();

int max_in_width = 0;
int max_in_height = 24;
int max_out_width = 0;
int max_out_height = 24;
bool have_audio_jack_in, have_audio_jack_out, have_midi_jack_in, have_midi_jack_out;
bool have_midi_a2j_in, have_midi_a2j_out, have_midi_alsa_in, have_midi_alsa_out;
have_audio_jack_in = have_midi_jack_in = have_midi_a2j_in = have_midi_alsa_in = false;
have_audio_jack_out = have_midi_jack_out = have_midi_a2j_out = have_midi_alsa_out = false;

// reset box size
p_width = 50;
p_height = 25;

// Check Text Name size
int app_name_size = QFontMetrics(m_font_name).width(m_group_name)+30;
if (app_name_size > p_width)
p_width = app_name_size;

// Get Port List
QList<port_dict_t> port_list;
foreach (const port_dict_t& port, canvas.port_list)
{
if (m_port_list_ids.contains(port.port_id))
port_list.append(port);
}

// Get Max Box Width/Height
foreach (const port_dict_t& port, port_list)
{
if (port.port_mode == PORT_MODE_INPUT)
{
max_in_height += 18;

int size = QFontMetrics(m_font_port).width(port.port_name);
if (size > max_in_width)
max_in_width = size;

if (port.port_type == PORT_TYPE_AUDIO_JACK && have_audio_jack_in == false)
{
have_audio_jack_in = true;
max_in_height += 2;
}
else if (port.port_type == PORT_TYPE_MIDI_JACK && have_midi_jack_in == false)
{
have_midi_jack_in = true;
max_in_height += 2;
}
else if (port.port_type == PORT_TYPE_MIDI_A2J && have_midi_a2j_in == false)
{
have_midi_a2j_in = true;
max_in_height += 2;
}
else if (port.port_type == PORT_TYPE_MIDI_ALSA && have_midi_alsa_in == false)
{
have_midi_alsa_in = true;
max_in_height += 2;
}
}
else if (port.port_mode == PORT_MODE_OUTPUT)
{
max_out_height += 18;

int size = QFontMetrics(m_font_port).width(port.port_name);
if (size > max_out_width)
max_out_width = size;

if (port.port_type == PORT_TYPE_AUDIO_JACK && have_audio_jack_out == false)
{
have_audio_jack_out = true;
max_out_height += 2;
}
else if (port.port_type == PORT_TYPE_MIDI_JACK && have_midi_jack_out == false)
{
have_midi_jack_out = true;
max_out_height += 2;
}
else if (port.port_type == PORT_TYPE_MIDI_A2J && have_midi_a2j_out == false)
{
have_midi_a2j_out = true;
max_out_height += 2;
}
else if (port.port_type == PORT_TYPE_MIDI_ALSA && have_midi_alsa_out == false)
{
have_midi_alsa_out = true;
max_out_height += 2;
}
}
}

int final_width = 30 + max_in_width + max_out_width;
if (final_width > p_width)
p_width = final_width;

if (max_in_height > p_height)
p_height = max_in_height;

if (max_out_height > p_height)
p_height = max_out_height;

// Remove bottom space
p_height -= 2;

int last_in_pos = 24;
int last_out_pos = 24;
PortType last_in_type = PORT_TYPE_NULL;
PortType last_out_type = PORT_TYPE_NULL;

// Re-position ports, AUDIO_JACK
foreach (const port_dict_t& port, port_list)
{
if (port.port_type == PORT_TYPE_AUDIO_JACK)
{
if (port.port_mode == PORT_MODE_INPUT)
{
port.widget->setPos(QPointF(1, last_in_pos));
port.widget->setPortWidth(max_in_width);

last_in_pos += 18;
last_in_type = port.port_type;
}
else if (port.port_mode == PORT_MODE_OUTPUT)
{
port.widget->setPos(QPointF(p_width-max_out_width-13, last_out_pos));
port.widget->setPortWidth(max_out_width);

last_out_pos += 18;
last_out_type = port.port_type;
}
}
}

// Re-position ports, MIDI_JACK
foreach (const port_dict_t& port, port_list)
{
if (port.port_type == PORT_TYPE_MIDI_JACK)
{
if (port.port_mode == PORT_MODE_INPUT)
{
if (last_in_type != PORT_TYPE_NULL && port.port_type != last_in_type)
last_in_pos += 2;

port.widget->setPos(QPointF(1, last_in_pos));
port.widget->setPortWidth(max_in_width);

last_in_pos += 18;
last_in_type = port.port_type;
}
else if (port.port_mode == PORT_MODE_OUTPUT)
{
if (last_out_type != PORT_TYPE_NULL && port.port_type != last_out_type)
last_out_pos += 2;

port.widget->setPos(QPointF(p_width-max_out_width-13, last_out_pos));
port.widget->setPortWidth(max_out_width);

last_out_pos += 18;
last_out_type = port.port_type;
}
}
}

// Re-position ports, MIDI_A2J
foreach (const port_dict_t& port, port_list)
{
if (port.port_type == PORT_TYPE_MIDI_A2J)
{
if (port.port_mode == PORT_MODE_INPUT)
{
if (last_in_type != PORT_TYPE_NULL && port.port_type != last_in_type)
last_in_pos += 2;

port.widget->setPos(QPointF(1, last_in_pos));
port.widget->setPortWidth(max_in_width);

last_in_pos += 18;
last_in_type = port.port_type;
}
else if (port.port_mode == PORT_MODE_OUTPUT)
{
if (last_out_type != PORT_TYPE_NULL && port.port_type != last_out_type)
last_out_pos += 2;

port.widget->setPos(QPointF(p_width-max_out_width-13, last_out_pos));
port.widget->setPortWidth(max_out_width);

last_out_pos += 18;
last_out_type = port.port_type;
}
}
}

// Re-position ports, MIDI_ALSA
foreach (const port_dict_t& port, port_list)
{
if (port.port_type == PORT_TYPE_MIDI_ALSA)
{
if (port.port_mode == PORT_MODE_INPUT)
{
if (last_in_type != PORT_TYPE_NULL && port.port_type != last_in_type)
last_in_pos += 2;

port.widget->setPos(QPointF(1, last_in_pos));
port.widget->setPortWidth(max_in_width);

last_in_pos += 18;
last_in_type = port.port_type;
}
else if (port.port_mode == PORT_MODE_OUTPUT)
{
if (last_out_type != PORT_TYPE_NULL && port.port_type != last_out_type)
last_out_pos += 2;

port.widget->setPos(QPointF(p_width-max_out_width-13, last_out_pos));
port.widget->setPortWidth(max_out_width);

last_out_pos += 18;
last_out_type = port.port_type;
}
}
}

repaintLines(true);
update();
}

void CanvasBox::repaintLines(bool forced)
{
if (pos() != m_last_pos || forced)
{
foreach (const cb_line_t& connection, m_connection_lines)
connection.line->updateLinePos();
}

m_last_pos = pos();
}

void CanvasBox::resetLinesZValue()
{
foreach (const connection_dict_t& connection, canvas.connection_list)
{
int z_value;
if (m_port_list_ids.contains(connection.port_out_id) && m_port_list_ids.contains(connection.port_in_id))
z_value = canvas.last_z_value;
else
z_value = canvas.last_z_value-1;

connection.widget->setZValue(z_value);
}
}

int CanvasBox::type() const
{
return CanvasBoxType;
}

void CanvasBox::contextMenuEvent(QGraphicsSceneContextMenuEvent* event)
{
QMenu menu;
QMenu discMenu("Disconnect", &menu);

QList<int> port_con_list;
QList<int> port_con_list_ids;

foreach (const int& port_id, m_port_list_ids)
{
QList<int> tmp_port_con_list = CanvasGetPortConnectionList(port_id);
foreach (const int& port_con_id, tmp_port_con_list)
{
if (port_con_list.contains(port_con_id) == false)
{
port_con_list.append(port_con_id);
port_con_list_ids.append(port_id);
}
}
}

if (port_con_list.count() > 0)
{
for (int i=0; i < port_con_list.count(); i++)
{
int port_con_id = CanvasGetConnectedPort(port_con_list[i], port_con_list_ids[i]);
QAction* act_x_disc = discMenu.addAction(CanvasGetFullPortName(port_con_id));
act_x_disc->setData(port_con_list[i]);
QObject::connect(act_x_disc, SIGNAL(triggered()), canvas.qobject, SLOT(PortContextMenuDisconnect()));
}
}
else
{
QAction* act_x_disc = discMenu.addAction("No connections");
act_x_disc->setEnabled(false);
}

menu.addMenu(&discMenu);
QAction* act_x_disc_all = menu.addAction("Disconnect &All");
QAction* act_x_sep1 = menu.addSeparator();
QAction* act_x_info = menu.addAction("&Info");
QAction* act_x_rename = menu.addAction("&Rename");
QAction* act_x_sep2 = menu.addSeparator();
QAction* act_x_split_join = menu.addAction(m_splitted ? "Join" : "Split");

if (features.group_info == false)
act_x_info->setVisible(false);

if (features.group_rename == false)
act_x_rename->setVisible(false);

if (features.group_info == false && features.group_rename == false)
act_x_sep1->setVisible(false);

bool haveIns, haveOuts;
haveIns = haveOuts = false;
foreach (const port_dict_t& port, canvas.port_list)
{
if (m_port_list_ids.contains(port.port_id))
{
if (port.port_mode == PORT_MODE_INPUT)
haveIns = true;
else if (port.port_mode == PORT_MODE_OUTPUT)
haveOuts = true;
}
}

if (m_splitted == false && (haveIns && haveOuts) == false)
{
act_x_sep2->setVisible(false);
act_x_split_join->setVisible(false);
}

QAction* act_selected = menu.exec(event->screenPos());

if (act_selected == act_x_disc_all)
{
foreach (const int& port_id, port_con_list)
canvas.callback(ACTION_PORTS_DISCONNECT, port_id, 0, "");
}
else if (act_selected == act_x_info)
{
canvas.callback(ACTION_GROUP_INFO, m_group_id, 0, "");
}
else if (act_selected == act_x_rename)
{
bool ok_check;
QString new_name = QInputDialog::getText(0, "Rename Group", "New name:", QLineEdit::Normal, m_group_name, &ok_check);
if (ok_check and !new_name.isEmpty())
{
canvas.callback(ACTION_GROUP_RENAME, m_group_id, 0, new_name);
}
}
else if (act_selected == act_x_split_join)
{
if (m_splitted)
canvas.callback(ACTION_GROUP_JOIN, m_group_id, 0, "");
else
canvas.callback(ACTION_GROUP_SPLIT, m_group_id, 0, "");

}

event->accept();
}

void CanvasBox::mousePressEvent(QGraphicsSceneMouseEvent* event)
{
canvas.last_z_value += 1;
setZValue(canvas.last_z_value);
resetLinesZValue();
m_cursor_moving = false;

if (event->button() == Qt::RightButton)
{
canvas.scene->clearSelection();
setSelected(true);
m_mouse_down = false;
return event->accept();
}
else if (event->button() == Qt::LeftButton)
{
if (sceneBoundingRect().contains(event->scenePos()))
m_mouse_down = true;
else
{
// Fixes a weird Qt behaviour with right-click mouseMove
m_mouse_down = false;
return event->ignore();
}
}
else
m_mouse_down = false;

QGraphicsItem::mousePressEvent(event);
}

void CanvasBox::mouseMoveEvent(QGraphicsSceneMouseEvent* event)
{
if (m_mouse_down)
{
if (m_cursor_moving == false)
{
setCursor(QCursor(Qt::SizeAllCursor));
m_cursor_moving = true;
}
repaintLines();
}
QGraphicsItem::mouseMoveEvent(event);
}

void CanvasBox::mouseReleaseEvent(QGraphicsSceneMouseEvent* event)
{
if (m_cursor_moving)
setCursor(QCursor(Qt::ArrowCursor));
m_mouse_down = false;
m_cursor_moving = false;
QGraphicsItem::mouseReleaseEvent(event);
}

QRectF CanvasBox::boundingRect() const
{
return QRectF(0, 0, p_width, p_height);
}

void CanvasBox::paint(QPainter* painter, const QStyleOptionGraphicsItem* /*option*/, QWidget* /*widget*/)
{
painter->setRenderHint(QPainter::Antialiasing, false);

if (isSelected())
painter->setPen(canvas.theme->box_pen_sel);
else
painter->setPen(canvas.theme->box_pen);

QLinearGradient box_gradient(0, 0, 0, p_height);
box_gradient.setColorAt(0, canvas.theme->box_bg_1);
box_gradient.setColorAt(1, canvas.theme->box_bg_2);

painter->setBrush(box_gradient);
painter->drawRect(0, 0, p_width, p_height);

QPointF text_pos(25, 16);

painter->setFont(m_font_name);
painter->setPen(canvas.theme->box_text);
painter->drawText(text_pos, m_group_name);

repaintLines();
}

END_NAMESPACE_PATCHCANVAS

+ 106
- 0
c++/patchcanvas/canvasbox.h View File

@@ -0,0 +1,106 @@
/*
* Patchbay Canvas engine using QGraphicsView/Scene
* Copyright (C) 2010-2012 Filipe Coelho <falktx@gmail.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* For a full copy of the GNU General Public License see the COPYING file
*/

#ifndef CANVASBOX_H
#define CANVASBOX_H

#include "patchcanvas.h"

class QGraphicsSceneContextMenuEvent;
class QGraphicsSceneMouseEvent;
class QPainter;

START_NAMESPACE_PATCHCANVAS

class AbstractCanvasLine;
class CanvasBoxShadow;
class CanvasPort;
class CanvasIcon;

struct cb_line_t {
AbstractCanvasLine* line;
int connection_id;
};

class CanvasBox : public QGraphicsItem
{
public:
CanvasBox(int group_id, QString group_name, Icon icon, QGraphicsItem* parent=0);
virtual ~CanvasBox();

int getGroupId();
QString getGroupName();
bool isSplitted();
PortMode getSplittedMode();

int getPortCount();
QList<int> getPortList();

void setIcon(Icon icon);
void setSplit(bool split, PortMode mode=PORT_MODE_NULL);
void setGroupName(QString group_name);

CanvasPort* addPortFromGroup(int port_id, QString port_name, PortMode port_mode, PortType port_type);
void removePortFromGroup(int port_id);
void addLineFromGroup(AbstractCanvasLine* line, int connection_id);
void removeLineFromGroup(int connection_id);

void checkItemPos();
void removeIconFromScene();

void updatePositions();
void repaintLines(bool forced=false);
void resetLinesZValue();

virtual int type() const;

private:
int m_group_id;
QString m_group_name;

int p_width;
int p_height;

QList<int> m_port_list_ids;
QList<cb_line_t> m_connection_lines;

QPointF m_last_pos;
bool m_splitted;
PortMode m_splitted_mode;

bool m_forced_split;
bool m_cursor_moving;
bool m_mouse_down;

QFont m_font_name;
QFont m_font_port;

CanvasIcon* icon_svg;
CanvasBoxShadow* shadow;

virtual void contextMenuEvent(QGraphicsSceneContextMenuEvent* event);
virtual void mousePressEvent(QGraphicsSceneMouseEvent* event);
virtual void mouseMoveEvent(QGraphicsSceneMouseEvent* event);
virtual void mouseReleaseEvent(QGraphicsSceneMouseEvent* event);

virtual QRectF boundingRect() const;
virtual void paint(QPainter* painter, const QStyleOptionGraphicsItem* option, QWidget* widget);
};

END_NAMESPACE_PATCHCANVAS

#endif // CANVASBOX_H

+ 46
- 0
c++/patchcanvas/canvasboxshadow.cpp View File

@@ -0,0 +1,46 @@
/*
* Patchbay Canvas engine using QGraphicsView/Scene
* Copyright (C) 2010-2012 Filipe Coelho <falktx@gmail.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* For a full copy of the GNU General Public License see the COPYING file
*/

#include "canvasboxshadow.h"

#include "canvasbox.h"

START_NAMESPACE_PATCHCANVAS

CanvasBoxShadow::CanvasBoxShadow(QObject* parent) :
QGraphicsDropShadowEffect(parent)
{
m_fakeParent = 0;

setBlurRadius(20);
setColor(canvas.theme->box_shadow);
setOffset(0, 0);
}

void CanvasBoxShadow::setFakeParent(CanvasBox* fakeParent)
{
m_fakeParent = fakeParent;
}

void CanvasBoxShadow::draw(QPainter* painter)
{
if (m_fakeParent)
m_fakeParent->repaintLines();
QGraphicsDropShadowEffect::draw(painter);
}

END_NAMESPACE_PATCHCANVAS

+ 44
- 0
c++/patchcanvas/canvasboxshadow.h View File

@@ -0,0 +1,44 @@
/*
* Patchbay Canvas engine using QGraphicsView/Scene
* Copyright (C) 2010-2012 Filipe Coelho <falktx@gmail.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* For a full copy of the GNU General Public License see the COPYING file
*/

#ifndef CANVASBOXSHADOW_H
#define CANVASBOXSHADOW_H

#include <QGraphicsDropShadowEffect>

#include "patchcanvas.h"

START_NAMESPACE_PATCHCANVAS

class CanvasBox;

class CanvasBoxShadow : public QGraphicsDropShadowEffect
{
public:
CanvasBoxShadow(QObject* parent);
void setFakeParent(CanvasBox* fakeParent);

protected:
virtual void draw(QPainter* painter);

private:
CanvasBox* m_fakeParent;
};

END_NAMESPACE_PATCHCANVAS

#endif // CANVASBOXSHADOW_H

+ 71
- 0
c++/patchcanvas/canvasfadeanimation.cpp View File

@@ -0,0 +1,71 @@
/*
* Patchbay Canvas engine using QGraphicsView/Scene
* Copyright (C) 2010-2012 Filipe Coelho <falktx@gmail.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* For a full copy of the GNU General Public License see the COPYING file
*/

#include "canvasfadeanimation.h"

#include <QGraphicsItem>

START_NAMESPACE_PATCHCANVAS

CanvasFadeAnimation::CanvasFadeAnimation(QGraphicsItem* item, bool show, QObject* parent) :
QAbstractAnimation(parent)
{
m_show = show;
m_duration = 0;
m_item = item;
}

void CanvasFadeAnimation::setDuration(int time)
{
if (m_show == false && m_item->opacity() == 0.0)
m_duration = 0;
else
{
m_item->show();
m_duration = time;
}
}

int CanvasFadeAnimation::duration() const
{
return m_duration;
}

void CanvasFadeAnimation::updateCurrentTime(int time)
{
if (m_duration == 0)
return;

float value;

if (m_show)
value = float(time)/m_duration;
else
value = 1.0-(float(time)/m_duration);

m_item->setOpacity(value);
}

void CanvasFadeAnimation::updateState(QAbstractAnimation::State /*newState*/, QAbstractAnimation::State /*oldState*/)
{
}

void CanvasFadeAnimation::updateDirection(QAbstractAnimation::Direction /*direction*/)
{
}

END_NAMESPACE_PATCHCANVAS

+ 51
- 0
c++/patchcanvas/canvasfadeanimation.h View File

@@ -0,0 +1,51 @@
/*
* Patchbay Canvas engine using QGraphicsView/Scene
* Copyright (C) 2010-2012 Filipe Coelho <falktx@gmail.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* For a full copy of the GNU General Public License see the COPYING file
*/

#ifndef CANVASFADEANIMATION_H
#define CANVASFADEANIMATION_H

#include <QtCore/QAbstractAnimation>

#include "patchcanvas.h"

class QGraphicsItem;

START_NAMESPACE_PATCHCANVAS

class CanvasFadeAnimation : public QAbstractAnimation
{
public:
CanvasFadeAnimation(QGraphicsItem* item, bool show, QObject* parent=0);

void setDuration(int time);

virtual int duration() const;

protected:
virtual void updateCurrentTime(int time);
virtual void updateState(QAbstractAnimation::State newState, QAbstractAnimation::State oldState);
virtual void updateDirection(QAbstractAnimation::Direction direction);

private:
bool m_show;
int m_duration;
QGraphicsItem* m_item;
};

END_NAMESPACE_PATCHCANVAS

#endif // CANVASFADEANIMATION_H

+ 134
- 0
c++/patchcanvas/canvasicon.cpp View File

@@ -0,0 +1,134 @@
/*
* Patchbay Canvas engine using QGraphicsView/Scene
* Copyright (C) 2010-2012 Filipe Coelho <falktx@gmail.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* For a full copy of the GNU General Public License see the COPYING file
*/

#include "canvasicon.h"

#include <QtGui/QPainter>
#include <QtGui/QGraphicsColorizeEffect>
#include <QtSvg/QSvgRenderer>

START_NAMESPACE_PATCHCANVAS

CanvasIcon::CanvasIcon(Icon icon, QString name, QGraphicsItem* parent) :
QGraphicsSvgItem(parent)
{
m_renderer = 0;
p_size = QRectF(0, 0, 0, 0);

m_colorFX = new QGraphicsColorizeEffect(this);
m_colorFX->setColor(canvas.theme->box_text.color());

setGraphicsEffect(m_colorFX);
setIcon(icon, name);
}

CanvasIcon::~CanvasIcon()
{
if (m_renderer)
delete m_renderer;
delete m_colorFX;
}

void CanvasIcon::setIcon(Icon icon, QString name)
{
name = name.toLower();
QString icon_path;

if (icon == ICON_APPLICATION)
{
p_size = QRectF(3, 2, 19, 18);

if (name.contains("audacious"))
{
p_size = QRectF(5, 4, 16, 16);
icon_path = ":/scalable/pb_audacious.svg";
}
else if (name.contains("clementine"))
{
p_size = QRectF(5, 4, 16, 16);
icon_path = ":/scalable/pb_clementine.svg";
}
else if (name.contains("jamin"))
{
p_size = QRectF(5, 3, 16, 16);
icon_path = ":/scalable/pb_jamin.svg";
}
else if (name.contains("mplayer"))
{
p_size = QRectF(5, 4, 16, 16);
icon_path = ":/scalable/pb_mplayer.svg";
}
else if (name.contains("vlc"))
{
p_size = QRectF(5, 3, 16, 16);
icon_path = ":/scalable/pb_vlc.svg";
}
else
{
p_size = QRectF(5, 3, 16, 16);
icon_path = ":/scalable/pb_generic.svg";
}
}
else if (icon == ICON_HARDWARE)
{
p_size = QRectF(5, 2, 16, 16);
icon_path = ":/scalable/pb_hardware.svg";

}
else if (icon == ICON_LADISH_ROOM)
{
p_size = QRectF(5, 2, 16, 16);
icon_path = ":/scalable/pb_hardware.svg";
}
else
{
p_size = QRectF(0, 0, 0, 0);
qCritical("PatchCanvas::CanvasIcon->setIcon(%s, %s) - unsupported Icon requested", icon2str(icon), name.toUtf8().constData());
return;
}

if (m_renderer)
delete m_renderer;

m_renderer = new QSvgRenderer(icon_path, canvas.scene);
setSharedRenderer(m_renderer);
update();
}

int CanvasIcon::type() const
{
return CanvasIconType;
}

QRectF CanvasIcon::boundingRect() const
{
return p_size;
}

void CanvasIcon::paint(QPainter* painter, const QStyleOptionGraphicsItem* option, QWidget* widget)
{
if (m_renderer)
{
painter->setRenderHint(QPainter::Antialiasing, false);
painter->setRenderHint(QPainter::TextAntialiasing, false);
m_renderer->render(painter, p_size);
}
else
QGraphicsSvgItem::paint(painter, option, widget);
}

END_NAMESPACE_PATCHCANVAS

+ 52
- 0
c++/patchcanvas/canvasicon.h View File

@@ -0,0 +1,52 @@
/*
* Patchbay Canvas engine using QGraphicsView/Scene
* Copyright (C) 2010-2012 Filipe Coelho <falktx@gmail.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* For a full copy of the GNU General Public License see the COPYING file
*/

#ifndef CANVASICON_H
#define CANVASICON_H

#include <QtSvg/QGraphicsSvgItem>

#include "patchcanvas.h"

class QPainter;
class QGraphicsColorizeEffect;
class QSvgRenderer;

START_NAMESPACE_PATCHCANVAS

class CanvasIcon : public QGraphicsSvgItem
{
public:
CanvasIcon(Icon icon, QString name, QGraphicsItem* parent);
~CanvasIcon();

void setIcon(Icon icon, QString name);

virtual int type() const;

private:
QGraphicsColorizeEffect* m_colorFX;
QSvgRenderer* m_renderer;
QRectF p_size;

virtual QRectF boundingRect() const;
virtual void paint(QPainter* painter, const QStyleOptionGraphicsItem* option, QWidget* widget);
};

END_NAMESPACE_PATCHCANVAS

#endif // CANVASICON_H

+ 148
- 0
c++/patchcanvas/canvasline.cpp View File

@@ -0,0 +1,148 @@
/*
* Patchbay Canvas engine using QGraphicsView/Scene
* Copyright (C) 2010-2012 Filipe Coelho <falktx@gmail.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* For a full copy of the GNU General Public License see the COPYING file
*/

#include "canvasline.h"

#include <QtGui/QPainter>

#include "canvasport.h"
#include "canvasportglow.h"

START_NAMESPACE_PATCHCANVAS

CanvasLine::CanvasLine(CanvasPort* item1_, CanvasPort* item2_, QGraphicsItem* parent) :
QGraphicsLineItem(parent, canvas.scene)
{
item1 = item1_;
item2 = item2_;

m_locked = false;
m_lineSelected = false;

setGraphicsEffect(0);
updateLinePos();
}

CanvasLine::~CanvasLine()
{
setGraphicsEffect(0);
}

void CanvasLine::deleteFromScene()
{
canvas.scene->removeItem(this);
delete this;
}

bool CanvasLine::isLocked() const
{
return m_locked;
}

void CanvasLine::setLocked(bool yesno)
{
m_locked = yesno;
}

bool CanvasLine::isLineSelected() const
{
return m_lineSelected;
}

void CanvasLine::setLineSelected(bool yesno)
{
if (m_locked)
return;

if (options.eyecandy)
{
if (yesno)
setGraphicsEffect(new CanvasPortGlow(item1->getPortType(), toGraphicsObject()));
else
setGraphicsEffect(0);
}

m_lineSelected = yesno;
updateLineGradient();
}

void CanvasLine::updateLinePos()
{
if (item1->getPortMode() == PORT_MODE_OUTPUT)
{
QLineF line(item1->scenePos().x() + item1->getPortWidth()+12, item1->scenePos().y()+7.5, item2->scenePos().x(), item2->scenePos().y()+7.5);
setLine(line);

m_lineSelected = false;
updateLineGradient();
}
}

int CanvasLine::type() const
{
return CanvasLineType;
}

void CanvasLine::updateLineGradient()
{
short pos1, pos2;
int pos_top = boundingRect().top();
int pos_bot = boundingRect().bottom();

if (item2->scenePos().y() >= item1->scenePos().y())
{
pos1 = 0;
pos2 = 1;
}
else
{
pos1 = 1;
pos2 = 0;
}

PortType port_type1 = item1->getPortType();
PortType port_type2 = item2->getPortType();
QLinearGradient port_gradient(0, pos_top, 0, pos_bot);

if (port_type1 == PORT_TYPE_AUDIO_JACK)
port_gradient.setColorAt(pos1, m_lineSelected ? canvas.theme->line_audio_jack_sel : canvas.theme->line_audio_jack);
else if (port_type1 == PORT_TYPE_MIDI_JACK)
port_gradient.setColorAt(pos1, m_lineSelected ? canvas.theme->line_midi_jack_sel : canvas.theme->line_midi_jack);
else if (port_type1 == PORT_TYPE_MIDI_A2J)
port_gradient.setColorAt(pos1, m_lineSelected ? canvas.theme->line_midi_a2j_sel : canvas.theme->line_midi_a2j);
else if (port_type1 == PORT_TYPE_MIDI_ALSA)
port_gradient.setColorAt(pos1, m_lineSelected ? canvas.theme->line_midi_alsa_sel : canvas.theme->line_midi_alsa);

if (port_type2 == PORT_TYPE_AUDIO_JACK)
port_gradient.setColorAt(pos2, m_lineSelected ? canvas.theme->line_audio_jack_sel : canvas.theme->line_audio_jack);
else if (port_type2 == PORT_TYPE_MIDI_JACK)
port_gradient.setColorAt(pos2, m_lineSelected ? canvas.theme->line_midi_jack_sel : canvas.theme->line_midi_jack);
else if (port_type2 == PORT_TYPE_MIDI_A2J)
port_gradient.setColorAt(pos2, m_lineSelected ? canvas.theme->line_midi_a2j_sel : canvas.theme->line_midi_a2j);
else if (port_type2 == PORT_TYPE_MIDI_ALSA)
port_gradient.setColorAt(pos2, m_lineSelected ? canvas.theme->line_midi_alsa_sel : canvas.theme->line_midi_alsa);

setPen(QPen(port_gradient, 2));
}

void CanvasLine::paint(QPainter* painter, const QStyleOptionGraphicsItem* option, QWidget* widget)
{
painter->setRenderHint(QPainter::Antialiasing, bool(options.antialiasing));
QGraphicsLineItem::paint(painter, option, widget);
}

END_NAMESPACE_PATCHCANVAS

+ 72
- 0
c++/patchcanvas/canvasline.h View File

@@ -0,0 +1,72 @@
/*
* Patchbay Canvas engine using QGraphicsView/Scene
* Copyright (C) 2010-2012 Filipe Coelho <falktx@gmail.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* For a full copy of the GNU General Public License see the COPYING file
*/

#ifndef CANVASLINE_H
#define CANVASLINE_H

#include <QtGui/QGraphicsLineItem>

#include "abstractcanvasline.h"

class QPainter;

START_NAMESPACE_PATCHCANVAS

class CanvasPort;
class CanvasPortGlow;

class CanvasLine :
public AbstractCanvasLine,
public QGraphicsLineItem
{
public:
CanvasLine(CanvasPort* item1, CanvasPort* item2, QGraphicsItem* parent);
~CanvasLine();

virtual void deleteFromScene();

virtual bool isLocked() const;
virtual void setLocked(bool yesno);

virtual bool isLineSelected() const;
virtual void setLineSelected(bool yesno);

virtual void updateLinePos();

virtual int type() const;

// QGraphicsItem generic calls
virtual void setZValue(qreal z)
{
QGraphicsLineItem::setZValue(z);
}

private:
CanvasPort* item1;
CanvasPort* item2;
CanvasPortGlow* glow;
bool m_locked;
bool m_lineSelected;

void updateLineGradient();

virtual void paint(QPainter* painter, const QStyleOptionGraphicsItem* option, QWidget* widget);
};

END_NAMESPACE_PATCHCANVAS

#endif // CANVASLINE_H

+ 94
- 0
c++/patchcanvas/canvaslinemov.cpp View File

@@ -0,0 +1,94 @@
/*
* Patchbay Canvas engine using QGraphicsView/Scene
* Copyright (C) 2010-2012 Filipe Coelho <falktx@gmail.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* For a full copy of the GNU General Public License see the COPYING file
*/

#include "canvaslinemov.h"

#include <QtGui/QPainter>

#include "canvasport.h"

START_NAMESPACE_PATCHCANVAS

CanvasLineMov::CanvasLineMov(PortMode port_mode, PortType port_type, QGraphicsItem* parent) :
QGraphicsLineItem(parent, canvas.scene)
{
m_port_mode = port_mode;
m_port_type = port_type;

// Port position doesn't change while moving around line
p_lineX = scenePos().x();
p_lineY = scenePos().y();
p_width = ((CanvasPort*)parentItem())->getPortWidth();

QPen pen;

if (port_type == PORT_TYPE_AUDIO_JACK)
pen = QPen(canvas.theme->line_audio_jack, 2);
else if (port_type == PORT_TYPE_MIDI_JACK)
pen = QPen(canvas.theme->line_midi_jack, 2);
else if (port_type == PORT_TYPE_MIDI_A2J)
pen = QPen(canvas.theme->line_midi_a2j, 2);
else if (port_type == PORT_TYPE_MIDI_ALSA)
pen = QPen(canvas.theme->line_midi_alsa, 2);
else
{
qWarning("PatchCanvas::CanvasLineMov(%s, %s, %p) - invalid port type", port_mode2str(port_mode), port_type2str(port_type), parent);
pen = QPen(Qt::black);
}

setPen(pen);
}

void CanvasLineMov::deleteFromScene()
{
canvas.scene->removeItem(this);
delete this;
}

void CanvasLineMov::updateLinePos(QPointF scenePos)
{
int item_pos[2] = { 0, 0 };

if (m_port_mode == PORT_MODE_INPUT)
{
item_pos[0] = 0;
item_pos[1] = 7.5;
}
else if (m_port_mode == PORT_MODE_OUTPUT)
{
item_pos[0] = p_width+12;
item_pos[1] = 7.5;
}
else
return;

QLineF line(item_pos[0], item_pos[1], scenePos.x()-p_lineX, scenePos.y()-p_lineY);
setLine(line);
}

int CanvasLineMov::type() const
{
return CanvasLineMovType;
}

void CanvasLineMov::paint(QPainter* painter, const QStyleOptionGraphicsItem* option, QWidget* widget)
{
painter->setRenderHint(QPainter::Antialiasing, bool(options.antialiasing));
QGraphicsLineItem::paint(painter, option, widget);
}

END_NAMESPACE_PATCHCANVAS

+ 60
- 0
c++/patchcanvas/canvaslinemov.h View File

@@ -0,0 +1,60 @@
/*
* Patchbay Canvas engine using QGraphicsView/Scene
* Copyright (C) 2010-2012 Filipe Coelho <falktx@gmail.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* For a full copy of the GNU General Public License see the COPYING file
*/

#ifndef CANVASLINEMOV_H
#define CANVASLINEMOV_H

#include <QGraphicsLineItem>

#include "abstractcanvasline.h"

class QPainter;

START_NAMESPACE_PATCHCANVAS

class CanvasLineMov :
public AbstractCanvasLineMov,
public QGraphicsLineItem
{
public:
CanvasLineMov(PortMode port_mode, PortType port_type, QGraphicsItem* parent);

virtual void deleteFromScene();

virtual void updateLinePos(QPointF scenePos);

virtual int type() const;

// QGraphicsItem generic calls
virtual void setZValue(qreal z)
{
QGraphicsLineItem::setZValue(z);
}

private:
PortMode m_port_mode;
PortType m_port_type;
int p_lineX;
int p_lineY;
int p_width;

virtual void paint(QPainter* painter, const QStyleOptionGraphicsItem* option, QWidget* widget);
};

END_NAMESPACE_PATCHCANVAS

#endif // CANVASLINEMOV_H

+ 447
- 0
c++/patchcanvas/canvasport.cpp View File

@@ -0,0 +1,447 @@
/*
* Patchbay Canvas engine using QGraphicsView/Scene
* Copyright (C) 2010-2012 Filipe Coelho <falktx@gmail.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* For a full copy of the GNU General Public License see the COPYING file
*/

#include "canvasport.h"

#include <QtCore/QTimer>
#include <QtGui/QCursor>
#include <QtGui/QGraphicsSceneContextMenuEvent>
#include <QtGui/QGraphicsSceneMouseEvent>
#include <QtGui/QInputDialog>
#include <QtGui/QMenu>
#include <QtGui/QPainter>

#include "canvaslinemov.h"
#include "canvasbezierlinemov.h"
#include "canvasbox.h"

START_NAMESPACE_PATCHCANVAS

CanvasPort::CanvasPort(int port_id, QString port_name, PortMode port_mode, PortType port_type, QGraphicsItem* parent) :
QGraphicsItem(parent, canvas.scene)
{
// Save Variables, useful for later
m_port_id = port_id;
m_port_mode = port_mode;
m_port_type = port_type;
m_port_name = port_name;

// Base Variables
m_port_width = 15;
m_port_height = 15;
m_port_font = QFont(canvas.theme->port_font_name, canvas.theme->port_font_size, canvas.theme->port_font_state);

m_line_mov = 0;
m_hover_item = 0;
m_last_selected_state = false;

m_mouse_down = false;
m_cursor_moving = false;

setFlags(QGraphicsItem::ItemIsSelectable);
}

int CanvasPort::getPortId()
{
return m_port_id;
}

PortMode CanvasPort::getPortMode()
{
return m_port_mode;
}

PortType CanvasPort::getPortType()
{
return m_port_type;
}

QString CanvasPort::getPortName()
{
return m_port_name;
}

QString CanvasPort::getFullPortName()
{
return ((CanvasBox*)parentItem())->getGroupName()+":"+m_port_name;
}

int CanvasPort::getPortWidth()
{
return m_port_width;
}

int CanvasPort::getPortHeight()
{
return m_port_height;
}

void CanvasPort::setPortMode(PortMode port_mode)
{
m_port_mode = port_mode;
update();
}

void CanvasPort::setPortType(PortType port_type)
{
m_port_type = port_type;
update();
}

void CanvasPort::setPortName(QString port_name)
{
if (QFontMetrics(m_port_font).width(port_name) < QFontMetrics(m_port_font).width(m_port_name))
QTimer::singleShot(0, canvas.scene, SLOT(update()));

m_port_name = port_name;
update();
}

void CanvasPort::setPortWidth(int port_width)
{
if (port_width < m_port_width)
QTimer::singleShot(0, canvas.scene, SLOT(update()));

m_port_width = port_width;
update();
}

int CanvasPort::type() const
{
return CanvasPortType;
}

void CanvasPort::mousePressEvent(QGraphicsSceneMouseEvent* event)
{
m_hover_item = 0;
m_mouse_down = (event->button() == Qt::LeftButton);
m_cursor_moving = false;
QGraphicsItem::mousePressEvent(event);
}

void CanvasPort::mouseMoveEvent(QGraphicsSceneMouseEvent* event)
{
if (m_mouse_down)
{
if (m_cursor_moving == false)
{
setCursor(QCursor(Qt::CrossCursor));
m_cursor_moving = true;

foreach (const connection_dict_t& connection, canvas.connection_list)
{
if (connection.port_out_id == m_port_id || connection.port_in_id == m_port_id)
connection.widget->setLocked(true);
}
}

if (! m_line_mov)
{
if (options.use_bezier_lines)
m_line_mov = new CanvasBezierLineMov(m_port_mode, m_port_type, this);
else
m_line_mov = new CanvasLineMov(m_port_mode, m_port_type, this);

canvas.last_z_value += 1;
m_line_mov->setZValue(canvas.last_z_value);
canvas.last_z_value += 1;
parentItem()->setZValue(canvas.last_z_value);
}

CanvasPort* item = 0;
QList<QGraphicsItem*> items = canvas.scene->items(event->scenePos(), Qt::ContainsItemShape, Qt::AscendingOrder);
for (int i=0; i < items.count(); i++)
{
if (items[i]->type() == CanvasPortType)
{
if (items[i] != this)
{
if (! item)
item = (CanvasPort*)items[i];
else if (items[i]->parentItem()->zValue() > item->parentItem()->zValue())
item = (CanvasPort*)items[i];
}
}
}

if (m_hover_item and m_hover_item != item)
m_hover_item->setSelected(false);

if (item)
{
bool a2j_connection = (item->getPortType() == PORT_TYPE_MIDI_JACK && m_port_type == PORT_TYPE_MIDI_A2J) || (item->getPortType() == PORT_TYPE_MIDI_A2J && m_port_type == PORT_TYPE_MIDI_JACK);
if (item->getPortMode() != m_port_mode && (item->getPortType() == m_port_type || a2j_connection))
{
item->setSelected(true);
m_hover_item = item;
}
else
m_hover_item = 0;
}
else
m_hover_item = 0;

m_line_mov->updateLinePos(event->scenePos());
return event->accept();
}

QGraphicsItem::mouseMoveEvent(event);
}

void CanvasPort::mouseReleaseEvent(QGraphicsSceneMouseEvent* event)
{
if (m_mouse_down)
{
if (m_line_mov)
{
m_line_mov->deleteFromScene();
m_line_mov = 0;
}

foreach (const connection_dict_t& connection, canvas.connection_list)
{
if (connection.port_out_id == m_port_id || connection.port_in_id == m_port_id)
connection.widget->setLocked(false);
}

if (m_hover_item)
{
bool check = false;
foreach (const connection_dict_t& connection, canvas.connection_list)
{
if ( (connection.port_out_id == m_port_id && connection.port_in_id == m_hover_item->getPortId()) ||
(connection.port_out_id == m_hover_item->getPortId() && connection.port_in_id == m_port_id) )
{
canvas.callback(ACTION_PORTS_DISCONNECT, connection.connection_id, 0, "");
check = true;
break;
}
}

if (check == false)
{
if (m_port_mode == PORT_MODE_OUTPUT)
canvas.callback(ACTION_PORTS_CONNECT, m_port_id, m_hover_item->getPortId(), "");
else
canvas.callback(ACTION_PORTS_CONNECT, m_hover_item->getPortId(), m_port_id, "");
}

canvas.scene->clearSelection();
}
}

if (m_cursor_moving)
setCursor(QCursor(Qt::ArrowCursor));

m_hover_item = 0;
m_mouse_down = false;
m_cursor_moving = false;
QGraphicsItem::mouseReleaseEvent(event);
}

void CanvasPort::contextMenuEvent(QGraphicsSceneContextMenuEvent* event)
{
canvas.scene->clearSelection();
setSelected(true);

QMenu menu;
QMenu discMenu("Disconnect", &menu);

QList<int> port_con_list = CanvasGetPortConnectionList(m_port_id);

if (port_con_list.count() > 0)
{
foreach (int port_id, port_con_list)
{
int port_con_id = CanvasGetConnectedPort(port_id, m_port_id);
QAction* act_x_disc = discMenu.addAction(CanvasGetFullPortName(port_con_id));
act_x_disc->setData(port_id);
QObject::connect(act_x_disc, SIGNAL(triggered()), canvas.qobject, SLOT(PortContextMenuDisconnect()));
}
}
else
{
QAction* act_x_disc = discMenu.addAction("No connections");
act_x_disc->setEnabled(false);
}

menu.addMenu(&discMenu);
QAction* act_x_disc_all = menu.addAction("Disconnect &All");
QAction* act_x_sep_1 = menu.addSeparator();
QAction* act_x_info = menu.addAction("Get &Info");
QAction* act_x_rename = menu.addAction("&Rename");

if (features.port_info == false)
act_x_info->setVisible(false);

if (features.port_rename == false)
act_x_rename->setVisible(false);

if (features.port_info == false && features.port_rename == false)
act_x_sep_1->setVisible(false);

QAction* act_selected = menu.exec(event->screenPos());

if (act_selected == act_x_disc_all)
{
foreach (int port_id, port_con_list)
canvas.callback(ACTION_PORTS_DISCONNECT, port_id, 0, "");
}
else if (act_selected == act_x_info)
{
canvas.callback(ACTION_PORT_INFO, m_port_id, 0, "");
}
else if (act_selected == act_x_rename)
{
bool ok_check;
QString new_name = QInputDialog::getText(0, "Rename Port", "New name:", QLineEdit::Normal, m_port_name, &ok_check);
if (ok_check and new_name.isEmpty() == false)
{
canvas.callback(ACTION_PORT_RENAME, m_port_id, 0, new_name);
}
}

event->accept();
}

QRectF CanvasPort::boundingRect() const
{
return QRectF(0, 0, m_port_width+12, m_port_height);
}

void CanvasPort::paint(QPainter* painter, const QStyleOptionGraphicsItem* /*option*/, QWidget* /*widget*/)
{
painter->setRenderHint(QPainter::Antialiasing, (options.antialiasing == ANTIALIASING_FULL));

QPointF text_pos;
int poly_locx[5] = { 0 };

if (m_port_mode == PORT_MODE_INPUT)
{
text_pos = QPointF(3, 12);

if (canvas.theme->port_mode == Theme::THEME_PORT_POLYGON)
{
poly_locx[0] = 0;
poly_locx[1] = m_port_width+5;
poly_locx[2] = m_port_width+12;
poly_locx[3] = m_port_width+5;
poly_locx[4] = 0;
}
else if (canvas.theme->port_mode == Theme::THEME_PORT_SQUARE)
{
poly_locx[0] = 0;
poly_locx[1] = m_port_width+5;
poly_locx[2] = m_port_width+5;
poly_locx[3] = m_port_width+5;
poly_locx[4] = 0;
}
else
{
qCritical("PatchCanvas::CanvasPort->paint() - invalid theme port mode '%i'", canvas.theme->port_mode);
return;
}
}
else if (m_port_mode == PORT_MODE_OUTPUT)
{
text_pos = QPointF(9, 12);

if (canvas.theme->port_mode == Theme::THEME_PORT_POLYGON)
{
poly_locx[0] = m_port_width+12;
poly_locx[1] = 7;
poly_locx[2] = 0;
poly_locx[3] = 7;
poly_locx[4] = m_port_width+12;
}
else if (canvas.theme->port_mode == Theme::THEME_PORT_SQUARE)
{
poly_locx[0] = m_port_width+12;
poly_locx[1] = 5;
poly_locx[2] = 5;
poly_locx[3] = 5;
poly_locx[4] = m_port_width+12;
}
else
{
qCritical("PatchCanvas::CanvasPort->paint() - invalid theme port mode '%i'", canvas.theme->port_mode);
return;
}
}
else
{
qCritical("PatchCanvas::CanvasPort->paint() - invalid port mode '%s'", port_mode2str(m_port_mode));
return;
}

QColor poly_color;
QPen poly_pen;

if (m_port_type == PORT_TYPE_AUDIO_JACK)
{
poly_color = isSelected() ? canvas.theme->port_audio_jack_bg_sel : canvas.theme->port_audio_jack_bg;
poly_pen = isSelected() ? canvas.theme->port_audio_jack_pen_sel : canvas.theme->port_audio_jack_pen;
}
else if (m_port_type == PORT_TYPE_MIDI_JACK)
{
poly_color = isSelected() ? canvas.theme->port_midi_jack_bg_sel : canvas.theme->port_midi_jack_bg;
poly_pen = isSelected() ? canvas.theme->port_midi_jack_pen_sel : canvas.theme->port_midi_jack_pen;
}
else if (m_port_type == PORT_TYPE_MIDI_A2J)
{
poly_color = isSelected() ? canvas.theme->port_midi_a2j_bg_sel : canvas.theme->port_midi_a2j_bg;
poly_pen = isSelected() ? canvas.theme->port_midi_a2j_pen_sel : canvas.theme->port_midi_a2j_pen;
}
else if (m_port_type == PORT_TYPE_MIDI_ALSA)
{
poly_color = isSelected() ? canvas.theme->port_midi_alsa_bg_sel : canvas.theme->port_midi_alsa_bg;
poly_pen = isSelected() ? canvas.theme->port_midi_alsa_pen_sel : canvas.theme->port_midi_alsa_pen;
}
else
{
qCritical("PatchCanvas::CanvasPort->paint() - invalid port type '%s'", port_type2str(m_port_type));
return;
}

QPolygonF polygon;
polygon += QPointF(poly_locx[0], 0);
polygon += QPointF(poly_locx[1], 0);
polygon += QPointF(poly_locx[2], 7.5);
polygon += QPointF(poly_locx[3], 15);
polygon += QPointF(poly_locx[4], 15);

painter->setBrush(poly_color);
painter->setPen(poly_pen);
painter->drawPolygon(polygon);

painter->setPen(canvas.theme->port_text);
painter->setFont(m_port_font);
painter->drawText(text_pos, m_port_name);

if (isSelected() != m_last_selected_state)
{
foreach (const connection_dict_t& connection, canvas.connection_list)
{
if (connection.port_out_id == m_port_id || connection.port_in_id == m_port_id)
connection.widget->setLineSelected(isSelected());
}
}

m_last_selected_state = isSelected();
}

END_NAMESPACE_PATCHCANVAS

+ 79
- 0
c++/patchcanvas/canvasport.h View File

@@ -0,0 +1,79 @@
/*
* Patchbay Canvas engine using QGraphicsView/Scene
* Copyright (C) 2010-2012 Filipe Coelho <falktx@gmail.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* For a full copy of the GNU General Public License see the COPYING file
*/

#ifndef CANVASPORT_H
#define CANVASPORT_H

#include "patchcanvas.h"

class QGraphicsSceneContextMenuEvent;
class QGraphicsSceneMouseEvent;
class QPainter;

START_NAMESPACE_PATCHCANVAS

class AbstractCanvasLineMov;

class CanvasPort : public QGraphicsItem
{
public:
CanvasPort(int port_id, QString port_name, PortMode port_mode, PortType port_type, QGraphicsItem* parent);

int getPortId();
PortMode getPortMode();
PortType getPortType();
QString getPortName();
QString getFullPortName();
int getPortWidth();
int getPortHeight();

void setPortMode(PortMode port_mode);
void setPortType(PortType port_type);
void setPortName(QString port_name);
void setPortWidth(int port_width);

virtual int type() const;

private:
int m_port_id;
PortMode m_port_mode;
PortType m_port_type;
QString m_port_name;

int m_port_width;
int m_port_height;
QFont m_port_font;

AbstractCanvasLineMov* m_line_mov;
CanvasPort* m_hover_item;
bool m_last_selected_state;

bool m_mouse_down;
bool m_cursor_moving;

virtual void mousePressEvent(QGraphicsSceneMouseEvent* event);
virtual void mouseMoveEvent(QGraphicsSceneMouseEvent* event);
virtual void mouseReleaseEvent(QGraphicsSceneMouseEvent* event);
virtual void contextMenuEvent(QGraphicsSceneContextMenuEvent* event);

virtual QRectF boundingRect() const;
virtual void paint(QPainter* painter, const QStyleOptionGraphicsItem* option, QWidget* widget);
};

END_NAMESPACE_PATCHCANVAS

#endif // CANVASPORT_H

+ 38
- 0
c++/patchcanvas/canvasportglow.cpp View File

@@ -0,0 +1,38 @@
/*
* Patchbay Canvas engine using QGraphicsView/Scene
* Copyright (C) 2010-2012 Filipe Coelho <falktx@gmail.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* For a full copy of the GNU General Public License see the COPYING file
*/

#include "canvasportglow.h"

START_NAMESPACE_PATCHCANVAS

CanvasPortGlow::CanvasPortGlow(PortType port_type, QObject* parent) :
QGraphicsDropShadowEffect(parent)
{
setBlurRadius(12);
setOffset(0, 0);

if (port_type == PORT_TYPE_AUDIO_JACK)
setColor(canvas.theme->line_audio_jack_glow);
else if (port_type == PORT_TYPE_MIDI_JACK)
setColor(canvas.theme->line_midi_jack_glow);
else if (port_type == PORT_TYPE_MIDI_A2J)
setColor(canvas.theme->line_midi_a2j_glow);
else if (port_type == PORT_TYPE_MIDI_ALSA)
setColor(canvas.theme->line_midi_alsa_glow);
}

END_NAMESPACE_PATCHCANVAS

+ 35
- 0
c++/patchcanvas/canvasportglow.h View File

@@ -0,0 +1,35 @@
/*
* Patchbay Canvas engine using QGraphicsView/Scene
* Copyright (C) 2010-2012 Filipe Coelho <falktx@gmail.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* For a full copy of the GNU General Public License see the COPYING file
*/

#ifndef CANVASPORTGLOW_H
#define CANVASPORTGLOW_H

#include <QGraphicsDropShadowEffect>

#include "patchcanvas.h"

START_NAMESPACE_PATCHCANVAS

class CanvasPortGlow : public QGraphicsDropShadowEffect
{
public:
CanvasPortGlow(PortType port_type, QObject* parent);
};

END_NAMESPACE_PATCHCANVAS

#endif // CANVASPORTGLOW_H

+ 405
- 0
c++/patchcanvas/canvastestapp.cpp View File

@@ -0,0 +1,405 @@
#include "canvastestapp.h"
#include "ui_canvastestapp.h"

#include <QMessageBox>
#include <QSettings>
#include <QVariant>
#include <QGLWidget>

struct group_name_to_id_t {
int id;
QString name;
};

struct port_name_to_id_t {
int group_id;
int port_id;
QString name;
};

struct connection_to_id_t {
int id;
int port_out;
int port_in;
};

static int last_group_id = 0;
static int last_port_id = 0;
static int last_connection_id = 0;

static CanvasTestApp* main_gui = 0;
static jack_client_t* jack_client = 0;

static QList<group_name_to_id_t> used_group_names;
static QList<port_name_to_id_t> used_port_names;
static QList<connection_to_id_t> used_connections;

int get_group_id(QString group_name)
{
for (int i=0; i < used_group_names.count(); i++)
{
if (used_group_names[i].name == group_name)
{
return used_group_names[i].id;
}
}
return -1;
}

int get_port_id(QString full_port_name)
{
QString group_name = full_port_name.split(":").at(0);
QString port_name = full_port_name.replace(group_name+":", "");
int group_id = get_group_id(group_name);

for (int i=0; i < used_port_names.count(); i++)
{
if (used_port_names[i].group_id == group_id && used_port_names[i].name == port_name)
{
return used_port_names[i].port_id;
}
}

return -1;
}

QString get_full_port_name(int port_id)
{
int group_id = -1;
QString group_name;
QString port_name;

for (int i=0; i < used_port_names.count(); i++)
{
if (used_port_names[i].port_id == port_id)
{
group_id = used_port_names[i].group_id;
port_name = used_port_names[i].name;
}
}

for (int i=0; i < used_group_names.count(); i++)
{
if (used_group_names[i].id == group_id)
{
group_name = used_group_names[i].name;
}
}

return group_name+":"+port_name;
}

void canvas_callback(PatchCanvas::CallbackAction action, int value1, int value2, QString value_str)
{
qDebug("--------------------------- Callback called %i|%i|%i|%s", action, value1, value2, value_str.toStdString().data());

switch (action)
{
case PatchCanvas::ACTION_PORT_INFO:
QMessageBox::information(main_gui, "port info dialog", "dummy text here");
break;
case PatchCanvas::ACTION_PORT_RENAME:
// Unused
break;
case PatchCanvas::ACTION_PORTS_CONNECT:
jack_connect(jack_client, get_full_port_name(value1).toStdString().data(), get_full_port_name(value2).toStdString().data());
break;
case PatchCanvas::ACTION_PORTS_DISCONNECT:
for (int i=0; i < used_connections.count(); i++)
{
if (used_connections[i].id == value1)
{
jack_disconnect(jack_client, get_full_port_name(used_connections[i].port_out).toStdString().data(), get_full_port_name(used_connections[i].port_in).toStdString().data());
break;
}
}
break;
case PatchCanvas::ACTION_GROUP_INFO:
QMessageBox::information(main_gui, "group info dialog", "dummy text here");
break;
case PatchCanvas::ACTION_GROUP_RENAME:
// Unused
break;
case PatchCanvas::ACTION_GROUP_SPLIT:
PatchCanvas::splitGroup(value1);
break;
case PatchCanvas::ACTION_GROUP_JOIN:
PatchCanvas::joinGroup(value1);
break;
default:
break;
}
}

CanvasTestApp::CanvasTestApp(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::CanvasTestApp)
{
ui->setupUi(this);

settings = new QSettings("PatchCanvas", "Canvas-test-app");
restoreGeometry(settings->value("Geometry").toByteArray());

main_gui = this;
used_group_names.clear();
used_port_names.clear();
used_connections.clear();

scene = new PatchScene(this, ui->graphicsView);
ui->graphicsView->setScene(scene);
ui->graphicsView->setRenderHint(QPainter::Antialiasing, true);
ui->graphicsView->setRenderHint(QPainter::TextAntialiasing, true);
//ui->graphicsView->setRenderHint(QPainter::HighQualityAntialiasing, true);
//ui->graphicsView->setViewport(new QGLWidget(ui->graphicsView));

PatchCanvas::options_t options;
options.auto_hide_groups = false;
options.use_bezier_lines = true;
options.antialiasing = PatchCanvas::ANTIALIASING_SMALL;
options.eyecandy = PatchCanvas::EYECANDY_FULL;
options.theme_name = PatchCanvas::getDefaultThemeName();

PatchCanvas::features_t features;
features.group_info = false;
features.group_rename = false;
features.port_info = false;
features.port_rename = false;
features.handle_group_pos = true;

PatchCanvas::setOptions(&options);
PatchCanvas::setFeatures(&features);
PatchCanvas::init(scene, canvas_callback, true);

connect(this, SIGNAL(clientRegisterCallback(QString,bool)), SLOT(handle_clientRegisterCallback(QString,bool)));
connect(this, SIGNAL(portRegisterCallback(int,bool)), SLOT(handle_portRegisterCallback(int,bool)));
connect(this, SIGNAL(connectionCallback(int,int,bool)), SLOT(handle_connectionCallback(int,int,bool)));

jack_client = jack_client_open("canvas-test-app", JackNullOption, 0);
jack_set_client_registration_callback(jack_client, client_register_callback, 0);
jack_set_port_registration_callback(jack_client, port_register_callback, 0);
jack_set_port_connect_callback(jack_client, port_connect_callback, 0);
jack_activate(jack_client);

// query initial jack ports
QList<QString> parsed_groups;
const char** ports = jack_get_ports(jack_client, 0, 0, 0);
if (ports) {
for (int i=0; ports[i]; i++) {
QString full_name(ports[i]);
QString group_name = full_name.split(":").at(0);
QString port_name = full_name.replace(group_name+":", "");
int group_id = -1;

if (parsed_groups.contains(group_name))
{
group_id = get_group_id(group_name);
}
else
{
group_id = last_group_id;

group_name_to_id_t group_name_to_id;
group_name_to_id.id = group_id;
group_name_to_id.name = group_name;
used_group_names.append(group_name_to_id);

parsed_groups.append(group_name);
PatchCanvas::addGroup(group_id, group_name);
last_group_id++;
}

PatchCanvas::PortMode port_mode;
PatchCanvas::PortType port_type;
jack_port_t* jack_port = jack_port_by_name(jack_client, ports[i]);

if (jack_port_flags(jack_port) & JackPortIsInput)
port_mode = PatchCanvas::PORT_MODE_INPUT;
else
port_mode = PatchCanvas::PORT_MODE_OUTPUT;

if (strcmp(jack_port_type(jack_port), JACK_DEFAULT_AUDIO_TYPE) == 0)
port_type = PatchCanvas::PORT_TYPE_AUDIO_JACK;
else
port_type = PatchCanvas::PORT_TYPE_MIDI_JACK;

port_name_to_id_t port_name_to_id;
port_name_to_id.group_id = group_id;
port_name_to_id.port_id = last_port_id;
port_name_to_id.name = port_name;
used_port_names.append(port_name_to_id);
PatchCanvas::addPort(group_id, last_port_id, port_name, port_mode, port_type);
last_port_id++;
}

jack_free(ports);
}

// query connections, after all ports are in place
ports = jack_get_ports(jack_client, 0, 0, JackPortIsOutput);
if (ports) {
for (int i=0; ports[i]; i++) {
QString this_full_name(ports[i]);
int this_port_id = get_port_id(this_full_name);

jack_port_t* jack_port = jack_port_by_name(jack_client, ports[i]);
const char** connections = jack_port_get_connections(jack_port);

if (connections) {
for (int j=0; connections[j]; j++) {
QString target_full_name(connections[j]);
int target_port_id = get_port_id(target_full_name);

connection_to_id_t connection;
connection.id = last_connection_id;
connection.port_out = this_port_id;
connection.port_in = target_port_id;
used_connections.append(connection);
PatchCanvas::connectPorts(last_connection_id, this_port_id, target_port_id);
last_connection_id++;
}

jack_free(connections);
}
}

jack_free(ports);
}
}

CanvasTestApp::~CanvasTestApp()
{
delete settings;
delete scene;
delete ui;
}

void CanvasTestApp::client_register_callback(const char* name, int register_, void*)
{
main_gui->emit clientRegisterCallback(QString(name), bool(register_));
}

void CanvasTestApp::port_register_callback(jack_port_id_t port_id_jack, int register_, void*)
{
main_gui->emit portRegisterCallback(port_id_jack, bool(register_));
}

void CanvasTestApp::port_connect_callback(jack_port_id_t port_a, jack_port_id_t port_b, int connect, void*)
{
main_gui->emit connectionCallback(port_a, port_b, bool(connect));
}

void CanvasTestApp::handle_clientRegisterCallback(QString name, bool yesno)
{
QString qname(name);

if (yesno)
{
group_name_to_id_t group_name_to_id;
group_name_to_id.id = last_group_id;
group_name_to_id.name = qname;
used_group_names.append(group_name_to_id);
PatchCanvas::addGroup(last_group_id, qname);
last_group_id++;
}
else
{
for (int i=0; i < used_group_names.count(); i++)
{
if (used_group_names[i].name == qname)
{
PatchCanvas::removeGroup(used_group_names[i].id);
used_group_names.takeAt(i);
break;
}
}
}
}

void CanvasTestApp::handle_portRegisterCallback(int port, bool yesno)
{
jack_port_t* jack_port = jack_port_by_id(jack_client, port);

QString full_name(jack_port_name(jack_port));
QString group_name = full_name.split(":").at(0);
QString port_name = full_name.replace(group_name+":", "");
int group_id = get_group_id(group_name);

if (yesno)
{
PatchCanvas::PortMode port_mode;
PatchCanvas::PortType port_type;

if (jack_port_flags(jack_port) & JackPortIsInput)
port_mode = PatchCanvas::PORT_MODE_INPUT;
else
port_mode = PatchCanvas::PORT_MODE_OUTPUT;

if (strcmp(jack_port_type(jack_port), JACK_DEFAULT_AUDIO_TYPE) == 0)
port_type = PatchCanvas::PORT_TYPE_AUDIO_JACK;
else
port_type = PatchCanvas::PORT_TYPE_MIDI_JACK;

port_name_to_id_t port_name_to_id;
port_name_to_id.group_id = group_id;
port_name_to_id.port_id = last_port_id;
port_name_to_id.name = port_name;
used_port_names.append(port_name_to_id);
PatchCanvas::addPort(group_id, last_port_id, port_name, port_mode, port_type);
last_port_id++;
}
else
{
for (int i=0; i < used_port_names.count(); i++)
{
if (used_port_names[i].group_id == group_id && used_port_names[i].name == port_name)
{
PatchCanvas::removePort(used_port_names[i].port_id);
used_port_names.takeAt(i);
break;
}
}
}
}

void CanvasTestApp::handle_connectionCallback(int port_a, int port_b, bool yesno)
{
jack_port_t* jack_port_a = jack_port_by_id(jack_client, port_a);
jack_port_t* jack_port_b = jack_port_by_id(jack_client, port_b);
int port_id_a = get_port_id(QString(jack_port_name(jack_port_a)));
int port_id_b = get_port_id(QString(jack_port_name(jack_port_b)));

if (yesno)
{
connection_to_id_t connection;
connection.id = last_connection_id;
connection.port_out = port_id_a;
connection.port_in = port_id_b;
used_connections.append(connection);
PatchCanvas::connectPorts(last_connection_id, port_id_a, port_id_b);
last_connection_id++;
}
else
{
for (int i=0; i < used_connections.count(); i++)
{
if (used_connections[i].port_out == port_id_a && used_connections[i].port_in == port_id_b)
{
PatchCanvas::disconnectPorts(used_connections[i].id);
used_connections.takeAt(i);
break;
}
}
}
}

void CanvasTestApp::closeEvent(QCloseEvent* event)
{
jack_deactivate(jack_client);
jack_client_close(jack_client);

PatchCanvas::clear();

settings->setValue("Geometry", QVariant(saveGeometry()));

QMainWindow::closeEvent(event);
}

+ 50
- 0
c++/patchcanvas/canvastestapp.h View File

@@ -0,0 +1,50 @@
/*
* PatchCanvas test app
*/

#ifndef CANVASTESTAPP_H
#define CANVASTESTAPP_H

#include <QMainWindow>

#include <jack/jack.h>

#include "patchcanvas-api.h"

namespace Ui {
class CanvasTestApp;
}

class QSettings;

class CanvasTestApp : public QMainWindow
{
Q_OBJECT

public:
explicit CanvasTestApp(QWidget *parent = 0);
~CanvasTestApp();

static void client_register_callback(const char* name, int register_, void *arg);
static void port_register_callback(jack_port_id_t port_id_jack, int register_, void *arg);
static void port_connect_callback(jack_port_id_t port_a, jack_port_id_t port_b, int connect, void* arg);

signals:
void clientRegisterCallback(QString name, bool yesno);
void portRegisterCallback(int port, bool yesno);
void connectionCallback(int port_a, int port_b, bool yesno);

private slots:
void handle_clientRegisterCallback(QString name, bool yesno);
void handle_portRegisterCallback(int port, bool yesno);
void handle_connectionCallback(int port_a, int port_b, bool yesno);

private:
Ui::CanvasTestApp* ui;
PatchScene* scene;
QSettings* settings;

virtual void closeEvent(QCloseEvent* event);
};

#endif // CANVASTESTAPP_H

+ 95
- 0
c++/patchcanvas/canvastestapp.ui View File

@@ -0,0 +1,95 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>CanvasTestApp</class>
<widget class="QMainWindow" name="CanvasTestApp">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>811</width>
<height>646</height>
</rect>
</property>
<property name="windowTitle">
<string>CanvasTestApp</string>
</property>
<widget class="QWidget" name="centralWidget">
<layout class="QVBoxLayout" name="verticalLayout">
<property name="spacing">
<number>0</number>
</property>
<property name="margin">
<number>0</number>
</property>
<item>
<widget class="QGraphicsView" name="graphicsView"/>
</item>
</layout>
</widget>
<action name="action_Quit">
<property name="text">
<string>&amp;Quit</string>
</property>
</action>
<action name="action_Arrange">
<property name="text">
<string>&amp;Arrange</string>
</property>
</action>
<action name="action_Refresh">
<property name="text">
<string>&amp;Refresh</string>
</property>
</action>
<action name="actionZoom_Fit">
<property name="text">
<string>Zoom Fit</string>
</property>
</action>
<action name="actionZoom_In">
<property name="text">
<string>Zoom In</string>
</property>
</action>
<action name="actionZoom_Out">
<property name="text">
<string>Zoom Out</string>
</property>
</action>
<action name="actionZoom_100">
<property name="text">
<string>Zoom 100%</string>
</property>
</action>
<action name="action_Print">
<property name="text">
<string>&amp;Print...</string>
</property>
</action>
<action name="action_Save_Image">
<property name="text">
<string>&amp;Save Image...</string>
</property>
</action>
</widget>
<layoutdefault spacing="6" margin="11"/>
<resources/>
<connections>
<connection>
<sender>action_Quit</sender>
<signal>triggered()</signal>
<receiver>CanvasTestApp</receiver>
<slot>close()</slot>
<hints>
<hint type="sourcelabel">
<x>-1</x>
<y>-1</y>
</hint>
<hint type="destinationlabel">
<x>198</x>
<y>148</y>
</hint>
</hints>
</connection>
</connections>
</ui>

+ 11
- 0
c++/patchcanvas/main.cpp View File

@@ -0,0 +1,11 @@
#include <QtGui/QApplication>
#include "canvastestapp.h"

int main(int argc, char *argv[])
{
QApplication a(argc, argv);
CanvasTestApp w;
w.show();

return a.exec();
}

+ 134
- 0
c++/patchcanvas/patchcanvas-api.h View File

@@ -0,0 +1,134 @@
/*
* Patchbay Canvas engine using QGraphicsView/Scene
* Copyright (C) 2010-2012 Filipe Coelho <falktx@gmail.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* For a full copy of the GNU General Public License see the COPYING file
*/

#ifndef PATCHCANVAS_API_H
#define PATCHCANVAS_API_H

#define START_NAMESPACE_PATCHCANVAS namespace PatchCanvas {
#define END_NAMESPACE_PATCHCANVAS }

#ifndef PATCHCANVAS_ORGANISATION_NAME
#define PATCHCANVAS_ORGANISATION_NAME "PatchCanvas"
#endif

#include <QtCore/QString>

#include "patchcanvas-theme.h"
#include "patchscene.h"

START_NAMESPACE_PATCHCANVAS

enum PortMode {
PORT_MODE_NULL = 0,
PORT_MODE_INPUT = 1,
PORT_MODE_OUTPUT = 2
};

enum PortType {
PORT_TYPE_NULL = 0,
PORT_TYPE_AUDIO_JACK = 1,
PORT_TYPE_MIDI_JACK = 2,
PORT_TYPE_MIDI_A2J = 3,
PORT_TYPE_MIDI_ALSA = 4
};

enum CallbackAction {
ACTION_GROUP_INFO = 0, // group_id, N, N
ACTION_GROUP_RENAME = 1, // group_id, N, new_name
ACTION_GROUP_SPLIT = 2, // group_id, N, N
ACTION_GROUP_JOIN = 3, // group_id, N, N
ACTION_PORT_INFO = 4, // port_id, N, N
ACTION_PORT_RENAME = 5, // port_id, N, new_name
ACTION_PORTS_CONNECT = 6, // out_id, in_id, N
ACTION_PORTS_DISCONNECT = 7 // conn_id, N, N
};

enum Icon {
ICON_HARDWARE = 0,
ICON_APPLICATION = 1,
ICON_LADISH_ROOM = 2
};

enum SplitOption {
SPLIT_UNDEF = 0,
SPLIT_NO = 1,
SPLIT_YES = 2
};

enum AntialiasingOption {
ANTIALIASING_NONE = 0,
ANTIALIASING_SMALL = 1,
ANTIALIASING_FULL = 2
};

enum EyeCandyOption {
EYECANDY_NONE = 0,
EYECANDY_SMALL = 1,
EYECANDY_FULL = 2
};

// Canvas options
struct options_t {
QString theme_name;
bool auto_hide_groups;
bool use_bezier_lines;
AntialiasingOption antialiasing;
EyeCandyOption eyecandy;
};

// Canvas features
struct features_t {
bool group_info;
bool group_rename;
bool port_info;
bool port_rename;
bool handle_group_pos;
};

typedef void (*Callback) (CallbackAction action, int value1, int value2, QString value_str);

// API starts here
void setOptions(options_t* options);
void setFeatures(features_t* features);
void init(PatchScene* scene, Callback callback, bool debug=false);
void clear();

void setInitialPos(int x, int y);
void setCanvasSize(int x, int y, int width, int height);

void addGroup(int group_id, QString group_name, SplitOption split=SPLIT_UNDEF, Icon icon=ICON_APPLICATION);
void removeGroup(int group_id);
void renameGroup(int group_id, QString new_group_name);
void splitGroup(int group_id);
void joinGroup(int group_id);
QPointF getGroupPos(int group_id, PortMode port_mode=PORT_MODE_OUTPUT);
void setGroupPos(int group_id, int group_pos_x, int group_pos_y);
void setGroupPos(int group_id, int group_pos_x, int group_pos_y, int group_pos_xs, int group_pos_ys);
void setGroupIcon(int group_id, Icon icon);

void addPort(int group_id, int port_id, QString port_name, PortMode port_mode, PortType port_type);
void removePort(int port_id);
void renamePort(int port_id, QString new_port_name);

void connectPorts(int connection_id, int port_out_id, int port_in_id);
void disconnectPorts(int connection_id);

void Arrange();

END_NAMESPACE_PATCHCANVAS

#endif // PATCHCANVAS_API_H

+ 178
- 0
c++/patchcanvas/patchcanvas-theme.cpp View File

@@ -0,0 +1,178 @@
/*
* Patchbay Canvas engine using QGraphicsView/Scene
* Copyright (C) 2010-2012 Filipe Coelho <falktx@gmail.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* For a full copy of the GNU General Public License see the COPYING file
*/

#include "patchcanvas-theme.h"

START_NAMESPACE_PATCHCANVAS

Theme::Theme(List id)
{
switch (id)
{
case THEME_MODERN_DARK:
// Name this theme
name = "Modern Dark";

// Canvas
canvas_bg = QColor(0, 0, 0);

// Boxes
box_pen = QPen(QColor(76,77,78), 1, Qt::SolidLine);
box_pen_sel = QPen(QColor(206,207,208), 1, Qt::DashLine);
box_bg_1 = QColor(32,34,35);
box_bg_2 = QColor(43,47,48);
box_shadow = QColor(89,89,89,180);

box_text = QPen(QColor(240,240,240), 0);
box_font_name = "Deja Vu Sans";
box_font_size = 8;
box_font_state = QFont::Bold;

// Ports
port_audio_jack_pen = QPen(QColor(63,90,126), 1);
port_audio_jack_pen_sel = QPen(QColor(63+30,90+30,126+30), 1);
port_midi_jack_pen = QPen(QColor(159,44,42), 1);
port_midi_jack_pen_sel = QPen(QColor(159+30,44+30,42+30), 1);
port_midi_a2j_pen = QPen(QColor(137,76,43), 1);
port_midi_a2j_pen_sel = QPen(QColor(137+30,76+30,43+30), 1);
port_midi_alsa_pen = QPen(QColor(93,141,46), 1);
port_midi_alsa_pen_sel = QPen(QColor(93+30,141+30,46+30), 1);

port_audio_jack_bg = QColor(35,61,99);
port_audio_jack_bg_sel = QColor(35+50,61+50,99+50);
port_midi_jack_bg = QColor(120,15,16);
port_midi_jack_bg_sel = QColor(120+50,15+50,16+50);
port_midi_a2j_bg = QColor(101,47,16);
port_midi_a2j_bg_sel = QColor(101+50,47+50,16+50);
port_midi_alsa_bg = QColor(64,112,18);
port_midi_alsa_bg_sel = QColor(64+50,112+50,18+50);

port_text = QPen(QColor(250,250,250), 0);
port_font_name = "Deja Vu Sans";
port_font_size = 8;
port_font_state = QFont::Normal;
port_mode = THEME_PORT_POLYGON;

// Lines
line_audio_jack = QColor(63,90,126);
line_audio_jack_sel = QColor(63+90,90+90,126+90);
line_audio_jack_glow = QColor(100,100,200);
line_midi_jack = QColor(159,44,42);
line_midi_jack_sel = QColor(159+90,44+90,42+90);
line_midi_jack_glow = QColor(200,100,100);
line_midi_a2j = QColor(137,76,43);
line_midi_a2j_sel = QColor(137+90,76+90,43+90);
line_midi_a2j_glow = QColor(166,133,133);
line_midi_alsa = QColor(93,141,46);
line_midi_alsa_sel = QColor(93+90,141+90,46+90);
line_midi_alsa_glow = QColor(100,200,100);

rubberband_pen = QPen(QColor(206,207,208), 1, Qt::SolidLine);
rubberband_brush = QColor(76,77,78,100);
break;

case THEME_CLASSIC_DARK:
// Name this theme
name = "Classic Dark";

// Canvas
canvas_bg = QColor(0,0,0);

// Boxes
box_pen = QPen(QColor(147-70,151-70,143-70), 2, Qt::SolidLine);
box_pen_sel = QPen(QColor(147,151,143), 2, Qt::DashLine);
box_bg_1 = QColor(30,34,36);
box_bg_2 = QColor(30,34,36);
box_shadow = QColor(89,89,89,180);

box_text = QPen(QColor(255,255,255), 0);
box_font_name = "Sans";
box_font_size = 9;
box_font_state = QFont::Normal;

// Ports
port_audio_jack_pen = QPen(QColor(35,61,99), 0);
port_audio_jack_pen_sel = QPen(QColor(255,0,0), 0);
port_midi_jack_pen = QPen(QColor(120,15,16), 0);
port_midi_jack_pen_sel = QPen(QColor(255,0,0), 0);
port_midi_a2j_pen = QPen(QColor(101,47,17), 0);
port_midi_a2j_pen_sel = QPen(QColor(255,0,0), 0);
port_midi_alsa_pen = QPen(QColor(63,112,19), 0);
port_midi_alsa_pen_sel = QPen(QColor(255,0,0), 0);

port_audio_jack_bg = QColor(35,61,99);
port_audio_jack_bg_sel = QColor(255,0,0);
port_midi_jack_bg = QColor(120,15,16);
port_midi_jack_bg_sel = QColor(255,0,0);
port_midi_a2j_bg = QColor(101,47,17);
port_midi_a2j_bg_sel = QColor(255,0,0);
port_midi_alsa_bg = QColor(63,112,19);
port_midi_alsa_bg_sel = QColor(255,0,0);

port_text = QPen(QColor(250,250,250), 0);
port_font_name = "Sans";
port_font_size = 8;
port_font_state = QFont::Normal;
port_mode = THEME_PORT_SQUARE;

// Lines
line_audio_jack = QColor(53,78,116);
line_audio_jack_sel = QColor(255,0,0);
line_audio_jack_glow = QColor(255,0,0);
line_midi_jack = QColor(139,32,32);
line_midi_jack_sel = QColor(255,0,0);
line_midi_jack_glow = QColor(255,0,0);
line_midi_a2j = QColor(120,65,33);
line_midi_a2j_sel = QColor(255,0,0);
line_midi_a2j_glow = QColor(255,0,0);
line_midi_alsa = QColor(81,130,36);
line_midi_alsa_sel = QColor(255,0,0);
line_midi_alsa_glow = QColor(255,0,0);

rubberband_pen = QPen(QColor(147,151,143), 2, Qt::SolidLine);
rubberband_brush = QColor(35,61,99,100);
break;

default:
break;
}
}

Theme::List getDefaultTheme()
{
return Theme::THEME_MODERN_DARK;
}

QString getThemeName(Theme::List id)
{
switch (id)
{
case Theme::THEME_MODERN_DARK:
return "Modern Dark";
case Theme::THEME_CLASSIC_DARK:
return "Classic Dark";
default:
return "";
}
}

QString getDefaultThemeName()
{
return "Modern Dark";
}

END_NAMESPACE_PATCHCANVAS

+ 106
- 0
c++/patchcanvas/patchcanvas-theme.h View File

@@ -0,0 +1,106 @@
/*
* Patchbay Canvas engine using QGraphicsView/Scene
* Copyright (C) 2010-2012 Filipe Coelho <falktx@gmail.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* For a full copy of the GNU General Public License see the COPYING file
*/

#ifndef PATCHCANVAS_THEME_H
#define PATCHCANVAS_THEME_H

#include <QtGui/QColor>
#include <QtGui/QFont>
#include <QtGui/QPen>

#include "patchcanvas-api.h"

START_NAMESPACE_PATCHCANVAS

class Theme
{
public:
enum PortType {
THEME_PORT_SQUARE = 0,
THEME_PORT_POLYGON = 1
};

enum List {
THEME_MODERN_DARK = 0,
THEME_CLASSIC_DARK = 1,
THEME_MAX = 2
};

Theme(List id);

// Canvas
QString name;

// Boxes
QColor canvas_bg;
QPen box_pen;
QPen box_pen_sel;
QColor box_bg_1;
QColor box_bg_2;
QColor box_shadow;
QPen box_text;
QString box_font_name;
int box_font_size;
QFont::Weight box_font_state;

// Ports
QPen port_audio_jack_pen;
QPen port_audio_jack_pen_sel;
QPen port_midi_jack_pen;
QPen port_midi_jack_pen_sel;
QPen port_midi_a2j_pen;
QPen port_midi_a2j_pen_sel;
QPen port_midi_alsa_pen;
QPen port_midi_alsa_pen_sel;
QColor port_audio_jack_bg;
QColor port_audio_jack_bg_sel;
QColor port_midi_jack_bg;
QColor port_midi_jack_bg_sel;
QColor port_midi_a2j_bg;
QColor port_midi_a2j_bg_sel;
QColor port_midi_alsa_bg;
QColor port_midi_alsa_bg_sel;
QPen port_text;
QString port_font_name;
int port_font_size;
QFont::Weight port_font_state;
PortType port_mode;

// Lines
QColor line_audio_jack;
QColor line_audio_jack_sel;
QColor line_audio_jack_glow;
QColor line_midi_jack;
QColor line_midi_jack_sel;
QColor line_midi_jack_glow;
QColor line_midi_a2j;
QColor line_midi_a2j_sel;
QColor line_midi_a2j_glow;
QColor line_midi_alsa;
QColor line_midi_alsa_sel;
QColor line_midi_alsa_glow;
QPen rubberband_pen;
QColor rubberband_brush;
};

Theme::List getDefaultTheme();
QString getThemeName(Theme::List id);
QString getDefaultThemeName();

END_NAMESPACE_PATCHCANVAS

#endif // PATCHCANVAS_THEME_H

+ 1020
- 0
c++/patchcanvas/patchcanvas.cpp
File diff suppressed because it is too large
View File


+ 129
- 0
c++/patchcanvas/patchcanvas.h View File

@@ -0,0 +1,129 @@
/*
* Patchbay Canvas engine using QGraphicsView/Scene
* Copyright (C) 2010-2012 Filipe Coelho <falktx@gmail.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* For a full copy of the GNU General Public License see the COPYING file
*/

#ifndef PATCHCANVAS_H
#define PATCHCANVAS_H

#include <QtGui/QGraphicsItem>

#include "patchcanvas-api.h"

#define foreach2(var, list) \
for (int i=0; i < list.count(); i++) { var = list[i];

class QSettings;
class QTimer;

class CanvasObject : public QObject {
Q_OBJECT

public:
CanvasObject(QObject* parent=0);

public slots:
void CanvasPostponedGroups();
void PortContextMenuDisconnect();
};

START_NAMESPACE_PATCHCANVAS

class AbstractCanvasLine;
class CanvasBox;
class CanvasPort;
class Theme;

// object types
enum CanvasType {
CanvasBoxType = QGraphicsItem::UserType + 1,
CanvasIconType = QGraphicsItem::UserType + 2,
CanvasPortType = QGraphicsItem::UserType + 3,
CanvasLineType = QGraphicsItem::UserType + 4,
CanvasBezierLineType = QGraphicsItem::UserType + 5,
CanvasLineMovType = QGraphicsItem::UserType + 6,
CanvasBezierLineMovType = QGraphicsItem::UserType + 7
};

// object lists
struct group_dict_t {
int group_id;
QString group_name;
bool split;
Icon icon;
CanvasBox* widgets[2];
};

struct port_dict_t {
int group_id;
int port_id;
QString port_name;
PortMode port_mode;
PortType port_type;
CanvasPort* widget;
};

struct connection_dict_t {
int connection_id;
int port_in_id;
int port_out_id;
AbstractCanvasLine* widget;
};

// Main Canvas object
class Canvas {
public:
Canvas();
~Canvas();

PatchScene* scene;
Callback callback;
bool debug;
unsigned long last_z_value;
int last_connection_id;
QPointF initial_pos;
QRectF size_rect;
QList<group_dict_t> group_list;
QList<port_dict_t> port_list;
QList<connection_dict_t> connection_list;
CanvasObject* qobject;
QSettings* settings;
Theme* theme;
bool initiated;
};

const char* bool2str(bool check);
const char* port_mode2str(PortMode port_mode);
const char* port_type2str(PortType port_type);
const char* icon2str(Icon icon);
const char* split2str(SplitOption split);

QString CanvasGetGroupName(int group_id);
int CanvasGetGroupPortCount(int group_id);
QPointF CanvasGetNewGroupPos(bool horizontal=false);
QString CanvasGetFullPortName(int port_id);
QList<int> CanvasGetPortConnectionList(int port_id);
int CanvasGetConnectedPort(int connection_id, int port_id);
void CanvasPostponedGroups();
void CanvasCallback(CallbackAction action, int value1, int value2, QString value_str);

// global objects
extern Canvas canvas;
extern options_t options;
extern features_t features;

END_NAMESPACE_PATCHCANVAS

#endif // PATCHCANVAS_H

+ 287
- 0
c++/patchcanvas/patchscene.cpp View File

@@ -0,0 +1,287 @@
/*
* Patchbay Canvas engine using QGraphicsView/Scene
* Copyright (C) 2010-2012 Filipe Coelho <falktx@gmail.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* For a full copy of the GNU General Public License see the COPYING file
*/

#include "patchscene.h"

#include <cmath>
#include <QtGui/QKeyEvent>
#include <QtGui/QGraphicsRectItem>
#include <QtGui/QGraphicsSceneMouseEvent>
#include <QtGui/QGraphicsSceneWheelEvent>
#include <QtGui/QGraphicsView>

#include "patchcanvas.h"
#include "canvasbox.h"

using namespace PatchCanvas;

PatchScene::PatchScene(QObject* parent, QGraphicsView* view) :
QGraphicsScene(parent)
{
m_ctrl_down = false;
m_mouse_down_init = false;
m_mouse_rubberband = false;

m_rubberband = addRect(QRectF(0, 0, 0, 0));
m_rubberband->setZValue(-1);
m_rubberband->hide();
m_rubberband_selection = false;
m_rubberband_orig_point = QPointF(0, 0);

m_view = view;
if (! m_view)
qFatal("PatchCanvas::PatchScene() - invalid view");
}

void PatchScene::fixScaleFactor()
{
qreal scale = m_view->transform().m11();
if (scale > 3.0)
{
m_view->resetTransform();
m_view->scale(3.0, 3.0);
}
else if (scale < 0.2)
{
m_view->resetTransform();
m_view->scale(0.2, 0.2);
}
emit scaleChanged(m_view->transform().m11());
}

void PatchScene::updateTheme()
{
setBackgroundBrush(canvas.theme->canvas_bg);
m_rubberband->setPen(canvas.theme->rubberband_pen);
m_rubberband->setBrush(canvas.theme->rubberband_brush);
}

void PatchScene::zoom_fit()
{
qreal min_x, min_y, max_x, max_y;
bool first_value = true;

QList<QGraphicsItem*> items_list = items();

if (items_list.count() > 0)
{
foreach (const QGraphicsItem* item, items_list)
{
if (item && item->isVisible() and item->type() == CanvasBoxType)
{
QPointF pos = item->scenePos();
QRectF rect = item->boundingRect();

if (first_value)
min_x = pos.x();
else if (pos.x() < min_x)
min_x = pos.x();

if (first_value)
min_y = pos.y();
else if (pos.y() < min_y)
min_y = pos.y();

if (first_value)
max_x = pos.x()+rect.width();
else if (pos.x()+rect.width() > max_x)
max_x = pos.x()+rect.width();

if (first_value)
max_y = pos.y()+rect.height();
else if (pos.y()+rect.height() > max_y)
max_y = pos.y()+rect.height();

first_value = false;
}
}

m_view->fitInView(min_x, min_y, abs(max_x-min_x), abs(max_y-min_y), Qt::KeepAspectRatio);
fixScaleFactor();
}
}

void PatchScene::zoom_in()
{
if (m_view->transform().m11() < 3.0)
m_view->scale(1.2, 1.2);
emit scaleChanged(m_view->transform().m11());
}

void PatchScene::zoom_out()
{
if (m_view->transform().m11() > 0.2)
m_view->scale(0.8, 0.8);
emit scaleChanged(m_view->transform().m11());
}

void PatchScene::zoom_reset()
{
m_view->resetTransform();
emit scaleChanged(1.0);
}

void PatchScene::keyPressEvent(QKeyEvent* event)
{
if (! m_view)
return event->ignore();

if (event->key() == Qt::Key_Control)
{
m_ctrl_down = true;
}
else if (event->key() == Qt::Key_Home)
{
zoom_fit();
return event->accept();
}
else if (m_ctrl_down)
{
if (event->key() == Qt::Key_Plus)
{
zoom_in();
return event->accept();
}
else if (event->key() == Qt::Key_Minus)
{
zoom_out();
return event->accept();
}
else if (event->key() == Qt::Key_1)
{
zoom_reset();
return event->accept();
}
}

QGraphicsScene::keyPressEvent(event);
}

void PatchScene::keyReleaseEvent(QKeyEvent* event)
{
if (event->key() == Qt::Key_Control)
m_ctrl_down = false;
QGraphicsScene::keyReleaseEvent(event);
}

void PatchScene::mousePressEvent(QGraphicsSceneMouseEvent* event)
{
m_mouse_down_init = (event->button() == Qt::LeftButton);
m_mouse_rubberband = false;
QGraphicsScene::mousePressEvent(event);
}

void PatchScene::mouseMoveEvent(QGraphicsSceneMouseEvent* event)
{
if (m_mouse_down_init)
{
m_mouse_down_init = false;
m_mouse_rubberband = (selectedItems().count() == 0);
}

if (m_mouse_rubberband)
{
if (m_rubberband_selection == false)
{
m_rubberband->show();
m_rubberband_selection = true;
m_rubberband_orig_point = event->scenePos();
}

int x, y;
QPointF pos = event->scenePos();

if (pos.x() > m_rubberband_orig_point.x())
x = m_rubberband_orig_point.x();
else
x = pos.x();

if (pos.y() > m_rubberband_orig_point.y())
y = m_rubberband_orig_point.y();
else
y = pos.y();

m_rubberband->setRect(x, y, abs(pos.x()-m_rubberband_orig_point.x()), abs(pos.y()-m_rubberband_orig_point.y()));
return event->accept();
}

QGraphicsScene::mouseMoveEvent(event);
}

void PatchScene::mouseReleaseEvent(QGraphicsSceneMouseEvent* event)
{
if (m_rubberband_selection)
{
QList<QGraphicsItem*> items_list = items();
if (items_list.count() > 0)
{
foreach (QGraphicsItem* item, items_list)
{
if (item && item->isVisible() && item->type() == CanvasBoxType)
{
QRectF item_rect = item->sceneBoundingRect();
QPointF item_top_left = QPointF(item_rect.x(), item_rect.y());
QPointF item_bottom_right = QPointF(item_rect.x()+item_rect.width(), item_rect.y()+item_rect.height());

if (m_rubberband->contains(item_top_left) && m_rubberband->contains(item_bottom_right))
item->setSelected(true);
}
}

m_rubberband->hide();
m_rubberband->setRect(0, 0, 0, 0);
m_rubberband_selection = false;
}
}
else
{
QList<QGraphicsItem*> items_list = selectedItems();
foreach (QGraphicsItem* item, items_list)
{
if (item && item->isVisible() && item->type() == CanvasBoxType)
{
CanvasBox* citem = (CanvasBox*)item;
citem->checkItemPos();
emit sceneGroupMoved(citem->getGroupId(), citem->getSplittedMode(), citem->scenePos());
}
}

if (items_list.count() > 1)
canvas.scene->update();
}

m_mouse_down_init = false;
m_mouse_rubberband = false;
QGraphicsScene::mouseReleaseEvent(event);
}

void PatchScene::wheelEvent(QGraphicsSceneWheelEvent* event)
{
if (! m_view)
return event->ignore();

if (m_ctrl_down)
{
double factor = std::pow(1.41, (event->delta()/240.0));
m_view->scale(factor, factor);

fixScaleFactor();
return event->accept();
}

QGraphicsScene::wheelEvent(event);
}

+ 67
- 0
c++/patchcanvas/patchscene.h View File

@@ -0,0 +1,67 @@
/*
* Patchbay Canvas engine using QGraphicsView/Scene
* Copyright (C) 2010-2012 Filipe Coelho <falktx@gmail.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* For a full copy of the GNU General Public License see the COPYING file
*/

#ifndef PATCHSCENE_H
#define PATCHSCENE_H

#include <QtGui/QGraphicsScene>

class QKeyEvent;
class QGraphicsRectItem;
class QGraphicsSceneMouseEvent;
class QGraphicsSceneWheelEvent;
class QGraphicsView;

class PatchScene : public QGraphicsScene
{
Q_OBJECT

public:
PatchScene(QObject* parent, QGraphicsView* view);

void fixScaleFactor();
void updateTheme();

void zoom_fit();
void zoom_in();
void zoom_out();
void zoom_reset();

signals:
void scaleChanged(double);
void sceneGroupMoved(int, int, QPointF);

private:
bool m_ctrl_down;
bool m_mouse_down_init;
bool m_mouse_rubberband;

QGraphicsRectItem* m_rubberband;
bool m_rubberband_selection;
QPointF m_rubberband_orig_point;

QGraphicsView* m_view;

virtual void keyPressEvent(QKeyEvent* event);
virtual void keyReleaseEvent(QKeyEvent* event);
virtual void mousePressEvent(QGraphicsSceneMouseEvent* event);
virtual void mouseMoveEvent(QGraphicsSceneMouseEvent* event);
virtual void mouseReleaseEvent(QGraphicsSceneMouseEvent* event);
virtual void wheelEvent(QGraphicsSceneWheelEvent* event);
};

#endif // PATCHSCENE_H

Loading…
Cancel
Save