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
from .view import InformationsView
from sakia.tools.decorators import asyncify
from sakia.tools.exceptions import NoPeerAvailable
from duniterpy.api import errors
import logging
class InformationsController(ComponentController):
"""
The informations component
......@@ -67,6 +69,19 @@ class InformationsController(ComponentController):
Refresh localized data in view
"""
localized_data = await self.model.get_localized_data()
if localized_data:
self.view.set_general_text(localized_data)
self.view.set_rules_text(localized_data)
\ No newline at end of file
try:
simple_data = await self.model.get_identity_data()
all_data = {**simple_data, **localized_data}
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 @@
<property name="windowTitle">
<string>Form</string>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="0" column="0">
<widget class="QScrollArea" name="scrollArea">
<property name="styleSheet">
<string notr="true">QGroupBox {
<property name="styleSheet">
<string notr="true">QGroupBox {
border: 1px solid gray;
border-radius: 9px;
margin-top: 0.5em;
......@@ -29,6 +26,12 @@ QGroupBox::title {
padding: 0 3px 0 3px;
font-weight: bold;
}</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 name="widgetResizable">
<bool>true</bool>
......@@ -39,7 +42,7 @@ QGroupBox::title {
<x>0</x>
<y>0</y>
<width>522</width>
<height>721</height>
<height>308</height>
</rect>
</property>
<layout class="QVBoxLayout" name="verticalLayout_5">
......@@ -148,6 +151,65 @@ QGroupBox::title {
</widget>
</widget>
</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>
</widget>
<resources>
......
......@@ -43,12 +43,11 @@ class InformationsModel(ComponentModel):
block_ud = await self.community.get_ud_block()
except NoPeerAvailable as e:
logging.debug('community get_ud_block error : ' + str(e))
return None
try:
block_ud_minus_1 = await self.community.get_ud_block(x=1)
except NoPeerAvailable as 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['diff_units'] = self.account.current_ref.instance(0, self.community, self.app, None).diff_units
......@@ -105,17 +104,45 @@ class InformationsModel(ComponentModel):
QDateTime.fromTime_t(block_ud_minus_1['medianTime']),
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:
localized_data['mass_minus_1_per_member'] = QLocale().toString(
float(0), 'f', self.app.preferences['digits_after_comma']
)
localized_data['mass_minus_1'] = QLocale().toString(
float(0), 'f', self.app.preferences['digits_after_comma']
)
localized_data['actual_growth'] = float(0)
localized_data['ud_median_time_minus_1'] = "####"
return localized_data
return None
mstime_remaining_text += "{hours} hours and {min} min.".format(hours=hours,
min=minutes)
return {
'amount': localized_amount,
'outdistanced': outdistanced_text,
'nb_certs': nb_certs,
'mstime': mstime_remaining_text,
'membership_state': mstime_remaining > 0
}
async def parameters(self):
"""
......
from PyQt5.QtWidgets import QWidget
from PyQt5.QtCore import QEvent
from .informations_uic import Ui_InformationsWidget
from enum import Enum
class InformationsView(QWidget, Ui_InformationsWidget):
......@@ -8,9 +9,65 @@ class InformationsView(QWidget, Ui_InformationsWidget):
The view of navigation panel
"""
class CommunityState(Enum):
NOT_INIT = 0
OFFLINE = 1
READY = 2
def __init__(self, parent):
super().__init__(parent)
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):
"""
......@@ -37,25 +94,25 @@ class InformationsView(QWidget, Ui_InformationsWidget):
<tr><td align="right"><b>{:}</b></td><td>{:}</td></tr>
</table>
""").format(
localized_data['ud'],
localized_data.get('ud', '####'),
self.tr('Universal Dividend UD(t) in'),
localized_data['diff_units'],
localized_data['mass_minus_1'],
self.tr('Monetary Mass M(t-1) in'),
localized_data['units'],
localized_data['members_count'],
localized_data.get('members_count', '####'),
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'),
localized_data['diff_units'],
localized_data['actual_growth'],
localized_data['days_per_dividend'],
localized_data.get('actual_growth', 0),
localized_data.get('days_per_dividend', '####'),
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)'),
localized_data['ud_median_time'],
localized_data.get('ud_median_time', '####'),
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)')
)
)
......@@ -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('Universal Dividend (formula)'),
self.tr('{:} = MAX {{ {:} {:} ; {:2.0%} &#215; {:} {:} / {:} }}').format(
localized_data['ud_plus_1'],
localized_data['ud'],
localized_data.get('ud_plus_1', '####'),
localized_data.get('ud', '####'),
localized_data['diff_units'],
localized_data['growth'],
localized_data['mass'],
localized_data.get('growth', '####'),
localized_data.get('mass', '####'),
localized_data['diff_units'],
localized_data['members_count']
localized_data.get('members_count', '####')
),
self.tr('Universal Dividend (computed)')
)
......
......@@ -8,8 +8,6 @@ class ToolbarView(QFrame, Ui_SakiaToolbar):
"""
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_revoke_uid_text = QT_TRANSLATE_NOOP("ToolbarView", "Revoke UID")
......@@ -22,20 +20,6 @@ class ToolbarView(QFrame, Ui_SakiaToolbar):
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_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)
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