def find_plugins(self, plugins_path): """ Find the plugins dir for the running configuration and read the metadata of plugins. Don't try to load actual python code yet :return: None """ if not plugins_path: return self.available_plugins = {} plugins_path = os.path.normpath(plugins_path) os.makedirs(plugins_path, exist_ok=True) sys.path.append(plugins_path) base_ends = len(plugins_path.split('/')) for root, dirs, files in os.walk(plugins_path): path_parts = root.split('/') if len(path_parts) == base_ends + 1 and not path_parts[base_ends].startswith('__') \ and 'plugin.json' in files: success = False try: plugin_file = open(root + '/plugin.json', 'r') data = json.load(plugin_file) plugin_file.close() success = True except: log.error(sys.exc_info()) print(sys.exc_info()) if success: mod_name = path_parts[base_ends] data['module_name'] = mod_name data['module_path'] = root self.available_plugins[mod_name] = data
def method(self, group_uid: str): """ Open group editing embed. :type group_uid: object """ if ctrl.ui.selection_group and ctrl.ui.selection_group.uid == group_uid: group = ctrl.ui.selection_group elif group_uid in ctrl.forest.groups: group = ctrl.forest.groups[group_uid] else: log.error(f'No such group: {group_uid}.') return ctrl.ui.toggle_group_label_editing(group)
def method(self, edge_uid: str): """ Remove connection between two nodes, this is triggered from the edge. :return: None """ try: edge = ctrl.forest.edges[edge_uid] except KeyError: log.error(f'No such edge: {edge_uid}.') return ctrl.drawing.disconnect_edge(edge) ctrl.ui.update_selections() ctrl.forest.forest_edited()
def action_finished(self, m='', undoable=True, error=None): """ Write action to undo stack, report back to user and redraw trees if necessary :param m: message for undo :param undoable: are we supposed to take a snapshot of changes after this action. :param error message """ if error: log.error(error) elif m: log.info(m) if ctrl.action_redraw: ctrl.forest.draw() if undoable and not error: ctrl.forest.undo_manager.take_snapshot(m) ctrl.graph_scene.start_animations() ctrl.ui.update_actions()
def activate_color_theme(self, theme_key, try_to_remember=True): """ Prepare root color (self.hsv), depending on what kind of color settings are active :param theme_key: :param try_to_remember: bool -- try to restore the previous base color, effective only for randomising palettes. """ self.theme_key = theme_key if theme_key in self.default_themes: data = self.default_themes[theme_key] elif theme_key in self.custom_themes: data = self.custom_themes[theme_key] else: self.theme_key = self.default data = self.default_themes[self.theme_key] log.error(f'Unable to find color theme "{theme_key}"') self.hsv = data.get('hsv', [0.00, 0.29, 0.35]) # dark rose) contrast = data.get('contrast', 55) faded = data.get('faded', False) bw = data.get('bw', False) colors = data.get('colors', None) build = data.get('build', '') if build == 'solarized_lt': self.build_solarized(light=True) return elif build == 'solarized_dk': self.build_solarized(light=False) return elif build == 'random': found = False if try_to_remember: remembered = ctrl.settings.get( 'last_key_colors') # found from forest's settings if theme_key in remembered: self.hsv = list(remembered[theme_key]) found = True if not found: lu_min = data.get('lu_min', 25) lu = 101 lu_max = data.get('lu_max', 95) while not (lu_min < lu < lu_max): r = random.random() g = random.random() b = random.random() hu, su, lu = rgb_to_husl(r, g, b) key_color = c.fromRgbF(r, g, b) self.hsv = list(key_color.getHsvF())[:3] if ctrl.forest: remembered = ctrl.settings.get('last_key_colors') if remembered: remembered[theme_key] = self.hsv else: remembered = {theme_key: self.hsv} ctrl.settings.set('last_key_colors', remembered, level=FOREST) if colors: for key, (r, g, b, a) in colors.items(): color = c.fromRgbF(r, g, b) color.setAlphaF(a) self.d[key] = color color = self.d['content1'] self.current_hex = color.name() self.hsv = list(color.getHsvF())[:3] self.gradient.setColorAt(1, self.d['background1']) self.gradient.setColorAt(0, self.d['background1'].lighter()) self.background_lightness = self.d['background1'].lightnessF() else: self.compute_palette(self.hsv, contrast=contrast, faded=faded)
def run(self, *args, fetch_params=True, print_command=True, **kwargs): """ Trigger action with parameters received from action data object and designated UI element :return: None """ if not self.isEnabled(): return # Prepare to use alt_command in feedback if the action supports it command = self.command if self.isCheckable() and self.isChecked() and self.command_alt: command = self.command_alt # -- Redraw and undo flags: these are on by default, can be switched off by action method ctrl.action_redraw = True # Disable undo if necessary if not self.undoable: ctrl.disable_undo() self.autoplay = True # manually given commands have their parameters, and the command prompt has taken # care for logging them. Commands run by UI triggers use a helper method # 'prepare_parameters' to set args before running the command. The command being run # is logged and made available in command prompt so that the user has better grasp of # inner workings of Kataja. if fetch_params: args, kwargs = self.prepare_parameters(args, kwargs) if print_command: # Print the command into console m = super(self.__class__, self) if m.method == self.method and m.k_action_uid: action_name = m.k_action_uid else: action_name = self.k_action_uid arg_parts = [repr(a) for a in args] kwarg_parts = [f'{key}={repr(value)}' for key, value in kwargs.items()] command_string = action_name + '(' + ', '.join(arg_parts + kwarg_parts) + ')' log.info('>>> ' + command_string) log.log_handler.add_to_command_backlog(command_string) try: message = self.method(*args, **kwargs) error = None except: message = '' error = "Action %r ('%s')<br/>" % (self, self.key) error += '<br/>'.join(traceback.format_exception(*sys.exc_info())) log.error("Unexpected error: %s" % str(sys.exc_info())) traceback.print_exc() # Restore undo state to what it was if not self.undoable: ctrl.resume_undo() if self.disable_undo_and_message: ctrl.main.action_finished(undoable=False, play=self.autoplay) else: sc = self.shortcut() if sc: sc = sc.toString() sc = sc.replace('Ctrl', running_environment.cmd_or_ctrl) reply = f'({sc}) {message or command}' else: reply = message ctrl.main.action_finished(m=reply, undoable=self.undoable and not ctrl.undo_disabled, error=error, play=self.autoplay)
def activate_color_theme(self, theme_key, try_to_remember=True): """ Prepare root color (self.hsv), depending on what kind of color settings are active :param theme_key: :param try_to_remember: bool -- try to restore the previous base color, effective only for randomising palettes. """ self.theme_key = theme_key if theme_key in self.default_themes: data = self.default_themes[theme_key] elif theme_key in self.custom_themes: data = self.custom_themes[theme_key] else: self.theme_key = self.default data = self.default_themes[self.theme_key] log.error(f'Unable to find color theme "{theme_key}"') self.hsv = data.get('hsv', [0.00, 0.29, 0.35]) # dark rose) contrast = data.get('contrast', 55) faded = data.get('faded', False) bw = data.get('bw', False) colors = data.get('colors', None) build = data.get('build', '') if build == 'solarized_lt': self.build_solarized(light=True) return elif build == 'solarized_dk': self.build_solarized(light=False) return elif build == 'random': found = False if try_to_remember: remembered = ctrl.settings.get('last_key_colors') # found from forest's settings if theme_key in remembered: self.hsv = list(remembered[theme_key]) found = True if not found: lu_min = data.get('lu_min', 25) lu = 101 lu_max = data.get('lu_max', 95) while not (lu_min < lu < lu_max): r = random.random() g = random.random() b = random.random() hu, su, lu = rgb_to_husl(r, g, b) key_color = c.fromRgbF(r, g, b) self.hsv = list(key_color.getHsvF())[:3] if ctrl.forest: remembered = ctrl.settings.get('last_key_colors') if remembered: remembered[theme_key] = self.hsv else: remembered = {theme_key: self.hsv} ctrl.settings.set('last_key_colors', remembered, level=FOREST) if colors: for key, (r, g, b, a) in colors.items(): color = c.fromRgbF(r, g, b) color.setAlphaF(a) self.d[key] = color color = self.d['content1'] self.current_hex = color.name() self.hsv = list(color.getHsvF())[:3] self.gradient.setColorAt(1, self.d['background1']) self.gradient.setColorAt(0, self.d['background1'].lighter()) else: self.compute_palette(self.hsv, contrast=contrast, faded=faded)