import logging import gi gi.require_version("Gtk", "3.0") from gi.repository import Gtk, Pango from ks_includes.screen_panel import ScreenPanel class Panel(ScreenPanel): def __init__(self, screen, title, **kwargs): title = title or _("license") super().__init__(screen, title) self.title_text = ( _("This device is not activated and is available for trial use only") + "\n" + _("Please enter a key to activate") ) self.key_len = 15 self.key_val_test = 1 self.key_val_add = 2 self.key_val_minus = 3 self.full = False self.interface = screen.license self.serial_num = self.interface.get_unique_id() or _("Unknown") self.is_active = self.interface.is_active() self.args = {} def update_time(self): total_printed_time = max(0, self.interface.get_total_printed_time()) trial_time = max(0, self.interface.get_trial_time()) remaining_time = max(0, trial_time - total_printed_time) self.license_box["elapsed_trial_time_value"].set_text(self.seconds_to_hms(total_printed_time)) self.license_box["trial_time_value"].set_text(self.seconds_to_hms(trial_time)) self.license_box["remain_time_value"].set_text(self.seconds_to_hms(remaining_time)) def seconds_to_hms(self, seconds): if not isinstance(seconds, (int, float)) or seconds < 0: raise ValueError(f"seconds must be a non-negative number, got {seconds}") hours, remainder = divmod(int(seconds), 3600) minutes, secs = divmod(remainder, 60) return f"{hours:03}:{minutes:02}:{secs:02}" def state_update(self, text): self.license_box["state_text_value"].set_text(text) def verify_key(self, key): try: res = self.interface.verify_activation_code(key) if res: if self.interface.is_active(): self.is_active = True self.state_update(_("Permanent Activation")) else: self.state_update(_("Key is valid")) else: self.state_update(_("Key is invalid")) except Exception as e: logging.exception(e) def active_refresh(self, **args): self.args["full"] = args.get("full") self.args["callback"] = args.get("func") self.args["file"] = args.get("file") self.args["onboarding"] = args.get("onboarding") self.display_dialog() def deactivate(self): self._screen.remove_keyboard() for child in self.content.get_children(): self.content.remove(child) def display_test_dialog(self, key_text=""): buttons = [ {"name": _("Add"), "response": self.key_val_add, "style": "dialog-secondary"}, {"name": _("Minus"), "response": self.key_val_minus, "style": "dialog-info"}, {"name": _("Close"), "response": Gtk.ResponseType.CLOSE, "style": "dialog-error"}, ] self.create_license_key_dialog(buttons=buttons, key=key_text) def display_dialog(self, full=False, key=""): BUTTON_CONFIGS = { "trial_with_callback": [ {"name": _("Activate"), "response": Gtk.ResponseType.OK, "style": "dialog-info"}, {"name": _("Skip"), "response": Gtk.ResponseType.CANCEL, "style": "dialog-error"}, ], "full_features": [ {"name": _("Test Mode"), "response": self.key_val_test, "style": "dialog-secondary"}, {"name": _("Activate"), "response": Gtk.ResponseType.OK, "style": "dialog-info"}, {"name": _("Close"), "response": Gtk.ResponseType.CLOSE, "style": "dialog-error"}, ], "Trial": [ {"name": _("Activate"), "response": Gtk.ResponseType.YES, "style": "dialog-info"}, {"name": _("Trial"), "response": Gtk.ResponseType.CLOSE, "style": "dialog-error"}, ], "default": [ {"name": _("Activate"), "response": Gtk.ResponseType.OK, "style": "dialog-info"}, {"name": _("Close"), "response": Gtk.ResponseType.CLOSE, "style": "dialog-error"}, ], } if self.args.get("callback") and self.interface.is_trial_active(): buttons = BUTTON_CONFIGS["trial_with_callback"] elif self.args.get("full"): buttons = BUTTON_CONFIGS["full_features"] elif self.args.get("onboarding"): buttons = BUTTON_CONFIGS["Trial"] else: buttons = BUTTON_CONFIGS["default"] self.create_license_key_dialog(buttons=buttons, key=key) def create_license_key_dialog(self, buttons=None, key=""): if buttons is None: buttons = [ {"name": _("Activate"), "response": Gtk.ResponseType.OK, "style": "dialog-info"}, {"name": _("Close"), "response": Gtk.ResponseType.CLOSE, "style": "dialog-error"}, ] self.title_label = Gtk.Label(hexpand=True, vexpand=False, wrap=True, wrap_mode=Pango.WrapMode.WORD_CHAR) self.title_label.set_markup(f"{self.title_text}\n") self.title_label.set_margin_top(50) self.title_label.set_margin_start(20) self.title_label.set_halign(Gtk.Align.START) self.license_box = {} self.grid = Gtk.Grid(column_spacing=20, row_spacing=20, hexpand=True, vexpand=True) def add_labeled_value(row, label_text, value_text): label = Gtk.Label(label=label_text, use_markup=True, xalign=0, wrap=True) value = Gtk.Label(label=value_text, use_markup=True, xalign=0, wrap=True) self.grid.attach(label, 0, row, 1, 1) self.grid.attach(value, 1, row, 1, 1) return label, value status_text = _("Not activated") if not self.interface.is_interface_valid(): status_text = _("Unknown") elif self.is_active: status_text = _("Permanent Activation") self.title_label.set_markup(f"{status_text}\n") self.license_box["state_text"], self.license_box["state_text_value"] = add_labeled_value( 0, _("State:"), status_text ) self.license_box["serial_num_text"], self.license_box["serial_num_value"] = add_labeled_value( 1, _("Serial Number:"), self.serial_num ) self.license_box["trial_time_text"], self.license_box["trial_time_value"] = add_labeled_value( 2, _("Trial Time:"), "000:00:00" ) self.license_box["elapsed_trial_time_text"], self.license_box["elapsed_trial_time_value"] = add_labeled_value( 3, _("Elapsed trial time:"), "000:00:00" ) self.license_box["remain_time_text"], self.license_box["remain_time_value"] = add_labeled_value( 4, _("Remaining Time:"), "000:00:00" ) self.license_box["key_text"] = Gtk.Label(label=_("Key:"), use_markup=True, xalign=0, wrap=True) self.grid.attach(self.license_box["key_text"], 0, 5, 1, 1) self.license_box["key_input"] = Gtk.Entry(hexpand=False, vexpand=False) self.license_box["key_input"].set_max_length(self.key_len) self.license_box["key_input"].set_text(key) self.license_box["key_input"].connect("button-press-event", self.on_show_keyboard) self.grid.attach(self.license_box["key_input"], 1, 5, 1, 1) image = self._gtk.Image("license", self._gtk.content_width * 0.4, self._gtk.content_height * 0.4) image.set_margin_start(60) image.set_margin_end(20) main_box = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, vexpand=True) horizontal_box = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL, vexpand=True) horizontal_box.set_margin_top(20) self.grid.set_margin_start(60) horizontal_box.pack_start(image, False, True, 0) horizontal_box.pack_start(self.grid, True, True, 0) main_box.pack_start(self.title_label, False, True, 0) main_box.pack_start(horizontal_box, True, True, 0) self.dialog = self._gtk.Dialog("License", buttons, main_box, self.confirm_license_response) self.update_time() def confirm_license_response(self, dialog, response_id): if response_id == Gtk.ResponseType.YES: if len(self.license_box["key_input"].get_text()) == 0: self.state_update(_("Key is empty")) return self.verify_key(self.license_box["key_input"].get_text()) self.update_time() if self.interface.is_active(): self._gtk.remove_dialog(dialog) self._screen._menu_go_back() elif response_id == Gtk.ResponseType.CLOSE: self._gtk.remove_dialog(dialog) self._screen._menu_go_back() elif response_id == Gtk.ResponseType.CANCEL: self._gtk.remove_dialog(dialog) self._screen._menu_go_back() if not self.interface.is_active() and self.interface.is_trial_active(): if self.args.get("callback"): self.args["callback"](self.args["file"]) elif response_id == Gtk.ResponseType.OK: if len(self.license_box["key_input"].get_text()) == 0: self.state_update(_("Key is empty")) return self.verify_key(self.license_box["key_input"].get_text()) self.update_time() elif response_id == self.key_val_test: if len(self.license_box["key_input"].get_text()) == 0: self.state_update(_("Key is empty")) return if self.interface.test_registration(self.license_box["key_input"].get_text()): self._gtk.remove_dialog(dialog) self.display_test_dialog() else: self.state_update(_("Key is invalid")) elif response_id == self.key_val_add: self.interface.add_registration_time() self.update_time() elif response_id == self.key_val_minus: self.interface.minus_registration_time() self.update_time() def on_show_keyboard(self, entry=None, event=None): self._gtk.remove_dialog(self.dialog) lbl = Gtk.Label(_("Please enter a key to activate"), halign=Gtk.Align.START, hexpand=False) self.labels["entry"] = Gtk.Entry(hexpand=True) self.labels["entry"].set_max_length(self.key_len) self.labels["entry"].connect("focus-in-event", self._screen.show_keyboard) save = self._gtk.Button("complete", _("Save"), "color3") save.set_hexpand(False) save.connect("clicked", self.on_save_key) input_box = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL, spacing=5) input_box.pack_start(self.labels["entry"], True, True, 5) input_box.pack_start(save, False, False, 5) self.labels["input_box"] = Gtk.Box( orientation=Gtk.Orientation.VERTICAL, spacing=5, hexpand=True, vexpand=True, valign=Gtk.Align.CENTER ) self.labels["input_box"].pack_start(lbl, True, True, 5) self.labels["input_box"].pack_start(input_box, True, True, 5) self.content.add(self.labels["input_box"]) self.labels["entry"].grab_focus_without_selecting() def on_save_key(self, dialog): key_text = self.labels["entry"].get_text() self._screen.remove_keyboard() for child in self.content.get_children(): self.content.remove(child) self.display_dialog(self.full, key=key_text)