Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 6 additions & 1 deletion app/libs/events_handler.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ class EventHandler(QtCore.QObject):
sig_indicator_settings_canceled = QtCore.Signal(object)
sig_indicator_settings_reseted = QtCore.Signal(object)

sig_action_triggered = QtCore.Signal(str)
sig_action_triggered = QtCore.Signal(str, dict)

sig_favorite_created = QtCore.Signal(str)
sig_favorite_loaded = QtCore.Signal(list)
Expand All @@ -32,3 +32,8 @@ class EventHandler(QtCore.QObject):
sig_favorite_clicked = QtCore.Signal(str)

sig_articles = QtCore.Signal(dict)

sig_graph_clicked = QtCore.Signal(list, object)
sig_graph_mouse_moved = QtCore.Signal(object)
sig_graph_mouse_pressed = QtCore.Signal(object)
sig_graph_mouse_released = QtCore.Signal(object)
46 changes: 46 additions & 0 deletions app/libs/graph/graphwidget.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
from PySide2 import QtCore, QtGui, QtWidgets

from libs.graph.candlestick import CandlestickItem
from libs.events_handler import EventHandler
from utils import utils

# TODO import from palette or Qss
Expand All @@ -19,11 +20,16 @@ def __init__(self, parent=None):
self.v_line = None
self.h_line = None

self.signals = EventHandler()

self.g_quotation = self.addPlot(row=0, col=0, name="Quotation")
self.g_quotation.showGrid(x=True, y=True, alpha=0.3)
self.g_vb = self.g_quotation.vb

self.set_cross_hair()
self.g_quotation.scene().sigMouseClicked.connect(
self._on_mouse_clicked
)

def plot_quotation(self, data, clear=True):
"""Plot the quotation
Expand Down Expand Up @@ -79,6 +85,7 @@ def set_cross_hair(self):
def set_time_x_axis(self, widget):
widget.setAxisItems({"bottom": pg.DateAxisItem(orientation="bottom")})

@QtCore.Slot(object)
def _on_mouse_moved(self, event):
"""Signal on mouse moved

Expand All @@ -91,6 +98,29 @@ def _on_mouse_moved(self, event):
self.v_line.setPos(mousePoint.x())
self.h_line.setPos(mousePoint.y())

@QtCore.Slot(object)
def _on_mouse_clicked(self, event):
"""Called on mouse clicked

:param event: Mouse clicked
:type event: event
"""
items = self.g_quotation.scene().items(event.scenePos())
plot_items = [x for x in items if isinstance(x, pg.PlotItem)]
self.signals.sig_graph_clicked.emit(plot_items, event)

def mousePressEvent(self, event):
self.signals.sig_graph_mouse_pressed.emit(event)
super(GraphView, self).mousePressEvent(event)

def mouseReleaseEvent(self, event):
self.signals.sig_graph_mouse_released.emit(event)
super(GraphView, self).mouseReleaseEvent(event)

def mouseMoveEvent(self, event):
self.signals.sig_graph_mouse_moved.emit(event)
super(GraphView, self).mouseMoveEvent(event)


class GraphWidget(QtWidgets.QWidget):
"""Widget wrapper for the graph"""
Expand All @@ -103,6 +133,22 @@ def __init__(self, parent=None):
layout.addWidget(self._graph)
self.setLayout(layout)

self.signals = EventHandler()

# Relay Signals
self._graph.signals.sig_graph_clicked.connect(
self.signals.sig_graph_clicked.emit
)
self._graph.signals.sig_graph_mouse_pressed.connect(
self.signals.sig_graph_mouse_pressed.emit
)
self._graph.signals.sig_graph_mouse_released.connect(
self.signals.sig_graph_mouse_released.emit
)
self._graph.signals.sig_graph_mouse_moved.connect(
self.signals.sig_graph_mouse_moved.emit
)

@property
def graph(self):
"""Return the graph
Expand Down
101 changes: 101 additions & 0 deletions app/libs/roi_manager.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
import time
import pyqtgraph as pg
from PySide2 import QtCore, QtWidgets


class ROIManager(QtCore.QObject):
def __init__(self, parent=None):
super(ROIManager, self).__init__(parent)

# Constants
self.current_tool = None
self.current_handle = None
self.current_graph = None
self._graph = self.parent().wgt_graph.graph

# Signals
self.parent().wgt_graph.signals.sig_graph_clicked.connect(
self._on_roi_add_requested
)
self.parent().wgt_graph.signals.sig_graph_mouse_moved.connect(self._on_mouse_moved)
# self.parent().wgt_graph.signals.sig_graph_mouse_pressed.connect(self._on_mouse_pressed)
# self.parent().wgt_graph.signals.sig_graph_mouse_released.connect(self._on_mouse_released)

def drawer(self, graph, event):
"""Drawer over the graph

:param graph: The graph on whch to draw
:type graph: pg.PlotItem
:param event: The event
:type event: object
"""
self.current_graph = graph
vb = graph.vb
mouse_point = vb.mapSceneToView(event.pos())
if self.current_tool:
self.current_tool(initial_pos=mouse_point) # Exec the current tool

def bounded_line_drawer(self, initial_pos, **kwargs):
"""Draw a bounded line
"""
roi = pg.LineSegmentROI((initial_pos, initial_pos), removable=True)
self.current_handle = roi.getHandles()[-1]
self.current_graph.addItem(roi)
roi.sigRemoveRequested.connect(self._on_roi_remove_requested)

def set_tool(self, **kwargs):
"""Set the current tool. kwargs may have a tool which corresponds to
the method to call inside this module.

:return: The current tool
:rtype: method if found, None instead
"""
self.current_tool = getattr(self, kwargs.get("tool", None), None)
return self.current_tool

def unset_tool(self):
"""Unset the current tool"""
self.current_tool = None
self.current_handle = None
self.current_graph = None

def remove_roi(self, roi):
"""Remove the given roi

:param roi: The roi to remove
:type roi: pg.ROI
"""
print(roi)

@QtCore.Slot(object)
def _on_mouse_moved(self, event):
if self.current_handle:
vb = self.current_graph.vb
mousePoint = vb.mapSceneToView(event.pos())
self.current_handle.setPos(mousePoint)

@QtCore.Slot(object)
def _on_mouse_released(self, event):
print("Released", event)

@QtCore.Slot(object)
def _on_mouse_pressed(self, event):
print("Pressed", event)

@QtCore.Slot(list, object)
def _on_roi_add_requested(self, objects, event):
"""Called on a draw requested"""
if not self.current_handle:
if objects:
self.drawer(graph=objects[0], event=event)
else:
self.unset_tool()

@QtCore.Slot(object)
def _on_roi_remove_requested(self, roi):
"""Called on a request for ROI deletion

:param roi: The roi to remove
:type roi: pg.ROI
"""
self.remove_roi(roi=roi)
3 changes: 2 additions & 1 deletion app/libs/widgets/toolbar.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ def __init__(self, parent=None):
def _trigger_action(self):
"""Called on action triggered"""
sender = self.sender()
self.signals.sig_action_triggered.emit(sender.action)
self.signals.sig_action_triggered.emit(sender.action, sender.args)

def init_toolbar(self):
"""This method inits the toolbar of the app"""
Expand Down Expand Up @@ -136,6 +136,7 @@ def __init__(self, parent=None, text=None, action=None, **kwargs):

# Properties
self.action = action
self.args = kwargs.get("args", {})

icon = kwargs.get("icon", None)
if icon:
Expand Down
5 changes: 4 additions & 1 deletion app/resources/toolbar/toolbar.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,10 @@
"type": "resources",
"value": ":/svg/trend-line.svg"
},
"action": "method_to_call",
"action": "roi_manager.set_tool",
"args": {
"tool": "bounded_line_drawer"
},
"tooltip": "Trend Line",
"text": "Trend Line",
"shortcut": "Alt+T",
Expand Down
13 changes: 8 additions & 5 deletions app/view.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
from libs.thread_pool import ThreadPool
from libs.graph.candlestick import CandlestickItem
from libs.io.favorite_settings import FavoritesManager
from libs.roi_manager import ROIManager

from ui import main_window

Expand All @@ -27,7 +28,7 @@ def __init__(self, parent=None, data=None):
super(MainWindow, self).__init__(parent=parent)

self.setupUi(self)
self.setWindowState(QtCore.Qt.WindowMaximized)
# self.setWindowState(QtCore.Qt.WindowMaximized)

# Constants
self.tickers_dialog = None
Expand All @@ -40,6 +41,7 @@ def __init__(self, parent=None, data=None):
self.thread_pool = ThreadPool()
self.signals = EventHandler()
self.favorites_manager = FavoritesManager(parent=self)
self.roi_manager = ROIManager(parent=self)

# Signals
self.lie_ticker.mousePressEvent = self.tickers_dialog.show
Expand Down Expand Up @@ -67,7 +69,6 @@ def __init__(self, parent=None, data=None):
self.signals.sig_ticker_infos_fetched.connect(
self.wgt_company._on_ticker_infos
)
##
self.signals.sig_ticker_articles_fetched.connect(
self.wgt_articles.get_articles
)
Expand Down Expand Up @@ -157,16 +158,18 @@ def _on_indicator_switched(self, indicator: object, state: bool):
else:
indicator.remove_indicator(graph_view=self.wgt_graph.graph)

@QtCore.Slot(str)
def _on_action_triggered(self, action: str):
@QtCore.Slot(str, dict)
def _on_action_triggered(self, action: str, args: dict):
"""Callback on action triggered from the toolbar

:param action: The action to find and call
:type action: str
:param args: Args for the action
:type args: dict
"""
action_obj = utils.find_method(module=action, obj=self)
if action_obj:
action_obj()
action_obj(**args)

def resizeEvent(self, event):
if self.tickers_dialog:
Expand Down