Caret6:DevelopmentQuickStart

From Van Essen Lab

(Difference between revisions)
Jump to: navigation, search
Line 1: Line 1:
== Development Tools Used for Caret6 Development ==
== Development Tools Used for Caret6 Development ==
-
Install tools in the order in which they are listed.
+
Install tools in the order in which they are listed.  If you already have a current installation of the JDK, Eclipse, and Mercurial, then you can skip to part 2 of this quick start.
=== Java ===
=== Java ===
Line 25: Line 25:
Mercurial is a distributed version control systems (DVCS).  With Caret source code, there is  "central" repository.  Developers will clone this central repository, make source changes, commit the changes to their cloned repositories, pull updates made by others from the central repository, and push their changes to the central repository.  The "hg" command may be executed anywhere in the projects directory tree.
Mercurial is a distributed version control systems (DVCS).  With Caret source code, there is  "central" repository.  Developers will clone this central repository, make source changes, commit the changes to their cloned repositories, pull updates made by others from the central repository, and push their changes to the central repository.  The "hg" command may be executed anywhere in the projects directory tree.
-
 
-
==== Common Mercurial Commands ====
 
-
 
-
* '''hg help''' will list all of the commands.
 
-
* '''hg add''' is used to add new files to the repository..
 
-
* '''hg clone''' is used to clone a repository.
 
-
* '''hg commit'''  is used to commit changed files to a repository.
 
-
* '''hg incoming''' lists changes made to the central repository that are not present in the cloned repository.
 
-
* '''hg log''' lists committed changes that have been made to a repository.
 
-
* '''hg outgoing''' lists changes made to a cloned repository that are not part of the central repository.
 
-
* '''hg init'''  creates a repository.
 
-
* '''hg pull''' gets changes that are in the central repository but not yet in the cloned repository (these changes are typically made by others.
 
-
* '''hg push''' puts changes in the cloned repository into the central repository.
 
-
* '''hg status'''  Lists changes that have been made but not committed to the repository.
 
=== Eclipse ===
=== Eclipse ===
Line 62: Line 48:
The current directory should now have three subdirectories.
The current directory should now have three subdirectories.
* '''caret6_source''' contains the source code.
* '''caret6_source''' contains the source code.
-
* '''distributions'''  contains files for assembling the Caret6 and WebCaret6 distributions.
 
* '''caret6lib'''  contains java libraries used by Caret6.
* '''caret6lib'''  contains java libraries used by Caret6.
Line 72: Line 57:
Create the Projects:
Create the Projects:
-
* In Eclipse, select File Menu->Import->Existing Projects into Workspace
+
* In Eclipse, select File Menu->Import
-
* Press the Next button.
+
** In the Import dialog:
-
* Ensure that 'Select Root Directory' is selected, and then click Browse... to navigate to the caret6_source directory created above
+
** Double-Click General
-
* Press the Ok button.
+
** Select 'Existing Projects into Workspace'
 +
** Press the Next button.
 +
** Ensure that 'Select Root Directory' is selected
 +
** Click Browse...  
 +
** Navigate to the caret6_source directory created above
 +
** Press the Ok button.
* You should now see the following projects selected in the 'Projects:' view:
* You should now see the following projects selected in the 'Projects:' view:
  brain, commandline, common, desktop, files, giftijlib, gui, statisticalalgorithm, statistics, web, wuswing
  brain, commandline, common, desktop, files, giftijlib, gui, statisticalalgorithm, statistics, web, wuswing
Line 81: Line 71:
Add the path to CARET6LIB:
Add the path to CARET6LIB:
-
* Right-click on the Desktop project and click 'properties'
+
* Right-click on the desktop project in Package Explorer and click 'properties'
-
* Select 'Java Build Path'
+
* In the Properties for desktop dialog:
-
* Select CARET6LIB
+
** Select 'Java Build Path'
-
* Click 'Edit...'
+
** Click on the 'Libraries tab'
-
* Click 'Variable...'
+
** Select CARET6LIB
-
* Click 'New...'
+
** Click 'Edit...'
-
* In the 'Name:' textbox, enter CARET6LIB
+
** Click 'Variable...'
-
* Click Folder...
+
** Click 'New...'
-
* Navigate to the caret6lib folder created above, and select the folder containing the libraries for your operating system (i.e. linux-amd64, linux-i586, windows-i586, etc.)
+
** In the 'Name:' textbox, enter CARET6LIB
 +
** Click Folder...
 +
** Navigate to the caret6lib folder created above, and select the folder containing the libraries for your operating system (i.e. linux-amd64, linux-i586, windows-i586, etc.)
 +
** Click 'Ok'
 +
** Click 'Ok'
 +
** Click 'Ok'
 +
** Answer 'Yes' when it asks you to do a full build now.
 +
** Congratulations, you've successfully built Caret6! Next we'll add a few settings to launch
 +
Caret within eclipse
 +
** Click 'Ok'
 +
** Select 'Run/Debug Settings in the Properties for desktop dialog
 +
** Click 'New...'
 +
** Select 'Java Application'
 +
** Click 'Ok'
 +
** Select the 'Main' tab if it isn't already highlighted
 +
** Click 'Search...'
 +
** Make sure that 'DesktopCaret - edu.wustl.caret.desktop' is highlighted
 +
** Click 'Ok'
 +
** Select the 'Environment' tab
 +
** Click 'New...'
 +
** In the 'Name' textbox, If on Max OSX, enter DYLD_LIBRARY_PATH.  If on Windows, enter PATH.  If on Linux, enter LD_LIBRARY_PATH
 +
** Enter the path to your caret6 libraries.  Note that this should be the exact same path that you used for CARET6LIB above.
 +
** Click 'Ok'
 +
** Click the 'Arguments' tab.
 +
**  In the VM Arguments section, add "-Xmx2g".
 +
** Click 'Ok'
* Click 'Ok'
* Click 'Ok'
-
* Click 'Ok'
+
* You should now have a working Caret6 development environment.  To launch select the project (Desktop) in the Package Explorer window and press F11 (Debug) or Ctrl+F11 (Run).
-
* Click 'Ok'
+
-
* Answer 'Yes' when it asks you to do a full build now.
+
-
* Click 'Ok'
+
-
* Select 'Run/Debug Settings
+
-
* Click 'New...'
+
-
* Select 'Java Application'
+
-
* Click 'Search...'
+
-
* Make sure that 'DesktopCaret - edu.wustl.caret.desktop' is highlight
+
-
* Click 'Ok'
+
-
* Select the 'Environment' tab
+
-
* Click 'New...'
+
-
* In the 'Name' textbox, If on Max OSX, enter DYLD_LIBRARY_PATH.  If on Windows, enter PATH.  If on Linux, enter LD_LIBRARY_PATH
+
-
* Enter the path to your caret6 libraries.  Note that this should be the exact same path that you used for CARET6LIB above.
+
-
* Click 'Ok'
+
-
* Click 'Ok'
+
-
* You should now have a working Caret6 development environment.  To launch select Desktop and press F11.
+
-
 
+
-
 
+
-
 
+
-
 
+
-
 
+
-
 
+
-
 
+
-
 
+
-
 
+
-
 
+
-
 
+
-
Some projects need external libraries added.  To add an external library:
+
-
* Right-click the project name.
+
-
* Select Properties from the menu.
+
-
* In the Properties dialog:
+
-
** Select Java Build Path
+
-
** Click the Libraries tab.
+
-
** Press the Add External JARs button.  Select the need JAR files from the "external_libraries" directory in caret6_development.
+
-
** The projects desktop, gui, and web need libraries_external/jogl/lib/jogl.jar, libraries_external/jogl/lib/gluegen-rt.jar, libraries_external/wizard/wizard.jar.
+
-
 
+
-
 
+
-
To run Caret6 from within Eclipse:
+
-
* Right-click desktop in the Package Explorer window.
+
-
* Select Properties from the menu.
+
-
* In the Properties dialog:
+
-
** Select Run/Debug Settings.
+
-
** Click DesktopCaret and press the Edit button.
+
-
** Click the Argument tab.
+
-
***  In the VM Arguments section, add "-Xmx2g".
+
-
** Press the Environment tab.
+
-
***  Press the New button.  Enter the environment's library path variable (MacOSX: DYLD_LIBRARY_PATH, Linux: LD_LIBRARY_PATH, Windows: PATH) for the name and in the value, enter the full path to <path>/caret6_development/distributions/caret6_deploy/caret6/lib_jogl/<JOGL-FOR-COMPUTER>/lib.
+
-
** Press the Classpath tab.
+
-
*** Click the mouse on the User Entries line.
+
-
*** Press the Add Projects button and select these projects: brain, common, files, giftijlib, gui, statisticalgorithm, wuswing.
+
-
*** Press the Add External JARs button.  Navigate to the <path>/caret6_development/libraries_external/jogl/lib directory and select both jogl.jar and gluegen-rt.jar.
+
-
*** Press the Add External JARs button.  Navigate to the <path>/caret6_development/libraries_external/wizard directory and select wizard.jar.
+
-
*** Press the OK button.
+
-
** Press the OK button to close the Preferences dialog.
+
-
* Select the project (desktop) in the Package Explorer window and then select Run Menu->Run and/or Run Menu->Debug.
+
-
 
+
-
 
+
-
 
+
-
 
+
-
 
+
-
 
+
-
 
+
-
 
+
=== Additional Eclipse Configuration ===
=== Additional Eclipse Configuration ===
Line 205: Line 157:
   * along with this program.  If not, see <http://www.gnu.org/licenses/>.
   * along with this program.  If not, see <http://www.gnu.org/licenses/>.
   */
   */
-
 
-
== Using Mercurial with Caret6 ==
 
-
 
-
It is probably easiest to operate with Mercurial on the command line rather than through Eclipse's Mercurial plug-in.
 
-
 
-
From the caret6_source directory:
 
-
* Run '''hg status''' to see what changes you have made that have not been committed to your repository.
 
-
* If files have been added or remove, run '''hg addremove'''.
 
-
* To commit changes to your repository, run '''hg commit -m "<comment describing changes>'''.
 
-
* To see if the central repository has been changed by other users, run '''hg incoming'''.  If changes have been made by others, run '''hg update''' to update your repository with changes from the central repository.  If necessary, run '''hg merge''' to combine your changes with changes from the central repository.  If needed, recommit and changes as a result of merging.
 
-
* Run '''hg push''' to push changes from your repository to the central repository.
 
-
* Run '''hg update''' to verify that your repository and the central repository do not differ.
 
-
 
-
== Multi-Structure Organization ==
 
-
 
-
* Brain - Contains that are independent of BrainStructures and contains BrainStructures.
 
-
* BrainStructure - Contains files that model a single structure such as a cerebral hemisphere or the cerebellum.
 
-
 
-
== Coding Conventions ==
 
-
 
-
* Follow Sun's [http://java.sun.com/docs/codeconv/CodeConventions.pdf Java Code Conventions].
 
-
* Write comments that support the [http://java.sun.com/j2se/javadoc/writingdoccomments/ Javadoc Tool].
 
-
* Declare one variable per line.
 
-
* For variable naming, do not use underscores and always start a variable name with a lower-case letter.  If the variable name consists of multiple words start the second and additional words with a capital letter.
 
-
* Like class naming, do not use underscores and all words in the class name, including the first, start with a capital letter.
 
-
* Use meaningful names for variables.  Avoid names like ''temp''.  Use of i, j, etc. for loop counters is acceptable.
 
-
* Do not declare a variable until it is needed.  A possible exception is variables that require a heap allocation inside a loop that is iterated many times.
 
-
* Use plenty of parenthesis for both logical and mathematical statements for clarity and to make precedence obvious.
 
-
* Use a ''for'' loop statement when looping with iterators  '''for (Iterator<String> iter = collection.iterator(); iter.hasNext(); ) {'''.  This limits the scope of the iterator to the loop.
 
-
* Use a ''for'' loop statement when looping through and reading the elements of an array  '''for (int value : anArray) {'''.
 
-
* Use plenty of comment indicate the intended function of the code.
 
-
* Use blank lines to break up the code.
 
-
* Use "this." when accessing member variable and methods.
 
-
* For method parameters, try to use ''Enums'' in place of boolean flags.
 
-
 
-
== Exceptions ==
 
-
 
-
If an Exception class is crated, always add a constructor that accepts any Exception.  This makes the stack trace available for locating the cause of the error.
 
-
 
-
  /**
 
-
    * Constructor that uses stack trace from the exception
 
-
    * passed in as a parameter.
 
-
    *
 
-
    * @param e Any exception whose stack trace becomes
 
-
    * this exception's stack trace.
 
-
    */
 
-
  public SomeException(Exception e) {
 
-
      super(e);
 
-
      this.setStackTrace(e.getStackTrace());
 
-
  }
 
-
 
-
 
-
When an exception needs to change type, pass the exception, not exception.getMessage() to the constructor.
 
-
 
-
Do this:
 
-
  new SomeException(otherException);
 
-
 
-
NOT this:
 
-
  new SomeException(otherException.getMessage());
 
-
 
-
== Performance Tips ==
 
-
 
-
=== Avoid Memory Allocations in Loops ===
 
-
 
-
While it is best to limit the scope of variables, such as '''array''' in this example:
 
-
    for (i = 0; i < infinity; i++) {
 
-
        float[] array = object.getXYZ();
 
-
    }
 
-
 
-
Allocating '''array''' many times can greatly harm performance.  Moving '''array''' outside
 
-
of the loop may greatly improve performance:
 
-
    float[] array = new float[3];
 
-
    for (i = 0; i < infinity; i++) {
 
-
      object.getXYZ(xyz);
 
-
        ...more code
 
-
    }
 
-
 
-
=== ArrayLists for Primitive Types ===
 
-
 
-
Do not use ArrayList<Integer> and ArrayList<Float>.  Instead, use ArrayListInt and ArrayListFloat from the common package.
 
-
 
-
=== Do Not Implement the Clonable Interface ===
 
-
 
-
Instead of implementing the Cloneable Interface for a class, create a copy constructor.
 
-
 
-
=== Avoid Multi-Dimensional Arrays ===
 
-
 
-
When possible, use a one-dimensional array instead of multi-dimensional arrays.  Accessing multi-dimensional arrays many times is slow than access of a one-dimensional array.
 
-
 
-
=== Avoid Repeatedly Making Heap Memory Requests ===
 
-
 
-
Instead of:
 
-
for (int i = 0; i < N; i++) {
 
-
    float[] xyz = object.getXYZ()
 
-
    statements...
 
-
}
 
-
 
-
Do this:
 
-
float[] xyz = new float[3];
 
-
for (int i = 0; i < N; i++) {
 
-
    object.getXYZ(xyz)
 
-
    statements...
 
-
}
 
-
 
-
=== Cloning Multi-Dimensional Arrays ===
 
-
 
-
int[][] a = new int[3][3];
 
-
 
-
Note that a.clone() only clones the first dimension of the array, not both dimensions.
 
-
 
-
=== Use StrictMath not Math ===
 
-
 
-
When a mathematical function is needed, use java.lang.StrictMath, not java.lang.Math.  StrictMath produces the same results in all Java Virtual Machines whereas Math may vary.
 
-
 
-
== Copyright ==
 
-
 
-
Include our lab's copyright statement at the top of each source code file.
 
-
 
-
/*
 
-
  * Copyright 1995-2010 Washington University School of Medicine.
 
-
  *
 
-
  * http://brainmap.wustl.edu
 
-
  *
 
-
  * CARET is free software
 
-
  *
 
-
  * 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 3 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, see <http://www.gnu.org/licenses/>.
 
-
  */
 
-
 
-
== GUI Development ==
 
-
 
-
=== Dialogs ===
 
-
 
-
* Create modal dialogs as a subclass of WuDialogModal.
 
-
* When a modal dialog is needed for data entry, use WuDataEntryDialog.
 
-
* Create non-modal dialogs as a subclass of WuDialogNonModal.  Non-modal dialogs should be maintained by GuiNonModalDialogManager so that the dialogs are updated as data is changed.
 
-
 
-
=== Layout Managers ===
 
-
 
-
With the exception, of BorderLayout, avoid using the AWT and Swing layout managers which are poorly designed and difficult to use.
 
-
 
-
In Swing, layout manages are added to JPanel objects.  The WuSwing package contains objects that are a combine a JPanel with a GridLayout and greatly simplify the building of user-interfaces.  This "layout-panels" are based on the QT layouts QBoxLayout and QGridLayout.
 
-
* WuPanelLayoutBox - Used for placing components in a single horizontal row or single vertical column.  Use the class' factory method to create a horizontal or vertical layout panel.
 
-
* WuPanelLayoutGrid - Used for placing components into a grid with varying row height and column widths.  Use the class' factory method to create a grid layout panel.
 
-
 
-
=== Spinners ===
 
-
 
-
Use WuSpinnerInt and WuSpinnerFloat for integer and floating-point spinner components.  These classes encapsulate the JSpinner class and ease the creation of spinners.
 
-
 
-
== Logging ==
 
-
 
-
Instead of "print" statements, use the CaretLogger.
 

Revision as of 17:50, 4 November 2010

Contents

Development Tools Used for Caret6 Development

Install tools in the order in which they are listed. If you already have a current installation of the JDK, Eclipse, and Mercurial, then you can skip to part 2 of this quick start.

Java

Java 6 is required for Caret6.

Java is pre-installed on Macs. Use Software update to check for new versions. Windows and Linux users should download Java from http://www.java.com.

Mercurial

Mercurial is used for source code control. Download from http://mercurial.selenic.com/ and install so that "hg" is in the user's path.

  • Read the Mercurial book.
  • Mercurial and Eclipse example.

In your home directory, create the file ".hgrc" and add the following text to it (with your name and email address):

[ui]
username =  FirstName LastName  Email-Address


With mercurial, there is a directory ".hg" which is created by Mercurial in the root directory of the project. In addition, uses may create a file in the root directory (same directory as ".hg") name ".hgignore". By default, Mercurial considers all files anywhere in and under the root directory as candidates for version control. ".hgignore" tells Mercurial which files should be ignored by Mercurial and are not candidates for source control. Examples of undesired files are object files and executables.

Mercurial is a distributed version control systems (DVCS). With Caret source code, there is "central" repository. Developers will clone this central repository, make source changes, commit the changes to their cloned repositories, pull updates made by others from the central repository, and push their changes to the central repository. The "hg" command may be executed anywhere in the projects directory tree.

Eclipse

Eclipse is an integrated development environment (IDE).

To install eclipse, download Eclipse IDE for Java Developers from http://www.eclipse.org/downloads and unzip in the desired directory (/Applications on Mac). Find the executable and draw to Finder (Mac) or set PATH environment variable.

Install FindBugs

  • Select Help->Install New Software and enter http://findbugs.cs.umd.edu/eclipse. Install it. Run it from the projects context menu (run from menu when project is right-clicked).

Creating a Caret6 Development Environment

Get the Source Code and Other Required Files

  • Create a new directory named "caret6_development" and change into the new directory.
  • Get the Caret6 Source code by running one of the following commands:
    • hg clone <path-to-hippocampus>/DS4600/REPOSITORIES_SOURCE_CODE/caret6/caret6_source ./caret6_source
    • hg clone ssh://hippocampus.wustl.edu//Volumes/DS4600/REPOSITORIES_SOURCE_CODE/caret6/caret6_source ./caret6_source
  • Copy the file "<path-to-hippocamps>/DS4600/REPOSITORIES_SOURCE_CODE/caret6/caret6_dev.zip" to the directory that contains "caret6_source".
  • Unzip the caret6_dev.zip.

The current directory should now have three subdirectories.

  • caret6_source contains the source code.
  • caret6lib contains java libraries used by Caret6.

Start and Setup Eclipse

  • Start Eclipse.
  • When asked for a "Workspace", choose a workspace location, it is recommended that you don't use your caret6 checkout directory.

Import Eclipse Projects

Create the Projects:

  • In Eclipse, select File Menu->Import
    • In the Import dialog:
    • Double-Click General
    • Select 'Existing Projects into Workspace'
    • Press the Next button.
    • Ensure that 'Select Root Directory' is selected
    • Click Browse...
    • Navigate to the caret6_source directory created above
    • Press the Ok button.
  • You should now see the following projects selected in the 'Projects:' view:
brain, commandline, common, desktop, files, giftijlib, gui, statisticalalgorithm, statistics, web, wuswing
  • Press the Finish button

Add the path to CARET6LIB:

  • Right-click on the desktop project in Package Explorer and click 'properties'
  • In the Properties for desktop dialog:
    • Select 'Java Build Path'
    • Click on the 'Libraries tab'
    • Select CARET6LIB
    • Click 'Edit...'
    • Click 'Variable...'
    • Click 'New...'
    • In the 'Name:' textbox, enter CARET6LIB
    • Click Folder...
    • Navigate to the caret6lib folder created above, and select the folder containing the libraries for your operating system (i.e. linux-amd64, linux-i586, windows-i586, etc.)
    • Click 'Ok'
    • Click 'Ok'
    • Click 'Ok'
    • Answer 'Yes' when it asks you to do a full build now.
    • Congratulations, you've successfully built Caret6! Next we'll add a few settings to launch

Caret within eclipse

    • Click 'Ok'
    • Select 'Run/Debug Settings in the Properties for desktop dialog
    • Click 'New...'
    • Select 'Java Application'
    • Click 'Ok'
    • Select the 'Main' tab if it isn't already highlighted
    • Click 'Search...'
    • Make sure that 'DesktopCaret - edu.wustl.caret.desktop' is highlighted
    • Click 'Ok'
    • Select the 'Environment' tab
    • Click 'New...'
    • In the 'Name' textbox, If on Max OSX, enter DYLD_LIBRARY_PATH. If on Windows, enter PATH. If on Linux, enter LD_LIBRARY_PATH
    • Enter the path to your caret6 libraries. Note that this should be the exact same path that you used for CARET6LIB above.
    • Click 'Ok'
    • Click the 'Arguments' tab.
    • In the VM Arguments section, add "-Xmx2g".
    • Click 'Ok'
  • Click 'Ok'
  • You should now have a working Caret6 development environment. To launch select the project (Desktop) in the Package Explorer window and press F11 (Debug) or Ctrl+F11 (Run).

Additional Eclipse Configuration

  • Select Preferences from File Menu (Eclipse Menu on Mac OSX).
  • Select General->Workspace.
    • Check Save Automatically Before Build.
  • Select General->Editors->Text Editors.
    • Check Insert Spaces for Tabs.
    • Check SHow Line Numbers.
  • Select Java->Code Style->Code Templates.
    • Select Comments->Files. Press the Edit button and enter the text with copyright as shown below.
    • Near the bottom of the dialog, select the checkbox next to Automatically Add Comments fro New Methods and Types.
  • Select Java->Editor->Folding.
    • Deselect Enable Folding.
  • Select Java->Code Style->Organize Imports. Press the New button and enter "edu".
  • Select Java->Compiler->Errors/Warnings.
    • Open Potential Programming Problems
      • Set Serializable Class without serialVersionUID to Ignore.
      • Set Possible Accidental Boolean Assignment to Warning.
      • Set Switch Case Fall Through to Warning.
      • Set Null Pointer Access to Warning.
  • Select Java->Installed JREs.
    • Check JVM1.6.0 (or newest) and deselect all others.
  • Select Java->Installed JREs->Execution Environment.
    • In the left section, select JavaSE-1.6. In the right section check JVM 1.6.0 and uncheck all others.
  • Select Java->Code Style->Formatter.
    • Press the Edit.. button in top right.
    • Select the Indentation tab. Remove "[built it]" from Profile Name.
    • Set Tab Policy to Spaces Only and set both tab size and indentation size to 4.
    • Do this for both the Java Conventions and Eclipse Conventions.
  • Press the OK button to close the preferences dialog. Answer No to Full Build pop-up.
/*
  * Copyright 1995-2010 Washington University School of Medicine.
  *
  * http://brainmap.wustl.edu
  *
  * CARET is free software
  *
  * 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 3 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, see <http://www.gnu.org/licenses/>.
  */
Personal tools
Sums Database