- ##Page is Developers' Guide to
<subtitle>Making Software Changes</subtitle> <articleinfo><corpauthor>OpenMFG, LLC</corpauthor><pubdate>$Date: 2008/03/12 15:39:26 $</pubdate><edition>cvs $Revision: 1.9 $</edition><copyright><year>2007</year><holder>OpenMFG, LLC</holder></copyright></articleinfo> This document describes the core development guidelines for contributing to the <orgname>xTuple</orgname> development effort. It assumes very little about software development experience but is not a tutorial for software development, software development tools, or programming languages. Most of the content will be familiar to experienced software developers.
The current draft is aimed at employees of <orgname>xTuple</orgname> working internally. Future versions will address the processes for customer, reseller, and third-party contributions.
The reader should read and follow the steps outlined in the OpenMFG Developers' Guide to Configuring a Development Environment before continuing with the steps below. The configuration document describes what tools you will need and how to obtain and install them.
Conventions:To contribute to the OpenMFG development effort, you must contact Trolltech and get a commercial license for Qt.
- Type this exactly as you see it
- The value that you type is dependent on your environment
The path to reach a certain file or directory. This may be a full- or relative-path. If the path starts with a slash (<literal>/</literal>) then you must specify the full path (this is rare).
- $ is the prompt and stuff is what you type after it
\
Programming and command line examples may be too long to fit across a printed page. In these cases a line of text in this document might end with a backslash character ('\'). This indicates that the next line of text in this document is part of the line ending with the backslash and should be typed without using the <keysym>Enter</keysym> or <keysym>Return</keysym> key and without the backslash.
Introductory Concepts
master copy of something vs. the copy that's actually used
the appropriate place(s) to make a change visible
what is part of the product and what is not
bug tracking
what are SVN and CVS?
SVN repository holds xtuple, xtupledocs, xtupleserver, updater, csvimport on SourceForge
CVS repository holds OpenRPT on SourceForge
Read-access to the SourceForge repositories is available to everyone while write/commit access is restricted. If you want commit access, please contact xTuple.
There is a private repository for OpenMFG client and server files
how we use CVS and SVN: if you check in, everyone sees it when they update
naming conventions
backing out changes if you've really screwed up
if it's broke, fix it; if it ain't broke, don't break it
use the language to simplify
images in the application
Changes that are not to be part of the xTuple ERP Product
one-off changes vs. experimental work vs. not generally applicable
don't do it - maintenance - but if you must, create your own CVS or SVN repository for your own work and keep each feature or bug-fix isolated to individual checkins. There are strategies for updating your own repository from a master and keeping your changes.
Fixing Bugs
reproduce
confirm
assign
resolve - checkin as few times as possible (combine contents of multiple directories) and the comment should include "fixes bug #12345" or "fixes issue #12345" if it really fixes the problem, or leave off the word "fixes" if it's only part of the solution, such as an intermediate checkin. This wording automatically updates the Mantis issue, adding a note in all of these cases and actually marking the issue as resolved if the comment includes the word "fixes". Note that the # symbol is significant, as is the fact that there should be no space between the # and the issue number.
close
Adding Features
understand
add issue
spec
implement
resolve
accept
close
Regardless of language or part of the application
Some Guidelines:
- If the code you're changing is broken (in some way other than what you're trying to change or fix), fix it anyway. There are only two exceptions:
- You know for a fact that someone else is working on fixing this problem.
- The product is approaching final release, as in you are making changes to a late beta release, a release candidate, or a final build.
If you are making additions to existing code, integrate your changes with the existing code. For example, if an existing stored procedure manipulates work orders with a status of Open and Exploded and you are trying to make it do the same thing with Imploded work orders, don't do this: IF (_statusVar IN (''O'', ''E'') THEN -- existing ... -- existing ELSEIF (_statusVar = ''I'') THEN same ... -- duplicated code: Bad Programmer! BRBRDo this instead: IF (_statusVar IN (''O'', ''E'', ''I'') THEN ...
Changing Reports
Master copies of all reports live in the share/reports subdirectory of the xtuple repository.
<literal>svn update</literal> your <literal>xtuple</literal> repository checkout
Load reportname.xml into the database
- Make and test your changes
- Save your changes to the database as level 0 of the report
Save your changes to .../OpenMFG/ReportDefinitions/OpenMFG/reportname.xml
- If you had to use a level other than 0 for testing, remove the non-level 0 copy of the report from the database.
<literal>svn diff <replaceable>reportname</replaceable>.xml</literal> and review the changes manually to make sure they look right
<literal>svn commit <replaceable>reportname</replaceable>.xml</literal>BRBRPut a short description of why you made this change in your checkin comment, including the Mantis issue number if there is one. The 'what' is clear from the differences between the previous version and what you checked in.
If this change is related to a Mantis issue, see the <link>Fixing Bugs</link> or <link>Adding Features</link> sections for further guidance.
Changing the GUI Client
One of the things we're trying to do to the existing code in OpenMFG is move the SQL out of the source code, particularly the more complex MetaSQL queries, and into a separate resource file. This will eventually allow for patching some bugs without shipping whole binary packages, sharing queries between source files, and other neat things. To implement queries as resources:
<literal>cd xtuple/guiclient</literal>
edit <literal>sql/<replaceable>file</replaceable>.mql</literal>BRBRwhere <literal><replaceable>file</replaceable></literal> = the name of the class followed by a simplified version of the method name from which the query is called, e.g. <literal>dspShipmentsByDateFillList.mql</literal> holds the query called by the <literal>sFillList()</literal> method in the <literal>dspShipmentsByDate.cpp</literal> source file. Put the query, including MetaSQL tags if necessary, in this <literal>.mql</literal> file.
add 3 lines to sql/OpenMFGQueryData.qrcBRBR <qresource prefix="module"> <file alias="/pseudo-path/nameofquery.mql">file.mql</file> <qeresource> <parameter>The <literal>module</literal> value for the <literal>prefix</literal> attribute should be the same as the prefix of the action name used to create the calling window in the menu structure (see elsewhere for action names).</parameter>BRBR<parameter>The <literal>pseudo-path</literal> should approximate the menu structure followed to get to the calling window.</parameter>BRBR<parameter>The <literal>nameofquery</literal> should be the name of the method that calls this query with perhaps a clarifying suffix.</parameter>BRBR<parameter>The content of the <literal>file</literal> tag should be the base filename of the file created in the previous step.</parameter>BRBR<parameter>An example:</parameter> <qresource prefix="sr"> <file alias="displays/ShipmentsByDate/FillListDetail.mql">dspShipmentsByDateFillList.mql</file> </qresource>
- In the C++ source file that needs to call this query:
- Rebuild the application and test.
Adding Custom Widgets
Guidelines for developing widgets haven't yet been codified.
There are several steps required to implement a new widget for use in the application and make it visible in <productname>Qt Designer</productname>. Here they all are:
Create the widget.cpp and widget.h file that implement your new widget in the widgets directory. The widget.h filename must be all lowercase regardless of the capitalization of widget.cpp or the class name.
Create the widget's plug-in widgetplugin.h file in widgets/plugins. Copy and edit an existing plug-in header file to make sure you get all of the required information. If widget.cpp and widget.h implement more than one custom widget that you want visible in Qt Designer, create separate plug-in header files for each widget.
Edit the widgets.pro file and add widgetplugin.h file(s) to the first <literal>HEADERS</literal> list, widget.cpp to the <literal>SOURCES</literal> list, and widget.h file to the second <literal>HEADERS</literal> list
Edit OpenMFGWidgets.cpp and add an #include for widgetplugin.h and add an m_plugins.append() for the plug-in class.
Rebuild the Makefiles in the widgets directory: cd widgets rm Makefile* qmake
Quit <productname>Qt Designer</productname> if you have it running.
From the top source directory, not the widgets subdirectory, build the application: cd .. make #or mingw32-make or ... You may have to remove the old plug-in shared library manually for this to work. The plug-in shared library is named something like $QTDIR/plugins/designer/libxtuplewidgets.shared-library-suffix.
Start <productname>Qt Designer</productname>.
Changing the Database Structure
The PostBooks and OpenMFG applications use very similar databases. The majority of tables, views, triggers, and stored procedures are shared. The xtupleserverSVN module holds scripts to create these shared views, triggers, and stored procedures. In addition, the scripts used to update individual aspects of the database structure from one release to the next, e.g. to add table columns or indexes, are also stored in the xtupleserver module. Any functionality or changes specific to OpenMFGshould be checked in to the appropriaterepository.
Here are the conventions for SQL scripts used to define or change aspects of the database structure:
File names should end with the suffix <literal>.sql</literal>
- File names should consist entirely of lowercase letters except as noted below.
Files which change the structure of existing tables should be named alterTablename.sql - note the uppercase letter at the beginning of the table name.
Files which add tables, privileges, and indexes should be named createShortdescrip.sql - again note the one uppercase letter in the middle.
Create explicit transactions for alter and create scripts that have multiple lines in them. Use <literal>COMMIT</literal> to close these transactions, never the PostgreSQL extension <literal>END</literal>.
Disable triggers before running <literal>ALTER TABLE</literal> if possible. This will prevent problems where updates to tables cause triggers to execute and potentially fail because of alterations to one or more tables. This can be skipped if there is reason to do so but if you don't disable the triggers then document the required specific order of script execution. ALTER TABLE table DISABLE TRIGGER ALL; -- make changes here ALTER TABLE table ENABLE TRIGGER ALL;
Create a precheck.sql or add to an existing precheck.sql file a <literal>SELECT</literal> statement to search for any data that might cause a database upgrade to fail. This <literal>SELECT</literal> statement should return <literal>TRUE</literal> if the data can be successfully upgraded and <literal>FALSE</literal> if not. For example, if changing a column to a foreign key, the precheck statement should query that column and return TRUE if all values in the existing data meet the foreign key requirement and FALSE if some values do not refer to existing records.
Changing Stored Procedures
Do not extract a stored procedure from a database to edit it; there are several reasons why this is a bad idea. Here is the correct process to follow:
<literal>update</literal> your xtupleserver and OpenMFG-specific checkouts.
change to the dbscripts/functions directory
- Find the file that contains the stored procedure(s) you need to change. Each file should be named after the stored procedure it contains.
Make and test your changes to the stored procedure file. To test them, you will need to load your changes into the database. One way to do this is with the <literal>psql</literal> command line tool: $ psql Password:database=# \i storedprocfilename
<literal>svn diff <replaceable>storedprocfilename</replaceable></literal> and review the changes manually to make sure they look right
<literal>svn commit <replaceable>storedprocfilename</replaceable></literal>BRBRPut a short description of why you made this change in your checkin comment, including the Mantis issue number if there is one. The 'what' is clear from the differences between the previous version and what you checked in.
If this change is related to a Mantis issue, see the <link>Fixing Bugs</link> or <link>Adding Features</link> sections for further guidance.
Style:
Use IF ... ELSIF ... ENDIF; as much as possible. It's much easier to code correctly and maintain than IF ... ELSE IF ... ENDIF; ENDIF;
Use single-quoting to wrap the body of a stored procedure, not $$ or $BODY$ quoting. These alternatives do not work with all of the versions of PostgreSQL that our customers use.
Changing Documentation
You may also want to edit the documentation, most of which is written in XML using DocBook for markup. Master copies of all of the documentation live in the <literal>xtupledocs</literal> repository.
developers' guide vs user documentation vs specs vs online help
Adding Images to the application
First read Qt's documentation on the Resource Compiler (rcc). Here are the xTuple conventions:
- Try to use a PNG or XMP file for your image.
Put the image file in the images subdirectory of the source code directory where the image is used by the application.
If there isn't already a Qt Resource (.qrc) file in the source code directory or in the images subdirectory, create one and name it after the directory in which you put it (e.g. guiclient.qrc)
Make sure the resource path referred to by the source code matches the resource path in the .qrc file.
