def build_header_bar(self): # Header bar hb = Gtk.HeaderBar() self.builder.expose_object("header-bar", hb) hb.set_show_close_button(True) # hb.props.title = "Pharmaship" hb.set_title("Pharmaship") self.set_titlebar(hb) self.set_title("Pharmaship") # Menu button builder = Gtk.Builder.new_from_file( utils.get_template("settings_menu.xml")) menu = builder.get_object("app-menu") button = widgets.ButtonWithImage("open-menu-symbolic", btn_class=Gtk.MenuButton) popover = Gtk.Popover.new_from_model(button, menu) button.set_popover(popover) hb.pack_end(button) # Search bar self.searchbar = Gtk.SearchEntry() self.searchbar.set_placeholder_text(_("Search something...")) self.searchbar.connect("activate", self.on_search) self.searchbar.props.width_request = 300 hb.pack_end(self.searchbar) # Mode button builder = Gtk.Builder.new_from_file( utils.get_template("mode_menu.xml")) menu = builder.get_object("app-menu") self.mode_button = Gtk.MenuButton(self.mode) popover = Gtk.Popover.new_from_model(self.mode_button, menu) self.mode_button.set_popover(popover) self.mode_button.props.width_request = 120 self.mode_button.get_style_context().add_class("suggested-action") hb.pack_start(self.mode_button) # Save button button = widgets.ButtonWithImage("document-save-as-symbolic", tooltip=_("Export as PDF"), action="app.save") hb.pack_start(button) self.builder.expose_object("hb-btn-save", button) # Create hb date check button self.create_hb_date_button() self.expiry_date_button_label()
def location_row_buttons(self, item, row_index): linked_btn = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL) linked_btn.get_style_context().add_class("linked") linked_btn.get_style_context().add_class("medicine-item-buttons") # Modify btn_modify = widgets.ButtonWithImage("document-edit-symbolic", tooltip="Modify", connect=self.dialog_modify, data=item) linked_btn.pack_end(btn_modify, False, True, 0) # Delete if item["id"] > 100: btn_delete = widgets.ButtonWithImage("edit-delete-symbolic", tooltip="Delete", connect=self.dialog_delete, data=item) btn_delete.get_style_context().add_class("medicine-btn-delete") linked_btn.pack_end(btn_delete, False, True, 0) self.grid.attach(linked_btn, 1, row_index, 1, 1)
def create_grid(self, toggle_row_num=None): grid = Gtk.Grid() # Header label = Gtk.Label(_("Name"), xalign=0) label.set_hexpand(True) label.get_style_context().add_class("header-cell") grid.attach(label, 0, 0, 1, 1) label = Gtk.Label(_("Remarks"), xalign=0) label.set_hexpand(True) label.get_style_context().add_class("header-cell") grid.attach(label, 1, 0, 1, 1) label = Gtk.Label(_("Packaging"), xalign=0) label.set_hexpand(True) label.get_style_context().add_class("header-cell") grid.attach(label, 2, 0, 1, 1) label = Gtk.Label(_("Location"), xalign=0) label.get_style_context().add_class("header-cell") grid.attach(label, 3, 0, 1, 1) label = Gtk.Label(_("Expiry"), xalign=0.5) label.get_style_context().add_class("header-cell") grid.attach(label, 4, 0, 1, 1) label = Gtk.Label(_("Quantity"), xalign=0.5) label.get_style_context().add_class("header-cell") grid.attach(label, 5, 0, 1, 1) label = Gtk.Label("", xalign=0) label.get_style_context().add_class("header-cell") # Size request because by default the colum content is "hidden" label.set_size_request(125, -1) grid.attach(label, 6, 0, 1, 1) data = parser(self.params) i = 0 toggle_equipment = None for equipment in data: i += 1 # If toggle_row_num is defined, record first the equipment then, when # all construction is done, call toggle_article function. if toggle_row_num and toggle_row_num == i: toggle_equipment = equipment if self.chosen and self.chosen == equipment["id"]: toggle_equipment = equipment toggle_row_num = i self.row_widget_num = i label = Gtk.Label(equipment["name"], xalign=0) label.set_line_wrap(True) label.set_lines(1) label.set_line_wrap_mode(2) label.get_style_context().add_class("item-cell") evbox = widgets.EventBox(equipment, self.toggle_article, 7, i) evbox.add(label) grid.attach(evbox, 0, i, 1, 1) label = Gtk.Label(equipment["remark"], xalign=0) label.set_line_wrap(True) label.set_lines(1) label.set_line_wrap_mode(2) label.get_style_context().add_class("item-cell") label.get_style_context().add_class("article-remark") evbox = widgets.EventBox(equipment, self.toggle_article, 7, i) evbox.add(label) grid.attach(evbox, 1, i, 1, 1) label = Gtk.Label(equipment["packaging"], xalign=0) label.get_style_context().add_class("item-cell") label.set_line_wrap(True) label.set_lines(1) label.set_line_wrap_mode(2) evbox = widgets.EventBox(equipment, self.toggle_article, 7, i) evbox.add(label) grid.attach(evbox, 2, i, 1, 1) # Get list of locations locations_len = len(equipment["locations"]) if locations_len == 0: locations_display = "" elif locations_len >= 1: equipment["locations"].sort() locations_display = equipment["locations"][0] if locations_len > 1: locations_display += ", ..." label = Gtk.Label(locations_display, xalign=0) label.set_line_wrap(True) label.set_lines(1) label.set_line_wrap_mode(2) label.get_style_context().add_class("item-cell") evbox = widgets.EventBox(equipment, self.toggle_article, 7, i) evbox.add(label) grid.attach(evbox, 3, i, 1, 1) # Get first expiry date date_display = "" if len(equipment["exp_dates"] ) > 0 and None not in equipment["exp_dates"]: date_display = min(equipment["exp_dates"]).strftime("%Y-%m-%d") label = Gtk.Label(date_display, xalign=0.5) label.get_style_context().add_class("item-cell") label.get_style_context().add_class("text-mono") if equipment["has_date_expired"]: label.get_style_context().add_class("article-expired") elif equipment["has_date_warning"]: label.get_style_context().add_class("article-warning") evbox = widgets.EventBox(equipment, self.toggle_article, 7, i) evbox.add(label) grid.attach(evbox, 4, i, 1, 1) label = Gtk.Label(xalign=0.5) label.set_markup("{0}<small>/{1}</small>".format( equipment["quantity"], equipment["required_quantity"])) label.get_style_context().add_class("item-cell") label.get_style_context().add_class("text-mono") # Change style if equipment has articles with non-conformity if equipment["has_nc"]: label.get_style_context().add_class("item-nc-quantity") # If quantity is less than required, affect corresponding style if equipment["quantity"] < equipment["required_quantity"]: label.get_style_context().add_class("article-expired") evbox = widgets.EventBox(equipment, self.toggle_article, 7, i) evbox.add(label) grid.attach(evbox, 5, i, 1, 1) # Set tooltip to give information on allowances requirements tooltip_text = [] for item in equipment["allowance"]: tooltip_text.append("<b>{0}</b> ({1})".format( item["name"], item["quantity"])) label.set_tooltip_markup("\n".join(tooltip_text)) if equipment["picture"]: # Button box for actions linked_btn = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL) linked_btn.get_style_context().add_class("linked") linked_btn.get_style_context().add_class( "equipment-item-buttons") evbox = widgets.EventBox(equipment, self.toggle_article, 7, i) evbox.add(linked_btn) grid.attach(evbox, 6, i, 1, 1) # Picture picture = equipment["picture"] btn_picture = widgets.ButtonWithImage( "image-x-generic-symbolic", tooltip=_("View picture"), connect=utils.picture_frame, data=picture) linked_btn.pack_end(btn_picture, False, True, 0) else: label = Gtk.Label("", xalign=0.5) label.get_style_context().add_class("item-cell") evbox = widgets.EventBox(equipment, self.toggle_article, 7, i) evbox.add(label) grid.attach(evbox, 6, i, 1, 1) # Toggle if active if toggle_row_num and toggle_equipment: self.toggle_article(source=None, grid=grid, equipment=toggle_equipment, row_num=toggle_row_num) query_count_all() return grid
def toggle_article(self, source, grid, equipment, row_num): # If already toggled, destroy the toggled part if self.toggled and self.toggled[0] > 0: # Remove the active-row CSS class of the parent item utils.grid_row_class(grid, self.toggled[0] - 1, 7, False) for i in range(self.toggled[1] - self.toggled[0] + 1): grid.remove_row(self.toggled[0]) # No need to recreate the widget, we just want to hide if row_num + 1 == self.toggled[0]: self.toggled = False return True # Add the active-row CSS class utils.grid_row_class(grid, row_num, 7) # Need to create the content new_row = row_num + 1 grid.insert_row(new_row) # Header row label = Gtk.Label(_("Commercial Name"), xalign=0) label.set_hexpand(True) label.get_style_context().add_class("article-header-cell") grid.attach(label, 0, 0 + new_row, 1, 1) label = Gtk.Label(_("Remarks"), xalign=0) label.get_style_context().add_class("article-header-cell") grid.attach(label, 1, 0 + new_row, 2, 1) label = Gtk.Label(_("Location"), xalign=0) label.get_style_context().add_class("article-header-cell") grid.attach(label, 3, 0 + new_row, 1, 1) label = Gtk.Label(_("Expiry"), xalign=0.5) label.get_style_context().add_class("article-header-cell") grid.attach(label, 4, 0 + new_row, 1, 1) label = Gtk.Label(_("Quantity"), xalign=0.5) label.get_style_context().add_class("article-header-cell") grid.attach(label, 5, 0 + new_row, 1, 1) label = Gtk.Label(_("Actions"), xalign=1) label.get_style_context().add_class("article-header-cell") grid.attach(label, 6, 0 + new_row, 1, 1) # Get related articles articles = equipment["articles"] i = new_row for article in articles: i += 1 grid.insert_row(i) label = Gtk.Label(article["name"], xalign=0) label.set_hexpand(True) label.get_style_context().add_class("article-item-cell-name") label.get_style_context().add_class("article-item-cell") grid.attach(label, 0, i, 1, 1) # Remark field (mainly used for non-compliance) remark_text = [] if article["nc_packaging"]: remark_text.append( NC_TEXT_TEMPLATE.format(_("Non-compliant packaging:"), article["nc_packaging"])) if article["remark"]: remark_text.append(article["remark"]) label = Gtk.Label(xalign=0) label.set_markup("\n".join(remark_text)) label.get_style_context().add_class("article-item-cell") label.get_style_context().add_class("article-remark") grid.attach(label, 1, i, 2, 1) label = Gtk.Label(xalign=0) label.get_style_context().add_class("article-item-cell") sequence = article["location"]["sequence"] if len(sequence) > 1: parents = " > ".join(sequence[:-1]) location_display = "<span foreground=\"#555\">{0} > </span>{1}".format( parents, sequence[-1]) else: location_display = sequence[0] label.set_markup(location_display) label.set_line_wrap(True) label.set_lines(1) label.set_line_wrap_mode(2) grid.attach(label, 3, i, 1, 1) if article["exp_date"]: label = Gtk.Label(article["exp_date"].strftime("%Y-%m-%d"), xalign=0.5) label.get_style_context().add_class("text-mono") else: label = Gtk.Label() label.get_style_context().add_class("article-item-cell") # If expiry is soon or due, affect corresponding style if article["expired"]: label.get_style_context().add_class("article-expired") elif article["warning"]: label.get_style_context().add_class("article-warning") grid.attach(label, 4, i, 1, 1) label = Gtk.Label(article["quantity"], xalign=0.5) label.get_style_context().add_class("article-item-cell") label.get_style_context().add_class("text-mono") grid.attach(label, 5, i, 1, 1) # Button box for actions linked_btn = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL) linked_btn.get_style_context().add_class("linked") linked_btn.get_style_context().add_class("article-item-buttons") # linked_btn.set_halign(Gtk.Align.END) grid.attach(linked_btn, 6, i, 1, 1) # Use if equipment["consumable"]: btn_use = widgets.ButtonWithImage("edit-redo-symbolic", tooltip=_("Use"), connect=self.dialog_use, data=article) linked_btn.pack_end(btn_use, False, True, 0) # Modify btn_modify = widgets.ButtonWithImage("document-edit-symbolic", tooltip=_("Modify"), connect=self.dialog_modify, data=article) linked_btn.pack_end(btn_modify, False, True, 0) # Delete btn_delete = widgets.ButtonWithImage("edit-delete-symbolic", tooltip=_("Delete"), connect=self.dialog_delete, data=article) btn_delete.get_style_context().add_class("article-btn-delete") linked_btn.pack_end(btn_delete, False, True, 0) i += 1 grid.insert_row(i) box = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL) button = Gtk.Button() label = Gtk.Label(_("Add an article"), xalign=0) button.add(label) button.set_relief(Gtk.ReliefStyle.NONE) button.get_style_context().add_class("article-btn-add") button.connect("clicked", self.dialog_add, equipment) box.add(button) box.get_style_context().add_class("article-item-cell-add") grid.attach(box, 0, i, 1, 1) # Empty row for styling purpose label = Gtk.Label("") label.get_style_context().add_class("article-item-cell-add") grid.attach(label, 1, i, 6, 1) grid.show_all() self.toggled = (new_row, i) query_count_all()
def toggle_item(self, source, grid, element, row_num, kit_id): # If already toggled, destroy the toggled part if self.toggled[kit_id] and self.toggled[kit_id][0] > 0: # Remove the active-row CSS class of the parent item utils.grid_row_class(grid, self.toggled[kit_id][0] - 1, 5, False) for i in range(self.toggled[kit_id][1] - self.toggled[kit_id][0] + 1): grid.remove_row(self.toggled[kit_id][0]) # No need to recreate the widget, we just want to hide if row_num + 1 == self.toggled[kit_id][0]: self.toggled[kit_id] = False return True # Add the active-row CSS class utils.grid_row_class(grid, row_num, 5) # Need to create the content new_row = row_num + 1 grid.insert_row(new_row) # Header row label = Gtk.Label(_("Commercial Name"), xalign=0) label.set_hexpand(True) label.get_style_context().add_class("article-header-cell") grid.attach(label, 0, 0 + new_row, 1, 1) label = Gtk.Label(_("Remarks"), xalign=0) label.get_style_context().add_class("article-header-cell") grid.attach(label, 1, 0 + new_row, 1, 1) label = Gtk.Label(_("Expiry"), xalign=0.5) label.get_style_context().add_class("article-header-cell") grid.attach(label, 2, 0 + new_row, 1, 1) label = Gtk.Label(_("Quantity"), xalign=0.5) label.get_style_context().add_class("article-header-cell") grid.attach(label, 3, 0 + new_row, 1, 1) label = Gtk.Label(_("Actions"), xalign=1) label.get_style_context().add_class("article-header-cell") grid.attach(label, 4, 0 + new_row, 1, 1) # Get related articles i = new_row for item in element["contents"]: i += 1 grid.insert_row(i) label = Gtk.Label(item["name"], xalign=0) label.set_hexpand(True) label.get_style_context().add_class("article-item-cell-name") label.get_style_context().add_class("article-item-cell") grid.attach(label, 0, i, 1, 1) # Remark field (mainly used for non-compliance) remark_text = [] if item["nc"]: nc_obj = json.loads(item["nc"]) if "packaging" in nc_obj and nc_obj["packaging"]: remark_text.append(NC_TEXT_TEMPLATE.format(_("Non-compliant packaging:"), nc_obj["packaging"])) if "composition" in nc_obj and nc_obj["composition"]: remark_text.append(NC_TEXT_TEMPLATE.format(_("Non-compliant composition:"), nc_obj["composition"])) if "molecule" in nc_obj and nc_obj["molecule"]: remark_text.append(NC_TEXT_TEMPLATE.format(_("Non-compliant molecule:"), nc_obj["molecule"])) if item["remark"]: remark_text.append(item["remark"]) label = Gtk.Label(xalign=0) label.set_markup("\n".join(remark_text)) label.get_style_context().add_class("article-item-cell") label.get_style_context().add_class("article-remark") grid.attach(label, 1, i, 1, 1) if item["exp_date"]: label = Gtk.Label(item["exp_date"].strftime("%Y-%m-%d"), xalign=0.5) label.get_style_context().add_class("text-mono") else: label = Gtk.Label() label.get_style_context().add_class("article-item-cell") # If expiry is soon or due, affect corresponding style if item["expired"]: label.get_style_context().add_class("article-expired") elif item["warning"]: label.get_style_context().add_class("article-warning") grid.attach(label, 2, i, 1, 1) label = Gtk.Label(item["quantity"], xalign=0.5) label.get_style_context().add_class("article-item-cell") label.get_style_context().add_class("text-mono") grid.attach(label, 3, i, 1, 1) # Button box for actions linked_btn = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL) linked_btn.get_style_context().add_class("linked") linked_btn.get_style_context().add_class("article-item-buttons") # linked_btn.set_halign(Gtk.Align.END) grid.attach(linked_btn, 4, i, 1, 1) # Use btn_use = widgets.ButtonWithImage("edit-redo-symbolic", tooltip="Use", connect=self.dialog_use, data=item) linked_btn.pack_end(btn_use, False, True, 0) # Modify btn_modify = widgets.ButtonWithImage("document-edit-symbolic", tooltip="Modify", connect=self.dialog_modify, data=(item, element["perishable"])) linked_btn.pack_end(btn_modify, False, True, 0) # Delete btn_delete = widgets.ButtonWithImage("edit-delete-symbolic", tooltip="Delete", connect=self.dialog_delete, data=item) btn_delete.get_style_context().add_class("article-btn-delete") linked_btn.pack_end(btn_delete, False, True, 0) i += 1 grid.insert_row(i) box = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL) button = Gtk.Button() label = Gtk.Label(_("Add an article"), xalign=0) button.add(label) button.set_relief(Gtk.ReliefStyle.NONE) button.get_style_context().add_class("article-btn-add") button.connect("clicked", self.dialog_add, element) box.add(button) box.get_style_context().add_class("article-item-cell-add") grid.attach(box, 0, i, 1, 1) # Empty row for styling purpose label = Gtk.Label("") label.get_style_context().add_class("article-item-cell-add") grid.attach(label, 1, i, 4, 1) grid.show_all() self.toggled[kit_id] = (new_row, i) query_count_all()
def build_grid(self, builder, data, toggle_row_num=None): grid = builder.get_object("grid") label = Gtk.Label(_("Name"), xalign=0) label.set_hexpand(True) label.get_style_context().add_class("header-cell") grid.attach(label, 0, 0, 2, 1) label = Gtk.Label(_("Expiry"), xalign=0.5) label.get_style_context().add_class("header-cell") grid.attach(label, 2, 0, 1, 1) label = Gtk.Label(_("Quantity"), xalign=0.5) label.get_style_context().add_class("header-cell") grid.attach(label, 3, 0, 1, 1) label = Gtk.Label("", xalign=0) label.get_style_context().add_class("header-cell") # Size request because by default the colum content is "hidden" label.set_size_request(125, -1) grid.attach(label, 4, 0, 1, 1) i = 0 toggle_item = None for element in data["elements"]: # log.debug(item) i += 1 if toggle_row_num and toggle_row_num == i: toggle_item = element label = Gtk.Label(element["name"], xalign=0) label.set_line_wrap(True) label.set_lines(1) label.set_line_wrap_mode(2) label.get_style_context().add_class("item-cell") evbox = widgets.EventBox(element, self.toggle_item, 5, i, data["id"]) evbox.add(label) grid.attach(evbox, 0, i, 2, 1) date_display = "" if len(element["exp_dates"]) > 0 and None not in element["exp_dates"]: date_display = min(element["exp_dates"]).strftime("%Y-%m-%d") label = Gtk.Label(date_display, xalign=0.5) label.get_style_context().add_class("item-cell") label.get_style_context().add_class("text-mono") if element["has_date_expired"]: label.get_style_context().add_class("article-expired") elif element["has_date_warning"]: label.get_style_context().add_class("article-warning") evbox = widgets.EventBox(element, self.toggle_item, 5, i, data["id"]) evbox.add(label) grid.attach(evbox, 2, i, 1, 1) label = Gtk.Label(xalign=0.5) label.set_markup("{0}<small>/{1}</small>".format(element["quantity"], element["required_quantity"])) label.get_style_context().add_class("item-cell") label.get_style_context().add_class("text-mono") # Change style if equipment has articles with non-conformity if element["has_nc"]: label.get_style_context().add_class("item-nc-quantity") # If quantity is less than required, affect corresponding style if element["quantity"] < element["required_quantity"]: label.get_style_context().add_class("article-expired") evbox = widgets.EventBox(element, self.toggle_item, 5, i, data["id"]) evbox.add(label) grid.attach(evbox, 3, i, 1, 1) # Set tooltip to give information on allowances requirements tooltip_text = [] for item in element["allowance"]: tooltip_text.append("<b>{0}</b> ({1})".format(item["name"], item["quantity"])) label.set_tooltip_markup("\n".join(tooltip_text)) if element["picture"]: # Button box for actions linked_btn = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL) linked_btn.get_style_context().add_class("linked") linked_btn.get_style_context().add_class("equipment-item-buttons") evbox = widgets.EventBox(element, self.toggle_item, 5, i, data["id"]) evbox.add(linked_btn) grid.attach(evbox, 4, i, 1, 1) # Picture picture = element["picture"] btn_picture = widgets.ButtonWithImage("image-x-generic-symbolic", tooltip=_("View picture"), connect=utils.picture_frame, data=picture) linked_btn.pack_end(btn_picture, False, True, 0) else: label = Gtk.Label("", xalign=0.5) label.get_style_context().add_class("item-cell") evbox = widgets.EventBox(element, self.toggle_item, 5, i, data["id"]) evbox.add(label) grid.attach(evbox, 4, i, 1, 1) # Toggle if active if toggle_row_num and toggle_item: self.toggle_item( source=None, grid=grid, element=toggle_item, row_num=toggle_row_num, kit_id=data["id"]) grid.show_all() query_count_all()