import os from pathlib import Path from PyQt5.QtCore import Qt, pyqtSignal, QSize, QRect from PyQt5.QtGui import QIcon from PyQt5.QtWidgets import ( QWidget, QHBoxLayout, QScroller, QVBoxLayout, QPushButton, QGridLayout, QScrollArea ) from .custom_button import CustomButton pkg_dir = str(Path(os.path.dirname(__file__)).parents[0]) file_back_icon = os.path.join(pkg_dir, 'share', 'back.svg') file_close_icon = os.path.join(pkg_dir, 'share', 'close.svg') file_menu_img = os.path.join(pkg_dir, 'share', 'menu.png') __all__ = ['GridButtons', 'MenuDash'] def money(v): return '${:9,}'.format(int(v)) class MenuDash(QWidget): def __init__(self, parent, values, selected_method=None, title=None): """ parent: parent window values: is to list of list/tuples values for data model [('a' 'b', 'c'), ('d', 'e', 'f')...] on_selected: method to call when triggered the selection title: title of window """ super(MenuDash, self).__init__() self.setContentsMargins(0, 0, 0, 0) self.setObjectName('dash_menu') self.parent = parent self.values = values self.current_view = '0' self._view = 0 self.main = QVBoxLayout() self.main.setSpacing(0) self.setLayout(self.main) self.ctx_widgets = {} self.button_size = parent.screen_size self.method_on_selected = getattr(self.parent, selected_method) self.create_categories() self.expand = False self.push_menu = QPushButton('MENU') self.push_menu.setObjectName('button_push_menu') self.push_menu.clicked.connect(self.expand_menu) self.close_menu = QPushButton() self.close_menu.setObjectName('button_close_menu') self.close_menu.setIcon(QIcon(file_close_icon)) self.close_menu.setIconSize(QSize(30, 30)) self.close_menu.clicked.connect(self.stretch_menu) self.close_menu.hide() widget_head = QWidget() widget_head.setContentsMargins(0, 0, 0, 0) widget_head.setStyleSheet("background-color: white; max-height: 70px") self.layout_head = QHBoxLayout() widget_head.setLayout(self.layout_head) self.main.addWidget(widget_head, 0) self.pushButtonBack = QPushButton() self.pushButtonBack.setObjectName('button_back_menu') self.pushButtonBack.setIcon(QIcon(file_back_icon)) self.pushButtonBack.setIconSize(QSize(30, 30)) self.layout_head.addWidget(self.pushButtonBack, stretch=0) self.layout_head.addWidget(self.push_menu, stretch=1) self.layout_head.addWidget(self.close_menu, stretch=0) self.main.addWidget(self.menu_area, 0) self.pushButtonBack.clicked.connect(self.action_back) width = self.parent.screen_width start_width = int(width / 3) last_width = width - start_width - 10 self.rect_expanded = QRect(start_width, 0, last_width, self.parent.screen_height) def paintEvent(self, event): super(MenuDash, self).paintEvent(event) if self.expand: self.expand_menu() def get_products(self, values, name=None): grid_buttons = GridButtons( self.parent, values, num_cols=4, action=self.method_on_selected ) scroll_area = QScrollArea() scroll_area.setWidgetResizable(True) scroll_area.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOn) scroll_area.setWidget(grid_buttons) QScroller.grabGesture(scroll_area, QScroller.LeftMouseButtonGesture) return scroll_area def change_view(self, view_id): view_id = str(view_id) view = self.ctx_widgets[self.current_view]['items'] view.hide() if not view_id: view_id = '0' new_view = self.ctx_widgets[view_id]['items'] if not new_view: return new_view.show() self.main.addWidget(new_view) self.current_view = view_id self.setGeometry(self.rect_expanded) def create_categories(self): # set the list model self.menu_area = QScrollArea() self.menu_area.setWidgetResizable(True) QScroller.grabGesture(self.menu_area, QScroller.LeftMouseButtonGesture) self.menu = QWidget() self.menu_area.setWidget(self.menu) self.main_categories = QGridLayout() self.main_categories.setSpacing(4) self.menu.setLayout(self.main_categories) num_cat_cols = 3 row_cat = 0 col_cat = 0 parent_id = '0' self.ctx_widgets = { '0': { 'items': self.menu_area, 'parent': None, }, } for value in self.values: cat_id = str(value['id']) if not value: continue if col_cat > num_cat_cols - 1: col_cat = 0 row_cat += 1 button = CustomButton( parent=self, id=value['id'], icon=value['icon'], method='selected_method', desc_extractor='name', record=value, size=self.button_size, name_style='toolbar' ) self.main_categories.addWidget(button, row_cat, col_cat) col_cat += 1 items = value.get('items') childs = value.get('childs', []) if items: products = self.get_products(items) self.ctx_widgets[cat_id] = { 'items': products, 'parent': parent_id, } if childs: subrow = 0 subcol = 0 sub_categories = QGridLayout() sub_categories.setSpacing(4) scroll_subarea = QScrollArea() scroll_subarea.setWidgetResizable(True) scroll_subarea.setLayout(sub_categories) self.ctx_widgets[cat_id] = { 'items': scroll_subarea, 'parent': parent_id, } for subcat in childs: sub_id = str(subcat['id']) if subcol > num_cat_cols - 1: subcol = 0 subrow += 1 button = CustomButton( parent=self, id=sub_id, icon=value['icon'], method='selected_method', desc_extractor='name', record=subcat, size=self.button_size, name_style='category_button' ) sub_categories.addWidget(button, subrow, subcol) subcol += 1 products_list = subcat.get('items') products_items = None if products_list: products_items = self.get_products(products_list) self.ctx_widgets[sub_id] = { 'items': products_items, 'parent': cat_id, } sub_categories.setRowStretch(subrow + 1, 1) self.main_categories.setRowStretch(row_cat + 1, 1) def action_back(self): parent_id = self.ctx_widgets[self.current_view]['parent'] if parent_id and parent_id != self.current_view: self.change_view(parent_id) def selected_method(self, args): self.change_view(args['id']) self.expand = True def setDisabled(self, bool): self.menu_area.setDisabled(bool) def stretch_menu(self): self.expand = False self.change_view('0') self.close_menu.hide() self.parent.show_right_panel(True) def expand_menu(self): self.expand = True self.parent.show_right_panel(False) self.close_menu.show() self.setGeometry(self.rect_expanded) class GridButtons(QWidget): sigItem_selected = pyqtSignal(str) def __init__(self, parent, values, num_cols, action, style='product_button'): """ values: a list of lists num_cols: number of columns? """ QWidget.__init__(self) self.parent = parent self.layout = QGridLayout() self.setLayout(self.layout) self.button_size = parent.screen_size self.values = values self.action = action self.num_cols = num_cols self.style = style self.create_list_items() self.layout.setSpacing(2) self.set_items() def create_list_items(self): self.list_items = [] for value in self.values: _button = CustomButton( parent=self, id=value['id'], desc_extractor='name', method='action_selected', record=value, size=self.button_size, name_style=self.style, ) self.list_items.append(_button) def action_selected(self, idx): self.action(idx) def set_items(self): colx = 0 rowy = 0 for item_button in self.list_items: if colx >= self.num_cols: colx = 0 rowy += 1 self.layout.addWidget(item_button, rowy, colx) colx += 1 self.layout.setRowStretch(rowy + 1, 1)