Skip to content
Snippets Groups Projects
Commit 1da703df authored by inso's avatar inso
Browse files

Remove community tile and migrate the info into informations

parent 3ab4b3ab
No related branches found
No related tags found
No related merge requests found
"""
@author: inso
"""
import enum
from PyQt5.QtWidgets import QFrame, QLabel, QVBoxLayout, QLayout
from PyQt5.QtCore import QSize, pyqtSignal, QTime
from duniterpy.documents.block import Block
from duniterpy.api import errors
from ..tools.decorators import asyncify, once_at_a_time, cancel_once_task
from ..tools.exceptions import NoPeerAvailable
from .widgets.busy import Busy
@enum.unique
class CommunityState(enum.Enum):
NOT_INIT = 0
OFFLINE = 1
READY = 2
class CommunityTile(QFrame):
clicked = pyqtSignal()
_hover_stylesheet = """QFrame#CommunityTile {
border-radius: 5px;
background-color: palette(midlight);
}
"""
_pressed_stylesheet = """QFrame#CommunityTile {
border-radius: 5px;
background-color: palette(dark);
}
"""
_standard_stylesheet = """QFrame#CommunityTile {
border-radius: 5px;
background-color: palette(base);
}
"""
def __init__(self, parent, app, community):
super().__init__(parent)
self.setObjectName("CommunityTile")
self.app = app
self.community = community
self.community.network.nodes_changed.connect(self.handle_nodes_change)
self.text_label = QLabel()
self.setLayout(QVBoxLayout())
self.layout().setSizeConstraint(QLayout.SetFixedSize)
self.layout().addWidget(self.text_label)
self.setFrameShape(QFrame.StyledPanel)
self.setFrameShadow(QFrame.Raised)
self.setStyleSheet(CommunityTile._standard_stylesheet)
self.busy = Busy(self)
self.busy.hide()
self._state = CommunityState.NOT_INIT
self.refresh()
def sizeHint(self):
return QSize(250, 250)
def handle_nodes_change(self):
if len(self.community.network.online_nodes) > 0:
if self.community.network.current_blockUID.sha_hash == Block.Empty_Hash:
state = CommunityState.NOT_INIT
else:
state = CommunityState.READY
else:
state = CommunityState.OFFLINE
if state != self._state:
self.refresh()
def cancel_refresh(self):
cancel_once_task(self, self.refresh)
@once_at_a_time
@asyncify
async def refresh(self):
self.busy.show()
self.setFixedSize(QSize(150, 150))
try:
current_block = await self.community.get_block()
members_pubkeys = await self.community.members_pubkeys()
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'])
if current_block['monetaryMass']:
localized_monetary_mass = await self.app.current_account.current_ref.instance(current_block['monetaryMass'],
self.community, self.app).diff_localized(units=True,
international_system=self.app.preferences['international_system_of_units'])
else:
localized_monetary_mass = ""
status = self.app.current_account.pubkey in members_pubkeys
account_identity = await self.app.current_account.identity(self.community)
mstime_remaining_text = self.tr("Expired or never published")
outdistanced_text = self.tr("Outdistanced")
requirements = await account_identity.requirements(self.community)
mstime_remaining = 0
nb_certs = 0
if requirements:
mstime_remaining = requirements['membershipExpiresIn']
nb_certs = len(requirements['certifications'])
if not requirements['outdistanced']:
outdistanced_text = self.tr("In WoT range")
if mstime_remaining > 0:
days, remainder = divmod(mstime_remaining, 3600*24)
hours, remainder = divmod(remainder, 3600)
minutes, seconds = divmod(remainder, 60)
mstime_remaining_text = self.tr("Expires in ")
if days > 0:
mstime_remaining_text += "{days} days".format(days=days)
else:
mstime_remaining_text += "{hours} hours and {min} min.".format(hours=hours,
min=minutes)
status_value = self.tr("Member") if status else self.tr("Non-Member")
status_color = '#00AA00' if status else self.tr('#FF0000')
description = """<html>
<body>
<p>
<span style=" font-size:16pt; font-weight:600;">{currency}</span>
</p>
<p>{nb_members} {members_label}</p>
<p><span style="font-weight:600;">{monetary_mass_label}</span> : {monetary_mass}</p>
<p><span style="font-weight:600;">{status_label}</span> : <span style="color:{status_color};">{status}</span></p>
<p><span style="font-weight:600;">{nb_certs_label}</span> : {nb_certs} ({outdistanced_text})</p>
<p><span style="font-weight:600;">{mstime_remaining_label}</span> : {mstime_remaining}</p>
<p><span style="font-weight:600;">{balance_label}</span> : {balance}</p>
</body>
</html>""".format(currency=self.community.currency,
nb_members=len(members_pubkeys),
members_label=self.tr("members"),
monetary_mass_label=self.tr("Monetary mass"),
monetary_mass=localized_monetary_mass,
status_color=status_color,
status_label=self.tr("Status"),
status=status_value,
nb_certs_label=self.tr("Certs. received"),
nb_certs=nb_certs,
outdistanced_text=outdistanced_text,
mstime_remaining_label=self.tr("Membership"),
mstime_remaining=mstime_remaining_text,
balance_label=self.tr("Balance"),
balance=localized_amount)
self.text_label.setText(description)
self._state = CommunityState.READY
except NoPeerAvailable:
description = """<html>
<body>
<p>
<span style=" font-size:16pt; font-weight:600;">{currency}</span>
</p>
<p>{message}</p>
</body>
</html>""".format(currency=self.community.currency,
message=self.tr("Not connected"))
self.text_label.setText(description)
self._state = CommunityState.OFFLINE
except errors.DuniterError as e:
if e.ucode == errors.BLOCK_NOT_FOUND:
description = """<html>
<body>
<p>
<span style=" font-size:16pt; font-weight:600;">{currency}</span>
</p>
<p>{message}</p>
</body>
</html>""".format(currency=self.community.currency,
message=self.tr("Community not initialized"))
self.text_label.setText(description)
self._state = CommunityState.NOT_INIT
else:
raise
self.busy.hide()
def mousePressEvent(self, event):
self.grabMouse()
self.setStyleSheet(CommunityTile._pressed_stylesheet)
return super().mousePressEvent(event)
def mouseReleaseEvent(self, event):
self.releaseMouse()
self.setStyleSheet(CommunityTile._hover_stylesheet)
self.clicked.emit()
return super().mouseReleaseEvent(event)
def resizeEvent(self, event):
self.busy.resize(event.size())
super().resizeEvent(event)
def enterEvent(self, event):
self.setStyleSheet(CommunityTile._hover_stylesheet)
return super().enterEvent(event)
def leaveEvent(self, event):
self.setStyleSheet(CommunityTile._standard_stylesheet)
return super().leaveEvent(event)
...@@ -3,8 +3,10 @@ from .model import InformationsModel ...@@ -3,8 +3,10 @@ from .model import InformationsModel
from .view import InformationsView from .view import InformationsView
from sakia.tools.decorators import asyncify from sakia.tools.decorators import asyncify
from sakia.tools.exceptions import NoPeerAvailable from sakia.tools.exceptions import NoPeerAvailable
from duniterpy.api import errors
import logging import logging
class InformationsController(ComponentController): class InformationsController(ComponentController):
""" """
The informations component The informations component
...@@ -67,6 +69,19 @@ class InformationsController(ComponentController): ...@@ -67,6 +69,19 @@ class InformationsController(ComponentController):
Refresh localized data in view Refresh localized data in view
""" """
localized_data = await self.model.get_localized_data() localized_data = await self.model.get_localized_data()
if localized_data: try:
self.view.set_general_text(localized_data) simple_data = await self.model.get_identity_data()
self.view.set_rules_text(localized_data) all_data = {**simple_data, **localized_data}
\ No newline at end of file self.view.set_simple_informations(all_data, InformationsView.CommunityState.READY)
except NoPeerAvailable as e:
logging.debug(str(e))
self.view.set_simple_informations(all_data, InformationsView.CommunityState.OFFLINE)
except errors.DuniterError as e:
if e.ucode == errors.BLOCK_NOT_FOUND:
self.view.set_simple_informations(all_data, InformationsView.CommunityState.NOT_INIT)
else:
raise
self.view.set_general_text(localized_data)
self.view.set_rules_text(localized_data)
...@@ -13,11 +13,8 @@ ...@@ -13,11 +13,8 @@
<property name="windowTitle"> <property name="windowTitle">
<string>Form</string> <string>Form</string>
</property> </property>
<layout class="QGridLayout" name="gridLayout"> <property name="styleSheet">
<item row="0" column="0"> <string notr="true">QGroupBox {
<widget class="QScrollArea" name="scrollArea">
<property name="styleSheet">
<string notr="true">QGroupBox {
border: 1px solid gray; border: 1px solid gray;
border-radius: 9px; border-radius: 9px;
margin-top: 0.5em; margin-top: 0.5em;
...@@ -29,6 +26,12 @@ QGroupBox::title { ...@@ -29,6 +26,12 @@ QGroupBox::title {
padding: 0 3px 0 3px; padding: 0 3px 0 3px;
font-weight: bold; font-weight: bold;
}</string> }</string>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="3" column="0">
<widget class="QScrollArea" name="scrollarea">
<property name="styleSheet">
<string notr="true"/>
</property> </property>
<property name="widgetResizable"> <property name="widgetResizable">
<bool>true</bool> <bool>true</bool>
...@@ -39,7 +42,7 @@ QGroupBox::title { ...@@ -39,7 +42,7 @@ QGroupBox::title {
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>522</width> <width>522</width>
<height>721</height> <height>308</height>
</rect> </rect>
</property> </property>
<layout class="QVBoxLayout" name="verticalLayout_5"> <layout class="QVBoxLayout" name="verticalLayout_5">
...@@ -148,6 +151,65 @@ QGroupBox::title { ...@@ -148,6 +151,65 @@ QGroupBox::title {
</widget> </widget>
</widget> </widget>
</item> </item>
<item row="1" column="0">
<layout class="QHBoxLayout" name="horizontalLayout">
<property name="topMargin">
<number>6</number>
</property>
<item>
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QPushButton" name="button_details">
<property name="text">
<string>Details</string>
</property>
<property name="checkable">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</item>
<item row="0" column="0">
<widget class="QGroupBox" name="group_uid_state">
<property name="title">
<string>UID</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QLabel" name="label_simple">
<property name="text">
<string/>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item row="2" column="0">
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
</layout> </layout>
</widget> </widget>
<resources> <resources>
......
...@@ -43,12 +43,11 @@ class InformationsModel(ComponentModel): ...@@ -43,12 +43,11 @@ class InformationsModel(ComponentModel):
block_ud = await self.community.get_ud_block() block_ud = await self.community.get_ud_block()
except NoPeerAvailable as e: except NoPeerAvailable as e:
logging.debug('community get_ud_block error : ' + str(e)) logging.debug('community get_ud_block error : ' + str(e))
return None
try: try:
block_ud_minus_1 = await self.community.get_ud_block(x=1) block_ud_minus_1 = await self.community.get_ud_block(x=1)
except NoPeerAvailable as e: except NoPeerAvailable as e:
logging.debug('community get_ud_block error : ' + str(e)) logging.debug('community get_ud_block error : ' + str(e))
return None
localized_data['units'] = self.account.current_ref.instance(0, self.community, self.app, None).units localized_data['units'] = self.account.current_ref.instance(0, self.community, self.app, None).units
localized_data['diff_units'] = self.account.current_ref.instance(0, self.community, self.app, None).diff_units localized_data['diff_units'] = self.account.current_ref.instance(0, self.community, self.app, None).diff_units
...@@ -105,17 +104,45 @@ class InformationsModel(ComponentModel): ...@@ -105,17 +104,45 @@ class InformationsModel(ComponentModel):
QDateTime.fromTime_t(block_ud_minus_1['medianTime']), QDateTime.fromTime_t(block_ud_minus_1['medianTime']),
QLocale.dateTimeFormat(QLocale(), QLocale.ShortFormat) QLocale.dateTimeFormat(QLocale(), QLocale.ShortFormat)
) )
return localized_data
async def get_identity_data(self):
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'])
account_identity = await self.app.current_account.identity(self.community)
mstime_remaining_text = self.tr("Expired or never published")
outdistanced_text = self.tr("Outdistanced")
requirements = await account_identity.requirements(self.community)
mstime_remaining = 0
nb_certs = 0
if requirements:
mstime_remaining = requirements['membershipExpiresIn']
nb_certs = len(requirements['certifications'])
if not requirements['outdistanced']:
outdistanced_text = self.tr("In WoT range")
if mstime_remaining > 0:
days, remainder = divmod(mstime_remaining, 3600 * 24)
hours, remainder = divmod(remainder, 3600)
minutes, seconds = divmod(remainder, 60)
mstime_remaining_text = self.tr("Expires in ")
if days > 0:
mstime_remaining_text += "{days} days".format(days=days)
else: else:
localized_data['mass_minus_1_per_member'] = QLocale().toString( mstime_remaining_text += "{hours} hours and {min} min.".format(hours=hours,
float(0), 'f', self.app.preferences['digits_after_comma'] min=minutes)
) return {
localized_data['mass_minus_1'] = QLocale().toString( 'amount': localized_amount,
float(0), 'f', self.app.preferences['digits_after_comma'] 'outdistanced': outdistanced_text,
) 'nb_certs': nb_certs,
localized_data['actual_growth'] = float(0) 'mstime': mstime_remaining_text,
localized_data['ud_median_time_minus_1'] = "####" 'membership_state': mstime_remaining > 0
return localized_data }
return None
async def parameters(self): async def parameters(self):
""" """
......
from PyQt5.QtWidgets import QWidget from PyQt5.QtWidgets import QWidget
from PyQt5.QtCore import QEvent from PyQt5.QtCore import QEvent
from .informations_uic import Ui_InformationsWidget from .informations_uic import Ui_InformationsWidget
from enum import Enum
class InformationsView(QWidget, Ui_InformationsWidget): class InformationsView(QWidget, Ui_InformationsWidget):
...@@ -8,9 +9,65 @@ class InformationsView(QWidget, Ui_InformationsWidget): ...@@ -8,9 +9,65 @@ class InformationsView(QWidget, Ui_InformationsWidget):
The view of navigation panel The view of navigation panel
""" """
class CommunityState(Enum):
NOT_INIT = 0
OFFLINE = 1
READY = 2
def __init__(self, parent): def __init__(self, parent):
super().__init__(parent) super().__init__(parent)
self.setupUi(self) self.setupUi(self)
self.scrollarea.hide()
self.button_details.clicked.connect(self.handle_details_click)
def handle_details_click(self):
if self.button_details.isChecked():
self.scrollarea.show()
else:
self.scrollarea.hide()
def set_simple_informations(self, data, state):
if state in (InformationsView.CommunityState.NOT_INIT, InformationsView.CommunityState.OFFLINE):
self.label_simple.setText("""<html>
<body>
<p>
<span style=" font-size:16pt; font-weight:600;">{currency}</span>
</p>
<p>{message}</p>
</body>
</html>""".format(currency=data['currency'],
message=InformationsView.simple_message[state]))
else:
status_value = self.tr("Member") if data['membership_state'] else self.tr("Non-Member")
status_color = '#00AA00' if data['membership_state'] else self.tr('#FF0000')
description = """<html>
<body>
<p>
<span style=" font-size:16pt; font-weight:600;">{currency}</span>
</p>
<p>{nb_members} {members_label}</p>
<p><span style="font-weight:600;">{monetary_mass_label}</span> : {monetary_mass}</p>
<p><span style="font-weight:600;">{status_label}</span> : <span style="color:{status_color};">{status}</span></p>
<p><span style="font-weight:600;">{nb_certs_label}</span> : {nb_certs} ({outdistanced_text})</p>
<p><span style="font-weight:600;">{mstime_remaining_label}</span> : {mstime_remaining}</p>
<p><span style="font-weight:600;">{balance_label}</span> : {balance}</p>
</body>
</html>""".format(currency=data['units'],
nb_members=data['members_count'],
members_label=self.tr("members"),
monetary_mass_label=self.tr("Monetary mass"),
monetary_mass=data['mass'],
status_color=status_color,
status_label=self.tr("Status"),
status=status_value,
nb_certs_label=self.tr("Certs. received"),
nb_certs=data['nb_certs'],
outdistanced_text=data['outdistanced'],
mstime_remaining_label=self.tr("Membership"),
mstime_remaining=data['mstime'],
balance_label=self.tr("Balance"),
balance=data['amount'])
self.label_simple.setText(description)
def set_general_text_no_dividend(self): def set_general_text_no_dividend(self):
""" """
...@@ -37,25 +94,25 @@ class InformationsView(QWidget, Ui_InformationsWidget): ...@@ -37,25 +94,25 @@ class InformationsView(QWidget, Ui_InformationsWidget):
<tr><td align="right"><b>{:}</b></td><td>{:}</td></tr> <tr><td align="right"><b>{:}</b></td><td>{:}</td></tr>
</table> </table>
""").format( """).format(
localized_data['ud'], localized_data.get('ud', '####'),
self.tr('Universal Dividend UD(t) in'), self.tr('Universal Dividend UD(t) in'),
localized_data['diff_units'], localized_data['diff_units'],
localized_data['mass_minus_1'], localized_data['mass_minus_1'],
self.tr('Monetary Mass M(t-1) in'), self.tr('Monetary Mass M(t-1) in'),
localized_data['units'], localized_data['units'],
localized_data['members_count'], localized_data.get('members_count', '####'),
self.tr('Members N(t)'), self.tr('Members N(t)'),
localized_data['mass_minus_1_per_member'], localized_data.get('mass_minus_1_per_member', '####'),
self.tr('Monetary Mass per member M(t-1)/N(t) in'), self.tr('Monetary Mass per member M(t-1)/N(t) in'),
localized_data['diff_units'], localized_data['diff_units'],
localized_data['actual_growth'], localized_data.get('actual_growth', 0),
localized_data['days_per_dividend'], localized_data.get('days_per_dividend', '####'),
self.tr('Actual growth c = UD(t)/[M(t-1)/N(t)]'), self.tr('Actual growth c = UD(t)/[M(t-1)/N(t)]'),
localized_data['ud_median_time_minus_1'], localized_data.get('ud_median_time_minus_1', '####'),
self.tr('Penultimate UD date and time (t-1)'), self.tr('Penultimate UD date and time (t-1)'),
localized_data['ud_median_time'], localized_data.get('ud_median_time', '####'),
self.tr('Last UD date and time (t)'), self.tr('Last UD date and time (t)'),
localized_data['next_ud_median_time'], localized_data.get('next_ud_median_time', '####'),
self.tr('Next UD date and time (t+1)') self.tr('Next UD date and time (t+1)')
) )
) )
...@@ -86,13 +143,13 @@ class InformationsView(QWidget, Ui_InformationsWidget): ...@@ -86,13 +143,13 @@ class InformationsView(QWidget, Ui_InformationsWidget):
self.tr('UD(t+1) = MAX { UD(t) ; c &#215; M(t) / N(t+1) }'), self.tr('UD(t+1) = MAX { UD(t) ; c &#215; M(t) / N(t+1) }'),
self.tr('Universal Dividend (formula)'), self.tr('Universal Dividend (formula)'),
self.tr('{:} = MAX {{ {:} {:} ; {:2.0%} &#215; {:} {:} / {:} }}').format( self.tr('{:} = MAX {{ {:} {:} ; {:2.0%} &#215; {:} {:} / {:} }}').format(
localized_data['ud_plus_1'], localized_data.get('ud_plus_1', '####'),
localized_data['ud'], localized_data.get('ud', '####'),
localized_data['diff_units'], localized_data['diff_units'],
localized_data['growth'], localized_data.get('growth', '####'),
localized_data['mass'], localized_data.get('mass', '####'),
localized_data['diff_units'], localized_data['diff_units'],
localized_data['members_count'] localized_data.get('members_count', '####')
), ),
self.tr('Universal Dividend (computed)') self.tr('Universal Dividend (computed)')
) )
......
...@@ -8,8 +8,6 @@ class ToolbarView(QFrame, Ui_SakiaToolbar): ...@@ -8,8 +8,6 @@ class ToolbarView(QFrame, Ui_SakiaToolbar):
""" """
The model of Navigation component 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")
_action_publish_uid_text = QT_TRANSLATE_NOOP("ToolbarView", "Publish UID") _action_publish_uid_text = QT_TRANSLATE_NOOP("ToolbarView", "Publish UID")
_action_revoke_uid_text = QT_TRANSLATE_NOOP("ToolbarView", "Revoke UID") _action_revoke_uid_text = QT_TRANSLATE_NOOP("ToolbarView", "Revoke UID")
...@@ -22,20 +20,6 @@ class ToolbarView(QFrame, Ui_SakiaToolbar): ...@@ -22,20 +20,6 @@ class ToolbarView(QFrame, Ui_SakiaToolbar):
self.action_publish_uid = QAction(self.tr(ToolbarView._action_publish_uid_text), self) self.action_publish_uid = QAction(self.tr(ToolbarView._action_publish_uid_text), self)
self.action_revoke_uid = QAction(self.tr(ToolbarView._action_revoke_uid_text), self) self.action_revoke_uid = QAction(self.tr(ToolbarView._action_revoke_uid_text), self)
self.action_showinfo = QAction(self.tr(ToolbarView._action_showinfo_text), self)
self.action_explorer = QAction(self.tr(ToolbarView._action_explore_text), self)
action_showinfo = QAction(self.tr("Show informations"), self.toolbutton_menu)
action_showinfo.triggered.connect(lambda: self.show_closable_tab(self.tab_informations,
QIcon(":/icons/informations_icon"),
self.tr("Informations")))
tool_menu.addAction(action_showinfo)
action_showexplorer = QAction(self.tr("Show explorer"), self.toolbutton_menu)
action_showexplorer.triggered.connect(lambda: self.show_closable_tab(self.tab_explorer.widget,
QIcon(":/icons/explorer_icon"),
self.tr("Explorer")))
tool_menu.addAction(action_showexplorer)
menu_advanced = QMenu(self.tr("Advanced"), self.toolbutton_menu) menu_advanced = QMenu(self.tr("Advanced"), self.toolbutton_menu)
self.action_gen_revokation = QAction(self.tr("Save revokation document"), menu_advanced) self.action_gen_revokation = QAction(self.tr("Save revokation document"), menu_advanced)
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment