diff --git a/src/sakia/gui/agent/model.py b/src/sakia/gui/agent/model.py deleted file mode 100644 index 61a2d366bd93c60c1ed4ec9d386983fcdf822511..0000000000000000000000000000000000000000 --- a/src/sakia/gui/agent/model.py +++ /dev/null @@ -1,19 +0,0 @@ -from PyQt5.QtCore import QObject - - -class AgentModel(QObject): - """ - An agent - """ - - def __init__(self, parent): - """ - Constructor of an agent - - :param sakia.core.gui.agent.controller.AbstractAgentController controller: the controller - """ - super().__init__(parent) - - @property - def account(self): - return self.app.current_account diff --git a/src/sakia/gui/agent/__init__.py b/src/sakia/gui/component/__init__.py similarity index 100% rename from src/sakia/gui/agent/__init__.py rename to src/sakia/gui/component/__init__.py diff --git a/src/sakia/gui/agent/controller.py b/src/sakia/gui/component/controller.py similarity index 61% rename from src/sakia/gui/agent/controller.py rename to src/sakia/gui/component/controller.py index 334ad3b71561ad400ac4fc31d66eb82c6ede4872..a98e7c0a910c0e69c13d2516c2e1d4cdf0bd6295 100644 --- a/src/sakia/gui/agent/controller.py +++ b/src/sakia/gui/component/controller.py @@ -1,14 +1,14 @@ from PyQt5.QtCore import QObject -class AgentController(QObject): +class ComponentController(QObject): """ The navigation panel """ def __init__(self, parent, view, model): """ - Constructor of the navigation agent + Constructor of the navigation component :param PyQt5.QtWidgets.QWidget presentation: the presentation :param sakia.core.gui.navigation.model.NavigationModel model: the model @@ -17,12 +17,16 @@ class AgentController(QObject): self.view = view self.model = model + @classmethod + def create(cls, parent, app, **kwargs): + raise NotImplementedError("Create method not implemented") + def attach(self, controller): """ - Attach an agent controller to this controller - :param AgentController controller: the attached controller + Attach an component controller to this controller + :param ComponentController controller: the attached controller :return: the attached controller - :rtype: AgentController + :rtype: ComponentController """ if controller: controller.setParent(self) diff --git a/src/sakia/gui/component/model.py b/src/sakia/gui/component/model.py new file mode 100644 index 0000000000000000000000000000000000000000..3ca16fdfd455cbe4c599e158ca6921f8d17debfa --- /dev/null +++ b/src/sakia/gui/component/model.py @@ -0,0 +1,15 @@ +from PyQt5.QtCore import QObject + + +class ComponentModel(QObject): + """ + An component + """ + + def __init__(self, parent): + """ + Constructor of an component + + :param sakia.core.gui.component.controller.AbstractAgentController controller: the controller + """ + super().__init__(parent) diff --git a/src/sakia/gui/homescreen.py b/src/sakia/gui/homescreen.py deleted file mode 100644 index 0f0618b11f6ff38018cccc0dbd64ed634ddc364b..0000000000000000000000000000000000000000 --- a/src/sakia/gui/homescreen.py +++ /dev/null @@ -1,101 +0,0 @@ -""" -Created on 31 janv. 2015 - -@author: vit -""" - -from PyQt5.QtWidgets import QWidget, QFrame, QGridLayout, QAction -from PyQt5.QtCore import QEvent, Qt, pyqtSlot, pyqtSignal -from ..presentation.homescreen_uic import Ui_HomescreenWidget -from .community_tile import CommunityTile -from ..core.community import Community -import logging - - -class FrameCommunities(QFrame): - community_tile_clicked = pyqtSignal(Community) - - def __init__(self, parent): - super().__init__(parent) - self.grid_layout = QGridLayout() - self.setLayout(self.grid_layout) - self.grid_layout.setAlignment(Qt.AlignLeft | Qt.AlignTop) - self.setFrameShape(QFrame.StyledPanel) - self.setFrameShadow(QFrame.Raised) - self.tiles = [] - - def sizeHint(self): - return self.parentWidget().size() - - def refresh(self, app): - for t in self.tiles: - t.cancel_refresh() - t.setParent(None) - self.tiles = [] - if app.current_account: - for c in app.current_account.communities: - community_tile = CommunityTile(self, app, c) - community_tile.clicked.connect(self.click_on_tile) - self.layout().addWidget(community_tile) - self.tiles.append(community_tile) - - def refresh_content(self): - for t in self.tiles: - t.refresh() - - @pyqtSlot() - def click_on_tile(self): - tile = self.sender() - logging.debug("Click on tile") - self.community_tile_clicked.emit(tile.community) - - -class HomeScreenWidget(QWidget, Ui_HomescreenWidget): - """ - classdocs - """ - - def __init__(self, app, status_label): - """ - Constructor - """ - super().__init__() - self.setupUi(self) - self.app = app - self.frame_communities = FrameCommunities(self) - self.layout().addWidget(self.frame_communities) - self.status_label = status_label - - def refresh(self): - self.frame_communities.refresh(self.app) - if self.app.current_account: - self.frame_connected.show() - self.label_connected.setText(self.tr("Connected as {0}".format(self.app.current_account.name))) - self.frame_disconnected.hide() - else: - self.frame_disconnected.show() - self.frame_connected.hide() - - def referential_changed(self): - self.frame_communities.refresh_content() - - def showEvent(self, QShowEvent): - """ - - :param QShowEvent: - :return: - """ - self.frame_communities.refresh_content() - self.status_label.setText("") - - def changeEvent(self, event): - """ - Intercepte LanguageChange event to translate UI - :param QEvent QEvent: Event - :return: - """ - if event.type() == QEvent.LanguageChange: - self.retranslateUi(self) - return super(HomeScreenWidget, self).changeEvent(event) - - diff --git a/src/sakia/gui/homescreen/__init__.py b/src/sakia/gui/homescreen/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/src/sakia/gui/homescreen/controller.py b/src/sakia/gui/homescreen/controller.py new file mode 100644 index 0000000000000000000000000000000000000000..bad5bec1620d460b85468a7130bc3059ddb5b4a8 --- /dev/null +++ b/src/sakia/gui/homescreen/controller.py @@ -0,0 +1,33 @@ +from ..component.controller import ComponentController +from .view import HomeScreenView +from .model import HomeScreenModel + + +class HomeScreenController(ComponentController): + """ + The navigation panel + """ + + def __init__(self, parent, view, model): + """ + Constructor of the navigation component + + :param PyQt5.QtWidgets.QWidget presentation: the presentation + :param sakia.core.gui.navigation.model.NavigationModel model: the model + """ + super().__init__(parent, view, model) + + @classmethod + def create(cls, parent, app, **kwargs): + """ + Instanciate a homescreen component + :param sakia.gui.agent.controller.AgentController parent: + :return: a new Homescreen controller + :rtype: NavigationController + """ + view = HomeScreenView(parent.view) + model = HomeScreenModel(None, app) + homescreen = cls(parent, view, model) + model.setParent(homescreen) + return homescreen + diff --git a/src/sakia/gui/homescreen/homescreen.py b/src/sakia/gui/homescreen/homescreen.py new file mode 100644 index 0000000000000000000000000000000000000000..081f313358d69736dc9134bde521dd7baaeec58c --- /dev/null +++ b/src/sakia/gui/homescreen/homescreen.py @@ -0,0 +1,56 @@ +""" +Created on 31 janv. 2015 + +@author: vit +""" + + +class HomeScreenWidget(QWidget, Ui_HomescreenWidget): + """ + classdocs + """ + + def __init__(self, parent, app, status_label): + """ + Constructor + """ + super().__init__() + self.setupUi(self) + self.app = app + self.frame_communities = FrameCommunities(self) + self.layout().addWidget(self.frame_communities) + self.status_label = status_label + + def refresh(self): + self.frame_communities.refresh(self.app) + if self.app.current_account: + self.frame_connected.show() + self.label_connected.setText(self.tr("Connected as {0}".format(self.app.current_account.name))) + self.frame_disconnected.hide() + else: + self.frame_disconnected.show() + self.frame_connected.hide() + + def referential_changed(self): + self.frame_communities.refresh_content() + + def showEvent(self, QShowEvent): + """ + + :param QShowEvent: + :return: + """ + self.frame_communities.refresh_content() + self.status_label.setText("") + + def changeEvent(self, event): + """ + Intercepte LanguageChange event to translate UI + :param QEvent QEvent: Event + :return: + """ + if event.type() == QEvent.LanguageChange: + self.retranslateUi(self) + return super(HomeScreenWidget, self).changeEvent(event) + + diff --git a/res/ui/homescreen.ui b/src/sakia/gui/homescreen/homescreen.ui similarity index 100% rename from res/ui/homescreen.ui rename to src/sakia/gui/homescreen/homescreen.ui diff --git a/src/sakia/gui/homescreen/model.py b/src/sakia/gui/homescreen/model.py new file mode 100644 index 0000000000000000000000000000000000000000..af5b2f6cba174e0e714acc637010ed1b85f40ecc --- /dev/null +++ b/src/sakia/gui/homescreen/model.py @@ -0,0 +1,11 @@ +from sakia.gui.component.model import ComponentModel + + +class HomeScreenModel(ComponentModel): + """ + The model of Navigation component + """ + + def __init__(self, parent, app): + super().__init__(parent) + self.app = app diff --git a/src/sakia/gui/homescreen/view.py b/src/sakia/gui/homescreen/view.py new file mode 100644 index 0000000000000000000000000000000000000000..dd4e7040a527151254a7dae2f1bc6ad583425967 --- /dev/null +++ b/src/sakia/gui/homescreen/view.py @@ -0,0 +1,16 @@ +from PyQt5.QtWidgets import QWidget +from .homescreen_uic import Ui_HomescreenWidget + + +class HomeScreenView(QWidget, Ui_HomescreenWidget): + """ + classdocs + """ + + def __init__(self, app): + """ + Constructor + """ + super().__init__() + self.setupUi(self) + self.app = app diff --git a/src/sakia/gui/main_window/controller.py b/src/sakia/gui/main_window/controller.py index 77180d8e5019ae0d6dc92033480f510433ae369d..5fdab5f359929cf5b487aa7b80980a4b987ca29a 100644 --- a/src/sakia/gui/main_window/controller.py +++ b/src/sakia/gui/main_window/controller.py @@ -14,15 +14,16 @@ from PyQt5.QtGui import QIcon from ..password_asker import PasswordAskerDialog from ...__init__ import __version__ from ..widgets import toast -from ..agent.controller import AgentController +from ..component.controller import ComponentController from .view import MainWindowView from .model import MainWindowModel from ..status_bar.controller import StatusBarController from ..toolbar.controller import ToolbarController from ..navigation.controller import NavigationController +from ..txhistory.controller import TxHistoryController -class MainWindowController(AgentController): +class MainWindowController(ComponentController): """ classdocs """ @@ -30,10 +31,10 @@ class MainWindowController(AgentController): def __init__(self, view, model, password_asker, status_bar, toolbar, navigation): """ Init - :param MainWindowView view: the ui of the mainwindow agent - :param sakia.gui.main_window.model.MainWindowModel: the model of the mainwindow agent - :param sakia.gui.status_bar.controller.StatusBarController status_bar: the controller of the status bar agent - :param sakia.gui.toolbar.controller.ToolbarController toolbar: the controller of the toolbar agent + :param MainWindowView view: the ui of the mainwindow component + :param sakia.gui.main_window.model.MainWindowModel: the model of the mainwindow component + :param sakia.gui.status_bar.controller.StatusBarController status_bar: the controller of the status bar component + :param sakia.gui.toolbar.controller.ToolbarController toolbar: the controller of the toolbar component :param sakia.gui.navigation.contoller.NavigationController navigation: the controller of the navigation :param PasswordAsker password_asker: the password asker of the application @@ -46,6 +47,7 @@ class MainWindowController(AgentController): self.status_bar = self.attach(status_bar) self.toolbar = self.attach(toolbar) self.navigation = self.attach(navigation) + self.stacked_widgets = {} QApplication.setWindowIcon(QIcon(":/icons/sakia_logo")) @@ -55,12 +57,16 @@ class MainWindowController(AgentController): model = MainWindowModel(None, app) password_asker = PasswordAskerDialog(None) main_window = cls(view, model, password_asker, None, None, None) + main_window.status_bar = main_window.attach(StatusBarController.create(main_window, app)) view.setStatusBar(main_window.status_bar.view) + main_window.toolbar = main_window.attach(ToolbarController.create(main_window, password_asker)) view.top_layout.addWidget(main_window.toolbar.view) + main_window.navigation = main_window.attach(NavigationController.create(main_window, app)) - view.bottom_layout.addWidget(main_window.navigation.view) + view.bottom_layout.insertWidget(0, main_window.navigation.view) + #app.version_requested.connect(main_window.latest_version_requested) #app.account_imported.connect(main_window.import_account_accepted) #app.account_changed.connect(main_window.change_account) @@ -69,12 +75,14 @@ class MainWindowController(AgentController): main_window.refresh() return main_window - def change_account(self): - if self.account: - self.account.contacts_changed.disconnect(self.refresh_contacts) - self.account = self.app.current_account - self.password_asker.change_account(self.account) - self.refresh() + def add_to_stack(self, index, widget): + """ + Add a view to the stack + :param int index: the index of the page + :param PyQt5.QtWidgets.QWidget widget: the view + """ + self.stack.addWidget(widget) + self.stacked_widgets[index] = widget @pyqtSlot(str) def display_error(self, error): @@ -84,11 +92,7 @@ class MainWindowController(AgentController): @pyqtSlot(int) def referential_changed(self, index): - if self.account: - self.account.set_display_referential(index) - if self.community_view: - self.community_view.referential_changed() - self.homescreen.referential_changed() + pass @pyqtSlot() def latest_version_requested(self): diff --git a/src/sakia/gui/main_window/model.py b/src/sakia/gui/main_window/model.py index 4febb459242150fbd6c27818f71145ac2d4d5eb9..d504aaa88cc53e5482db5d807dbdf2bc320a4c9a 100644 --- a/src/sakia/gui/main_window/model.py +++ b/src/sakia/gui/main_window/model.py @@ -1,9 +1,9 @@ -from sakia.gui.agent.model import AgentModel +from sakia.gui.component.model import ComponentModel -class MainWindowModel(AgentModel): +class MainWindowModel(ComponentModel): """ - The model of Navigation agent + The model of Navigation component """ def __init__(self, parent, app): diff --git a/src/sakia/gui/main_window/view.py b/src/sakia/gui/main_window/view.py index 784bc7ddeb257be8d18997ff08728bf027998cea..2cd838a2ef6982eaa3995d8ea2cbdc2ada0b9446 100644 --- a/src/sakia/gui/main_window/view.py +++ b/src/sakia/gui/main_window/view.py @@ -4,7 +4,7 @@ from .mainwindow_uic import Ui_MainWindow class MainWindowView(QMainWindow, Ui_MainWindow): """ - The model of Navigation agent + The model of Navigation component """ def __init__(self, parent): diff --git a/src/sakia/gui/navigation/controller.py b/src/sakia/gui/navigation/controller.py index 9da1479de45e366444b97383dac75a013e2131f1..ef7f5b554e9d25b95f84e0a773a8cdad5e430de0 100644 --- a/src/sakia/gui/navigation/controller.py +++ b/src/sakia/gui/navigation/controller.py @@ -1,28 +1,34 @@ -from PyQt5.QtWidgets import QTreeView from .model import NavigationModel -from ..agent.controller import AgentController +from ..component.controller import ComponentController from .view import NavigationView +from ..txhistory.controller import TxHistoryController +from ..homescreen.controller import HomeScreenController -class NavigationController(AgentController): +class NavigationController(ComponentController): """ The navigation panel """ def __init__(self, parent, view, model): """ - Constructor of the navigation agent + Constructor of the navigation component - :param PyQt5.QtWidgets.QTreeView view: the presentation - :param sakia.core.gui.navigation.model.NavigationModel model: the model + :param sakia.gui.navigation.view view: the view + :param sakia.gui.navigation.model.NavigationModel model: the model """ super().__init__(parent, view, model) - self.view.setModel(model.tree()) + self.components = { + 'TxHistory': TxHistoryController, + 'HomeScreen': HomeScreenController, + 'Network': TxHistoryController, + 'Identities': TxHistoryController + } @classmethod def create(cls, parent, app): """ - Instanciate a navigation agent + Instanciate a navigation component :param sakia.gui.agent.controller.AgentController parent: :return: a new Navigation controller :rtype: NavigationController @@ -31,5 +37,24 @@ class NavigationController(AgentController): model = NavigationModel(None, app) navigation = cls(parent, view, model) model.setParent(navigation) + navigation.init_navigation() return navigation + def init_navigation(self): + def parse_node(node_data): + if 'component' in node_data['node']: + component_class = self.components[node_data['node']['component']] + component = component_class.create(self, self.model.app, **node_data['node']) + widget = self.view.add_widget(component.view) + node_data['node']['widget'] = widget + if 'children' in node_data: + for child in node_data['children']: + parse_node(child) + return node + self.model.init_navigation_data() + + for node in self.model.navigation: + parse_node(node) + + self.view.set_model(self.model) + diff --git a/src/sakia/gui/navigation/model.py b/src/sakia/gui/navigation/model.py index e1c5ab12c963d0b6dc89498eef14dec75e2f8480..ea51af900d256e3efc8a6b528b923a2c0cd4864f 100644 --- a/src/sakia/gui/navigation/model.py +++ b/src/sakia/gui/navigation/model.py @@ -1,43 +1,67 @@ -from ..agent.model import AgentModel +from ..component.model import ComponentModel from sakia.models.generic_tree import GenericTreeModel +from PyQt5.QtCore import pyqtSignal -class NavigationModel(AgentModel): +class NavigationModel(ComponentModel): """ - The model of Navigation agent + The model of Navigation component """ + navigation_changed = pyqtSignal(GenericTreeModel) + def __init__(self, parent, app): + """ + + :param sakia.gui.component.controller.ComponentController parent: + :param sakia.core.app.Application app: + """ super().__init__(parent) self.app = app + self.navigation = {} - def tree(self): - navigation = [{'node': { - 'title': self.app.current_account.name - }, - 'children': [] - } - ] + def init_navigation_data(self): + self.navigation = [ + { + 'node': { + 'title': self.app.current_account.name, + 'component': "HomeScreen" + }, + 'children': [] + } + ] for c in self.app.current_account.communities: - navigation[0]['children'].append({ + self.navigation[0]['children'].append({ 'node': { - 'title': c.currency + 'title': c.currency, }, 'children': [ { 'node': { - 'title': self.tr('Transfers') + 'title': self.tr('Transfers'), + 'component': "TxHistory", + 'community': c, + 'account': self.app.current_account } }, { 'node': { - 'title': self.tr('Network') + 'title': self.tr('Network'), + 'component': "Network", + 'community': c, + 'account': self.app.current_account } }, { 'node': { - 'title': self.tr('Network') + 'title': self.tr('Identities'), + 'component': "Identities", + 'community': c, + 'account': self.app.current_account } } ] }) - return GenericTreeModel.create("Navigation", navigation) + return self.navigation + + def generic_tree(self): + return GenericTreeModel.create("Navigation", self.navigation) diff --git a/src/sakia/gui/navigation/navigation.ui b/src/sakia/gui/navigation/navigation.ui new file mode 100644 index 0000000000000000000000000000000000000000..0da57f788436ddbfe80153f08eda624ea2ad030f --- /dev/null +++ b/src/sakia/gui/navigation/navigation.ui @@ -0,0 +1,47 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> + <class>Navigation</class> + <widget class="QFrame" name="Navigation"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>685</width> + <height>477</height> + </rect> + </property> + <property name="windowTitle"> + <string>Frame</string> + </property> + <property name="frameShape"> + <enum>QFrame::StyledPanel</enum> + </property> + <property name="frameShadow"> + <enum>QFrame::Raised</enum> + </property> + <layout class="QHBoxLayout" name="horizontalLayout"> + <item> + <widget class="QTreeView" name="tree_view"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Maximum" vsizetype="Expanding"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + </widget> + </item> + <item> + <widget class="QStackedWidget" name="stacked_widget"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Preferred" vsizetype="Preferred"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + </widget> + </item> + </layout> + </widget> + <resources/> + <connections/> +</ui> diff --git a/src/sakia/gui/navigation/view.py b/src/sakia/gui/navigation/view.py index eb1dd54783ecb44007f098ae73695dccbbe8c26f..63c01cf5c90566fa145f5379810df3eebebb4d08 100644 --- a/src/sakia/gui/navigation/view.py +++ b/src/sakia/gui/navigation/view.py @@ -1,11 +1,42 @@ -from PyQt5.QtWidgets import QTreeView, QSizePolicy +from PyQt5.QtWidgets import QFrame, QSizePolicy +from PyQt5.QtCore import QModelIndex +from .navigation_uic import Ui_Navigation +from ...models.generic_tree import GenericTreeModel -class NavigationView(QTreeView): +class NavigationView(QFrame, Ui_Navigation): """ The view of navigation panel """ def __init__(self, parent): super().__init__(parent) - self.setSizePolicy(QSizePolicy.Maximum, QSizePolicy.Expanding) \ No newline at end of file + self.setupUi(self) + self.tree_view.clicked.connect(self.handle_click) + + def set_model(self, model): + """ + Change the navigation pane + :param sakia.gui.navigation.model.NavigationModel + """ + self.tree_view.setModel(model.generic_tree()) + + def add_widget(self, widget): + """ + Add a widget to the stacked_widget + :param PyQt5.QtWidgets.QWidget widget: the new widget + """ + self.stacked_widget.addWidget(widget) + return widget + + def handle_click(self, index): + """ + Click on the navigation pane + :param PyQt5.QtCore.QModelIndex index: the index + :return: + """ + if index.isValid(): + raw_data = self.tree_view.model().data(index, GenericTreeModel.ROLE_RAW_DATA) + widget = raw_data['widget'] + if self.stacked_widget.indexOf(widget): + self.stacked_widget.setCurrentWidget(widget) \ No newline at end of file diff --git a/src/sakia/gui/status_bar/controller.py b/src/sakia/gui/status_bar/controller.py index 9cf519ccf500f711e0ab6ec578a029a8765a8643..2791714d9970226d74f5de7e55a780201b996bea 100644 --- a/src/sakia/gui/status_bar/controller.py +++ b/src/sakia/gui/status_bar/controller.py @@ -1,18 +1,18 @@ from PyQt5.QtCore import QLocale, pyqtSlot, QDateTime, QTimer -from ..agent.controller import AgentController +from ..component.controller import ComponentController from .model import StatusBarModel from .view import StatusBarView import logging -class StatusBarController(AgentController): +class StatusBarController(ComponentController): """ The navigation panel """ def __init__(self, parent, view, model): """ - Constructor of the navigation agent + Constructor of the navigation component :param sakia.gui.status_bar.view.StatusBarView view: the presentation :param sakia.core.status_bar.model.StatusBarModel model: the model @@ -24,7 +24,7 @@ class StatusBarController(AgentController): @classmethod def create(cls, parent, app): """ - Instanciate a navigation agent + Instanciate a navigation component :param sakia.gui.main_window.controller.MainWindowController parent: :return: a new Navigation controller :rtype: NavigationController diff --git a/src/sakia/gui/status_bar/model.py b/src/sakia/gui/status_bar/model.py index f3865bbd42afbd356e270af7702d3a9d99f2e79b..cd3649cac7296445064e52a4398c7f989b895e7f 100644 --- a/src/sakia/gui/status_bar/model.py +++ b/src/sakia/gui/status_bar/model.py @@ -1,16 +1,21 @@ -from sakia.gui.agent.model import AgentModel +from sakia.gui.component.model import ComponentModel from sakia.core.money import Referentials import logging -class StatusBarModel(AgentModel): + +class StatusBarModel(ComponentModel): """ - The model of Navigation agent + The model of Navigation component """ def __init__(self, parent, app): super().__init__(parent) self.app = app + @property + def account(self): + return self.app.current_account + def referentials(self): return Referentials diff --git a/src/sakia/gui/status_bar/view.py b/src/sakia/gui/status_bar/view.py index 5f631e69bdcdaf93df00beb6eca243608e9176ce..e5dbdc5b45151234730e58b60cc46928b35a74e6 100644 --- a/src/sakia/gui/status_bar/view.py +++ b/src/sakia/gui/status_bar/view.py @@ -5,7 +5,7 @@ from PyQt5.QtCore import Qt class StatusBarView(QStatusBar): """ - The model of Navigation agent + The model of Navigation component """ def __init__(self, parent): diff --git a/src/sakia/gui/toolbar/controller.py b/src/sakia/gui/toolbar/controller.py index 6b538c7d4edb189566a12150461c032400f50b42..6edb59a906caf6e59b7069ca404f0dcd99877641 100644 --- a/src/sakia/gui/toolbar/controller.py +++ b/src/sakia/gui/toolbar/controller.py @@ -1,6 +1,6 @@ from PyQt5.QtWidgets import QDialog, QMessageBox from PyQt5.QtCore import QT_TRANSLATE_NOOP, Qt -from ..agent.controller import AgentController +from ..component.controller import ComponentController from .model import ToolbarModel from .view import ToolbarView from ...tools.decorators import asyncify, once_at_a_time, cancel_once_task @@ -9,7 +9,7 @@ from ..widgets import toast import logging -class ToolbarController(AgentController): +class ToolbarController(ComponentController): """ The navigation panel """ @@ -32,7 +32,7 @@ class ToolbarController(AgentController): @classmethod def create(cls, parent, password_asker): """ - Instanciate a navigation agent + Instanciate a navigation component :param sakia.gui.agent.controller.AgentController parent: :return: a new Toolbar controller :rtype: ToolbarController diff --git a/src/sakia/gui/toolbar/model.py b/src/sakia/gui/toolbar/model.py index 5e6250e96c61d883494e47c8b6f0daffbd69e666..6d8d4ce41e719462c5cc561d52632b3ca093fdd4 100644 --- a/src/sakia/gui/toolbar/model.py +++ b/src/sakia/gui/toolbar/model.py @@ -1,9 +1,9 @@ -from sakia.gui.agent.model import AgentModel +from sakia.gui.component.model import ComponentModel -class ToolbarModel(AgentModel): +class ToolbarModel(ComponentModel): """ - The model of Navigation agent + The model of Navigation component """ def __init__(self, parent): diff --git a/src/sakia/gui/toolbar/toolbar.ui b/src/sakia/gui/toolbar/toolbar.ui index b90226b937cf566c22bb009f306d835036056ef5..63f494287f7f137dc243514a1975b9520cb4d43c 100644 --- a/src/sakia/gui/toolbar/toolbar.ui +++ b/src/sakia/gui/toolbar/toolbar.ui @@ -6,10 +6,16 @@ <rect> <x>0</x> <y>0</y> - <width>690</width> - <height>240</height> + <width>666</width> + <height>237</height> </rect> </property> + <property name="sizePolicy"> + <sizepolicy hsizetype="Expanding" vsizetype="Preferred"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> <property name="windowTitle"> <string>Frame</string> </property> @@ -26,7 +32,7 @@ <string>Send money</string> </property> <property name="icon"> - <iconset resource="../icons/icons.qrc"> + <iconset resource="../../../../res/icons/icons.qrc"> <normaloff>:/icons/payment_icon</normaloff>:/icons/payment_icon</iconset> </property> <property name="iconSize"> @@ -43,7 +49,7 @@ <string>Certification</string> </property> <property name="icon"> - <iconset resource="../icons/icons.qrc"> + <iconset resource="../../../../res/icons/icons.qrc"> <normaloff>:/icons/certification_icon</normaloff>:/icons/certification_icon</iconset> </property> <property name="iconSize"> @@ -60,7 +66,7 @@ <string>Renew membership</string> </property> <property name="icon"> - <iconset resource="../icons/icons.qrc"> + <iconset resource="../../../../res/icons/icons.qrc"> <normaloff>:/icons/renew_membership</normaloff>:/icons/renew_membership</iconset> </property> <property name="iconSize"> @@ -78,7 +84,7 @@ </property> <property name="sizeHint" stdset="0"> <size> - <width>169</width> + <width>1000</width> <height>221</height> </size> </property> @@ -90,7 +96,7 @@ <string/> </property> <property name="icon"> - <iconset resource="../icons/icons.qrc"> + <iconset resource="../../../../res/icons/icons.qrc"> <normaloff>:/icons/menu_icon</normaloff>:/icons/menu_icon</iconset> </property> <property name="iconSize"> @@ -113,7 +119,7 @@ </layout> </widget> <resources> - <include location="../icons/icons.qrc"/> + <include location="../../../../res/icons/icons.qrc"/> </resources> <connections/> </ui> diff --git a/src/sakia/gui/toolbar/view.py b/src/sakia/gui/toolbar/view.py index df1dfd1f487deb17d957c8b55465bee7154e8f0b..c53cadb2185b8509ad4dd5247b3badd8ccc50ee2 100644 --- a/src/sakia/gui/toolbar/view.py +++ b/src/sakia/gui/toolbar/view.py @@ -6,7 +6,7 @@ from .toolbar_uic import Ui_SakiaToolbar class ToolbarView(QFrame, Ui_SakiaToolbar): """ - The model of Navigation agent + The model of Navigation component """ _action_showinfo_text = QT_TRANSLATE_NOOP("ToolbarView", "Show informations") _action_explore_text = QT_TRANSLATE_NOOP("ToolbarView", "Explore the Web of Trust") diff --git a/src/sakia/gui/transactions_tab.py b/src/sakia/gui/transactions_tab.py deleted file mode 100644 index 656b855b7658946c130d81882301e1c48b522144..0000000000000000000000000000000000000000 --- a/src/sakia/gui/transactions_tab.py +++ /dev/null @@ -1,222 +0,0 @@ -import logging - -from duniterpy.api import errors -from PyQt5.QtWidgets import QWidget, QAbstractItemView, QHeaderView -from PyQt5.QtCore import Qt, QObject, QDateTime, QTime, QModelIndex, pyqtSignal, pyqtSlot, QEvent -from PyQt5.QtGui import QCursor - -from ..presentation.transactions_tab_uic import Ui_transactionsTabWidget -from ..models.txhistory import HistoryTableModel, TxFilterProxyModel -from ..tools.exceptions import NoPeerAvailable -from ..tools.decorators import asyncify, once_at_a_time, cancel_once_task -from .widgets.context_menu import ContextMenu -from .widgets import toast - - -class TransactionsTabWidget(QObject): - """ - classdocs - """ - view_in_wot = pyqtSignal(object) - - def __init__(self, app, account=None, community=None, password_asker=None, - widget=QWidget, view=Ui_transactionsTabWidget): - """ - Init - - :param sakia.core.app.Application app: Application instance - :param sakia.core.Account account: The account displayed in the widget - :param sakia.core.Community community: The community displayed in the widget - :param sakia.gui.Password_Asker: password_asker: The widget to ask for passwords - :param class widget: The class of the PyQt5 widget used for this tab - :param class view: The class of the UI View for this tab - """ - - super().__init__() - self.widget = widget() - self.ui = view() - self.ui.setupUi(self.widget) - self.app = app - self.account = account - self.community = community - self.password_asker = password_asker - self.ui.busy_balance.hide() - - ts_from = self.ui.date_from.dateTime().toTime_t() - ts_to = self.ui.date_to.dateTime().toTime_t() - model = HistoryTableModel(self.app, self.account, self.community) - proxy = TxFilterProxyModel(ts_from, ts_to) - proxy.setSourceModel(model) - proxy.setDynamicSortFilter(True) - proxy.setSortRole(Qt.DisplayRole) - - self.ui.table_history.setModel(proxy) - self.ui.table_history.setSelectionBehavior(QAbstractItemView.SelectRows) - self.ui.table_history.setSortingEnabled(True) - self.ui.table_history.horizontalHeader().setSectionResizeMode(QHeaderView.Interactive) - self.ui.table_history.resizeColumnsToContents() - - self.ui.table_history.customContextMenuRequested['QPoint'].connect(self.history_context_menu) - self.ui.date_from.dateChanged['QDate'].connect(self.dates_changed) - self.ui.date_to.dateChanged['QDate'].connect(self.dates_changed) - - model.modelAboutToBeReset.connect(lambda: self.ui.table_history.setEnabled(False)) - model.modelReset.connect(lambda: self.ui.table_history.setEnabled(True)) - self.app.refresh_transfers.connect(self.refresh) - - self.ui.progressbar.hide() - self.refresh() - - def cancel_once_tasks(self): - cancel_once_task(self, self.refresh_minimum_maximum) - cancel_once_task(self, self.refresh_balance) - cancel_once_task(self, self.history_context_menu) - - def change_account(self, account, password_asker): - self.cancel_once_tasks() - self.account = account - self.password_asker = password_asker - self.ui.table_history.model().sourceModel().change_account(account) - if account: - self.connect_progress() - - def change_community(self, community): - self.cancel_once_tasks() - self.community = community - self.ui.progressbar.hide() - self.ui.table_history.model().sourceModel().change_community(self.community) - self.refresh() - - @once_at_a_time - @asyncify - async def refresh_minimum_maximum(self): - try: - block = await self.community.get_block(1) - minimum_datetime = QDateTime() - minimum_datetime.setTime_t(block['medianTime']) - minimum_datetime.setTime(QTime(0, 0)) - - self.ui.date_from.setMinimumDateTime(minimum_datetime) - self.ui.date_from.setDateTime(minimum_datetime) - self.ui.date_from.setMaximumDateTime(QDateTime().currentDateTime()) - - self.ui.date_to.setMinimumDateTime(minimum_datetime) - tomorrow_datetime = QDateTime().currentDateTime().addDays(1) - self.ui.date_to.setDateTime(tomorrow_datetime) - self.ui.date_to.setMaximumDateTime(tomorrow_datetime) - except NoPeerAvailable as e: - logging.debug(str(e)) - except errors.DuniterError as e: - logging.debug(str(e)) - - def refresh(self): - if self.community: - refresh_task = self.ui.table_history.model().sourceModel().refresh_transfers() - refresh_task.add_done_callback(lambda fut: self.ui.table_history.resizeColumnsToContents()) - self.refresh_minimum_maximum() - self.refresh_balance() - - def connect_progress(self): - def progressing(community, value, maximum): - if community == self.community: - self.ui.progressbar.show() - self.ui.progressbar.setValue(value) - self.ui.progressbar.setMaximum(maximum) - self.account.loading_progressed.connect(progressing) - self.account.loading_finished.connect(self.stop_progress) - - def stop_progress(self, community, received_list): - if community == self.community: - self.ui.progressbar.hide() - self.ui.table_history.model().sourceModel().refresh_transfers() - self.ui.table_history.resizeColumnsToContents() - self.notification_reception(received_list) - - @asyncify - async def notification_reception(self, received_list): - if len(received_list) > 0: - amount = 0 - for r in received_list: - amount += r.metadata['amount'] - localized_amount = await self.app.current_account.current_ref.instance(amount, self.community, self.app)\ - .localized(units=True, - international_system=self.app.preferences['international_system_of_units']) - text = self.tr("Received {amount} from {number} transfers").format(amount=localized_amount , - number=len(received_list)) - if self.app.preferences['notifications']: - toast.display(self.tr("New transactions received"), text) - - @once_at_a_time - @asyncify - async def refresh_balance(self): - self.ui.busy_balance.show() - try: - amount = await self.app.current_account.amount(self.community) - localized_amount = await self.app.current_account.current_ref.instance(amount, self.community, - self.app).localized(units=True, - international_system=self.app.preferences['international_system_of_units']) - - # set infos in label - self.ui.label_balance.setText( - self.tr("{:}") - .format( - localized_amount - ) - ) - except NoPeerAvailable as e: - logging.debug(str(e)) - except errors.DuniterError as e: - logging.debug(str(e)) - self.ui.busy_balance.hide() - - @once_at_a_time - @asyncify - async def history_context_menu(self, point): - index = self.ui.table_history.indexAt(point) - model = self.ui.table_history.model() - if index.isValid() and index.row() < model.rowCount(QModelIndex()): - source_index = model.mapToSource(index) - - pubkey_col = model.sourceModel().columns_types.index('pubkey') - pubkey_index = model.sourceModel().index(source_index.row(), - pubkey_col) - pubkey = model.sourceModel().data(pubkey_index, Qt.DisplayRole) - - identity = await self.app.identities_registry.future_find(pubkey, self.community) - - transfer = model.sourceModel().transfers()[source_index.row()] - menu = ContextMenu.from_data(self.widget, self.app, self.account, self.community, self.password_asker, - (identity, transfer)) - menu.view_identity_in_wot.connect(self.view_in_wot) - - # Show the context menu. - menu.qmenu.popup(QCursor.pos()) - - def dates_changed(self): - logging.debug("Changed dates") - if self.ui.table_history.model(): - qdate_from = self.ui.date_from - qdate_from.setTime(QTime(0, 0, 0)) - qdate_to = self.ui.date_to - qdate_to.setTime(QTime(0, 0, 0)) - ts_from = qdate_from.dateTime().toTime_t() - ts_to = qdate_to.dateTime().toTime_t() - - self.ui.table_history.model().set_period(ts_from, ts_to) - - self.refresh_balance() - - def resizeEvent(self, event): - self.ui.busy_balance.resize(event.size()) - super().resizeEvent(event) - - def changeEvent(self, event): - """ - Intercepte LanguageChange event to translate UI - :param QEvent QEvent: Event - :return: - """ - if event.type() == QEvent.LanguageChange: - self.retranslateUi(self) - self.refresh() - return super(TransactionsTabWidget, self).changeEvent(event) diff --git a/src/sakia/gui/txhistory/__init__.py b/src/sakia/gui/txhistory/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/src/sakia/gui/txhistory/controller.py b/src/sakia/gui/txhistory/controller.py new file mode 100644 index 0000000000000000000000000000000000000000..b6e3549b4bb98b23abb41a2e3aade5d8f9268a8d --- /dev/null +++ b/src/sakia/gui/txhistory/controller.py @@ -0,0 +1,165 @@ +import logging + +from duniterpy.api import errors +from PyQt5.QtCore import QDateTime, QTime, pyqtSignal, QEvent + +from ..component.controller import ComponentController +from .view import TxHistoryView +from .model import TxHistoryModel +from ...tools.exceptions import NoPeerAvailable +from ...tools.decorators import asyncify, once_at_a_time, cancel_once_task +from ..widgets import toast + + +class TxHistoryController(ComponentController): + """ + Transfer history component controller + """ + view_in_wot = pyqtSignal(object) + + def __init__(self, parent, view, model, password_asker=None): + """ + Init + :param sakia.gui.txhistory.view.TxHistoryView view: + :param sakia.gui.txhistory.model.TxHistoryModel model: + :param password_asker: + """ + + super().__init__(parent, view, model) + self.password_asker = password_asker + + ts_from = self.view.date_from.dateTime().toTime_t() + ts_to = self.view.date_to.dateTime().toTime_t() + model = self.model.history_table_model(ts_from, ts_to) + self.view.table_history.setModel(model) + + self.view.date_from.dateChanged['QDate'].connect(self.dates_changed) + self.view.date_to.dateChanged['QDate'].connect(self.dates_changed) + + model.modelAboutToBeReset.connect(lambda: self.view.table_history.setEnabled(False)) + model.modelReset.connect(lambda: self.view.table_history.setEnabled(True)) + #self.app.refresh_transfers.connect(self.refresh) + + self.view.progressbar.hide() + self.refresh() + + @classmethod + def create(cls, parent, app, **kwargs): + account = kwargs['account'] + community = kwargs['community'] + + view = TxHistoryView(parent.view) + model = TxHistoryModel(None, app, account, community) + txhistory = cls(parent, view, model) + model.setParent(txhistory) + return txhistory + + @once_at_a_time + @asyncify + async def refresh_minimum_maximum(self): + try: + block = await self.community.get_block(1) + minimum_datetime = QDateTime() + minimum_datetime.setTime_t(block['medianTime']) + minimum_datetime.setTime(QTime(0, 0)) + + self.view.date_from.setMinimumDateTime(minimum_datetime) + self.view.date_from.setDateTime(minimum_datetime) + self.view.date_from.setMaximumDateTime(QDateTime().currentDateTime()) + + self.view.date_to.setMinimumDateTime(minimum_datetime) + tomorrow_datetime = QDateTime().currentDateTime().addDays(1) + self.view.date_to.setDateTime(tomorrow_datetime) + self.view.date_to.setMaximumDateTime(tomorrow_datetime) + except NoPeerAvailable as e: + logging.debug(str(e)) + except errors.DuniterError as e: + logging.debug(str(e)) + + def refresh(self): + refresh_task = self.view.table_history.model().sourceModel().refresh_transfers() + refresh_task.add_done_callback(lambda fut: self.view.table_history.resizeColumnsToContents()) + self.refresh_minimum_maximum() + self.refresh_balance() + + def connect_progress(self): + def progressing(community, value, maximum): + if community == self.community: + self.view.progressbar.show() + self.view.progressbar.setValue(value) + self.view.progressbar.setMaximum(maximum) + self.account.loading_progressed.connect(progressing) + self.account.loading_finished.connect(self.stop_progress) + + def stop_progress(self, community, received_list): + if community == self.community: + self.view.progressbar.hide() + self.view.table_history.model().sourceModel().refresh_transfers() + self.view.table_history.resizeColumnsToContents() + self.notification_reception(received_list) + + @asyncify + async def notification_reception(self, received_list): + if len(received_list) > 0: + amount = 0 + for r in received_list: + amount += r.metadata['amount'] + localized_amount = await self.app.current_account.current_ref.instance(amount, self.community, self.app)\ + .localized(units=True, + international_system=self.app.preferences['international_system_of_units']) + text = self.tr("Received {amount} from {number} transfers").format(amount=localized_amount , + number=len(received_list)) + if self.app.preferences['notifications']: + toast.display(self.tr("New transactions received"), text) + + @once_at_a_time + @asyncify + async def refresh_balance(self): + self.view.busy_balance.show() + try: + amount = await self.app.current_account.amount(self.community) + localized_amount = await self.app.current_account.current_ref.instance(amount, self.community, + self.app).localized(units=True, + international_system=self.app.preferences['international_system_of_units']) + + # set infos in label + self.view.label_balance.setText( + self.tr("{:}") + .format( + localized_amount + ) + ) + except NoPeerAvailable as e: + logging.debug(str(e)) + except errors.DuniterError as e: + logging.debug(str(e)) + self.view.busy_balance.hide() + + def dates_changed(self): + logging.debug("Changed dates") + if self.view.table_history.model(): + qdate_from = self.view.date_from + qdate_from.setTime(QTime(0, 0, 0)) + qdate_to = self.view.date_to + qdate_to.setTime(QTime(0, 0, 0)) + ts_from = qdate_from.dateTime().toTime_t() + ts_to = qdate_to.dateTime().toTime_t() + + self.view.table_history.model().set_period(ts_from, ts_to) + + self.refresh_balance() + + def resizeEvent(self, event): + self.view.busy_balance.resize(event.size()) + super().resizeEvent(event) + + def changeEvent(self, event): + """ + Intercepte LanguageChange event to translate UI + :param QEvent QEvent: Event + :return: + """ + if event.type() == QEvent.LanguageChange: + self.retranslateUi(self) + self.refresh() + return super(TxHistoryController).changeEvent(event) diff --git a/src/sakia/gui/txhistory/model.py b/src/sakia/gui/txhistory/model.py new file mode 100644 index 0000000000000000000000000000000000000000..51fc48d23fc74101017758a7b355c6caad02684e --- /dev/null +++ b/src/sakia/gui/txhistory/model.py @@ -0,0 +1,29 @@ +from sakia.gui.component.model import ComponentModel +from .table_model import HistoryTableModel, TxFilterProxyModel +from PyQt5.QtCore import Qt + + +class TxHistoryModel(ComponentModel): + """ + The model of Navigation component + """ + + def __init__(self, parent, app, account, community): + super().__init__(parent) + self.app = app + self.account = account + self.community = community + + def history_table_model(self, ts_from, ts_to): + """ + Generates a history table model + :param int ts_from: date from where to filter tx + :param int ts_to: date to where to filter tx + :return: + """ + model = HistoryTableModel(self.app, self.account, self.community) + proxy = TxFilterProxyModel(ts_from, ts_to) + proxy.setSourceModel(model) + proxy.setDynamicSortFilter(True) + proxy.setSortRole(Qt.DisplayRole) + return proxy \ No newline at end of file diff --git a/src/sakia/models/txhistory.py b/src/sakia/gui/txhistory/table_model.py similarity index 98% rename from src/sakia/models/txhistory.py rename to src/sakia/gui/txhistory/table_model.py index 5ea783e80ea738d7c5069a6faefd41b0b63ff15b..a0cb25ce0182a950bdbde505582fec2f4c953a7b 100644 --- a/src/sakia/models/txhistory.py +++ b/src/sakia/gui/txhistory/table_model.py @@ -8,10 +8,10 @@ import datetime import logging import asyncio import math -from ..core.transfer import Transfer, TransferState -from ..core.net.network import MAX_CONFIRMATIONS -from ..tools.exceptions import NoPeerAvailable -from ..tools.decorators import asyncify, once_at_a_time, cancel_once_task +from ...core.transfer import Transfer, TransferState +from ...core.net.network import MAX_CONFIRMATIONS +from ...tools.exceptions import NoPeerAvailable +from ...tools.decorators import asyncify, once_at_a_time, cancel_once_task from PyQt5.QtCore import QAbstractTableModel, Qt, QVariant, QSortFilterProxyModel, \ QDateTime, QLocale, QModelIndex diff --git a/res/ui/transactions_tab.ui b/src/sakia/gui/txhistory/txhistory.ui similarity index 95% rename from res/ui/transactions_tab.ui rename to src/sakia/gui/txhistory/txhistory.ui index 737ecfa4aa93d0e094da40eed917ae4b71e16457..8aa79961a224b47b29042bc02e8f62d752040095 100644 --- a/res/ui/transactions_tab.ui +++ b/src/sakia/gui/txhistory/txhistory.ui @@ -1,7 +1,7 @@ <?xml version="1.0" encoding="UTF-8"?> <ui version="4.0"> - <class>transactionsTabWidget</class> - <widget class="QWidget" name="transactionsTabWidget"> + <class>TxHistoryWidget</class> + <widget class="QWidget" name="TxHistoryWidget"> <property name="geometry"> <rect> <x>0</x> @@ -117,7 +117,7 @@ </customwidget> </customwidgets> <resources> - <include location="../icons/icons.qrc"/> + <include location="../../../../res/icons/icons.qrc"/> </resources> <connections/> </ui> diff --git a/src/sakia/gui/txhistory/view.py b/src/sakia/gui/txhistory/view.py new file mode 100644 index 0000000000000000000000000000000000000000..5466d544e2ae99dfc4d0a6188d13c3a50af44148 --- /dev/null +++ b/src/sakia/gui/txhistory/view.py @@ -0,0 +1,46 @@ +from PyQt5.QtWidgets import QWidget, QAbstractItemView, QHeaderView +from PyQt5.QtGui import QCursor +from PyQt5.QtCore import Qt, QModelIndex +from .txhistory_uic import Ui_TxHistoryWidget +from ...tools.decorators import asyncify, once_at_a_time +from ..widgets.context_menu import ContextMenu + + +class TxHistoryView(QWidget, Ui_TxHistoryWidget): + """ + The model of Navigation component + """ + + def __init__(self, parent): + super().__init__(parent) + self.setupUi(self) + self.busy_balance.hide() + + self.table_history.setSelectionBehavior(QAbstractItemView.SelectRows) + self.table_history.setSortingEnabled(True) + self.table_history.horizontalHeader().setSectionResizeMode(QHeaderView.Interactive) + self.table_history.resizeColumnsToContents() + self.table_history.customContextMenuRequested['QPoint'].connect(self.history_context_menu) + + @once_at_a_time + @asyncify + async def history_context_menu(self, point): + index = self.table_history.indexAt(point) + model = self.table_history.model() + if index.isValid() and index.row() < model.rowCount(QModelIndex()): + source_index = model.mapToSource(index) + + pubkey_col = model.sourceModel().columns_types.index('pubkey') + pubkey_index = model.sourceModel().index(source_index.row(), + pubkey_col) + pubkey = model.sourceModel().data(pubkey_index, Qt.DisplayRole) + + identity = await self.app.identities_registry.future_find(pubkey, self.community) + + transfer = model.sourceModel().transfers()[source_index.row()] + menu = ContextMenu.from_data(self, self.app, self.account, self.community, self.password_asker, + (identity, transfer)) + menu.view_identity_in_wot.connect(self.view_in_wot) + + # Show the context menu. + menu.qmenu.popup(QCursor.pos()) diff --git a/src/sakia/models/generic_tree.py b/src/sakia/models/generic_tree.py index 4703d03b9ff3ddeaa8acc55c06da51fd6e07b95d..c7b49ce05813f4e783fc17420cb69752cce2a740 100644 --- a/src/sakia/models/generic_tree.py +++ b/src/sakia/models/generic_tree.py @@ -38,6 +38,9 @@ class NodeItem(QAbstractItemModel): if role == Qt.DecorationRole and 'icon' in self.node: return QIcon(self.node['icon']) + if role == GenericTreeModel.ROLE_RAW_DATA: + return self.node + def row(self): if self.parent_item: return self.parent_item.row() + self.parent_item.children.index(self) @@ -59,6 +62,9 @@ class GenericTreeModel(QAbstractItemModel): """ + ROLE_RAW_DATA = 101 + + def __init__(self, title, root_item): """ Constructor @@ -95,6 +101,8 @@ class GenericTreeModel(QAbstractItemModel): if role == Qt.DisplayRole and index.column() == 0: return item.data(0, role) + elif role == GenericTreeModel.ROLE_RAW_DATA: + return item.data(0, role) return None