From c755ff3ba0889d3da7f8097f9175f482d78c56fe Mon Sep 17 00:00:00 2001 From: Matthias Clasen Date: Sat, 22 Jun 2019 04:38:16 +0000 Subject: scangobj: Introspect GTK4 actions GTK4 can define actions for widget classes. Write these out to a .actions file. --- gtkdoc/scangobj.py | 73 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 73 insertions(+) diff --git a/gtkdoc/scangobj.py b/gtkdoc/scangobj.py index 003c517..296fd85 100644 --- a/gtkdoc/scangobj.py +++ b/gtkdoc/scangobj.py @@ -100,6 +100,7 @@ const gchar *hierarchy_filename = "${new_hierarchy_filename}"; const gchar *interfaces_filename = "${new_interfaces_filename}"; const gchar *prerequisites_filename = "${new_prerequisites_filename}"; const gchar *args_filename = "${new_args_filename}"; +const gchar *actions_filename = "${new_actions_filename}"; static void output_signals (void); static void output_object_signals (FILE *fp, @@ -125,6 +126,9 @@ static void output_prerequisites (FILE *fp, static void output_args (void); static void output_object_args (FILE *fp, GType object_type); +static void output_actions (void); +static void output_object_actions (FILE *fp, GType object_type); + int main (${main_func_params}) { @@ -137,6 +141,7 @@ main (${main_func_params}) output_object_interfaces (); output_interface_prerequisites (); output_args (); + output_actions (); return 0; } @@ -565,6 +570,71 @@ output_prerequisites (FILE *fp, #endif } +static void +output_actions (void) +{ + FILE *fp; + gint i; + + fp = fopen (actions_filename, "w"); + if (fp == NULL) { + g_warning ("Couldn't open output file: %s : %s", actions_filename, g_strerror(errno)); + return; + } + + for (i = 0; object_types[i]; i++) { + output_object_actions (fp, object_types[i]); + } + + fclose (fp); +} + +static void +output_object_actions (FILE *fp, GType object_type) +{ + gpointer class; + + if (!G_TYPE_IS_OBJECT (object_type)) + return; + + class = g_type_class_peek (object_type); + if (!class) + return; + +#ifdef GTK_IS_WIDGET_CLASS +#if GTK_CHECK_VERSION(3,96,0) + if (GTK_IS_WIDGET_CLASS (class)) { + guint i = 0; + const char *action_name; + GType owner; + const GVariantType *parameter_type; + const char *property_name; + const gchar *object_class_name; + + object_class_name = g_type_name (object_type); + while (gtk_widget_class_query_action (GTK_WIDGET_CLASS (class), + i, + &owner, + &action_name, + ¶meter_type, + &property_name)) { + i++; + if (owner == G_TYPE_FROM_CLASS (class)) + fprintf (fp, "\\n" + "%s:::%s\\n" + "%s\\n" + "%s\\n" + "\\n\\n", + object_class_name, + action_name, + parameter_type ? g_variant_type_peek_string (parameter_type) : "", + property_name ? property_name : ""); + } + } +#endif +#endif +} + static void output_args (void) { @@ -1225,6 +1295,8 @@ def run(options): new_prerequisites_filename = base_filename + '.prerequisites.new' old_args_filename = base_filename + '.args' new_args_filename = base_filename + '.args.new' + old_actions_filename = base_filename + '.actions' + new_actions_filename = base_filename + '.actions.new' # generate a C program to scan the types @@ -1335,5 +1407,6 @@ def run(options): common.UpdateFileIfChanged(old_interfaces_filename, new_interfaces_filename, False) common.UpdateFileIfChanged(old_prerequisites_filename, new_prerequisites_filename, False) common.UpdateFileIfChanged(old_args_filename, new_args_filename, False) + common.UpdateFileIfChanged(old_actions_filename, new_actions_filename, False) return 0 -- cgit v1.2.1 From 3dc235b6fe1d2edcf1caa51e444b63319b7622a4 Mon Sep 17 00:00:00 2001 From: Matthias Clasen Date: Sun, 23 Jun 2019 04:10:01 +0000 Subject: mkdb: Generate sections for actions This is building on the work in the previous commit. The syntax chosen for doc comments is Class|action. We also need to allow periods in symbols, since those are commonly used to separate prefixes in action names. Here is a typical doc comment for an action: /** * GtkColorChooserWidget|color.select: * @red: the red value, between 0 and 1 * @green: the green value, between 0 and 1 * @blue: the blue value, between 0 and 1 * @alpha: the alpha value, between 0 and 1 * * Emits the #GtkColorChooser::color-activated signal for * the given color. */ --- gtkdoc/mkdb.py | 190 +++++++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 186 insertions(+), 4 deletions(-) diff --git a/gtkdoc/mkdb.py b/gtkdoc/mkdb.py index 87fdf24..f32fb1f 100644 --- a/gtkdoc/mkdb.py +++ b/gtkdoc/mkdb.py @@ -57,6 +57,11 @@ ArgBlurbs = [] # Docstring of the Arg. ArgDefaults = [] # Default value of the Arg. ArgRanges = [] # The range of the Arg type +ActionObjects = [] +ActionNames = [] +ActionParams = [] +ActionProperties = [] + # These global hashes store declaration info keyed on a symbol name. Declarations = {} DeclarationTypes = {} @@ -207,7 +212,7 @@ DB_REFENTRY = string.Template('''${header} ${short_desc} ${stability} -${functions_synop}${args_synop}${signals_synop}${object_anchors}${other_synop}${hierarchy}${prerequisites}${derived}${interfaces}${implementations} +${functions_synop}${args_synop}${signals_synop}${actions_synop}${object_anchors}${other_synop}${hierarchy}${prerequisites}${derived}${interfaces}${implementations} ${include_output} Description @@ -217,7 +222,7 @@ ${extralinks}${long_desc} Functions ${functions_details} -${other_desc}${args_desc}${signals_desc}${see_also} +${other_desc}${args_desc}${signals_desc}${actions_desc}${see_also} ''') @@ -285,6 +290,7 @@ def Run(options): ReadKnownSymbols(os.path.join(ROOT_DIR, MODULE + "-sections.txt")) ReadSignalsFile(os.path.join(ROOT_DIR, MODULE + ".signals")) ReadArgsFile(os.path.join(ROOT_DIR, MODULE + ".args")) + ReadActionsFile(os.path.join(ROOT_DIR, MODULE + ".actions")) obj_tree = ReadObjectHierarchy(os.path.join(ROOT_DIR, MODULE + ".hierarchy")) ReadInterfaces(os.path.join(ROOT_DIR, MODULE + ".interfaces")) ReadPrerequisites(os.path.join(ROOT_DIR, MODULE + ".prerequisites")) @@ -513,6 +519,8 @@ def OutputDB(file, options): args_desc = '' child_args_desc = '' style_args_desc = '' + actions_synop = '' + actions_desc = '' hierarchy_str = '' hierarchy = [] interfaces = '' @@ -627,6 +635,30 @@ def OutputDB(file, options): args_desc += make_refsect1_desc(style_args_desc, 'Style Property Details', section_id, 'style-property-details') + actions_synop = re.sub(r'^\n*', '', actions_synop) + actions_synop = re.sub(r'\n+$', '\n', actions_synop) + if actions_synop != '': + actions_synop = ''' +Actions + + + + + + +%s + + + + +''' % (section_id, actions_synop) + actions_desc = trim_leading_and_trailing_nl(actions_desc) + actions_desc = ''' +Action Details +%s + +''' % (section_id, actions_desc) + hierarchy_str = AddTreeLineArt(hierarchy) if hierarchy_str != '': hierarchy_str = make_refsect1_desc('' + hierarchy_str + '\n', @@ -657,6 +689,7 @@ def OutputDB(file, options): functions_details, other_desc, signals_synop, signals_desc, args_synop, args_desc, + actions_synop, actions_desc, hierarchy_str, interfaces, implementations, prerequisites, derived, @@ -683,6 +716,8 @@ def OutputDB(file, options): args_desc = '' child_args_desc = '' style_args_desc = '' + actions_synop = '' + actions_desc = '' hierarchy_str = '' hierarchy = [] interfaces = '' @@ -721,6 +756,7 @@ def OutputDB(file, options): sig_synop, sig_desc = GetSignals(symbol) arg_synop, child_arg_synop, style_arg_synop, arg_desc, child_arg_desc, style_arg_desc = GetArgs( symbol) + action_synop, action_desc = GetActions(symbol) ifaces = GetInterfaces(symbol) impls = GetImplementations(symbol) prereqs = GetPrerequisites(symbol) @@ -735,6 +771,8 @@ def OutputDB(file, options): args_desc += arg_desc child_args_desc += child_arg_desc style_args_desc += style_arg_desc + actions_synop += action_synop + actions_desc += action_desc interfaces += ifaces implementations += impls prerequisites += prereqs @@ -1123,6 +1161,7 @@ def OutputDeclaration(symbol, declaration): """ dtype = DeclarationTypes[symbol] + logging.info('Output Symbol: "%s" "%s"', symbol, dtype) if dtype == 'MACRO': return OutputMacro(symbol, declaration) elif dtype == 'TYPEDEF': @@ -2051,7 +2090,7 @@ def ParseStabilityLevel(stability, file, line, message): return str(stability) -def OutputDBFile(file, title, section_id, includes, functions_synop, other_synop, functions_details, other_desc, signals_synop, signals_desc, args_synop, args_desc, hierarchy, interfaces, implementations, prerequisites, derived, file_objects, default_stability): +def OutputDBFile(file, title, section_id, includes, functions_synop, other_synop, functions_details, other_desc, signals_synop, signals_desc, args_synop, args_desc, actions_synop, actions_desc, hierarchy, interfaces, implementations, prerequisites, derived, file_objects, default_stability): """Outputs the final DocBook file for one section. Args: @@ -2068,6 +2107,8 @@ def OutputDBFile(file, title, section_id, includes, functions_synop, other_synop signal_desc (str): the DocBook for the Signal Description part args_synop (str): the DocBook for the Arg Synopsis part args_desc (str): the DocBook for the Arg Description part + actions_synop (str): the DocBook for the Action Synopsis part + actions_desc (str): the DocBook for the Action Description part hierarchy (str): the DocBook for the Object Hierarchy part interfaces (str): the DocBook for the Interfaces part implementations (str): the DocBook for the Known Implementations part @@ -2187,6 +2228,8 @@ def OutputDBFile(file, title, section_id, includes, functions_synop, other_synop # "" OUTPUT.write(DB_REFENTRY.substitute({ + 'actions_desc': actions_desc, + 'actions_synop': actions_synop, 'args_desc': args_desc, 'args_synop': args_synop, 'derived': derived, @@ -3601,6 +3644,72 @@ def GetArgs(gobject): return (synop, child_synop, style_synop, desc, child_desc, style_desc) +def GetActions(gobject): + """Generate action docs. + + Returns the synopsis and detailed description DocBook output + for the actions of a given GtkWidget subclass. + + Args: + object (str): the GObject subclass, e.g. 'GtkButton'. + + Returns: + str: action docs + """ + synop = '' + desc = '' + + for i in range(len(ActionObjects)): + if ActionObjects[i] == gobject: + logging.info("Found action: %s", ActionNames[i]) + name = ActionNames[i] + params = ActionParams[i] + prop = ActionProperties[i] + + # Remember: pipe, so we don't clash with signals. + symbol = '%s|%s' % (gobject, name) + sid = common.CreateValidSGMLID(symbol) + + AllSymbols[symbol] = 1 + blurb = '' + if symbol in SymbolDocs and not IsEmptyDoc(SymbolDocs[symbol]): + blurb = ConvertMarkDown(symbol, SymbolDocs[symbol]) + logging.info(".. [%s][%s]", SymbolDocs[symbol], blurb) + AllDocumentedSymbols[symbol] = 1 + + else: + # FIXME: print a warning? + logging.info(".. no description") + + pad1 = '' + if len(name) < 24: + pad1 = " " * (24 - len(name)) + + action_synop = "%s%s\n" % ( + sid, name, params) + action_desc = u"The <literal>ā€œ%sā€</literal> action\n" % ( + sid, name) + action_desc += MakeIndexterms(symbol, sid) + action_desc += "\n" + action_desc += OutputSymbolExtraLinks(symbol) + if blurb != '': + action_desc += blurb + elif prop != '': + action_desc += "The %s action sets the %s property.\n" % (name, MakeHashXRef (gobject + ':' + prop, "type")) + action_desc += MakeDeprecationNote(symbol) + + if params != '': + action_desc += "Parameter type: %s\n" % params + + action_desc += OutputParamDescriptions("ACTION", symbol, None) + action_desc += OutputSymbolTraits(symbol) + action_desc += "\n" + + synop += action_synop + desc += action_desc + + return (synop, desc) + def IgnorePath(path, source_dirs, ignore_files): for sdir in source_dirs: # Cut off base directory @@ -3763,9 +3872,18 @@ def SegmentCommentBlock(lines, line_number=0, ifile=''): logging.info("scanning[%s] :%s", in_part, line.strip()) # If we haven't found the symbol name yet, look for it. + # We need to allow for the following cases: + # function: + # Class::signal: + # Class:property: + # Class|action: + # Signal and property names can contain dashes, action names + # can contain period. + # In all cases, there might be annotations in parentheses + # following the symbol name. if not symbol: m1 = re.search(r'^\s*((SECTION|PROGRAM):\s*\S+)', line) - m2 = re.search(r'^\s*([\w:-]*\w)\s*:?\s*(\(.+?\)\s*)*$', line) + m2 = re.search(r'^\s*([\w:.|-]*\w)\s*:?\s*(\(.+?\)\s*)*$', line) if m1: symbol = m1.group(1) logging.info("docs found in source for : '%s'", symbol) @@ -4664,6 +4782,70 @@ def ReadArgsFile(ifile): INPUT.close() +def ReadActionsFile(ifile): + """Reads information about object actions + + It creates the arrays ActionObjects, ActionNames, ActionParams + and ActionProperties containing info on the actions. + + Args: + ifile (str): the input filename. + """ + in_action = False + action_object = None + action_name = None + action_param = None + action_prop = None + + # Reset the args info. + ActionObjects[:] = [] + ActionNames[:] = [] + ActionParams[:] = [] + ActionProperties[:] = [] + + if not os.path.isfile(ifile): + return + + INPUT = open(ifile, 'r', encoding='utf-8') + line_number = 0 + for line in INPUT: + line_number += 1 + if not in_action: + if line.startswith(''): + in_action = True + action_object = '' + action_name = '' + action_param = '' + action_prop = '' + + else: + m1 = re.search(r'^(.*)', line) + m2 = re.search(r'^(.*)', line) + m3 = re.search(r'^(.*)', line) + if m1: + action_name = m1.group(1) + m1_1 = re.search(r'^(.*):::(.*)$', action_name) + if m1_1: + action_object = m1_1.group(1) + action_name = m1_1.group(2).replace('_', '-') + logging.info("Found action: %s", action_name) + else: + common.LogWarning(ifile, line_number, "Invalid action name: " + action_name) + + elif m2: + action_param = m2.group(1) + elif m3: + action_prop = m3.group(1) + elif re.search(r'^', line): + logging.info("Found end of action: %s::%s", action_object, action_name) + ActionObjects.append(action_object) + ActionNames.append(action_name) + ActionParams.append(action_param) + ActionProperties.append(action_prop) + in_action = False + + INPUT.close() + def AddTreeLineArt(tree): """Generate a line art tree. -- cgit v1.2.1 From 6357e9fc598c8e1eb46b04b8f5aa8377a3d9cb16 Mon Sep 17 00:00:00 2001 From: Matthias Clasen Date: Sun, 23 Jun 2019 04:11:57 +0000 Subject: Add actions to the navigation header --- gtk-doc.xsl | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/gtk-doc.xsl b/gtk-doc.xsl index 1a7a1ee..c5d3a9d 100644 --- a/gtk-doc.xsl +++ b/gtk-doc.xsl @@ -399,6 +399,7 @@ Get a newer version at http://docbook.sourceforge.net/projects/xsl/ + @@ -481,6 +482,12 @@ Get a newer version at http://docbook.sourceforge.net/projects/xsl/ + +   |  + + + +