Skip to content
GitLab
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in
Toggle navigation
Menu
Open sidebar
TASTE
OpenGEODE
Commits
44c9ff3d
Commit
44c9ff3d
authored
Sep 18, 2016
by
Maxime Perrotin
Browse files
Introduce connection start/end zones
parent
61f6d9f6
Changes
4
Hide whitespace changes
Inline
Side-by-side
opengeode/Connectors.py
View file @
44c9ff3d
...
...
@@ -457,6 +457,12 @@ class Channel(Signalroute):
def
add_point
(
self
,
scene_coord
):
self
.
_middle_points
.
append
(
scene_coord
)
def
paint
(
self
,
painter
,
_
,
___
):
''' Apply anti-aliasing '''
painter
.
setRenderHint
(
QPainter
.
Antialiasing
,
True
)
super
(
Channel
,
self
).
paint
(
painter
,
_
,
___
)
class
Controlpoint
(
QGraphicsPathItem
,
object
):
''' Class handling one edge control point (to change bezier curves) '''
...
...
opengeode/genericSymbols.py
View file @
44c9ff3d
...
...
@@ -89,7 +89,8 @@ class Symbol(QObject, QGraphicsPathItem, object):
_insertable_followers
=
[]
# no limit to insert below current symbol
_terminal_followers
=
[]
# cannot be inserted between two symbols
# List of symbols that can be connected, but without parent-child relation
_connectable_siblings
=
[]
_conn_sources
=
[]
# source types that can connect to this symbol
_conn_targets
=
[]
# target types that can connect to this symbol
# By default a symbol is resizeable
resizeable
=
True
# By default symbol size may expand when inner text exceeds border
...
...
@@ -154,7 +155,7 @@ class Symbol(QObject, QGraphicsPathItem, object):
# and default text alignment within a textbox
self
.
text_alignment
=
Qt
.
AlignLeft
# Activate cache mode to boost rendering by calling paint less often
self
.
setCacheMode
(
QGraphicsItem
.
DeviceCoordinateCache
)
#
self.setCacheMode(QGraphicsItem.DeviceCoordinateCache)
# Apply symbol default mouse cursor
self
.
setCursor
(
self
.
default_cursor
)
# De-ativate cache mode otherwise paint is not properly updated
...
...
@@ -226,6 +227,28 @@ class Symbol(QObject, QGraphicsPathItem, object):
''' Set the value of the nested scene '''
self
.
_nested_scene
=
value
# Connection zones (for start and end of connection) are lists of QRect
# that define areas for the mouse to grab the symbol and start a connection
# These zones depend on the shape of the symbol and must be defined in
# sub-classes. By default there are none. Example in SDL symbol "Process".
# Zones are defined as properties because they must be dynamically
# computed, e.g. based on the current size of the symbol.
@
property
def
conn_start_zones
(
self
):
return
[]
@
property
def
conn_end_zones
(
self
):
return
[]
def
in_start_zone
(
self
,
point
):
# type: QPoint
''' Return true if "point" is in one of the connection start zones '''
return
any
(
rect
.
contains
(
point
)
for
rect
in
self
.
conn_start_zones
)
def
in_end_zone
(
self
,
point
):
# type: QPoint
''' Return true if "point" is in one of the connection end zones '''
return
any
(
rect
.
contains
(
point
)
for
rect
in
self
.
conn_end_zones
)
def
closest_connection_point
(
self
,
coord
):
'''
Given a position (QPointF), expected in this symbol's
...
...
@@ -901,6 +924,8 @@ class Cornergrabber(QGraphicsPolygonItem, object):
# Parent item may have changed its cursor (e.g. when inserting
# items). In that case, don't override the cursor for that area
cursor
=
self
.
parent
.
cursor
()
elif
self
.
parent
.
in_start_zone
(
event
.
pos
().
toPoint
()):
cursor
=
Qt
.
CrossCursor
elif
not
self
.
parent
.
resizeable
:
cursor
=
self
.
parent
.
default_cursor
self
.
resize_mode
=
''
...
...
opengeode/opengeode.py
View file @
44c9ff3d
...
...
@@ -410,7 +410,7 @@ class SDL_Scene(QtGui.QGraphicsScene, object):
self
.
click_coordinates
=
None
self
.
orig_pos
=
None
# When connecting symbols, store list of intermediate points
self
.
edge_points
=
[]
#
type: List[QPointF] in scene coordinates
self
.
edge_points
=
[]
# type: List[QPointF] in scene coordinates
self
.
temp_lines
=
[]
# type: List[QGraphicsLineItem]
self
.
process_name
=
'opengeode'
# Scene name is used to update the tab window name when scene changes
...
...
@@ -1296,10 +1296,10 @@ class SDL_Scene(QtGui.QGraphicsScene, object):
item
.
bezier_set_visible
(
False
)
except
AttributeError
:
pass
elif
symb
.
user_can_connect
\
and
event
.
modifiers
()
==
Qt
.
ControlModifier
:
#
TODO check if symbol can be a connection source, can have
#
more than one connection if there is already one
, etc.
elif
symb
.
user_can_connect
and
symb
.
in_start_zone
(
event
.
pos
().
toPoint
()):
# TODO check if symbol can have more than
#
one connection if there is already one, if start
#
and end can be on the same symbol
, etc.
self
.
mode
=
'wait_next_connection_point'
click_point
=
event
.
scenePos
()
point
=
self
.
border_point
(
symb
,
click_point
)
...
...
@@ -1371,6 +1371,13 @@ class SDL_Scene(QtGui.QGraphicsScene, object):
if
map
(
setup_action
,
candidates
):
menu
.
exec_
(
pos
)
def
cancel
(
self
):
''' Return to idle mode, reset current actions '''
self
.
select_rect
.
hide
()
for
each
in
self
.
temp_lines
:
each
.
setVisible
(
False
)
self
.
mode
=
'idle'
# pylint: disable=C0103
def
mouseReleaseEvent
(
self
,
event
):
if
self
.
mode
==
'select_items'
:
...
...
@@ -1389,9 +1396,8 @@ class SDL_Scene(QtGui.QGraphicsScene, object):
# No items to select, so propose a context dependent menu
self
.
quick_menu
(
event
.
screenPos
(),
rect
)
#self.removeItem(self.select_rect)
# XXX stop with removeItem, it provokes segfault
self
.
select_rect
.
hide
()
self
.
mode
=
'idle'
# stop with removeItem, it provokes segfault
self
.
cancel
()
elif
self
.
mode
==
'wait_next_connection_point'
:
point
=
event
.
scenePos
()
previous
=
self
.
edge_points
[
-
1
]
...
...
@@ -1400,26 +1406,8 @@ class SDL_Scene(QtGui.QGraphicsScene, object):
if
abs
(
point
.
y
()
-
previous
.
y
())
<
15
:
point
.
setY
(
previous
.
y
())
symb
=
self
.
symbol_near
(
point
,
dist
=
1
)
if
symb
:
# Clicked on a symbol: create the actual connector
connector
=
Channel
(
parent
=
self
.
connection_start
,
child
=
symb
)
connector
.
start_point
=
self
.
edge_points
[
0
]
connector
.
middle_points
=
self
.
edge_points
[
1
:]
connector
.
end_point
=
self
.
border_point
(
symb
,
point
)
# connector = Connection(parent=self.connection_start,
# child=symb)
# connector._start_point = \
# connector.mapFromScene(self.edge_points[0])
# connector._middle_points = [connector.mapFromScene(p)
# for p in self.edge_points[1:]]
# connector._end_point = \
# connector.mapFromScene(self.border_point(symb, point))
for
each
in
self
.
temp_lines
:
# Just hide to avoid pyside segfaults
each
.
setVisible
(
False
)
self
.
mode
=
'idle'
else
:
if
previous
!=
point
:
# Draw a temporary line to the scene
current_line
=
self
.
temp_lines
[
-
1
]
line
=
current_line
.
line
()
current_line
.
setLine
(
line
.
x1
(),
line
.
y1
(),
...
...
@@ -1429,6 +1417,23 @@ class SDL_Scene(QtGui.QGraphicsScene, object):
point
.
y
(),
point
.
x
(),
point
.
y
()))
# Decide if the connection is valid, create it accordingly
valid
=
(
symb
and
symb
.
__class__
.
__name__
in
self
.
connection_start
.
_conn_sources
and
self
.
connection_start
.
__class__
.
__name__
in
symb
.
_conn_targets
and
len
(
self
.
edge_points
)
>
2
)
if
symb
and
valid
:
nb_segments
=
len
(
self
.
edge_points
)
-
1
for
each
in
self
.
temp_lines
[
-
nb_segments
:]:
# check lines that collide with the source or dest TODO
pass
# Clicked on a symbol: create the actual connector
connector
=
Channel
(
parent
=
self
.
connection_start
,
child
=
symb
)
connector
.
start_point
=
self
.
edge_points
[
0
]
connector
.
middle_points
=
self
.
edge_points
[
1
:
-
1
]
connector
.
end_point
=
self
.
border_point
(
symb
,
point
)
self
.
cancel
()
super
(
SDL_Scene
,
self
).
mouseReleaseEvent
(
event
)
...
...
@@ -1442,6 +1447,8 @@ class SDL_Scene(QtGui.QGraphicsScene, object):
self
.
clearSelection
()
self
.
clear_highlight
()
self
.
clear_focus
()
elif
event
.
key
()
==
Qt
.
Key_Escape
:
self
.
cancel
()
elif
event
.
matches
(
QtGui
.
QKeySequence
.
Undo
):
if
not
isinstance
(
self
.
focusItem
(),
EditableText
):
LOG
.
debug
(
'UNDO '
+
self
.
undo_stack
.
undoText
())
...
...
opengeode/sdlSymbols.py
View file @
44c9ff3d
...
...
@@ -1008,7 +1008,8 @@ class Process(HorizontalSymbol):
arrow_tail
=
'angle'
# Process can be connected to other processes by the user
user_can_connect
=
True
_connectable_siblings
=
[
'Process'
]
_conn_sources
=
[
'Process'
]
_conn_targets
=
[
'Process'
]
def
__init__
(
self
,
ast
=
None
,
subscene
=
None
):
ast
=
ast
or
ogAST
.
Process
()
...
...
@@ -1028,6 +1029,25 @@ class Process(HorizontalSymbol):
self
.
output_signals
=
ast
.
output_signals
self
.
insert_symbol
(
None
,
self
.
x
(),
self
.
y
())
@
property
def
conn_start_zones
(
self
):
''' Redefined - define the zones in the symbol from which user can
start a connection with another symbol '''
rect
=
self
.
boundingRect
()
yield
QRect
(
15
,
5
,
rect
.
width
()
-
30
,
10
)
yield
QRect
(
5
,
5
,
10
,
rect
.
height
()
-
10
)
yield
QRect
(
rect
.
width
()
-
15
,
5
,
10
,
rect
.
height
()
-
10
)
yield
QRect
(
15
,
rect
.
height
()
-
15
,
rect
.
width
()
-
30
,
10
)
@
property
def
conn_end_zones
(
self
):
''' Redefined - define the zones that can receive a connection '''
rect
=
self
.
boundingRect
()
yield
QRect
(
15
,
5
,
rect
.
width
()
-
30
,
10
)
yield
QRect
(
5
,
5
,
10
,
rect
.
height
()
-
10
)
yield
QRect
(
rect
.
width
()
-
15
,
5
,
10
,
rect
.
height
()
-
10
)
yield
QRect
(
15
,
rect
.
heigth
()
-
15
,
rect
.
width
()
-
30
,
10
)
def
insert_symbol
(
self
,
parent
,
x
,
y
):
''' Redefinition - adds connection line to env '''
super
(
Process
,
self
).
insert_symbol
(
parent
,
x
,
y
)
...
...
Write
Preview
Supports
Markdown
0%
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment