Revision: 4640 http://geany.svn.sourceforge.net/geany/?rev=4640&view=rev Author: elextr Date: 2010-02-06 10:02:36 +0000 (Sat, 06 Feb 2010)
Log Message: ----------- Add design spec and a temporary Pyton prototype of the configure dialog for the build system.
Modified Paths: -------------- branches/bs2/ChangeLog
Added Paths: ----------- branches/bs2/doc/build_system_design_spec.html branches/bs2/scripts/build_dialog_prototype.py
Modified: branches/bs2/ChangeLog =================================================================== --- branches/bs2/ChangeLog 2010-02-06 06:58:57 UTC (rev 4639) +++ branches/bs2/ChangeLog 2010-02-06 10:02:36 UTC (rev 4640) @@ -1,3 +1,10 @@ +2010-02-06 Lex Trotman <elextr.at.gmail.dot.com> + + * doc/build_system_design_spec.html, scripts/build_dialog_prototype.py + Add design spec and a temporary Pyton prototype of the configure + dialog for the build system. + + 2010-02-01 Enrico Tröger <enrico(dot)troeger(at)uvena(dot)de>
* src/symbols.c:
Added: branches/bs2/doc/build_system_design_spec.html =================================================================== --- branches/bs2/doc/build_system_design_spec.html (rev 0) +++ branches/bs2/doc/build_system_design_spec.html 2010-02-06 10:02:36 UTC (rev 4640) @@ -0,0 +1,1743 @@ +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" + "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd"> +<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en"> +<head> +<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> +<meta name="generator" content="AsciiDoc 8.5.3" /> +<title>Geany Build System Changes</title> +<style type="text/css"> +/* Debug borders */ +p, li, dt, dd, div, pre, h1, h2, h3, h4, h5, h6 { +/* + border: 1px solid red; +*/ +} + +body { + margin: 1em 5% 1em 5%; +} + +a { + color: blue; + text-decoration: underline; +} +a:visited { + color: fuchsia; +} + +em { + font-style: italic; + color: navy; +} + +strong { + font-weight: bold; + color: #083194; +} + +tt { + color: navy; +} + +h1, h2, h3, h4, h5, h6 { + color: #527bbd; + font-family: sans-serif; + margin-top: 1.2em; + margin-bottom: 0.5em; + line-height: 1.3; +} + +h1, h2, h3 { + border-bottom: 2px solid silver; +} +h2 { + padding-top: 0.5em; +} +h3 { + float: left; +} +h3 + * { + clear: left; +} + +div.sectionbody { + font-family: serif; + margin-left: 0; +} + +hr { + border: 1px solid silver; +} + +p { + margin-top: 0.5em; + margin-bottom: 0.5em; +} + +ul, ol, li > p { + margin-top: 0; +} + +pre { + padding: 0; + margin: 0; +} + +span#author { + color: #527bbd; + font-family: sans-serif; + font-weight: bold; + font-size: 1.1em; +} +span#email { +} +span#revnumber, span#revdate, span#revremark { + font-family: sans-serif; +} + +div#footer { + font-family: sans-serif; + font-size: small; + border-top: 2px solid silver; + padding-top: 0.5em; + margin-top: 4.0em; +} +div#footer-text { + float: left; + padding-bottom: 0.5em; +} +div#footer-badges { + float: right; + padding-bottom: 0.5em; +} + +div#preamble { + margin-top: 1.5em; + margin-bottom: 1.5em; +} +div.tableblock, div.imageblock, div.exampleblock, div.verseblock, +div.quoteblock, div.literalblock, div.listingblock, div.sidebarblock, +div.admonitionblock { + margin-top: 1.0em; + margin-bottom: 1.5em; +} +div.admonitionblock { + margin-top: 2.0em; + margin-bottom: 2.0em; + margin-right: 10%; + color: #606060; +} + +div.content { /* Block element content. */ + padding: 0; +} + +/* Block element titles. */ +div.title, caption.title { + color: #527bbd; + font-family: sans-serif; + font-weight: bold; + text-align: left; + margin-top: 1.0em; + margin-bottom: 0.5em; +} +div.title + * { + margin-top: 0; +} + +td div.title:first-child { + margin-top: 0.0em; +} +div.content div.title:first-child { + margin-top: 0.0em; +} +div.content + div.title { + margin-top: 0.0em; +} + +div.sidebarblock > div.content { + background: #ffffee; + border: 1px solid silver; + padding: 0.5em; +} + +div.listingblock > div.content { + border: 1px solid silver; + background: #f4f4f4; + padding: 0.5em; +} + +div.quoteblock, div.verseblock { + padding-left: 1.0em; + margin-left: 1.0em; + margin-right: 10%; + border-left: 5px solid #dddddd; + color: #777777; +} + +div.quoteblock > div.attribution { + padding-top: 0.5em; + text-align: right; +} + +div.verseblock > pre.content { + font-family: inherit; +} +div.verseblock > div.attribution { + padding-top: 0.75em; + text-align: left; +} +/* DEPRECATED: Pre version 8.2.7 verse style literal block. */ +div.verseblock + div.attribution { + text-align: left; +} + +div.admonitionblock .icon { + vertical-align: top; + font-size: 1.1em; + font-weight: bold; + text-decoration: underline; + color: #527bbd; + padding-right: 0.5em; +} +div.admonitionblock td.content { + padding-left: 0.5em; + border-left: 3px solid #dddddd; +} + +div.exampleblock > div.content { + border-left: 3px solid #dddddd; + padding-left: 0.5em; +} + +div.imageblock div.content { padding-left: 0; } +span.image img { border-style: none; } +a.image:visited { color: white; } + +dl { + margin-top: 0.8em; + margin-bottom: 0.8em; +} +dt { + margin-top: 0.5em; + margin-bottom: 0; + font-style: normal; + color: navy; +} +dd > *:first-child { + margin-top: 0.1em; +} + +ul, ol { + list-style-position: outside; +} +ol.arabic { + list-style-type: decimal; +} +ol.loweralpha { + list-style-type: lower-alpha; +} +ol.upperalpha { + list-style-type: upper-alpha; +} +ol.lowerroman { + list-style-type: lower-roman; +} +ol.upperroman { + list-style-type: upper-roman; +} + +div.compact ul, div.compact ol, +div.compact p, div.compact p, +div.compact div, div.compact div { + margin-top: 0.1em; + margin-bottom: 0.1em; +} + +div.tableblock > table { + border: 3px solid #527bbd; +} +thead, p.table.header { + font-family: sans-serif; + font-weight: bold; +} +tfoot { + font-weight: bold; +} +td > div.verse { + white-space: pre; +} +p.table { + margin-top: 0; +} +/* Because the table frame attribute is overriden by CSS in most browsers. */ +div.tableblock > table[frame="void"] { + border-style: none; +} +div.tableblock > table[frame="hsides"] { + border-left-style: none; + border-right-style: none; +} +div.tableblock > table[frame="vsides"] { + border-top-style: none; + border-bottom-style: none; +} + + +div.hdlist { + margin-top: 0.8em; + margin-bottom: 0.8em; +} +div.hdlist tr { + padding-bottom: 15px; +} +dt.hdlist1.strong, td.hdlist1.strong { + font-weight: bold; +} +td.hdlist1 { + vertical-align: top; + font-style: normal; + padding-right: 0.8em; + color: navy; +} +td.hdlist2 { + vertical-align: top; +} +div.hdlist.compact tr { + margin: 0; + padding-bottom: 0; +} + +.comment { + background: yellow; +} + +.footnote, .footnoteref { + font-size: 0.8em; +} + +span.footnote, span.footnoteref { + vertical-align: super; +} + +#footnotes { + margin: 20px 0 20px 0; + padding: 7px 0 0 0; +} + +#footnotes div.footnote { + margin: 0 0 5px 0; +} + +#footnotes hr { + border: none; + border-top: 1px solid silver; + height: 1px; + text-align: left; + margin-left: 0; + width: 20%; + min-width: 100px; +} + + +@media print { + div#footer-badges { display: none; } +} + +div#toc { + margin-bottom: 2.5em; +} + +div#toctitle { + color: #527bbd; + font-family: sans-serif; + font-size: 1.1em; + font-weight: bold; + margin-top: 1.0em; + margin-bottom: 0.1em; +} + +div.toclevel1, div.toclevel2, div.toclevel3, div.toclevel4 { + margin-top: 0; + margin-bottom: 0; +} +div.toclevel2 { + margin-left: 2em; + font-size: 0.9em; +} +div.toclevel3 { + margin-left: 4em; + font-size: 0.9em; +} +div.toclevel4 { + margin-left: 6em; + font-size: 0.9em; +} +/* Workarounds for IE6's broken and incomplete CSS2. */ + +div.sidebar-content { + background: #ffffee; + border: 1px solid silver; + padding: 0.5em; +} +div.sidebar-title, div.image-title { + color: #527bbd; + font-family: sans-serif; + font-weight: bold; + margin-top: 0.0em; + margin-bottom: 0.5em; +} + +div.listingblock div.content { + border: 1px solid silver; + background: #f4f4f4; + padding: 0.5em; +} + +div.quoteblock-attribution { + padding-top: 0.5em; + text-align: right; +} + +pre.verseblock-content { + font-family: inherit; +} +div.verseblock-attribution { + padding-top: 0.75em; + text-align: left; +} + +div.exampleblock-content { + border-left: 3px solid #dddddd; + padding-left: 0.5em; +} + +/* IE6 sets dynamically generated links as visited. */ +div#toc a:visited { color: blue; } +</style> +<script type="text/javascript"> +/*<![CDATA[*/ +window.onload = function(){asciidoc.footnotes();} +var asciidoc = { // Namespace. + +///////////////////////////////////////////////////////////////////// +// Table Of Contents generator +///////////////////////////////////////////////////////////////////// + +/* Author: Mihai Bazon, September 2002 + * http://students.infoiasi.ro/~mishoo + * + * Table Of Content generator + * Version: 0.4 + * + * Feel free to use this script under the terms of the GNU General Public + * License, as long as you do not remove or alter this notice. + */ + + /* modified by Troy D. Hanson, September 2006. License: GPL */ + /* modified by Stuart Rackham, 2006, 2009. License: GPL */ + +// toclevels = 1..4. +toc: function (toclevels) { + + function getText(el) { + var text = ""; + for (var i = el.firstChild; i != null; i = i.nextSibling) { + if (i.nodeType == 3 /* Node.TEXT_NODE */) // IE doesn't speak constants. + text += i.data; + else if (i.firstChild != null) + text += getText(i); + } + return text; + } + + function TocEntry(el, text, toclevel) { + this.element = el; + this.text = text; + this.toclevel = toclevel; + } + + function tocEntries(el, toclevels) { + var result = new Array; + var re = new RegExp('[hH]([2-'+(toclevels+1)+'])'); + // Function that scans the DOM tree for header elements (the DOM2 + // nodeIterator API would be a better technique but not supported by all + // browsers). + var iterate = function (el) { + for (var i = el.firstChild; i != null; i = i.nextSibling) { + if (i.nodeType == 1 /* Node.ELEMENT_NODE */) { + var mo = re.exec(i.tagName); + if (mo && (i.getAttribute("class") || i.getAttribute("className")) != "float") { + result[result.length] = new TocEntry(i, getText(i), mo[1]-1); + } + iterate(i); + } + } + } + iterate(el); + return result; + } + + var toc = document.getElementById("toc"); + var entries = tocEntries(document.getElementById("content"), toclevels); + for (var i = 0; i < entries.length; ++i) { + var entry = entries[i]; + if (entry.element.id == "") + entry.element.id = "_toc_" + i; + var a = document.createElement("a"); + a.href = "#" + entry.element.id; + a.appendChild(document.createTextNode(entry.text)); + var div = document.createElement("div"); + div.appendChild(a); + div.className = "toclevel" + entry.toclevel; + toc.appendChild(div); + } + if (entries.length == 0) + toc.parentNode.removeChild(toc); +}, + + +///////////////////////////////////////////////////////////////////// +// Footnotes generator +///////////////////////////////////////////////////////////////////// + +/* Based on footnote generation code from: + * http://www.brandspankingnew.net/archive/2005/07/format_footnote.html + */ + +footnotes: function () { + var cont = document.getElementById("content"); + var noteholder = document.getElementById("footnotes"); + var spans = cont.getElementsByTagName("span"); + var refs = {}; + var n = 0; + for (i=0; i<spans.length; i++) { + if (spans[i].className == "footnote") { + n++; + // Use [\s\S] in place of . so multi-line matches work. + // Because JavaScript has no s (dotall) regex flag. + note = spans[i].innerHTML.match(/\s*\[([\s\S]*)]\s*/)[1]; + noteholder.innerHTML += + "<div class='footnote' id='_footnote_" + n + "'>" + + "<a href='#_footnoteref_" + n + "' title='Return to text'>" + + n + "</a>. " + note + "</div>"; + spans[i].innerHTML = + "[<a id='_footnoteref_" + n + "' href='#_footnote_" + n + + "' title='View footnote' class='footnote'>" + n + "</a>]"; + var id =spans[i].getAttribute("id"); + if (id != null) refs["#"+id] = n; + } + } + if (n == 0) + noteholder.parentNode.removeChild(noteholder); + else { + // Process footnoterefs. + for (i=0; i<spans.length; i++) { + if (spans[i].className == "footnoteref") { + var href = spans[i].getElementsByTagName("a")[0].getAttribute("href"); + href = href.match(/#.*/)[0]; // Because IE return full URL. + n = refs[href]; + spans[i].innerHTML = + "[<a href='#_footnote_" + n + + "' title='View footnote' class='footnote'>" + n + "</a>]"; + } + } + } +} + +} +/*]]>*/ +</script> +</head> +<body style="max-width:40em"> +<div id="header"> +<h1>Geany Build System Changes</h1> +<span id="author">Lex Trotman</span><br /> +<span id="email"><tt><<a href="mailto:geany-devel@uvena.de">geany-devel@uvena.de</a>></tt></span><br /> +<span id="revdate">January 2010</span> +</div> +<div id="content"> +<div id="preamble"> +<div class="sectionbody"> +<div class="paragraph"><p>This document describes the proposed changes to the Geany build system +specification and design. This document describes changes from the last +released version of Geany (0.18), but also reflects the lessons learned +from a first implementation attempt.</p></div> +</div> +</div> +<h2 id="_purpose">Purpose</h2> +<div class="sectionbody"> +<div class="paragraph"><p>The purpose of the changes is to improve the flexibility and +configurability of the actions performed by the Build menu.</p></div> +<div class="paragraph"><p>The main use cases which triggered the changes were:</p></div> +<div class="ulist"><ul> +<li> +<p> +support for running more genralised commands to support build tools + other than make +</p> +</li> +<li> +<p> +ability to store customisations in project files to support projects + using different tool sets +</p> +</li> +<li> +<p> +ability to set working directories for customised commands +</p> +</li> +<li> +<p> +GUI setup of all customisations +</p> +</li> +<li> +<p> +ability for plugins to affect the build process +</p> +</li> +</ul></div> +</div> +<h2 id="_requirements">Requirements</h2> +<div class="sectionbody"> +<h3 id="_operations">Operations</h3><div style="clear:left"></div> +<div class="paragraph"><p>Since the terms action, event, command etc. have specific meanings the +term <strong>operation</strong> will be used in this document to describe what happens +when a Build menu item is activated.</p></div> +<div class="paragraph"><p>An operation has a configurable label with mnemonic, to be shown on +the Build menu. The label must allow for translations to be provided +and an optional icon to be shown on the build menu and the toolbar.</p></div> +<div class="paragraph"><p>Other than this icon there is no interface between operations and +the toolbar, as the toolbar should work by activating the +appropriate Build menu item and so does not need an interface to +the operations.</p></div> +<div class="paragraph"><p>The Build menu must be able to trigger operations which are:</p></div> +<div class="ulist"><ul> +<li> +<p> +internal to the Geany or plugin code, initially: +</p> +<div class="ulist"><ul> +<li> +<p> +next error +</p> +</li> +<li> +<p> +previous error +</p> +</li> +<li> +<p> +show configuration dialog +</p> +</li> +</ul></div> +</li> +<li> +<p> +programs to be executed external to Geany. +</p> +</li> +</ul></div> +<div class="paragraph"><p>External operations must be able to configure the following attributes:</p></div> +<div class="ulist"><ul> +<li> +<p> +the command to be executed in a shell +</p> +</li> +<li> +<p> +a working directory where the command is to be executed +</p> +</li> +<li> +<p> +how the command output is handled: +</p> +<div class="ulist"><ul> +<li> +<p> +output parsed by Geany to the Build message tab (re-named + Compiler tab) and a regex must be configurable for that parsing (or + fallback to coded parsing ?still needed?) +</p> +</li> +<li> +<p> +output to a terminal (VTE or the configured terminal) +</p> +</li> +<li> +<p> +output to Geany’s terminal (or lost if Geany is started fron a + Gnome/KDE/Xfce etc menu) +</p> +</li> +</ul></div> +</li> +<li> +<p> +a menu label if the command is stopable, the menu item will change to + this label while the command is running and the icon will change to + the standard stop icon. Activating the menu item again will attempt + to stop the running command. +</p> +</li> +<li> +<p> +a sensitivity group, only one operation of a sensitivity group can + run at any time, all menu items with operations in the same group are + set insensitive while a command in the group is running. The menu + item which triggered the operation will also be insensitive if the + command is not stopable. +</p> +</li> +</ul></div> +<div class="paragraph"><p>All commands whose output is to be parsed will automatically be in +one sensitivity group so that only one parser stream is required at +any one time.</p></div> +<div class="paragraph"><p>An empty or undefined working directory is an error rather than +default to some value. This ensures that commands don’t accidently +do something you don’t want soemwhere you don’t want it.</p></div> +<div class="paragraph"><p>The command and working directory fields will accept the following +substitutions:</p></div> +<div class="ulist"><ul> +<li> +<p> +%c{…} - the text returned from a dialog box +</p> +</li> +<li> +<p> +%d - the full path of the directory of the current document +</p> +</li> +<li> +<p> +%e - the filename of the current document without extension +</p> +</li> +<li> +<p> +%f - the filename of the current document +</p> +</li> +<li> +<p> +%p - the project base path as configured in the open project +</p> +</li> +<li> +<p> +%s - the current file separator (i.e. %d%s%f = full path to the + current document) +</p> +</li> +</ul></div> +<div class="paragraph"><p>The substitutions %d, %e, %f will substitute nothing if there is no +current named document. The substitution %p will substitute +nothing if no project is open.</p></div> +<div class="paragraph"><p>The dialog box generated by %c will have the menu label as the +title, it will contain a text entry with the text inside the {} +displayed above the entry. The dialog will have an Ok button which +causes the text in the entry to replace the %c{..} and a Cancel +button which will replace the %c{…} with nothing. The dialog +will default to the last entry and remember previous entries. A missing +{} will display no text.</p></div> +<h3 id="_configuration_sources">Configuration Sources</h3><div style="clear:left"></div> +<div class="paragraph"><p>The configuration of operations must come from multiple sources:</p></div> +<div class="ulist"><ul> +<li> +<p> +defaults +</p> +</li> +<li> +<p> +system configuration files (installed with Geany) +</p> +</li> +<li> +<p> +user configuration files +</p> +</li> +<li> +<p> +the Geany program or plugins +</p> +</li> +</ul></div> +<div class="paragraph"><p>Each source must be able to provide configuration for a specific +filetype and for all filetypes not specifically configured.</p></div> +<div class="paragraph"><p>When more than one source has an operation configured for the same +build menu item the one that will be used is chosen using a simple +fixed priority order, from first choice to last:</p></div> +<div class="ulist"><ul> +<li> +<p> +configuration by Geany or a plugin for the filetype of the current + document +</p> +</li> +<li> +<p> +configuration by Geany or a plugin for any filetype +</p> +</li> +<li> +<p> +user configuration for the filetype of the current document +</p> +</li> +<li> +<p> +user configuration for any filetype +</p> +</li> +<li> +<p> +system configuration for the filetype of the current document +</p> +</li> +<li> +<p> +system configuration for any filetype +</p> +</li> +<li> +<p> +default values +</p> +</li> +</ul></div> +<div class="paragraph"><p>The first source with a configuration present will provide all +values, if a value is not set for an attribute in a configuration +then a blank string, off or the first of a list will be used as +appropraite to the type of attribute..</p></div> +<h3 id="_menu_layout">Menu Layout</h3><div style="clear:left"></div> +<div class="paragraph"><p>The build menu must be able to be organised in to several groups of +items with separators between them. Grouping similar operations +provides a better user experience in a menu which has the potential +to contain widely differing operations. The number of groups and +the number of operations in them must be configurable but a maximum +must be set at startup. The default and minimum will be 5 sections +sized from the top of the menu 3, 4, 2, 2, 1.</p></div> +<div class="paragraph"><p>The default menu layout is:</p></div> +<div class="ulist"><ul> +<li> +<p> +current file related operations section, language dependent e.g. for + the C language: +</p> +<div class="ulist"><ul> +<li> +<p> +Compile current file +</p> +</li> +<li> +<p> +Link current file +</p> +</li> +</ul></div> +</li> +<li> +<p> +multi file related operations section, language independent: +</p> +<div class="ulist"><ul> +<li> +<p> +Make +</p> +</li> +<li> +<p> +Make Custom Target +</p> +</li> +<li> +<p> +Make Object +</p> +</li> +</ul></div> +</li> +<li> +<p> +error navigation operations section: +</p> +<div class="ulist"><ul> +<li> +<p> +Next error +</p> +</li> +<li> +<p> +Previous error +</p> +</li> +</ul></div> +</li> +<li> +<p> +execution related operations section, language independent: +</p> +<div class="ulist"><ul> +<li> +<p> +Execute current file +</p> +</li> +</ul></div> +</li> +<li> +<p> +Configuration operations section: +</p> +<div class="ulist"><ul> +<li> +<p> +Show configuration dialog +</p> +</li> +</ul></div> +</li> +</ul></div> +<h3 id="_configuration">Configuration</h3><div style="clear:left"></div> +<div class="paragraph"><p>Other than the number of sections and their sizes, all configuration +shall be available from the GUI.</p></div> +<div class="paragraph"><p>Only one dialog shall be used for the whole menu. The dialog shall +indicate the form that the menu will take after the changes are applied.</p></div> +<div class="paragraph"><p>The dialog shall have more than one level of detail so that it will +not be overwhelming on first use.</p></div> +<div class="paragraph"><p>The dialog must be able to edit the configuration for user and +project sources for both the filetype of the current document and +the filetype independent settings. To prevent the filetype changing the +dialog may be modal.</p></div> +<div class="paragraph"><p>At full detail the dialog must be able to show other configuration +sources that may influence the operation that a menu item will +perform (eg system or default), however these cannot be changed by +the dialog.</p></div> +</div> +<h2 id="_design">Design</h2> +<div class="sectionbody"> +<h3 id="_menu_operation">Menu Operation</h3><div style="clear:left"></div> +<div class="paragraph"><p>Just call <tt>do_it</tt> on the appropriate current operation.</p></div> +<div class="paragraph"><p>Each menu item with a %c has a separate dialog memory.</p></div> +<h3 id="_addressing_menu_items">Addressing Menu Items</h3><div style="clear:left"></div> +<div class="paragraph"><p>Since the size of the sections of the menu can vary, just specifying +a number within the menu won’t work, enlarging a section would bring +the first item of the next section into the preceding section.</p></div> +<div class="paragraph"><p>So address by section number and item within section.</p></div> +<div class="paragraph"><p>Since section sizes differ an operation list will be an array of +pointers to arrays of pointers to operation objects, not a 2d array.</p></div> +<h3 id="_addressing_of_operations">Addressing of Operations</h3><div style="clear:left"></div> +<div class="paragraph"><p>Operation lists need to be addressed by current (ie which one is in use), +and by source. Sources have filetype independent and filetype dependent +contents.</p></div> +<div class="paragraph"><p>Operations are stored as lists addressed by menu item (ie section, +number).</p></div> +<div class="paragraph"><p>Current can be a build.c static operation list pointer, +<tt>current_operations</tt>. This is updated by the operation setter on +any change to an operation that might change which operation is +used for a menu item and is used to update the menu and to select +operation to run on activation.</p></div> +<div class="paragraph"><p>Filetype independent sources just need a build.c static pointer each, +<tt>internal_operations</tt>, <tt>project_operations</tt>, <tt>user_operations</tt>, +<tt>system_operations</tt>, <tt>default_operations</tt>.</p></div> +<div class="paragraph"><p>The simplest way of storing filetype dependent data is to add it to +the existing filetype structure. Add fields with names the same as +the first four above in the "plugins don’t use this" part of the +structure.</p></div> +<div class="paragraph"><p>For use outside build.c provide a function <tt>operation +*build_get_operations(source)</tt> and <tt>operation +*build_get_filetype_operations(source)</tt> where source is an enum.</p></div> +<div class="paragraph"><p>IF these are actually a performance problem they can be made macros but +since that would increase coupling, until proven guilty will be functions.</p></div> +<h3 id="_operation_object">Operation Object</h3><div style="clear:left"></div> +<div class="paragraph"><p>This is the main structure representing an operation. +Operation structure should be opaque with getter/setter. The setter +should trigger gui update if needed and therefore should be +multi-field. Updating all fields that are to change at once allows +consistency checking. Updating one field at a time may result in +inconsistent states between field updates, (ie update one field +creates an inconsistent state until another field is updated to +match) so it is difficult to know when it is safe to to check +consistency and when it is safe to update the GUI. Also batching reduces +the number of potential GUI updates.</p></div> +<div class="paragraph"><p>In C, typesafe variable argument calls are not possible, instead use +a transaction technique, ie <tt>start changes</tt>, <tt>change field</tt>, …, +<tt>apply</tt>. Having a start call ensures that here are no left over +changes hanging around, this is an error. Cancel instead of apply +is useful when UI cancel is activated so provide it.</p></div> +<div class="paragraph"><p>The change field call has two options:</p></div> +<div class="ulist"><ul> +<li> +<p> +the function specifies the field, eg <tt>change_field(operation *, + new_value)</tt>, or +</p> +</li> +<li> +<p> +the function specifies the data type, eg <tt>change_string(operation *, + enum field, new_value)</tt> +</p> +</li> +</ul></div> +<div class="paragraph"><p>The second option has fewer functions, (string, enum/integer, boolean vs +8-10 fields) and is as ABI conpatible as first if field enum is only +ever added to.</p></div> +<div class="paragraph"><p>The first option is shorter to call, and more similar to the GTK +interface and each function is shorter and independent so choose +first option. Getters the same way ie <tt>value_type +get_fieldname(operation *)</tt>.</p></div> +<div class="paragraph"><p>In the case of multiple changes during a transaction, most recent +wins.</p></div> +<div class="paragraph"><p>Implement by operation structure having a pointer to another +operation structure created by the <tt>start changes</tt> function. This +structure holds the changed structure values until <tt>apply</tt>ed. +<tt>apply</tt> promotes the new structure and frees the old operation +structure.</p></div> +<div class="paragraph"><p>Operation needs a <tt>deleted</tt> boolean field so delete is +<tt>apply</tt>able. It is the caller that decides to clear other fields +or not.</p></div> +<div class="paragraph"><p>Each field can have a callback specified to be called on change of that +field, signature <tt>on_change_func(operation *)</tt>. The pointer points to +the new operation structure not the old one. Set by <tt>on_change_func * +on_change_fieldname(on_change_func *)</tt> returns previous setting. +Used to trigger the configuration GUI update.</p></div> +<div class="paragraph"><p>Configure GUI (see below) needs to determine highest priority +operation based on changes made (but not necessarily applied) so +make that available as well, returns <tt>current_operations</tt> like list +but pointing to the new rather than current operations where they +are relevant, free after use.</p></div> +<div class="paragraph"><p>Sensitivity flag is needed for internals to set, gives feedback to +update_menu when Geany/plugins want some special sensitivity +behaviour.</p></div> +<div class="paragraph"><p>The operation object has a <tt>do_it</tt> function that performs the operation +and updates the menu sensitivities during and after the operation.</p></div> +<h3 id="_build_menu">Build Menu</h3><div style="clear:left"></div> +<div class="paragraph"><p>The build menu is an array of widgets (actually widget +pointers), note this includes separator widgets.</p></div> +<div class="paragraph"><p>Non-separator widgets need the following extra attributes:</p></div> +<div class="ulist"><ul> +<li> +<p> +section, item: for fast conversion to the operations list addressing +</p> +</li> +<li> +<p> +pointer to process data: process ID, sensitivity group, other data +</p> +</li> +<li> +<p> +pointer to operation for this item +</p> +</li> +</ul></div> +<h3 id="_sensitivity_group">Sensitivity Group</h3><div style="clear:left"></div> +<div class="paragraph"><p>Linked list linking items of same group so all their sensitivity is +controlled at once by <tt>set_sensitive</tt> and <tt>set_insensitive</tt> calls +on the group structure.</p></div> +<div class="paragraph"><p>For GUI purposes groups can have a name, but do not need to. The name +"Parsed" is reserved.</p></div> +<h3 id="_configure_gui">Configure GUI</h3><div style="clear:left"></div> +<div class="paragraph"><p>The configure GUI is a dialog with OK, apply, cancel buttons and an</p></div> +<div class="paragraph"><p>The dialog two panes, left one looks like the menu (as it will be when +the changes are applied) and is used to select the items to be +shown in the right pane. Only one item at a time can be selected +in the left hand pane and must stay selected, and separators must +not be selectable.</p></div> +<h4 id="_left_pane">Left Pane</h4> +<div class="paragraph"><p>Actually using a menu would give the best appearance, but menus do +not stay visible and keep the selection active so something else +must be used.</p></div> +<div class="paragraph"><p>Use a list with separators shown and single selection only.</p></div> +<div class="paragraph"><p>Model only needs two fields, a text field for the displayed label and +an integer which is the index to the build menu array above.</p></div> +<div class="paragraph"><p>Nothing in this list is editable, the label is updated when a change +field for a label is called.</p></div> +<h4 id="_right_pane">Right Pane</h4> +<div class="paragraph"><p>The right hand pane contains the operations from each source for the +menu item selected in the left pane and an advanced toggle button +and (when in advanced) a show all sources toggle button.</p></div> +<div class="paragraph"><p>Each operation has the fields defined below.</p></div> +<div class="paragraph"><p>The operations are stacked in the following order (priority by source):</p></div> +<div class="ulist"><ul> +<li> +<p> +internal - insensitive - S +</p> +</li> +<li> +<p> +project filetype xxx (if project open) - editable - N +</p> +</li> +<li> +<p> +project filetype independent (if project open) - editable -N +</p> +</li> +<li> +<p> +user filetype xxx - editable - N +</p> +</li> +<li> +<p> +user filetype independent - editable - N +</p> +</li> +<li> +<p> +system filetype xxx - insensitive - S +</p> +</li> +<li> +<p> +system filetype independent (config file?? or built-in default) - +insensitive - S +</p> +</li> +</ul></div> +<div class="paragraph"><p>The operations are each shown in a frame labelled with the source +and the list above indicates which are editable and which are shown +normally ( - N ) and which only when "Show all sources" is selected +( - S ). The frame will be different for the source which will be +used when changes are applied.</p></div> +<h5 id="_each_operation">Each Operation</h5> +<div class="paragraph"><p>All operations show a GUI form with the following fields. The +fields marked N show in normal and advanced mode, those marked A +are only shown in advanced mode:</p></div> +<div class="ulist"><ul> +<li> +<p> +label - text entry - N +</p> +</li> +<li> +<p> +icon - the current icon on a "change" button to call the <tt>select icon</tt> +dialog - N +</p> +</li> +<li> +<p> +internal or external command - combo box, "External" and the internal +commands - N +</p> +</li> +<li> +<p> +command - text entry - N +</p> +</li> +<li> +<p> +working Directory - text entry - N +</p> +</li> +<li> +<p> +output handling - combo box "Parsed", "Terminal" or "Geany Shell??" - A +</p> +</li> +<li> +<p> +stopable - check box - A +</p> +</li> +<li> +<p> +stop label - text entry, insensitive if unstopable - A +</p> +</li> +<li> +<p> +regular expression source - combo box "Filetype", the source this +operation is in, "Local" - A +</p> +</li> +<li> +<p> +regular expression value - entry, shows/edits the selected source - A +</p> +</li> +<li> +<p> +sensitivity group - combo box entry has "Parsed", "Single" and user +entries - A +</p> +</li> +<li> +<p> +clear - button removes the operation & defaults the dialog fields +</p> +<div class="dlist"><dl> +<dt class="hdlist1"> +Notes +</dt> +<dd> +<div class="olist arabic"><ol class="arabic"> +<li> +<p> +a better name needed for "Geany Shell" on the combo box +</p> +</li> +<li> +<p> +sensitivity group is forced to Parsed and set insensitive if +parsed output is chosen +</p> +</li> +<li> +<p> +A "single" sensitivity group means only this operation is a member +of an unnamed group +</p> +</li> +<li> +<p> +Sensitivity user group names are deleted when no operations are +members of the group. +</p> +</li> +</ol></div> +</dd> +</dl></div> +</li> +</ul></div> +<div class="paragraph"><p>In advanced mode the "show all sources" selection button is also shown.</p></div> +<h5 id="_select_icon">Select Icon</h5> +<div class="paragraph"><p>The select icon sub dialog displays the icons from +<tt>gtk_stock_list_ids</tt> in an iconview and a text entry +and file browse button calling the file chooser to choose an +external icon.</p></div> +<div class="paragraph"><p>This capability might not be in version one since it needs to be able to +interface to the toolbar to set the icons.</p></div> +<h3 id="_load_and_store">Load and Store</h3><div style="clear:left"></div> +<div class="paragraph"><p>Operations are stored in <tt>g_key_files</tt> which are <tt>key=value</tt> +formatted files with groups of keys separated by <tt>[groupname]</tt>.</p></div> +<div class="paragraph"><p>Build operations data should be in separate group(s) so as to not +interfere with other contents of the config file.</p></div> +<div class="paragraph"><p>The values have to be stored by:</p></div> +<div class="ulist"><ul> +<li> +<p> +fieldname +</p> +</li> +<li> +<p> +position in menu, ie section number and item number +</p> +</li> +<li> +<p> +for the project file only, optional filetype the entry relates to +</p> +</li> +<li> +<p> +language the entry relates to (labels are human readable so translatable) +</p> +</li> +</ul></div> +<div class="paragraph"><p>Thats five levels of structure, but key files have only two. So +allocate levels:</p></div> +<div class="ulist"><ul> +<li> +<p> +filetype (or no filetype) to group level, makes the the format of +each group the same +</p> +</li> +<li> +<p> +position and language to the key, locale dependent choice of key is +a built in keyfile capability +</p> +</li> +<li> +<p> +fieldname to the contents of the value, means one value per operation +so convert to/from string can be part of the operation object. +</p> +</li> +</ul></div> +<div class="paragraph"><p>The format will be:</p></div> +<div class="ulist"><ul> +<li> +<p> +for the groupname, start with <tt>build-operations</tt> followed by <em>-</em> +and the filetype if relevant. +</p> +</li> +<li> +<p> +for the key, since a key can’t start with a number, <em>s</em>, two digit +section number, <em>i</em>, two digit item number. Locale specifier can +follow. +</p> +</li> +<li> +<p> +for the value, since some config files are human edited make the format +slightly readable as a list of semicolon (;) separated entries consisting +of, two letter fieldname, <em>:</em>, field value. +</p> +</li> +</ul></div> +<div class="paragraph"><p>Fieldnames and value types are:</p></div> +<div class="tableblock"> +<table rules="all" +style="margin-left:auto; margin-right:auto;" +width="70%" +frame="border" +cellspacing="0" cellpadding="4"> +<col width="4%" /> +<col width="18%" /> +<col width="77%" /> +<tbody> +<tr> +<td align="center" valign="top"><p class="table">ic</p></td> +<td align="center" valign="top"><p class="table">String</p></td> +<td align="left" valign="top"><p class="table">Internal command, see below</p></td> +</tr> +<tr> +<td align="center" valign="top"><p class="table">lb</p></td> +<td align="center" valign="top"><p class="table">String</p></td> +<td align="left" valign="top"><p class="table">Menu label</p></td> +</tr> +<tr> +<td align="center" valign="top"><p class="table">cm</p></td> +<td align="center" valign="top"><p class="table">String</p></td> +<td align="left" valign="top"><p class="table">Command</p></td> +</tr> +<tr> +<td align="center" valign="top"><p class="table">wd</p></td> +<td align="center" valign="top"><p class="table">string</p></td> +<td align="left" valign="top"><p class="table">Working directory</p></td> +</tr> +<tr> +<td align="center" valign="top"><p class="table">op</p></td> +<td align="center" valign="top"><p class="table">Character</p></td> +<td align="left" valign="top"><p class="table">Output handling, see below</p></td> +</tr> +<tr> +<td align="center" valign="top"><p class="table">st</p></td> +<td align="center" valign="top"><p class="table">Boolean</p></td> +<td align="left" valign="top"><p class="table">Stopable</p></td> +</tr> +<tr> +<td align="center" valign="top"><p class="table">sl</p></td> +<td align="center" valign="top"><p class="table">String</p></td> +<td align="left" valign="top"><p class="table">Stop label</p></td> +</tr> +<tr> +<td align="center" valign="top"><p class="table">rs</p></td> +<td align="center" valign="top"><p class="table">Character</p></td> +<td align="left" valign="top"><p class="table">Regular expression source, see below</p></td> +</tr> +<tr> +<td align="center" valign="top"><p class="table">rv</p></td> +<td align="center" valign="top"><p class="table">String</p></td> +<td align="left" valign="top"><p class="table">Local regex value</p></td> +</tr> +<tr> +<td align="center" valign="top"><p class="table">sg</p></td> +<td align="center" valign="top"><p class="table">Integer or String</p></td> +<td align="left" valign="top"><p class="table">Sensitivity group, see below</p></td> +</tr> +</tbody> +</table> +</div> +<div class="paragraph"><p>Boolean data is a string with the first character t or f, the rest is +ignored, warning and the value false if not t or f.</p></div> +<div class="paragraph"><p>The following fields are encoded as specified:</p></div> +<div class="ulist"><ul> +<li> +<p> +ic: an identifying string, the following are reserved +</p> +<div class="ulist"><ul> +<li> +<p> +_x - external command +</p> +</li> +<li> +<p> +_n - next error +</p> +</li> +<li> +<p> +_p - previous error +</p> +</li> +<li> +<p> +_c - show config dialog +</p> +</li> +</ul></div> +</li> +<li> +<p> +op: character, one of +</p> +<div class="ulist"><ul> +<li> +<p> +p - parsed to build tab of mesage window +</p> +</li> +<li> +<p> +t - to the terminal +</p> +</li> +<li> +<p> +s - spawned, output to Geany’s terminal +</p> +</li> +</ul></div> +</li> +<li> +<p> +rs: character one of +</p> +<div class="ulist"><ul> +<li> +<p> +s - the source regex +</p> +</li> +<li> +<p> +f - the filetype regex +</p> +</li> +<li> +<p> +l - the local regex in the rv field +</p> +</li> +</ul></div> +</li> +<li> +<p> +sg: a string if named group, integer if unnamed, <tt>is_ascii_digit</tt> on +the first character to decide. +</p> +</li> +</ul></div> +<h4 id="_old_formats">Old Formats</h4> +<div class="paragraph"><p>The <tt>[build-menu]</tt> format of the current SVN will not be supported, +if there is sufficient demand a one-time conversion utility can be +produced.</p></div> +<div class="paragraph"><p>The <tt>[build-settings]</tt> format of 0.18 will be supported for read +only. It will only be used when the appropriate operation has not +been defined in the new format. It will be mapped to the current data +format as follows:</p></div> +<div class="ulist"><ul> +<li> +<p> +system and user filetype files: +</p> +<div class="ulist"><ul> +<li> +<p> +<tt>compiler</tt> - filetype operations section 0, item 0 +</p> +<div class="ulist"><ul> +<li> +<p> +ic = "_x" +</p> +</li> +<li> +<p> +lb = "_Compiler" +</p> +</li> +<li> +<p> +cm = the value +</p> +</li> +<li> +<p> +wd = "%d" +</p> +</li> +<li> +<p> +op = <em>p</em> +</p> +</li> +<li> +<p> +st = false +</p> +</li> +<li> +<p> +rs = <em>f</em> +</p> +</li> +<li> +<p> +sg = "Parsed" +</p> +</li> +</ul></div> +</li> +<li> +<p> +<tt>linker</tt> - filetype operations section 0, item 1 +</p> +<div class="ulist"><ul> +<li> +<p> +ic = "_x" +</p> +</li> +<li> +<p> +lb = "_Build" +</p> +</li> +<li> +<p> +cm = the value +</p> +</li> +<li> +<p> +wd = "%d" +</p> +</li> +<li> +<p> +op = <em>p</em> +</p> +</li> +<li> +<p> +st = false +</p> +</li> +<li> +<p> +rs = <em>f</em> +</p> +</li> +<li> +<p> +sg = "Parsed" +</p> +</li> +</ul></div> +</li> +<li> +<p> +<tt>run_cmd</tt> - filetype operations section 3, item 0 +</p> +<div class="ulist"><ul> +<li> +<p> +ic = "_x" +</p> +</li> +<li> +<p> +lb = "_Execute" +</p> +</li> +<li> +<p> +cm = the value +</p> +</li> +<li> +<p> +wd = "%d" +</p> +</li> +<li> +<p> +op = <em>t</em> +</p> +</li> +<li> +<p> +st = true +</p> +</li> +<li> +<p> +sl = "Stop" +</p> +</li> +<li> +<p> +sg = 1 +</p> +</li> +</ul></div> +</li> +<li> +<p> +<tt>error_regex</tt> - filetype regular expression +</p> +</li> +</ul></div> +</li> +<li> +<p> +user preferences: +</p> +<div class="paragraph"><p>If the <tt>make_cmd</tt> key is present the value will be used to create the +following operations if they don’t already exist in the user filetype +independent operations:</p></div> +<div class="ulist"><ul> +<li> +<p> +Section 1, item 0 - lb = "_Make", cm = value +</p> +</li> +<li> +<p> +Section 1, item 1 - lb = "Make Custom _Target", cm = value plus + " %c{Enter custom options here, all text will be passed to the Make + command}" +</p> +</li> +<li> +<p> +Section 1, item 2 - lb = "Make _Object", cm = value plus " %e.o" +</p> +</li> +</ul></div> +<div class="paragraph"><p>The rest of the fields have the values:</p></div> +<div class="ulist"><ul> +<li> +<p> +ic = "_x" +</p> +</li> +<li> +<p> +wd = "%d" +</p> +</li> +<li> +<p> +op = <em>p</em> +</p> +</li> +<li> +<p> +st = false +</p> +</li> +<li> +<p> +rs = <em>s</em> +</p> +</li> +<li> +<p> +sg = "Parsed" +</p> +</li> +</ul></div> +</li> +<li> +<p> +project files: +</p> +<div class="paragraph"><p>If the <tt>run_cmd</tt> key is present create the project filetype independent +section 3, item 0 operation if it doesn’t exist, with the fields:</p></div> +<div class="ulist"><ul> +<li> +<p> +ic = "_x" +</p> +</li> +<li> +<p> +lb = "_Execute" +</p> +</li> +<li> +<p> +cm = the value +</p> +</li> +<li> +<p> +wd = "%d" +</p> +</li> +<li> +<p> +op = <em>t</em> +</p> +</li> +<li> +<p> +st = true +</p> +</li> +<li> +<p> +sl = "Stop" +</p> +</li> +<li> +<p> +sg = 1 +</p> +</li> +</ul></div> +<div class="paragraph"><p>The <tt>make_in_base_path</tt> key does not map easily into the new system +since that assumes each source is independent, but this setting +exists in the project source and effects commands from the user +filetype independent source. Changing the working directory of +another source is hard to undo when the project is closed.</p></div> +<div class="paragraph"><p>Instead create operations in the project filetype independent source +which copy the same operation from the user filetype independent +source for section 1, items 0 to 2 only if they don’t exist in the +project filetype independent source and the matching user filetype +independent operation was created from the <tt>make_cmd</tt> key.</p></div> +</li> +</ul></div> +<h3 id="_default_operations">Default Operations</h3><div style="clear:left"></div> +<div class="paragraph"><p>Makes and internals</p></div> +</div> +</div> +<div id="footnotes"><hr /></div> +<div id="footer"> +<div id="footer-text"> +Last updated 2010-02-03 15:43:26 EST +</div> +</div> +</body> +</html>
Added: branches/bs2/scripts/build_dialog_prototype.py =================================================================== --- branches/bs2/scripts/build_dialog_prototype.py (rev 0) +++ branches/bs2/scripts/build_dialog_prototype.py 2010-02-06 10:02:36 UTC (rev 4640) @@ -0,0 +1,249 @@ +#!/usr/bin/env python +# +# geany.py +# +# Copyright 2010 Lex Trotman <elextr.at.gmail.dot.com> +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, +# MA 02110-1301, USA. + +import pygtk +pygtk.require('2.0') +import gtk +import pango + +def the_end(widget, data=None ): + gtk.main_quit() + +class data: + def __init__(self, name, ft, sens): + xp = 6 #padding + yp = 6 + self.frame = gtk.Frame( name + ft ) + self.tab = gtk.Table(6, 5, False) + self.tlab = gtk.Label("Type:") + self.tab.attach(self.tlab, 2,3,0,1) + self.ic = gtk.combo_box_new_text() + self.ic.append_text("External") + self.ic.append_text("Next Error") + self.ic.append_text("Prev Error") + self.ic.append_text("Show Config") + self.tab.attach(self.ic, 3,4,0,1) + self.llab = gtk.Label("Label:") + self.tab.attach(self.llab, 0,1, 0, 1,0,0, xpadding=xp,ypadding=yp) + self.lb = gtk.Entry() + self.tab.attach(self.lb, 1,2,0,1) + self.clab = gtk.Label("Command:") + self.tab.attach(self.clab, 0,1, 2,3,0,0, xpadding=xp,ypadding=yp) + self.cm = gtk.Entry() + self.tab.attach(self.cm, 1,5, 2,3) + self.wlab = gtk.Label("Working Dir:") + self.tab.attach(self.wlab, 0,1, 3,4,0) + self.wd = gtk.Entry() + self.tab.attach(self.wd, 1,5, 3,4) + self.olab = gtk.Label("Output:") + self.tab.attach(self.olab, 0,1, 4,5,0,0) + self.op = gtk.combo_box_new_text() + self.op.append_text("Parsed") + self.op.append_text("Terminal") + self.op.append_text("Shell") + self.tab.attach(self.op,1,2,4,5) + self.rlab = gtk.Label("Regex:") + self.tab.attach(self.rlab,2,3,4,5) + self.rs = gtk.combo_box_new_text() + self.rs.append_text("Local") + self.rs.append_text(name) + self.rs.append_text("From filetype") + self.tab.attach(self.rs,3,4,4,5) + self.rv = gtk.Entry() + self.tab.attach(self.rv,4,5,4,5) + self.st = gtk.CheckButton("Stopable") + self.tab.attach(self.st, 2,3,5,6) + self.slab = gtk.Label("Stop Label:") + self.tab.attach(self.slab,3,4,5,6) + self.sl = gtk.Entry() + self.tab.attach(self.sl, 4,5,5,6) + self.glab = gtk.Label("Group:") + self.tab.attach(self.glab, 0,1,5,6,0,0) + self.sg = gtk.combo_box_entry_new_text() + self.sg.append_text("Parsed") + self.sg.append_text("Single") + self.tab.attach(self.sg, 1,2,5,6) + self.sens = sens + if sens : + self.clr = gtk.Button(stock=gtk.STOCK_CLEAR) + self.tab.attach(self.clr, 4,5,0,1,0,0) + else: + self.frame.set_sensitive(False) + self.frame.add(self.tab) + + def advanced(self, val): + for w in [self.tlab, self.ic, self.olab, self.op, self.rlab, self.rs, self.rv, self.st, self.slab, self.sl, self.glab, self.sg]: + if val: + w.show_all() + else: + w.hide_all() + +class menu_list: + def is_separator(self, model, iter, data=None): + return model.get_value(iter,1)<0 + + def __init__(self): + self.store = gtk.ListStore(str, int) + self.store.append(["Compile", 0]) + self.store.append(["Build", 1]) + self.store.append(["", 2]) + self.store.append(["", -1]) + self.store.append(["Make", 3]) + self.store.append(["Make Custom Target",4]) + self.store.append(["Make Object", 5]) + self.store.append(["", 6]) + self.store.append(["", -1]) + self.store.append(["Next Error", 7]) + self.store.append(["Prev Error", 8]) + self.store.append(["",-1]) + self.store.append(["Execute", 9]) + self.store.append(["",10]) + self.store.append(["",-1]) + self.store.append(["Show Configure Dialog", 11]) + self.view = gtk.TreeView(self.store) + self.view.set_row_separator_func(self.is_separator) + self.col = gtk.TreeViewColumn("Menu", gtk.CellRendererText(), text=0) + self.view.append_column(self.col) + +class dialog: + def show_sources(self, widget, data=None): + val = widget.get_active() + for d in self.d: + if not d.sens: + if val: + d.frame.show_all() + else: + d.frame.hide_all() + + def advanced(self, widget, data=None): + val = widget.get_active() + self.shall.set_active(False) + self.show_sources(self.shall) + if self.proj: + self.dpf.advanced(val) + self.dp.advanced(val) + self.duf.advanced(val) + self.du.advanced(val) + if val: + self.shall.show() + else: + self.shall.hide() + + def show_as(self, proj): + self.proj = proj + if proj: + self.dpf.frame.show_all() + self.dp.frame.show_all() + else: + self.dpf.frame.hide_all() + self.dp.frame.hide_all() + self.advanced(self.adv) + ret = self.win.run() + self.win.hide() + return ret + + def __init__(self): + self.proj = True + self.win = gtk.Dialog("Build Menu Configuration", + None, + gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT, + ( gtk.STOCK_CANCEL, gtk.RESPONSE_REJECT, + gtk.STOCK_OK, gtk.RESPONSE_ACCEPT, + gtk.STOCK_APPLY, gtk.RESPONSE_ACCEPT)) + self.win.set_size_request(800,400) + self.panes = gtk.HPaned() + self.left = menu_list() + self.panes.pack1(self.left.view) + self.right = gtk.VBox() + self.d = [] + self.dif = data("Internal Preferences", " for Filetype XXX", False) + self.right.pack_start(self.dif.frame,False,False) + self.d.append(self.dif) + self.di = data("Internal Preferences", " Filetype Independent", False) + self.right.pack_start(self.di.frame,False,False) + self.d.append(self.di) + self.dpf = data("Project Preferences", " for Filetype XXX", True) + self.right.pack_start(self.dpf.frame,False,False) + self.d.append(self.dpf) + self.dp = data("Project Preferences", " Filetype Independent", True) + self.right.pack_start(self.dp.frame,False,False) + self.d.append(self.dp) + self.duf = data("User Preferences", " for Filetype XXX", True) + self.right.pack_start(self.duf.frame,False,False) + self.d.append(self.duf) + l = self.duf.frame.get_label_widget() + x = pango.AttrWeight(pango.WEIGHT_BOLD,0,len(l.get_label())) + a = pango.AttrList(); a.insert(x) + l.set_attributes(a) + self.du = data("User Preferences", " Filetype Independent", True) + self.right.pack_start(self.du.frame,False,False) + self.d.append(self.du) + self.dsf = data("System", " for Filetype XXX", False) + self.right.pack_start(self.dsf.frame,False,False) + self.d.append(self.dsf) + self.df = data("System", " Filetype Independent", False) + self.right.pack_start(self.df.frame,False,False) + self.d.append(self.df) + self.swin = gtk.ScrolledWindow() + self.swin.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC) + self.swin.add_with_viewport(self.right) + self.rt = gtk.VBox() + self.rt.pack_start(self.swin) + self.ba = gtk.HBox() + self.adv = gtk.ToggleButton("Advanced...") + self.ba.pack_start(self.adv, False, False) + self.adv.connect("toggled", self.advanced) + self.shall = gtk.ToggleButton("Show all Sources") + self.shall.connect("toggled", self.show_sources) + self.ba.pack_end(self.shall, False, False) + self.rt.pack_start(self.ba, False, False) + self.panes.pack2(self.rt) + self.panes.show_all() + self.win.vbox.pack_start(self.panes) + self.win.connect("destroy", the_end) + self.shall.set_active(False) + self.adv.set_active(False) + self.advanced(self.adv) + +the_dialog = None + +def show_dialog(widget, val): + global the_dialog + if the_dialog == None: + the_dialog = dialog() + print the_dialog.show_as(val) + +def main(): + win = gtk.Window(gtk.WINDOW_TOPLEVEL) + vb = gtk.VBox() + b1 = gtk.Button("Without a project open") + vb.pack_start(b1) + b2 = gtk.Button("With a project open") + vb.pack_start(b2) + b1.connect("clicked", show_dialog, False) + b2.connect("clicked", show_dialog, True) + win.add(vb) + win.connect("destroy", the_end) + win.show_all() + gtk.main() + return 0 + +if __name__ == '__main__': main()
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.