class _Commit(list): """ A convenience wrapper to create the tuples to pass to `GPS.VCS2_Task_Visitor.history_line` """ Kind = gs_utils.enum( HEAD=0, # current working dir LOCAL=1, # a local branch name exists for this commit REMOTE=2, # a remote branch name exists for this commit TAG=3) # a tag exists for this commit Flags = gs_utils.enum( UNPUSHED=2**1, # an unpushed local commit UNCOMMITTED=2**2) # uncommitted local changes def __init__(self, id, author, date, subject, parents, names=None, flags=0): """ :param str id: the unique id for the commit :param str author: the author of the commit :param str date: the date of the commit :param str subject: the first line of the commit message :param List(str) parents: a list of commit ids, the parents of the commit. There are multiple parents when this is a merge commit. :param List((str, GPS.VCS2.Commit.Kind)) names: a list of tag names or branch names associated with this commit. Each of the items indicates the type of the name :param GPS.VCS2.Commit.Flags: a combination of flags, which influence of the commit is represented in the History view. """ list.__init__(self, (id, author, date, subject, parents, names, flags)) @property def subject(self): return self[3] @subject.setter def set_subject(self, str): self[3] = str
class Search(Dialog): """ An interface for the Search dialog. It opens up the dialog, and then gets pointers to the various widgets into fields of Search. """ Context = gs_utils.enum(CURRENT_FILE="Current File", CURRENT_SELECTION="Current Selection", OPEN_FILES="Open Files", FILES="Files...", FILES_FROM_RUNTIME="Files From Runtime", FILES_FROM_PROJECT="Files From Projects") def open_and_yield(self, docked=False): """ Open the search dialog, and returns a handle to it. This is compatible with run_test_driver: editor = GPS.Search() yield editor.open_and_yield() """ yield self._open_and_yield("Search") if docked: self.dialog = GPS.MDI.get("Search").pywidget() else: self.dialog = get_window_by_prefix('GNAT Studio - Search -') if self.dialog: combos = get_widgets_by_type(Gtk.ComboBox, self.dialog) self.find = get_button_from_label("Find", self.dialog) self.find_all = get_button_from_label("Find All", self.dialog) self.next = self.find # This is in fact the same button self.replace = get_button_from_label("Replace", self.dialog) self.replace_all = get_button_from_label("Replace All", self.dialog) self.close = get_button_from_label("Close", self.dialog) self.replace_and_find = get_button_from_label( "Replace & Find", self.dialog) self.scope = get_widget_by_name("search scope combo", self.dialog) self.pattern = combos[0].get_child() self.replace_text = combos[1].get_child() self.look_in = combos[3] if len(combos) >= 4 else combos[2] self.previous = get_button_from_label("Previous", self.dialog) toggle_buttons = get_widgets_by_type(Gtk.ToggleButton, self.dialog) self.regexp = toggle_buttons[0] self.case = toggle_buttons[1] self.whole_word = toggle_buttons[2] # Disable confirmation dialog for 'Replace all' button GPS.Preference("Ask-Confirmation-For-Replace-All").set(False) def current_scope(self): """ Return the name of the current context """ return self.scope.get_model()[self.scope.get_active()][0] def set_scope(self, name): """ Select a specific scope. :param: either a string (the name to select) or one of the constants defined in Search.Context """ if isinstance(name, str): select_combo(self.scope, name) else: self.look_in.set_active_text(name) def yield_find(self): # Could open a modal dialog to warn that we reached the end yield idle_modal_dialog(self.find.clicked) def yield_find_all(self): yield idle_modal_dialog(self.find_all.clicked) def yield_replace(self): yield idle_modal_dialog(self.replace.clicked) def yield_replace_all(self): yield idle_modal_dialog(self.replace_all.clicked) def yield_replace_and_find(self): yield idle_modal_dialog(self.replace_and_find.clicked) def yield_close(self): self.close.clicked() yield wait_idle()
import gs_utils import workflows import time from workflows.promises import Promise from gi.repository import GLib import types import platform GPS.VCS2.Status = gs_utils.enum(NO_VCS=0, UNMODIFIED=2**0, MODIFIED=2**1, STAGED_MODIFIED=2**2, STAGED_ADDED=2**3, DELETED=2**4, STAGED_DELETED=2**5, STAGED_RENAMED=2**6, STAGED_COPIED=2**7, UNTRACKED=2**8, IGNORED=2**9, CONFLICT=2**10, LOCAL_LOCKED=2**11, LOCKED_BY_OTHER=2**12, NEEDS_UPDATE=2**13) # Valid statuses for files (they can be combined) GPS.VCS2.Actions = gs_utils.enum(DOUBLE_CLICK=0, TOOLTIP=1, ADD=2, REMOVE=3, RENAME=4)
class AnalysisReport(Dialog): FilterKind = gs_utils.enum(TOOL=0, SEVERITY=1, RULE=2) MessagesReportColumn = gs_utils.enum(ICON_NAME=0, ENTITY_ID=1, ENTITY_NAME=2, TOTAL=3) MetricsReportColumn = gs_utils.enum(NAME=0, VALUE=1) def open_and_yield(self, force=False): self.report_mdi = GPS.MDI.get("Analysis Report") if (self.report_mdi is None) or force: yield self._open_and_yield('gnathub display analysis') self.report_mdi = GPS.MDI.get("Analysis Report") self.report = self.report_mdi.pywidget() self.filters = GPS.MDI.get("Filters").pywidget() self.tools = get_widget_by_name('gnathub tools editor', self.filters) self.severities = get_widget_by_name('gnathub severities editor', self.filters) self.rules = get_widget_by_name('gnathub rules editor', self.filters) self.messages_report = get_widget_by_name('messages-report', self.report) self.metrics_report = get_widget_by_name('metrics-report', self.report) def yield_close(self): self.report_mdi.close() yield wait_idle() def __get_filters_tree(self, filter_kind): if filter_kind == AnalysisReport.FilterKind.TOOL: tree = get_widgets_by_type(Gtk.TreeView, self.tools)[0] elif filter_kind == AnalysisReport.FilterKind.SEVERITY: tree = get_widgets_by_type(Gtk.TreeView, self.severities)[0] else: tree = get_widgets_by_type(Gtk.TreeView, self.rules)[0] return tree def yield_toggle_filter(self, name, filter_kind): """ Toggle the filter identified by the given name and kind (eg: AnalysisReport.FilterKind.TOOL to toggle a tool filter). :param name: The name of the filter to toggle. :param kind: The filter's kind """ tree = self.__get_filters_tree(filter_kind) model = tree.get_model() for row in model: if row[0] == name: pygps.tree.click_in_tree(tree, row.path, column=0) return yield wait_tasks() def get_filters(self, filter_kind): """ Return the list of dictionaries representing the filters of the given kind. The returned dictionaries have the following form: {"name": string, "number": string, "state": bool} :param kind: The filter's kind """ model = self.__get_filters_tree(filter_kind).get_model() filters = [] for row in model: filters.append({"name": row[0], "number": row[1], "state": row[2]}) return filters def yield_select_in_messages(self, entity): """ Select the given entity in the message's report :param entity: The entity's name """ self.messages_report.get_selection().unselect_all() yield wait_idle() select_in_tree(self.messages_report, AnalysisReport.MessagesReportColumn.ENTITY_NAME, entity) yield wait_idle() def dump_filters(self, filter_kind): """ Dump the filters editor corresponding to the given kind. e.g: >>> report.dump_filters(AnalysisReport.FilterKind.TOOL) >>> [['codepeer', '5', True], ['gnatcheck', '1', True]] """ model = self.__get_filters_tree(filter_kind).get_model() return dump_tree_model(model, -1) def dump_messages_report(self, column): """ Dump the messages report of the given column. :param column: an AnalysisReport.MessagesReportColumn """ model = self.messages_report.get_model() return dump_tree_model(model, column) def dump_metrics_report(self, column): """ Dump the metrics report of the given column. :param column: an AnalysisReport.MetricsReportColumn """ model = self.metrics_report.get_model() return dump_tree_model(model, column) def get_messages_report_total(self): """ Return the total number of messages displayed in the messages report's first row. :return: An integer """ total_row = self.messages_report.get_model()[0] return total_row[AnalysisReport.MessagesReportColumn.TOTAL]