[med-svn] [bppphyview] 01/07: Import Upstream version 0.2.0

Andreas Tille tille at debian.org
Wed Jun 14 11:49:21 UTC 2017


This is an automated email from the git hooks/post-receive script.

tille pushed a commit to branch master
in repository bppphyview.

commit 1b76dab61526328ad438451e5e515409799a9370
Author: Andreas Tille <tille at debian.org>
Date:   Wed Jun 14 13:38:39 2017 +0200

    Import Upstream version 0.2.0
---
 AUTHORS.txt                  |    1 +
 CMakeLists.txt               |  191 +++++++
 COPYING.txt                  |  340 ++++++++++++
 ChangeLog                    |   11 +
 INSTALL.txt                  |   12 +
 NEWS                         |    0
 README                       |    0
 bppPhyView.spec              |   55 ++
 bppPhyView/CMakeLists.txt    |   26 +
 bppPhyView/PhyView.cpp       | 1166 ++++++++++++++++++++++++++++++++++++++++++
 bppPhyView/PhyView.h         |  387 ++++++++++++++
 bppPhyView/TreeCommands.cpp  |  149 ++++++
 bppPhyView/TreeCommands.h    |  339 ++++++++++++
 bppPhyView/TreeDocument.h    |  142 +++++
 bppPhyView/TreeSubWindow.cpp |  232 +++++++++
 bppPhyView/TreeSubWindow.h   |  111 ++++
 debian/bppphyview.manpages   |    1 +
 debian/changelog             |   13 +
 debian/compat                |    1 +
 debian/control               |   17 +
 debian/copyright             |   62 +++
 debian/rules                 |  147 ++++++
 debian/source/format         |    1 +
 man/CMakeLists.txt           |    7 +
 man/phyview.1.txt            |   47 ++
 25 files changed, 3458 insertions(+)

diff --git a/AUTHORS.txt b/AUTHORS.txt
new file mode 100755
index 0000000..2fe9f67
--- /dev/null
+++ b/AUTHORS.txt
@@ -0,0 +1 @@
+Julien Dutheil <julien.dutheil at univ-montp2.fr>
diff --git a/CMakeLists.txt b/CMakeLists.txt
new file mode 100644
index 0000000..82491a8
--- /dev/null
+++ b/CMakeLists.txt
@@ -0,0 +1,191 @@
+# CMake script for Bio++ PhyView
+# Author: Julien Dutheil
+# Created: 22/08/2009
+
+# Global parameters
+CMAKE_MINIMUM_REQUIRED(VERSION 2.6)
+PROJECT(bppphyview CXX C)
+IF(NOT CMAKE_BUILD_TYPE)
+  SET(CMAKE_BUILD_TYPE RelWithDebInfo CACHE STRING
+      "Choose the type of build, options are: None Debug Release RelWithDebInfo MinSizeRel."
+      FORCE)
+ENDIF(NOT CMAKE_BUILD_TYPE)
+
+SET(CMAKE_CXX_FLAGS "-Wall")
+IF(NOT NO_VIRTUAL_COV)
+  SET(NO_VIRTUAL_COV FALSE CACHE BOOL
+      "Disable covariant return type with virtual inheritance, for compilers that do not support it."
+      FORCE)
+ENDIF(NOT NO_VIRTUAL_COV)
+
+IF(NO_VIRTUAL_COV)
+  MESSAGE("-- Covariant return with virtual inheritance disabled.")
+  SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DNO_VIRTUAL_COV=1")
+ENDIF(NO_VIRTUAL_COV)
+
+IF(NOT NO_DEP_CHECK)
+  SET(NO_DEP_CHECK FALSE CACHE BOOL
+      "Disable dependencies check for building distribution only."
+      FORCE)
+ENDIF(NOT NO_DEP_CHECK)
+
+IF(NO_DEP_CHECK)
+  MESSAGE("-- Dependencies checking disabled. Only distribution can be built.")
+ELSE(NO_DEP_CHECK)
+
+#static linkage?
+IF(NOT BUILD_STATIC)
+  SET(BUILD_STATIC FALSE CACHE BOOL
+      "Enable static linkage."
+      FORCE)
+ENDIF()
+IF(BUILD_STATIC)
+  MESSAGE("-- Static linkage requested.")
+  SET(CMAKE_CXX_FLAGS "-static -static-libgcc ${CMAKE_CXX_FLAGS}")
+ENDIF()
+
+#build man pages?
+IF(NOT DEFINED MAN)
+  SET(MAN UNIX)
+ENDIF(NOT DEFINED MAN)
+
+#find executables for documentation
+FIND_PROGRAM(NROFF_EXE NAMES nroff)
+
+#here is a useful function:
+MACRO(IMPROVED_FIND_LIBRARY OUTPUT_LIBS lib_name include_to_find)
+  #start:
+  FIND_PATH(${lib_name}_INCLUDE_DIR ${include_to_find})
+  INCLUDE_DIRECTORIES(${${lib_name}_INCLUDE_DIR})
+
+  IF(BUILD_STATIC)
+    SET(${lib_name}_STATIC_NAMES lib${lib_name}.a)
+    FIND_LIBRARY(${lib_name}_STATIC_LIBRARY NAMES ${${lib_name}_STATIC_NAMES} PATH_SUFFIXES lib${LIB_SUFFIX})
+    IF(${lib_name}_STATIC_LIBRARY)
+      MESSAGE("-- Library ${lib_name} found here:")
+      MESSAGE("   includes: ${${lib_name}_INCLUDE_DIR}")
+      MESSAGE("   static libraries: ${${lib_name}_STATIC_LIBRARY}")
+    ELSE()
+      MESSAGE(FATAL_ERROR "${lib_name} required but not found.")
+    ENDIF()
+    #add the dependency:
+    SET(${OUTPUT_LIBS} ${${OUTPUT_LIBS}} ${${lib_name}_STATIC_LIBRARY})
+  ELSE()
+    SET(${lib_name}_NAMES ${lib_name} ${lib_name}.lib ${lib_name}.dll)
+    FIND_LIBRARY(${lib_name}_LIBRARY NAMES ${${lib_name}_NAMES} PATH_SUFFIXES lib${LIB_SUFFIX})
+    IF(${lib_name}_LIBRARY)
+      MESSAGE("-- Library ${lib_name} found here:")
+      MESSAGE("   includes: ${${lib_name}_INCLUDE_DIR}")
+      MESSAGE("   dynamic libraries: ${${lib_name}_LIBRARY}")
+    ELSE()
+      MESSAGE(FATAL_ERROR "${lib_name} required but not found.")
+    ENDIF()
+    #add the dependency:
+    SET(${OUTPUT_LIBS} ${${OUTPUT_LIBS}} ${${lib_name}_LIBRARY})
+  ENDIF()
+  
+ENDMACRO(IMPROVED_FIND_LIBRARY)
+
+# Set the CMAKE_PREFIX_PATH for the find_library fonction when using non
+# standard install location
+IF(CMAKE_INSTALL_PREFIX)
+  SET(CMAKE_PREFIX_PATH "${CMAKE_INSTALL_PREFIX}" ${CMAKE_PREFIX_PATH})
+ENDIF(CMAKE_INSTALL_PREFIX)
+
+#Find the libraries. The order is very important for static linkage, it won't
+#link if you change it!
+IMPROVED_FIND_LIBRARY(LIBS bpp-qt Bpp/Qt/QtGraphicDevice.h)
+IMPROVED_FIND_LIBRARY(LIBS bpp-phyl Bpp/Phyl/Tree.h)
+#Not needed for now:
+#IMPROVED_FIND_LIBRARY(LIBS bpp-seq Bpp/Seq/Alphabet/Alphabet.h)
+IMPROVED_FIND_LIBRARY(LIBS bpp-core Bpp/Clonable.h)
+
+# Find the Qt installation
+FIND_PACKAGE(Qt4 4.4.0 COMPONENTS QtCore QtGui REQUIRED)
+INCLUDE(${QT_USE_FILE})
+SET(LIBS ${LIBS} ${QT_LIBRARIES})
+
+IF(NROFF_EXE)
+  MESSAGE("-- Found nroff here: ${NROFF_EXE}")
+  MESSAGE("   Adding targets: man")
+
+  ADD_CUSTOM_TARGET(man
+    COMMAND cp phyview.1.txt phyview.1
+    COMMAND gzip -f phyview.1
+    WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/man
+    )
+  SET_DIRECTORY_PROPERTIES(PROPERTIES ADDITIONAL_MAKE_CLEAN_FILES man/phyview.1.gz)
+ENDIF(NROFF_EXE)
+
+# Subdirectories
+ADD_SUBDIRECTORY(bppPhyView)
+ADD_SUBDIRECTORY(man)
+
+ENDIF(NO_DEP_CHECK)
+
+# Packager
+SET(CPACK_PACKAGE_NAME "bppphyview")
+SET(CPACK_PACKAGE_VENDOR "Bio++ Development Team")
+SET(CPACK_PACKAGE_VERSION "0.2.0")
+SET(CPACK_PACKAGE_VERSION_MAJOR "0")
+SET(CPACK_PACKAGE_VERSION_MINOR "2")
+SET(CPACK_PACKAGE_VERSION_PATCH "0")
+SET(CPACK_PACKAGE_DESCRIPTION_SUMMARY "The Bio++ Phylogenetic Viewer")
+SET(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_SOURCE_DIR}/COPYING.txt")
+SET(CPACK_RESOURCE_FILE_AUTHORS "${CMAKE_SOURCE_DIR}/AUTHORS.txt")
+SET(CPACK_RESOURCE_FILE_INSTALL "${CMAKE_SOURCE_DIR}/INSTALL.txt")
+SET(CPACK_SOURCE_GENERATOR "TGZ")
+SET(CPACK_SOURCE_IGNORE_FILES
+ "CMakeFiles"
+ "Makefile"
+ "_CPack_Packages"
+ "CMakeCache.txt"
+ ".*\\\\.cmake"
+ ".*\\\\.git"
+ ".*\\\\.gz"
+ ".*\\\\.deb"
+ ".*\\\\.rpm"
+ ".*\\\\.dmg"
+ ".*\\\\.sh"
+ ".*\\\\..*\\\\.swp"
+ ".*moc_.*"
+ "bppPhyView/\\\\..*"
+ "bppPhyView/phyview"
+ "man/.*\\\\.1.gz"
+ "debian/tmp"
+ "debian/bppphyview/"
+ "debian/bppphyview\\\\.substvars"
+ "debian/bppphyview\\\\.debhelper"
+ "debian/debhelper\\\\.log"
+ "install_manifest.txt"
+ "DartConfiguration.tcl"
+ ${CPACK_SOURCE_IGNORE_FILES}
+)
+IF (MACOS)
+  SET(CPACK_GENERATOR "Bundle")
+ENDIF()
+
+SET(CPACK_SOURCE_PACKAGE_FILE_NAME "${CMAKE_PROJECT_NAME}-${CPACK_PACKAGE_VERSION_MAJOR}.${CPACK_PACKAGE_VERSION_MINOR}.${CPACK_PACKAGE_VERSION_PATCH}")
+SET(CPACK_DEBSOURCE_PACKAGE_FILE_NAME "${CMAKE_PROJECT_NAME}_${CPACK_PACKAGE_VERSION_MAJOR}.${CPACK_PACKAGE_VERSION_MINOR}.${CPACK_PACKAGE_VERSION_PATCH}.orig")
+INCLUDE(CPack)
+
+#This adds the 'dist' target
+ADD_CUSTOM_TARGET(dist COMMAND ${CMAKE_MAKE_PROGRAM} package_source)
+
+IF(NOT NO_DEP_CHECK)
+IF (UNIX)
+#This creates deb packages:
+ADD_CUSTOM_TARGET(origdist COMMAND cp ${CPACK_SOURCE_PACKAGE_FILE_NAME}.tar.gz ../${CPACK_DEBSOURCE_PACKAGE_FILE_NAME}.tar.gz)
+ADD_DEPENDENCIES(origdist dist)
+ADD_CUSTOM_TARGET(deb dpkg-buildpackage -uc -us -i${CPACK_SOURCE_PACKAGE_FILE_NAME}.tar.gz)
+ADD_DEPENDENCIES(deb origdist)
+ADD_DEPENDENCIES(deb man)
+
+#This creates rpm packages:
+ADD_CUSTOM_TARGET(rpm rpmbuild -ta ${CPACK_SOURCE_PACKAGE_FILE_NAME}.tar.gz)
+ADD_DEPENDENCIES(rpm dist man)
+
+#ADD_DEPENDENCIES(info install)
+ENDIF(UNIX)
+
+ENDIF(NOT NO_DEP_CHECK)
diff --git a/COPYING.txt b/COPYING.txt
new file mode 100755
index 0000000..d60c31a
--- /dev/null
+++ b/COPYING.txt
@@ -0,0 +1,340 @@
+		    GNU GENERAL PUBLIC LICENSE
+		       Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+     59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+			    Preamble
+
+  The licenses for most software are designed to take away your
+freedom to share and change it.  By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users.  This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it.  (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.)  You can apply it to
+your programs, too.
+
+  When we speak of free software, we are referring to freedom, not
+price.  Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+  To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+  For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have.  You must make sure that they, too, receive or can get the
+source code.  And you must show them these terms so they know their
+rights.
+
+  We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+  Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software.  If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+  Finally, any free program is threatened constantly by software
+patents.  We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary.  To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.
+

+		    GNU GENERAL PUBLIC LICENSE
+   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+  0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License.  The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language.  (Hereinafter, translation is included without limitation in
+the term "modification".)  Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope.  The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+  1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+  2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+    a) You must cause the modified files to carry prominent notices
+    stating that you changed the files and the date of any change.
+
+    b) You must cause any work that you distribute or publish, that in
+    whole or in part contains or is derived from the Program or any
+    part thereof, to be licensed as a whole at no charge to all third
+    parties under the terms of this License.
+
+    c) If the modified program normally reads commands interactively
+    when run, you must cause it, when started running for such
+    interactive use in the most ordinary way, to print or display an
+    announcement including an appropriate copyright notice and a
+    notice that there is no warranty (or else, saying that you provide
+    a warranty) and that users may redistribute the program under
+    these conditions, and telling the user how to view a copy of this
+    License.  (Exception: if the Program itself is interactive but
+    does not normally print such an announcement, your work based on
+    the Program is not required to print an announcement.)
+

+These requirements apply to the modified work as a whole.  If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works.  But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+  3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+    a) Accompany it with the complete corresponding machine-readable
+    source code, which must be distributed under the terms of Sections
+    1 and 2 above on a medium customarily used for software interchange; or,
+
+    b) Accompany it with a written offer, valid for at least three
+    years, to give any third party, for a charge no more than your
+    cost of physically performing source distribution, a complete
+    machine-readable copy of the corresponding source code, to be
+    distributed under the terms of Sections 1 and 2 above on a medium
+    customarily used for software interchange; or,
+
+    c) Accompany it with the information you received as to the offer
+    to distribute corresponding source code.  (This alternative is
+    allowed only for noncommercial distribution and only if you
+    received the program in object code or executable form with such
+    an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it.  For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable.  However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+

+  4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License.  Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+  5. You are not required to accept this License, since you have not
+signed it.  However, nothing else grants you permission to modify or
+distribute the Program or its derivative works.  These actions are
+prohibited by law if you do not accept this License.  Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+  6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions.  You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+  7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all.  For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices.  Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+

+  8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded.  In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+  9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time.  Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number.  If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation.  If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+  10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission.  For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this.  Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+			    NO WARRANTY
+
+  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+		     END OF TERMS AND CONDITIONS
+

+	    How to Apply These Terms to Your New Programs
+
+  If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+  To do so, attach the following notices to the program.  It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+    <one line to give the program's name and a brief idea of what it does.>
+    Copyright (C) <year>  <name of author>
+
+    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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+    Gnomovision version 69, Copyright (C) year  name of author
+    Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+    This is free software, and you are welcome to redistribute it
+    under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License.  Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary.  Here is a sample; alter the names:
+
+  Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+  `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+  <signature of Ty Coon>, 1 April 1989
+  Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs.  If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library.  If this is what you want to do, use the GNU Library General
+Public License instead of this License.
diff --git a/ChangeLog b/ChangeLog
new file mode 100755
index 0000000..9c8dcb0
--- /dev/null
+++ b/ChangeLog
@@ -0,0 +1,11 @@
+11/06/11 -*- Version 0.2.0 -*-
+
+* Small interface improvement (mainly associated data management)
+
+28/02/11 -*- Version 0.1.0 -*-
+
+28/02/11 Julien Dutheil
+* Added package files.
+
+22/08/09 Julien Dutheil
+* Added CMake configuration files.
diff --git a/INSTALL.txt b/INSTALL.txt
new file mode 100644
index 0000000..c8859da
--- /dev/null
+++ b/INSTALL.txt
@@ -0,0 +1,12 @@
+This software needs cmake >= 2.6 to build.
+
+After installing cmake, run it with the following command:
+cmake -DCMAKE_INSTALL_PREFIX=[where to install, for instance /usr/local or $HOME/.local] .
+
+If available, you can also use ccmake instead of cmake for a more user-friendly interface.
+
+Then compile and install the software with
+make install
+
+You may also consider installing and using the software checkinstall for easier system administration.
+
diff --git a/NEWS b/NEWS
new file mode 100755
index 0000000..e69de29
diff --git a/README b/README
new file mode 100755
index 0000000..e69de29
diff --git a/bppPhyView.spec b/bppPhyView.spec
new file mode 100644
index 0000000..bd8721c
--- /dev/null
+++ b/bppPhyView.spec
@@ -0,0 +1,55 @@
+%define name bppphyview
+%define version 0.1.0
+%define release 1
+%define _prefix /usr
+
+Summary: The Bio++ Phylogenetic Viewer.
+Name: %{name}
+Version: %{version}
+Release: %{release}
+Vendor: Julien Dutheil
+Source: http://download.gna.org/bppsuite/%{name}-%{version}.tar.gz
+License: CeCILL 2
+Group: System Environment/Libraries
+BuildRoot: %{_builddir}/%{name}-root
+Packager: Julien Dutheil
+Prefix: %{_prefix}
+AutoReq: yes
+AutoProv: yes
+
+%description
+Bio++ Phylogenetic Viewer, using the Qt library.
+
+%prep
+%setup -q
+
+%build
+CFLAGS="-I%{_prefix}/include $RPM_OPT_FLAGS"
+CMAKE_FLAGS="-DCMAKE_INSTALL_PREFIX=%{_prefix}"
+if [ %{_lib} == 'lib64' ] ; then
+  CMAKE_FLAGS="$CMAKE_FLAGS -DLIB_SUFFIX=64"
+fi
+cmake $CMAKE_FLAGS .
+make
+
+%install
+rm -rf $RPM_BUILD_ROOT
+make DESTDIR=$RPM_BUILD_ROOT install
+
+%clean
+rm -rf $RPM_BUILD_ROOT
+
+%post -p /sbin/ldconfig
+
+%postun -p /sbin/ldconfig
+
+%files
+%defattr(-,root,root)
+%doc AUTHORS.txt COPYING.txt INSTALL.txt ChangeLog
+%{_prefix}/bin/phyview
+%{_prefix}/share/man/man1/phyview.1.gz
+
+%changelog
+* Mon Feb 28 2011 Julien Dutheil <julien.dutheil at univ-montp2.fr>
+- PhyView 0.1.0 release
+
diff --git a/bppPhyView/CMakeLists.txt b/bppPhyView/CMakeLists.txt
new file mode 100644
index 0000000..47249d4
--- /dev/null
+++ b/bppPhyView/CMakeLists.txt
@@ -0,0 +1,26 @@
+# CMake script for Bio++ PhyView
+# Author: Julien Dutheil
+# Created: 22/08/2009
+
+set(phyview_SRCS
+  PhyView.cpp
+  TreeSubWindow.cpp
+  TreeCommands.cpp
+  )
+
+set(phyview_MOC_HDRS
+  PhyView.h
+  TreeSubWindow.h
+  )
+
+set(phyview_HDRS
+  TreeDocument.h
+  TreeCommands.h
+  )
+
+qt4_wrap_cpp(phyview_MOC_SRCS ${phyview_MOC_HDRS})
+add_executable(phyview ${phyview_SRCS} ${phyview_MOC_SRCS})
+target_link_libraries(phyview ${LIBS})
+
+# Install libs
+install(TARGETS phyview DESTINATION bin)
diff --git a/bppPhyView/PhyView.cpp b/bppPhyView/PhyView.cpp
new file mode 100644
index 0000000..8a6e0b0
--- /dev/null
+++ b/bppPhyView/PhyView.cpp
@@ -0,0 +1,1166 @@
+//
+// File: PhyView.cpp
+// Created by: Julien Dutheil
+// Created on: Tue Aug 05 14:59 2009
+//
+
+/*
+Copyright or © or Copr. Bio++ Development Team, (November 16, 2004)
+
+This software is a computer program whose purpose is to provide
+graphic components to develop bioinformatics applications.
+
+This software is governed by the CeCILL  license under French law and
+abiding by the rules of distribution of free software.  You can  use, 
+modify and/ or redistribute the software under the terms of the CeCILL
+license as circulated by CEA, CNRS and INRIA at the following URL
+"http://www.cecill.info". 
+
+As a counterpart to the access to the source code and  rights to copy,
+modify and redistribute granted by the license, users are provided only
+with a limited warranty  and the software's author,  the holder of the
+economic rights,  and the successive licensors  have only  limited
+liability. 
+
+In this respect, the user's attention is drawn to the risks associated
+with loading,  using,  modifying and/or developing or reproducing the
+software by the user in light of its specific status of free software,
+that may mean  that it is complicated to manipulate,  and  that  also
+therefore means  that it is reserved for developers  and  experienced
+professionals having in-depth computer knowledge. Users are therefore
+encouraged to load and test the software's suitability as regards their
+requirements in conditions enabling the security of their systems and/or 
+data to be ensured and,  more generally, to use and operate it in the 
+same conditions as regards security. 
+
+The fact that you are presently reading this means that you have had
+knowledge of the CeCILL license and that you accept its terms.
+*/
+
+#include "PhyView.h"
+#include "TreeSubWindow.h"
+#include "TreeDocument.h"
+
+#include <QApplication>
+#include <QtGui>
+
+#include <Bpp/Qt/QtGraphicDevice.h>
+
+#include <Bpp/Numeric/DataTable.h>
+
+#include <Bpp/Phyl/Tree.h>
+#include <Bpp/Phyl/Io.all>
+#include <Bpp/Phyl/Graphics/PhylogramPlot.h>
+
+#include <fstream>
+
+using namespace std;    
+using namespace bpp;
+
+MouseActionListener::MouseActionListener(PhyView* phyview):
+  phyview_(phyview),
+  treeChooser_(new QDialog()),
+  treeList_(new QListWidget(treeChooser_))
+{
+  treeChooser_->setParent(phyview_);
+  treeChooser_->setModal(true);
+  QVBoxLayout* layout = new QVBoxLayout;
+  layout->addWidget(treeList_);
+  layout->addStretch(1);
+  treeChooser_->setLayout(layout);
+  treeChooser_->connect(treeList_, SIGNAL(itemClicked(QListWidgetItem*)), treeChooser_, SLOT(accept()));
+}
+
+
+
+TranslateNameChooser::TranslateNameChooser(PhyView* phyview) :
+  QDialog(phyview), phyview_(phyview), fileDialog_(new QFileDialog(this))
+{
+  fileFilters_ << "Coma separated columns (*.txt *.csv)"
+               << "Tab separated columns (*.txt *.csv)";
+  fileDialog_->setNameFilters(fileFilters_);
+
+  QFormLayout* layout = new QFormLayout;
+  fromList_ = new QComboBox;
+  toList_   = new QComboBox;
+  ok_       = new QPushButton(tr("Ok"));
+  cancel_   = new QPushButton(tr("Cancel"));
+  layout->addRow(tr("From"), fromList_);
+  layout->addRow(tr("To")  , toList_);
+  layout->addRow(cancel_, ok_);
+  connect(ok_, SIGNAL(clicked(bool)), this, SLOT(accept()));
+  connect(cancel_, SIGNAL(clicked(bool)), this, SLOT(reject()));
+  setLayout(layout);
+}
+
+void TranslateNameChooser::translateTree(TreeTemplate<Node>& tree)
+{
+  fileDialog_->setAcceptMode(QFileDialog::AcceptOpen);
+  if (fileDialog_->exec() == QDialog::Accepted) {
+    QStringList path = fileDialog_->selectedFiles();
+    string sep = ",";
+    if (fileDialog_->selectedNameFilter() == fileFilters_[1])
+      sep = "\t";
+    ifstream file(path[0].toStdString().c_str(), ios::in);
+    DataTable* table = DataTable::read(file, sep);
+
+    //Clean button groups:
+    fromList_->clear();
+    toList_->clear();
+
+    //Now add the new ones:
+    for (unsigned int i = 0; i < table->getNumberOfColumns(); ++i) {
+      fromList_->addItem(QtTools::toQt(table->getColumnName(i)));
+        toList_->addItem(QtTools::toQt(table->getColumnName(i)));
+    }
+    if (exec() == QDialog::Accepted)
+      phyview_->submitCommand(new TranslateNodeNamesCommand(phyview_->getActiveDocument(), *table, fromList_->currentIndex(),  toList_->currentIndex()));
+  }
+}
+
+
+
+
+DataLoader::DataLoader(PhyView* phyview) :
+  QDialog(phyview), phyview_(phyview)
+{
+  QFormLayout* layout = new QFormLayout;
+  idIndex_   = new QRadioButton(tr("Index from id"));
+  idIndex_->setChecked(true);
+  nameIndex_ = new QRadioButton(tr("Index from name"));
+  indexCol_  = new QComboBox;
+  QButtonGroup* bg = new QButtonGroup();
+  bg->addButton(idIndex_);
+  bg->addButton(nameIndex_);
+  ok_       = new QPushButton(tr("Ok"));
+  cancel_   = new QPushButton(tr("Cancel"));
+  layout->addRow(idIndex_, nameIndex_);
+  layout->addRow(tr("Column"), indexCol_);
+  layout->addRow(cancel_, ok_);
+  connect(ok_, SIGNAL(clicked(bool)), this, SLOT(accept()));
+  connect(cancel_, SIGNAL(clicked(bool)), this, SLOT(reject()));
+  setLayout(layout);
+}
+
+void DataLoader::load(const DataTable* data)
+{
+  indexCol_->clear();
+  for (unsigned int i = 0; i < data->getNumberOfColumns(); ++i)
+    indexCol_->addItem(QtTools::toQt(data->getColumnName(i)));
+  if (exec() == QDialog::Accepted) {
+    unsigned int index = static_cast<unsigned int>(indexCol_->currentIndex());
+    phyview_->submitCommand(new AttachDataCommand(phyview_->getActiveDocument(), *data, index, nameIndex_->isChecked()));
+  }
+}
+
+ImageExportDialog::ImageExportDialog(PhyView* phyview):
+  QDialog(phyview)
+{
+  QGridLayout* layout = new QGridLayout;
+  path_   = new QLabel;
+  path_->setText("(none selected)");
+  layout->addWidget(path_, 1, 1);
+  
+  browse_ = new QPushButton(tr("&Browse"));
+  connect(browse_, SIGNAL(clicked(bool)), this, SLOT(chosePath()));
+  layout->addWidget(browse_, 1, 2);
+  
+  height_ = new QSpinBox;
+  height_->setRange(100, 10000);
+  layout->addWidget(new QLabel(tr("Height:")), 2, 1);
+  layout->addWidget(height_, 2, 2);
+  
+  width_ = new QSpinBox;
+  width_->setRange(100, 10000);
+  layout->addWidget(new QLabel(tr("Width:")), 3, 1);
+  layout->addWidget(width_, 3, 2);
+  
+  transparent_ = new QCheckBox(tr("Transparent"));
+  layout->addWidget(transparent_, 4, 1, 1, 2);
+
+  keepAspectRatio_ = new QCheckBox(tr("Keep aspect ratio"));
+  layout->addWidget(keepAspectRatio_, 5, 1, 1, 2);
+
+  ok_       = new QPushButton(tr("Ok"));
+  ok_->setDisabled(true);
+  connect(ok_, SIGNAL(clicked(bool)), this, SLOT(accept()));
+  layout->addWidget(ok_, 6, 2);
+
+  cancel_   = new QPushButton(tr("Cancel"));
+  connect(cancel_, SIGNAL(clicked(bool)), this, SLOT(reject()));
+  layout->addWidget(cancel_, 6, 1);
+
+  setLayout(layout);
+    
+  imageFileDialog_ = new QFileDialog(this, "Image File");
+  QList<QByteArray> formats = QImageWriter::supportedImageFormats();
+  for (int i = 0; i < formats.size(); ++i)
+    imageFileFilters_ << QString(formats[i]) + QString(" (*.*)");
+  imageFileDialog_->setNameFilters(imageFileFilters_);
+
+}
+
+void ImageExportDialog::chosePath()
+{
+  if (imageFileDialog_->exec() == QDialog::Accepted) {
+    QStringList path = imageFileDialog_->selectedFiles();
+    int i = imageFileFilters_.indexOf(imageFileDialog_->selectedNameFilter());
+    path_->setText(path[0] + " (" + QString(QImageWriter::supportedImageFormats()[i]) + ")");
+    ok_->setEnabled(true);
+  }
+}
+
+void ImageExportDialog::process(QGraphicsScene* scene)
+{
+  if (ok_->isEnabled()) {
+    QStringList path = imageFileDialog_->selectedFiles();
+    int i = imageFileFilters_.indexOf(imageFileDialog_->selectedNameFilter());
+    //Chose the correct format according to options:
+    QImage::Format format = QImage::Format_RGB32;
+    QBrush bckBrush = scene->backgroundBrush();
+    if (transparent_->isChecked()) {
+      format = QImage::Format_ARGB32_Premultiplied;
+      scene->setBackgroundBrush(Qt::NoBrush);
+    } else {
+      if (bckBrush == Qt::NoBrush)
+        scene->setBackgroundBrush(Qt::white);
+    }
+    QImage image(width_->value(), height_->value(), format);
+    QPainter painter;
+    painter.begin(&image);
+    if (keepAspectRatio_->isChecked())
+      scene->render(&painter);
+    else
+      scene->render(&painter, QRectF(), QRectF(), Qt::IgnoreAspectRatio);
+    painter.end();
+    scene->setBackgroundBrush(bckBrush);
+    image.save(path[0], QImageWriter::supportedImageFormats()[i]);
+  } else {
+    throw Exception("Can't process image as no file has been selected.");
+  }
+}
+
+
+TypeNumberDialog::TypeNumberDialog(PhyView* phyview, const string& what, unsigned int min, unsigned int max) :
+  QDialog(phyview)
+{
+  QFormLayout* layout = new QFormLayout;
+  spinBox_  = new QSpinBox;
+  spinBox_->setRange(min, max);
+  ok_       = new QPushButton(tr("Ok"));
+  cancel_   = new QPushButton(tr("Cancel"));
+  layout->addRow(QtTools::toQt(what), spinBox_);
+  layout->addRow(cancel_, ok_);
+  connect(ok_, SIGNAL(clicked(bool)), this, SLOT(accept()));
+  connect(cancel_, SIGNAL(clicked(bool)), this, SLOT(reject()));
+  setLayout(layout);
+}
+
+
+
+void MouseActionListener::mousePressEvent(QMouseEvent *event)
+{
+  if (dynamic_cast<NodeMouseEvent*>(event)->hasNodeId())
+  {
+    int nodeId = dynamic_cast<NodeMouseEvent*>(event)->getNodeId();
+    QString action;
+    if (event->button() == Qt::LeftButton)
+      action = phyview_->getMouseLeftButtonActionType();
+    else if (event->button() == Qt::MidButton)
+      action = phyview_->getMouseMiddleButtonActionType();
+    else if (event->button() == Qt::RightButton)
+      action = phyview_->getMouseRightButtonActionType();
+    else
+      action = "None";
+
+    if (action == "Swap")
+    {
+      if (!phyview_->getActiveDocument()->getTree()->isRoot(nodeId))
+      {
+        int fatherId = phyview_->getActiveDocument()->getTree()->getFatherId(nodeId);
+        vector<int> sonsId = phyview_->getActiveDocument()->getTree()->getSonsId(fatherId);
+        unsigned int i1 = 0, i2 = 0;
+        if (sonsId[0] == nodeId) {
+          i1 = 0;
+          i2 = sonsId.size() - 1;
+        } else {
+          for (unsigned int i = 1; i < sonsId.size(); ++i)
+            if (sonsId[i] == nodeId) {
+              i1 = i;
+              i2 = i - 1;
+            }
+        }
+        phyview_->submitCommand(new SwapCommand(phyview_->getActiveDocument(), fatherId, i1, i2 , nodeId, sonsId[i2]));
+      }
+    }
+    else if (action == "Order down")
+    {
+      phyview_->submitCommand(new OrderCommand(phyview_->getActiveDocument(), nodeId, true));
+    }
+    else if (action == "Order up")
+    {
+      phyview_->submitCommand(new OrderCommand(phyview_->getActiveDocument(), nodeId, false));
+    }
+    else if (action == "Root on node")
+      phyview_->submitCommand(new RerootCommand(phyview_->getActiveDocument(), nodeId));
+    else if (action == "Root on branch")
+      phyview_->submitCommand(new OutgroupCommand(phyview_->getActiveDocument(), nodeId));
+    else if (action == "Collapse") {
+      TreeCanvas& tc = phyview_->getActiveSubWindow()->getTreeCanvas();
+      tc.collapseNode(nodeId, !tc.isNodeCollapsed(nodeId));
+      tc.redraw();
+    }
+    else if (action == "Sample subtree") {
+      Node* n = phyview_->getActiveDocument()->getTree()->getNode(nodeId);
+      TypeNumberDialog dial(phyview_, "Sample size", 1u, TreeTemplateTools::getNumberOfLeaves(*n));
+      if (dial.exec() == QDialog::Accepted) {
+        unsigned int size = dial.getValue();
+        phyview_->submitCommand(new SampleSubtreeCommand(phyview_->getActiveDocument(), nodeId, size));
+      }
+    } else if (action == "Delete subtree") {
+      phyview_->submitCommand(new DeleteSubtreeCommand(phyview_->getActiveDocument(), nodeId));
+    }
+    else if (action == "Copy subtree") {
+      Node* subtree = TreeTemplateTools::cloneSubtree<Node>(*phyview_->getActiveDocument()->getTree()->getNode(nodeId));
+      auto_ptr< TreeTemplate<Node> > tt(new TreeTemplate<Node>(subtree));
+      phyview_->createNewDocument(tt.get());
+    }
+    else if (action == "Cut subtree") {
+      Node* subtree = TreeTemplateTools::cloneSubtree<Node>(*phyview_->getActiveDocument()->getTree()->getNode(nodeId));
+      auto_ptr< TreeTemplate<Node> > tt(new TreeTemplate<Node>(subtree));
+      phyview_->submitCommand(new DeleteSubtreeCommand(phyview_->getActiveDocument(), nodeId));
+      phyview_->createNewDocument(tt.get());
+    }
+    else if (action == "Insert on node") {
+      if (phyview_->getNonActiveDocuments().size() == 0) {
+        QMessageBox::critical(phyview_, QString("Oups..."), QString("No tree to insert."));
+        return;
+      }
+      TreeTemplate<Node>* tree = pickTree_();
+      if (tree) {
+        Node* subtree = TreeTemplateTools::cloneSubtree<Node>(*tree->getRootNode());
+        phyview_->submitCommand(new InsertSubtreeAtNodeCommand(phyview_->getActiveDocument(), nodeId, subtree));
+      }
+    }
+    else if (action == "Insert on branch") {
+      if (phyview_->getNonActiveDocuments().size() == 0) {
+        QMessageBox::critical(phyview_, QString("Oups..."), QString("No tree to insert."));
+        return;
+      }
+      TreeTemplate<Node>* tree = pickTree_();
+      if (tree) {
+        Node* subtree = TreeTemplateTools::cloneSubtree<Node>(*tree->getRootNode());
+        phyview_->submitCommand(new InsertSubtreeOnBranchCommand(phyview_->getActiveDocument(), nodeId, subtree));
+      }
+    }
+  }
+}
+
+
+
+TreeTemplate<Node>* MouseActionListener::pickTree_()
+{
+  QList<TreeDocument*> documents = phyview_->getNonActiveDocuments();
+  treeList_->clear();
+  for (int i = 0; i < documents.size(); ++i) {
+    QString text = QtTools::toQt(documents[i]->getName());
+    if (text == "") text = "(unknown)";
+    vector<string> leaves = documents[i]->getTree()->getLeavesNames(); 
+    text += QtTools::toQt(" " + TextTools::toString(leaves.size()) + " leaves ");
+    for (unsigned int j = 0; j < min(static_cast<unsigned int>(leaves.size()), 5u); ++j) {
+      text += QtTools::toQt(", " + leaves[j]);
+    }
+    if (leaves.size() >= 5) text += "...";
+    treeList_->addItem(text);
+  }
+  treeChooser_->exec();
+  return documents[treeList_->currentRow()]->getTree();
+}
+
+
+
+
+PhyView::PhyView():
+  manager_(),
+  collapsedNodesListener_(true)
+{
+  setAttribute(Qt::WA_DeleteOnClose);
+  setAttribute(Qt::WA_QuitOnClose);
+  initGui_();
+  createActions_();
+  createMenus_();
+  createStatusBar_();
+  resize(1000, 600);
+}
+
+
+
+void PhyView::initGui_()
+{
+  mdiArea_ = new QMdiArea;
+  connect(mdiArea_, SIGNAL(subWindowActivated(QMdiSubWindow*)), this, SLOT(setCurrentSubWindow(QMdiSubWindow*)));
+  setCentralWidget(mdiArea_);
+  
+  //Stats panel:
+  createStatsPanel_();
+  statsDockWidget_ = new QDockWidget(tr("Statistics"));
+  statsDockWidget_->setWidget(statsPanel_);
+  statsDockWidget_->setAllowedAreas(Qt::LeftDockWidgetArea | Qt::RightDockWidgetArea);
+  addDockWidget(Qt::RightDockWidgetArea, statsDockWidget_);
+
+  //Display panel:
+  createDisplayPanel_();
+  displayDockWidget_ = new QDockWidget(tr("Display"));
+  displayDockWidget_->setWidget(displayPanel_);
+  displayDockWidget_->setAllowedAreas(Qt::LeftDockWidgetArea | Qt::RightDockWidgetArea);
+  addDockWidget(Qt::RightDockWidgetArea, displayDockWidget_);
+
+  //Search panel:
+  createSearchPanel_();
+  searchDockWidget_ = new QDockWidget(tr("Search in tree"));
+  searchDockWidget_->setWidget(searchPanel_);
+  searchDockWidget_->setAllowedAreas(Qt::LeftDockWidgetArea | Qt::RightDockWidgetArea);
+  addDockWidget(Qt::LeftDockWidgetArea, searchDockWidget_);
+
+  //Undo panel:
+  QUndoView* undoView = new QUndoView;
+  undoView->setGroup(&manager_);
+  undoDockWidget_ = new QDockWidget(tr("Undo list"));
+  undoDockWidget_->setWidget(undoView);
+  undoDockWidget_->setAllowedAreas(Qt::LeftDockWidgetArea | Qt::RightDockWidgetArea);
+  addDockWidget(Qt::LeftDockWidgetArea, undoDockWidget_);
+
+  //Branch lengths panel:
+  createBrlenPanel_();
+  brlenDockWidget_ = new QDockWidget(tr("Branch lengths"));
+  brlenDockWidget_->setWidget(brlenPanel_);
+  brlenDockWidget_->setAllowedAreas(Qt::LeftDockWidgetArea | Qt::RightDockWidgetArea);
+  addDockWidget(Qt::LeftDockWidgetArea, brlenDockWidget_);
+  brlenDockWidget_->setVisible(false);
+
+  //Mouse control panel:
+  createMouseControlPanel_();
+  mouseControlDockWidget_ = new QDockWidget(tr("Mouse control"));
+  mouseControlDockWidget_->setWidget(mouseControlPanel_);
+  mouseControlDockWidget_->setAllowedAreas(Qt::LeftDockWidgetArea | Qt::RightDockWidgetArea);
+  addDockWidget(Qt::LeftDockWidgetArea, mouseControlDockWidget_);
+
+  //Names operations panel:
+  createDataPanel_();
+  dataDockWidget_ = new QDockWidget(tr("Associated Data"));
+  dataDockWidget_->setWidget(dataPanel_);
+  dataDockWidget_->setAllowedAreas(Qt::LeftDockWidgetArea | Qt::RightDockWidgetArea);
+  addDockWidget(Qt::RightDockWidgetArea, dataDockWidget_);
+  dataDockWidget_->setVisible(false);
+ 
+  //Other stuff...
+  treeFileDialog_ = new QFileDialog(this, "Tree File");
+  treeFileFilters_ << "Newick files (*.dnd *.tre *.tree *.nwk *.newick *.phy *.txt)"
+                   << "Nexus files (*.nx *.nex *.nexus)"
+                   << "Nhx files (*.nhx)";
+  treeFileDialog_->setNameFilters(treeFileFilters_);
+  treeFileDialog_->setConfirmOverwrite(true);
+
+  dataFileDialog_ = new QFileDialog(this, "Data File");
+  dataFileFilters_ << "Coma separated columns (*.txt *.csv)"
+                   << "Tab separated columns (*.txt *.csv)";
+  dataFileDialog_->setNameFilters(dataFileFilters_);
+
+  imageExportDialog_ = new ImageExportDialog(this);
+
+  printer_ = new QPrinter(QPrinter::HighResolution);
+  printDialog_ = new QPrintDialog(printer_, this);
+
+  translateNameChooser_ = new TranslateNameChooser(this);
+
+  dataLoader_ = new DataLoader(this);
+}
+
+void PhyView::createDisplayPanel_()
+{
+  displayPanel_ = new QWidget(this);
+  treeControlers_ = new TreeCanvasControlers();
+  treeControlers_->addActionListener(this);
+  for (unsigned int i = 0; i < treeControlers_->getNumberOfTreeDrawings(); ++i)
+    treeControlers_->getTreeDrawing(i)->addTreeDrawingListener(&collapsedNodesListener_);
+  
+  QGroupBox* drawingOptions = new QGroupBox(tr("Drawing"));
+  QFormLayout* drawingLayout = new QFormLayout;
+  drawingLayout->addRow(tr("&Type:"),        treeControlers_->getControlerById(TreeCanvasControlers::ID_DRAWING_CTRL));
+  drawingLayout->addRow(tr("&Orientation:"), treeControlers_->getControlerById(TreeCanvasControlers::ID_ORIENTATION_CTRL));
+  drawingLayout->addRow(tr("Width (px):"),   treeControlers_->getControlerById(TreeCanvasControlers::ID_WIDTH_CTRL));
+  drawingLayout->addRow(tr("&Height (px):"), treeControlers_->getControlerById(TreeCanvasControlers::ID_HEIGHT_CTRL));
+  drawingOptions->setLayout(drawingLayout);
+
+  QGroupBox* displayOptions = new QGroupBox(tr("Display"));
+  QVBoxLayout* displayLayout = new QVBoxLayout;
+  displayLayout->addWidget(treeControlers_->getControlerById(TreeCanvasControlers::ID_DRAW_NODE_IDS_CTRL));
+  displayLayout->addWidget(treeControlers_->getControlerById(TreeCanvasControlers::ID_DRAW_LEAF_NAMES_CTRL));
+  displayLayout->addWidget(treeControlers_->getControlerById(TreeCanvasControlers::ID_DRAW_BRANCH_LENGTHS_CTRL));
+  displayLayout->addWidget(treeControlers_->getControlerById(TreeCanvasControlers::ID_DRAW_BOOTSTRAP_VALUES_CTRL));
+  displayLayout->addWidget(treeControlers_->getControlerById(TreeCanvasControlers::ID_DRAW_CLICKABLE_AREAS_CTRL));
+  displayOptions->setLayout(displayLayout);
+  
+  QVBoxLayout* layout = new QVBoxLayout;
+  layout->addWidget(drawingOptions);
+  layout->addWidget(displayOptions);
+  layout->addStretch(1);
+  displayPanel_->setLayout(layout);
+}
+
+void PhyView::createStatsPanel_()
+{
+  statsPanel_ = new QWidget(this);
+  QVBoxLayout* statsLayout = new QVBoxLayout;
+  statsBox_ = new TreeStatisticsBox;
+  statsLayout->addWidget(statsBox_);
+  QPushButton* update = new QPushButton(tr("Update"));
+  connect(update, SIGNAL(clicked(bool)), this, SLOT(updateStatistics()));
+  statsLayout->addWidget(update);
+  statsLayout->addStretch(1);
+  statsPanel_->setLayout(statsLayout);
+}
+
+void PhyView::createBrlenPanel_()
+{
+  brlenPanel_ = new QWidget(this);
+  QVBoxLayout* brlenLayout = new QVBoxLayout;
+
+  //Set all lengths:
+  brlenSetLengths_ = new QDoubleSpinBox;
+  brlenSetLengths_->setDecimals(6);
+  brlenSetLengths_->setSingleStep(0.01);
+  QPushButton* brlenSetLengthsGo = new QPushButton(tr("Go!"));
+  connect(brlenSetLengthsGo, SIGNAL(clicked(bool)), this, SLOT(setLengths()));
+  
+  QGroupBox* brlenSetLengthsBox = new QGroupBox(tr("Set all lengths"));
+  QHBoxLayout* brlenSetLengthsBoxLayout = new QHBoxLayout;
+  brlenSetLengthsBoxLayout->addWidget(brlenSetLengths_);
+  brlenSetLengthsBoxLayout->addWidget(brlenSetLengthsGo);
+  brlenSetLengthsBoxLayout->addStretch(1);
+  brlenSetLengthsBox->setLayout(brlenSetLengthsBoxLayout);
+  
+  brlenLayout->addWidget(brlenSetLengthsBox);
+
+  //Grafen method:
+  QPushButton* brlenInitGrafen = new QPushButton(tr("Init"));
+  connect(brlenInitGrafen, SIGNAL(clicked(bool)), this, SLOT(initLengthsGrafen()));
+  
+  brlenComputeGrafen_ = new QDoubleSpinBox;
+  brlenComputeGrafen_->setValue(1.);
+  brlenComputeGrafen_->setDecimals(2);
+  brlenComputeGrafen_->setSingleStep(0.1);
+  QPushButton* brlenComputeGrafenGo = new QPushButton(tr("Go!"));
+  connect(brlenComputeGrafenGo, SIGNAL(clicked(bool)), this, SLOT(computeLengthsGrafen()));
+
+  QGroupBox* brlenGrafenBox = new QGroupBox(tr("Grafen"));
+  QHBoxLayout* brlenGrafenBoxLayout = new QHBoxLayout;
+  brlenGrafenBoxLayout->addWidget(brlenInitGrafen);
+  brlenGrafenBoxLayout->addWidget(brlenComputeGrafen_);
+  brlenGrafenBoxLayout->addWidget(brlenComputeGrafenGo);
+  brlenGrafenBoxLayout->addStretch(1);
+  brlenGrafenBox->setLayout(brlenGrafenBoxLayout);
+  
+  brlenLayout->addWidget(brlenGrafenBox);
+
+  //To clock tree:
+  QPushButton* brlenToClockTree = new QPushButton(tr("Convert to clock"));
+  connect(brlenToClockTree, SIGNAL(clicked(bool)), this, SLOT(convertToClockTree()));
+  brlenLayout->addWidget(brlenToClockTree);
+
+  //Midpoint rooting:
+  QPushButton* brlenMidpointRooting = new QPushButton(tr("Midpoint rooting"));
+  connect(brlenMidpointRooting, SIGNAL(clicked(bool)), this, SLOT(midpointRooting()));
+  brlenLayout->addWidget(brlenMidpointRooting);
+
+  ////
+  brlenLayout->addStretch(1);
+  brlenPanel_->setLayout(brlenLayout);
+}
+
+void PhyView::createMouseControlPanel_()
+{
+  mouseControlPanel_ = new QWidget;
+
+  QStringList mouseActions;
+  mouseActions.append(tr("None"));
+  mouseActions.append(tr("Swap"));
+  mouseActions.append(tr("Order down"));
+  mouseActions.append(tr("Order up"));
+  mouseActions.append(tr("Root on node"));
+  mouseActions.append(tr("Root on branch"));
+  mouseActions.append(tr("Sample subtree"));
+  mouseActions.append(tr("Collapse"));
+  mouseActions.append(tr("Delete subtree"));
+  mouseActions.append(tr("Copy subtree"));
+  mouseActions.append(tr("Cut subtree"));
+  mouseActions.append(tr("Insert on node"));
+  mouseActions.append(tr("Insert on branch"));
+
+  leftButton_ = new QComboBox;
+  leftButton_->addItems(mouseActions);
+  middleButton_ = new QComboBox;
+  middleButton_->addItems(mouseActions);
+  rightButton_ = new QComboBox;
+  rightButton_->addItems(mouseActions);
+
+  QFormLayout* formLayout = new QFormLayout;
+  formLayout->addRow(tr("Left:"), leftButton_);
+  formLayout->addRow(tr("Middle:"), middleButton_);
+  formLayout->addRow(tr("Right:"), rightButton_);
+
+  mouseControlPanel_->setLayout(formLayout);
+}
+
+void PhyView::createDataPanel_()
+{
+  dataPanel_ = new QWidget;
+  QVBoxLayout* dataLayout = new QVBoxLayout;
+  
+  loadData_ = new QPushButton(tr("Load Data"));
+  connect(loadData_, SIGNAL(clicked(bool)), this, SLOT(attachData()));
+  dataLayout->addWidget(loadData_);
+  
+  saveData_ = new QPushButton(tr("Save Data"));
+  connect(saveData_, SIGNAL(clicked(bool)), this, SLOT(saveData()));
+  dataLayout->addWidget(saveData_);
+ 
+  addData_ = new QPushButton(tr("Add Data"));
+  connect(addData_, SIGNAL(clicked(bool)), this, SLOT(addData()));
+  dataLayout->addWidget(addData_);
+ 
+  removeData_ = new QPushButton(tr("Remove Data"));
+  connect(removeData_, SIGNAL(clicked(bool)), this, SLOT(removeData()));
+  dataLayout->addWidget(removeData_);
+  
+  renameData_ = new QPushButton(tr("Rename Data"));
+  connect(renameData_, SIGNAL(clicked(bool)), this, SLOT(renameData()));
+  dataLayout->addWidget(renameData_);
+
+  translateNames_ = new QPushButton(tr("Translate"));
+  connect(translateNames_, SIGNAL(clicked(bool)), this, SLOT(translateNames()));
+  dataLayout->addWidget(translateNames_);
+
+  duplicateDownSelection_ = new QPushButton(tr("Duplicate down"));
+  connect(duplicateDownSelection_, SIGNAL(clicked(bool)), this, SLOT(duplicateDownSelection()));
+  dataLayout->addWidget(duplicateDownSelection_);
+
+  snapData_ = new QPushButton(tr("Snap shot"));
+  connect(snapData_, SIGNAL(clicked(bool)), this, SLOT(snapData()));
+  dataLayout->addWidget(snapData_);
+   
+  dataPanel_->setLayout(dataLayout);
+}
+
+void PhyView::createSearchPanel_()
+{
+  searchPanel_ = new QWidget;
+  QVBoxLayout* searchLayout = new QVBoxLayout;
+  
+  searchText_ = new QLineEdit();
+  connect(searchText_, SIGNAL(returnPressed()), this, SLOT(searchText()));
+  searchLayout->addWidget(searchText_);
+  
+  searchResults_ = new QListWidget();
+  searchResults_->setSelectionMode(QAbstractItemView::SingleSelection);
+  connect(searchResults_, SIGNAL(itemClicked(QListWidgetItem*)), this, SLOT(searchResultSelected()));
+  searchLayout->addWidget(searchResults_);
+  
+  searchPanel_->setLayout(searchLayout);
+}
+
+void PhyView::createActions_()
+{
+  openAction_ = new QAction(tr("&Open"), this);
+  openAction_->setShortcut(tr("Ctrl+O"));
+  openAction_->setStatusTip(tr("Open a new tree file"));
+  connect(openAction_, SIGNAL(triggered()), this, SLOT(openTree()));
+
+  saveAction_ = new QAction(tr("&Save"), this);
+  saveAction_->setShortcut(tr("Ctrl+S"));
+  saveAction_->setStatusTip(tr("Save the current tree to file"));
+  saveAction_->setDisabled(true);
+  connect(saveAction_, SIGNAL(triggered()), this, SLOT(saveTree()));
+
+  saveAsAction_ = new QAction(tr("Save &as"), this);
+  saveAsAction_->setShortcut(tr("Ctrl+Shift+S"));
+  saveAsAction_->setStatusTip(tr("Save the current tree to a file"));
+  saveAsAction_->setDisabled(true);
+  connect(saveAsAction_, SIGNAL(triggered()), this, SLOT(saveTreeAs()));
+
+  closeAction_ = new QAction(tr("&Close"), this);
+  closeAction_->setShortcut(tr("Ctrl+W"));
+  closeAction_->setStatusTip(tr("Close the current tree plot."));
+  closeAction_->setDisabled(true);
+  connect(closeAction_, SIGNAL(triggered()), this, SLOT(closeTree()));
+
+  exportAction_ = new QAction(tr("Export as &Image"), this);
+  exportAction_->setShortcut(tr("Ctrl+I"));
+  exportAction_->setStatusTip(tr("Print the current tree plot."));
+  exportAction_->setDisabled(true);
+  connect(exportAction_, SIGNAL(triggered()), this, SLOT(exportTree()));
+
+  printAction_ = new QAction(tr("&Print"), this);
+  printAction_->setShortcut(tr("Ctrl+P"));
+  printAction_->setStatusTip(tr("Print the current tree plot."));
+  printAction_->setDisabled(true);
+  connect(printAction_, SIGNAL(triggered()), this, SLOT(printTree()));
+
+  exitAction_ = new QAction(tr("&Quit"), this);
+  exitAction_->setShortcut(tr("Ctrl+Q"));
+  exitAction_->setStatusTip(tr("Quit PhyView"));
+  connect(exitAction_, SIGNAL(triggered()), this, SLOT(exit()));
+
+  cascadeWinAction_ = new QAction(tr("&Cascade windows"), this);
+  connect(cascadeWinAction_, SIGNAL(triggered()), mdiArea_, SLOT(cascadeSubWindows()));
+
+  tileWinAction_ = new QAction(tr("&Tile windows"), this);
+  connect(tileWinAction_, SIGNAL(triggered()), mdiArea_, SLOT(tileSubWindows()));
+  
+  aboutAction_ = new QAction(tr("About"), this);
+  connect(aboutAction_, SIGNAL(triggered()), this, SLOT(about()));
+  aboutBppAction_ = new QAction(tr("About Bio++"), this);
+  connect(aboutBppAction_, SIGNAL(triggered()), this, SLOT(aboutBpp()));
+  aboutQtAction_ = new QAction(tr("About Qt"), this);
+  connect(aboutQtAction_, SIGNAL(triggered()), qApp, SLOT(aboutQt()));
+
+  undoAction_ = manager_.createUndoAction(this);
+  redoAction_ = manager_.createRedoAction(this);
+  undoAction_->setShortcut(QKeySequence("Ctrl+Z"));
+  redoAction_->setShortcut(QKeySequence("Shift+Ctrl+Z"));
+}
+
+
+
+
+void PhyView::createMenus_()
+{
+  fileMenu_ = menuBar()->addMenu(tr("&File"));
+  fileMenu_->addAction(openAction_);
+  fileMenu_->addAction(saveAction_);
+  fileMenu_->addAction(saveAsAction_);
+  fileMenu_->addAction(closeAction_);
+  fileMenu_->addAction(exportAction_);
+  fileMenu_->addAction(printAction_);
+  fileMenu_->addAction(exitAction_);
+  
+  editMenu_ = menuBar()->addMenu(tr("&Edit"));
+  editMenu_->addAction(undoAction_);
+  editMenu_->addAction(redoAction_);
+  
+  viewMenu_ = menuBar()->addMenu(tr("&View"));
+  viewMenu_->addAction(statsDockWidget_->toggleViewAction());
+  viewMenu_->addAction(displayDockWidget_->toggleViewAction());
+  viewMenu_->addAction(brlenDockWidget_->toggleViewAction());
+  viewMenu_->addAction(undoDockWidget_->toggleViewAction());
+  viewMenu_->addAction(mouseControlDockWidget_->toggleViewAction());
+  viewMenu_->addAction(dataDockWidget_->toggleViewAction());
+  viewMenu_->addAction(searchDockWidget_->toggleViewAction());
+  viewMenu_->addAction(cascadeWinAction_);
+  viewMenu_->addAction(tileWinAction_);
+  
+  helpMenu_ = menuBar()->addMenu(tr("&Help"));
+  helpMenu_->addAction(aboutAction_);
+  helpMenu_->addAction(aboutBppAction_);
+  helpMenu_->addAction(aboutQtAction_);
+}
+
+
+
+
+void PhyView::createStatusBar_()
+{
+  updateStatusBar();
+}
+
+
+void PhyView::closeEvent(QCloseEvent* event)
+{
+
+}
+
+
+
+TreeDocument* PhyView::createNewDocument(Tree* tree)
+{
+  TreeDocument* doc = new TreeDocument();
+  doc->setTree(*tree);
+  manager_.addStack(&doc->getUndoStack());
+  TreeSubWindow *subWindow = new TreeSubWindow(this, doc, treeControlers_->getSelectedTreeDrawing());
+  mdiArea_->addSubWindow(subWindow);
+  treeControlers_->applyOptions(&subWindow->getTreeCanvas());
+  subWindow->show();
+  setCurrentSubWindow(subWindow);
+  return doc;
+}
+
+
+
+QList<TreeDocument*> PhyView::getNonActiveDocuments()
+{
+  QList<TreeDocument*> documents;
+  QList<QMdiSubWindow *> lst = mdiArea_->subWindowList();
+  for (int i = 0; i < lst.size(); ++i) {
+    if (lst[i] != mdiArea_->currentSubWindow())
+      documents.push_back(dynamic_cast<TreeSubWindow*>(lst[i])->getDocument());
+  }
+  return documents;
+}
+
+
+
+void PhyView::readTree(const QString& path, const string& format)
+{
+  auto_ptr<ITree> treeReader(ioTreeFactory_.createReader(format));
+  try {
+    auto_ptr<Tree> tree(treeReader->read(path.toStdString()));
+    TreeDocument* doc = createNewDocument(tree.get());
+    doc->setFile(path.toStdString(), format);
+    saveAction_->setEnabled(true);
+    saveAsAction_->setEnabled(true);
+    closeAction_->setEnabled(true);
+    exportAction_->setEnabled(true);
+    printAction_->setEnabled(true);
+    //We need to remove and add action again for menu to be updated :s
+    fileMenu_->removeAction(saveAction_);
+    fileMenu_->removeAction(saveAsAction_);
+    fileMenu_->removeAction(closeAction_);
+    fileMenu_->removeAction(exportAction_);
+    fileMenu_->removeAction(printAction_);
+    fileMenu_->insertAction(exitAction_, saveAction_);
+    fileMenu_->insertAction(exitAction_, saveAsAction_);
+    fileMenu_->insertAction(exitAction_, closeAction_);
+    fileMenu_->insertAction(exitAction_, exportAction_);
+    fileMenu_->insertAction(exitAction_, printAction_);
+  } catch (Exception& e) {
+    QMessageBox::critical(this, tr("Ouch..."), tr("Error when reading file:\n") + tr(e.what()));
+  }
+}
+
+
+
+void PhyView::openTree()
+{
+  treeFileDialog_->setAcceptMode(QFileDialog::AcceptOpen);
+  if (treeFileDialog_->exec() == QDialog::Accepted) {
+    QStringList path = treeFileDialog_->selectedFiles();
+    string format = IOTreeFactory::NEWICK_FORMAT;
+    if (treeFileDialog_->selectedNameFilter() == treeFileFilters_[1])
+      format = IOTreeFactory::NEXUS_FORMAT;
+    else if (treeFileDialog_->selectedNameFilter() == treeFileFilters_[2])
+      format = IOTreeFactory::NHX_FORMAT;
+    readTree(path[0], format);
+  }
+}
+
+
+
+void PhyView::setCurrentSubWindow(TreeSubWindow* tsw)
+{
+  clearSearchResults();
+  if (tsw)
+  {
+    statsBox_->updateTree(tsw->getTree());
+    treeControlers_->setTreeCanvas(&tsw->getTreeCanvas());
+    treeControlers_->actualizeOptions();
+    manager_.setActiveStack(&tsw->getDocument()->getUndoStack());
+  }
+}
+
+bool PhyView::saveTree()
+{
+  TreeDocument* doc = getActiveDocument();
+  if (doc->getFilePath() == "")
+    return saveTreeAs();
+  string format = doc->getFileFormat();
+  auto_ptr<OTree> treeWriter(ioTreeFactory_.createWriter(format));
+  Nhx* nhx = dynamic_cast<Nhx*>(treeWriter.get());
+  if (nhx) {
+    TreeTemplate<Node> treeCopy(*doc->getTree());
+    nhx->changeNamesToTags(*treeCopy.getRootNode());
+    treeWriter->write(treeCopy, doc->getFilePath(), true);
+  } else {
+    treeWriter->write(*doc->getTree(), doc->getFilePath(), true);
+
+  }
+  return true;
+}
+
+bool PhyView::saveTreeAs()
+{
+  treeFileDialog_->setAcceptMode(QFileDialog::AcceptSave);
+  if (treeFileDialog_->exec() == QDialog::Accepted) {
+    QStringList path = treeFileDialog_->selectedFiles();
+    TreeDocument* doc = getActiveDocument();
+    string format = IOTreeFactory::NEWICK_FORMAT;
+    if (treeFileDialog_->selectedNameFilter() == treeFileFilters_[1])
+      format = IOTreeFactory::NEXUS_FORMAT;
+    else if (treeFileDialog_->selectedNameFilter() == treeFileFilters_[2])
+      format = IOTreeFactory::NHX_FORMAT;
+    doc->setFile(path[0].toStdString(), format);
+    return saveTree();
+  }
+  return false;
+}
+
+void PhyView::exportTree()
+{
+  if (imageExportDialog_->exec() == QDialog::Accepted) {
+    imageExportDialog_->process(getActiveSubWindow()->getTreeCanvas().scene());
+  }
+}
+
+void PhyView::printTree()
+{
+  if (printDialog_->exec() == QDialog::Accepted) {
+    QPainter painter(printer_);
+    getActiveSubWindow()->getTreeCanvas().scene()->render(&painter);
+    painter.end();
+  }
+}
+
+void PhyView::closeTree()
+{
+  if (mdiArea_->currentSubWindow())
+    mdiArea_->currentSubWindow()->close();
+  if (mdiArea_->subWindowList().size() == 0) {
+    saveAction_->setDisabled(true);
+    saveAsAction_->setDisabled(true);
+    closeAction_->setDisabled(true);
+    exportAction_->setDisabled(true);
+    saveAction_->setDisabled(true);
+  }
+}
+
+void PhyView::exit()
+{
+  close();
+}
+
+void PhyView::aboutBpp()
+{
+  QMessageBox msgBox;
+  msgBox.setText("Bio++ 2.0.1.");
+  msgBox.setInformativeText("bpp-core 2.0.2\nbpp-seq 2.0.2.\nbpp-phyl 2.0.2.\nbpp-qt 2.0.1");
+  msgBox.exec();
+}
+
+void PhyView::about()
+{
+  QMessageBox msgBox;
+  msgBox.setText("This is Bio++ Phy View version 0.2.0.");
+  msgBox.setInformativeText("Julien Dutheil <julien.dutheil at univ-montp2.fr>.");
+  msgBox.exec();
+}
+
+void PhyView::updateStatusBar()
+{
+}
+
+void PhyView::setLengths()
+{
+  if (hasActiveDocument())
+    submitCommand(new SetLengthCommand(getActiveDocument(), brlenSetLengths_->value()));
+}
+
+void PhyView::initLengthsGrafen()
+{
+  if (hasActiveDocument())
+    submitCommand(new InitGrafenCommand(getActiveDocument()));
+}
+
+void PhyView::computeLengthsGrafen()
+{
+  if (hasActiveDocument())
+    submitCommand(new ComputeGrafenCommand(getActiveDocument(), brlenComputeGrafen_->value()));
+}
+
+void PhyView::convertToClockTree()
+{
+  if (hasActiveDocument())
+    submitCommand(new ConvertToClockTreeCommand(getActiveDocument()));
+}
+
+void PhyView::midpointRooting()
+{
+  if (hasActiveDocument())
+    try {
+      submitCommand(new MidpointRootingCommand(getActiveDocument()));
+    } catch (NodeException& ex) {
+      QMessageBox::critical(this, tr("Oups..."), tr("Some branch do not have lengths."));
+    }
+}
+
+void PhyView::translateNames()
+{
+  if (hasActiveDocument())
+  {
+    translateNameChooser_->translateTree(*getActiveDocument()->getTree()); 
+  }
+}
+
+void PhyView::controlerTakesAction()
+{
+  QList<QMdiSubWindow *> lst = mdiArea_->subWindowList();
+  for (int i = 0; i < lst.size(); ++i) {
+    dynamic_cast<TreeSubWindow*>(lst[i])->getTreeCanvas().redraw();
+  }
+}
+
+void PhyView::attachData()
+{
+  dataFileDialog_->setAcceptMode(QFileDialog::AcceptOpen);
+  if (dataFileDialog_->exec() == QDialog::Accepted) {
+    QStringList path = dataFileDialog_->selectedFiles();
+    string sep = ",";
+    if (dataFileDialog_->selectedNameFilter() == dataFileFilters_[1])
+      sep = "\t";
+    ifstream file(path[0].toStdString().c_str(), ios::in);
+    DataTable* table = DataTable::read(file, sep);
+    dataLoader_->load(table);
+  }
+}
+
+void PhyView::saveData()
+{
+  if (hasActiveDocument())
+  {
+    dataFileDialog_->setAcceptMode(QFileDialog::AcceptSave);
+    if (dataFileDialog_->exec() == QDialog::Accepted) {
+      QStringList path = dataFileDialog_->selectedFiles();
+      string sep = ",";
+      if (dataFileDialog_->selectedNameFilter() == dataFileFilters_[1])
+        sep = "\t";
+
+      getActiveSubWindow()->writeTableToFile(path[0].toStdString(), sep);
+    }
+  }
+}
+
+void PhyView::addData()
+{
+  if (hasActiveDocument())
+  {
+    bool ok;
+    QString name = QInputDialog::getText(this, tr("Set property name"), tr("Property name"), QLineEdit::Normal, tr("New property"), &ok);
+    if (ok)
+      submitCommand(new AddDataCommand(getActiveDocument(), name));
+  }
+}
+
+void PhyView::removeData()
+{
+  if (hasActiveDocument())
+  {
+    vector<string> tmp;
+    TreeTemplateTools::getNodePropertyNames(*getActiveDocument()->getTree()->getRootNode(), tmp);
+    if (tmp.size() == 0) {
+      QMessageBox::information(this, tr("Warning"), tr("No removable data is attached to this tree."), QMessageBox::Cancel);
+      return;
+    }
+    QStringList properties;
+    for (size_t i = 0; i < tmp.size(); ++i) {
+      properties.append(QtTools::toQt(tmp[i]));
+    }
+    bool ok;
+    QString name = QInputDialog::getItem(this, tr("Get property name"), tr("Property name"), properties, 0, false, &ok);
+    if (ok)
+      submitCommand(new RemoveDataCommand(getActiveDocument(), name));
+  }
+}
+
+void PhyView::renameData()
+{
+  if (hasActiveDocument())
+  {
+    vector<string> tmp;
+    TreeTemplateTools::getNodePropertyNames(*getActiveDocument()->getTree()->getRootNode(), tmp);
+    if (tmp.size() == 0) {
+      QMessageBox::information(this, tr("Warning"), tr("No data which can be renaded is attached to this tree."), QMessageBox::Cancel);
+      return;
+    }
+    QStringList properties;
+    for (size_t i = 0; i < tmp.size(); ++i) {
+      properties.append(QtTools::toQt(tmp[i]));
+    }
+    bool ok;
+    QString fromName = QInputDialog::getItem(this, tr("Get property name"), tr("Property name"), properties, 0, false, &ok);
+    if (ok) {
+      QString toName = QInputDialog::getText(this, tr("Set property name"), tr("Property name"), QLineEdit::Normal, tr("New property"), &ok);
+      if (ok) { 
+        submitCommand(new RenameDataCommand(getActiveDocument(), fromName, toName));
+      }
+    }
+  }
+}
+
+void PhyView::duplicateDownSelection()
+{
+  if (hasActiveDocument())
+  {
+    getActiveSubWindow()->duplicateDownSelection(1);
+  }
+}
+
+void PhyView::snapData()
+{
+  if (hasActiveDocument())
+  {
+    submitCommand(new SnapCommand(getActiveDocument()));
+  }
+}
+
+
+void PhyView::searchText()
+{
+  if (!getActiveSubWindow())
+    return;
+  getActiveSubWindow()->getTreeCanvas().redraw();
+  clearSearchResults();
+  QList<QGraphicsTextItem*> results = getActiveSubWindow()->getTreeCanvas().searchText(searchText_->text());
+  for (int i = 0; i < results.size(); ++i) {
+    searchResults_->addItem(results[i]->toPlainText());
+    searchResultsItems_.append(results[i]);
+    results[i]->setDefaultTextColor(Qt::red);
+  }
+}
+
+void PhyView::searchResultSelected()
+{
+  getActiveSubWindow()->getTreeCanvas().ensureVisible(searchResultsItems_[searchResults_->currentRow()]);
+}
+
+int main(int argc, char *argv[])
+{
+  QApplication app(argc, argv);
+
+  PhyView* phyview = new PhyView();
+  phyview->show();
+  
+  //Parse command line arguments:
+  QStringList args = app.arguments();
+  string format = IOTreeFactory::NEWICK_FORMAT;
+  QTextCodec* codec = QTextCodec::codecForLocale();
+  for (int i = 1; i < args.size(); ++i) {
+    if (args[i] == "--nhx") {
+      format = IOTreeFactory::NHX_FORMAT;
+    } else if (args[i] == "--nexus") {
+      format = IOTreeFactory::NEWICK_FORMAT;
+    } else if (args[i] == "--newick") {
+      format = IOTreeFactory::NEWICK_FORMAT;
+    } else if (args[i] == "--enc") {
+      if (i == args.size() - 1) {
+        cerr << "You must specify a text encoding after --enc tag." << endl;
+        exit(1);
+      }
+      ++i;
+      codec = QTextCodec::codecForName(args[i].toStdString().c_str());
+    } else {
+      phyview->readTree(args[i], format);
+    }
+  }
+  QTextCodec::setCodecForCStrings(codec);
+  return app.exec();
+}
+
+
diff --git a/bppPhyView/PhyView.h b/bppPhyView/PhyView.h
new file mode 100644
index 0000000..75f926f
--- /dev/null
+++ b/bppPhyView/PhyView.h
@@ -0,0 +1,387 @@
+//
+// File: PhyView.h
+// Created by: Julien Dutheil
+// Created on: Tue Aug 05 14:59 2009
+//
+
+/*
+Copyright or © or Copr. Bio++ Development Team, (November 16, 2004)
+
+This software is a computer program whose purpose is to provide
+graphic components to develop bioinformatics applications.
+
+This software is governed by the CeCILL  license under French law and
+abiding by the rules of distribution of free software.  You can  use, 
+modify and/ or redistribute the software under the terms of the CeCILL
+license as circulated by CEA, CNRS and INRIA at the following URL
+"http://www.cecill.info". 
+
+As a counterpart to the access to the source code and  rights to copy,
+modify and redistribute granted by the license, users are provided only
+with a limited warranty  and the software's author,  the holder of the
+economic rights,  and the successive licensors  have only  limited
+liability. 
+
+In this respect, the user's attention is drawn to the risks associated
+with loading,  using,  modifying and/or developing or reproducing the
+software by the user in light of its specific status of free software,
+that may mean  that it is complicated to manipulate,  and  that  also
+therefore means  that it is reserved for developers  and  experienced
+professionals having in-depth computer knowledge. Users are therefore
+encouraged to load and test the software's suitability as regards their
+requirements in conditions enabling the security of their systems and/or 
+data to be ensured and,  more generally, to use and operate it in the 
+same conditions as regards security. 
+
+The fact that you are presently reading this means that you have had
+knowledge of the CeCILL license and that you accept its terms.
+*/
+
+#include "TreeSubWindow.h"
+#include "TreeCommands.h"
+
+//From Qt:
+#include <QWidget>
+#include <QPaintEvent>
+#include <QMainWindow>
+#include <QFileDialog>
+#include <QMdiArea>
+#include <QUndoGroup>
+#include <QDialog>
+#include <QListWidget>
+#include <QRadioButton>
+#include <QPrinter>
+#include <QPrintDialog>
+
+class QAction;
+class QLabel;
+
+#include <Bpp/Phyl/Graphics/TreeDrawing.h>
+#include <Bpp/Phyl/Io/IoTreeFactory.h>
+#include <Bpp/Qt/Tree/TreeCanvas.h>
+#include <Bpp/Qt/Tree/TreeCanvasControlers.h>
+#include <Bpp/Qt/Tree/TreeStatisticsBox.h>
+
+using namespace bpp;
+
+class PhyView;
+
+class MouseActionListener:
+  public MouseAdapter
+{
+  private:
+    PhyView* phyview_;
+    QDialog* treeChooser_;
+    QListWidget* treeList_;
+
+  public:
+    MouseActionListener(PhyView* phyview);
+
+    MouseActionListener* clone() const { return new MouseActionListener(*this); }
+    
+    void mousePressEvent(QMouseEvent *event);
+
+    bool isAutonomous() const { return false; }
+
+  private:
+    TreeTemplate<Node>* pickTree_();
+
+};  
+
+
+
+class TranslateNameChooser :
+  public QDialog
+{
+  Q_OBJECT
+
+  private:
+    PhyView* phyview_;
+    QFileDialog* fileDialog_;
+    QStringList fileFilters_;
+    QComboBox* fromList_, * toList_;
+    QPushButton* ok_, *cancel_;
+
+  public:
+    TranslateNameChooser(PhyView* phyview);
+
+    ~TranslateNameChooser()
+    {
+      delete fileDialog_;
+    }
+
+  public:
+    void translateTree(TreeTemplate<Node>& tree);
+};
+
+
+
+class DataLoader :
+  public QDialog
+{
+  Q_OBJECT
+
+  private:
+    PhyView* phyview_;
+    QRadioButton* idIndex_, * nameIndex_;
+    QComboBox* indexCol_;
+    QPushButton* ok_, * cancel_;
+
+  public:
+    DataLoader(PhyView* phyview);
+
+    ~DataLoader() {}
+
+  public:
+    void load(const DataTable* data);
+
+  private:
+    void addProperties_(Node* node, const DataTable& data);
+};
+
+
+
+class ImageExportDialog :
+  public QDialog
+{
+  Q_OBJECT
+
+  private:
+    PhyView* phyview_;
+    QLabel* path_;
+    QSpinBox* width_, * height_;
+    QCheckBox* transparent_, * keepAspectRatio_;
+    QPushButton* ok_, * cancel_, * browse_;
+    QFileDialog* imageFileDialog_;
+    QStringList imageFileFilters_;
+
+  public:
+    ImageExportDialog(PhyView* phyview);
+
+    ~ImageExportDialog() {}
+
+  public:
+    void process(QGraphicsScene* scene);
+
+  public slots:
+    void chosePath();
+
+};
+
+
+
+
+class TypeNumberDialog :
+  public QDialog
+{
+  Q_OBJECT
+
+  private:
+    QSpinBox* spinBox_;
+    QPushButton* ok_, * cancel_;
+
+  public:
+    TypeNumberDialog(PhyView* phyview, const string& what, unsigned int min, unsigned int max);
+
+    ~TypeNumberDialog() {}
+
+  public:
+    unsigned int getValue() const { return spinBox_->value(); }
+};
+
+
+
+class PhyView :
+  public QMainWindow,
+  public TreeCanvasControlersListener
+{
+  Q_OBJECT
+
+  private:
+    QMenu* fileMenu_;
+    QMenu* editMenu_;
+    QMenu* viewMenu_;
+    QMenu* helpMenu_;
+    QAction* openAction_;
+    QAction* saveAction_;
+    QAction* saveAsAction_;
+    QAction* closeAction_;
+    QAction* printAction_;
+    QAction* exportAction_;
+    QAction* exitAction_;
+    QAction* cascadeWinAction_;
+    QAction* tileWinAction_;
+    QAction* aboutAction_;
+    QAction* aboutBppAction_;
+    QAction* aboutQtAction_;
+    QAction* undoAction_;
+    QAction* redoAction_;
+
+    QUndoGroup manager_;
+
+    QMdiArea* mdiArea_;
+    QFileDialog* treeFileDialog_;
+    QStringList treeFileFilters_;
+    QFileDialog* dataFileDialog_;
+    QStringList dataFileFilters_;
+    IOTreeFactory ioTreeFactory_;
+    QPrinter* printer_;
+    QPrintDialog* printDialog_;
+    TreeCanvasControlers* treeControlers_;
+    QWidget* displayPanel_;
+    TreeStatisticsBox* statsBox_;
+    QWidget* statsPanel_;
+    QWidget* brlenPanel_;
+    QWidget* mouseControlPanel_;
+    QWidget* dataPanel_;
+    QWidget* searchPanel_;
+
+    QDockWidget* statsDockWidget_; 
+    QDockWidget* displayDockWidget_;
+    QDockWidget* undoDockWidget_;
+    
+    //Branch lengths operations:
+    QDockWidget* brlenDockWidget_;
+    QDoubleSpinBox* brlenSetLengths_;
+    QDoubleSpinBox* brlenComputeGrafen_;
+
+    //Mouse actions change:
+    QDockWidget* mouseControlDockWidget_;
+    QComboBox* leftButton_;
+    QComboBox* middleButton_;
+    QComboBox* rightButton_;
+
+    //Data operations:
+    QDockWidget* dataDockWidget_;
+    QPushButton* translateNames_;
+    QPushButton* loadData_;
+    QPushButton* saveData_;
+    QPushButton* addData_;
+    QPushButton* removeData_;
+    QPushButton* renameData_;
+    QPushButton* duplicateDownSelection_;
+    QPushButton* snapData_;
+
+    //Searching:
+    QDockWidget* searchDockWidget_;
+    QLineEdit*   searchText_;
+    QListWidget* searchResults_;
+
+    LabelCollapsedNodesTreeDrawingListener collapsedNodesListener_;
+
+    TranslateNameChooser* translateNameChooser_;
+
+    DataLoader* dataLoader_;
+
+    ImageExportDialog* imageExportDialog_;
+
+    QList<QGraphicsTextItem*> searchResultsItems_;
+
+  public:
+    PhyView();
+
+  public:
+    bool hasActiveDocument() const
+    {
+      return mdiArea_->currentSubWindow() != 0;
+    }
+
+    TreeDocument* getActiveDocument()
+    {
+      return dynamic_cast<TreeSubWindow*>(mdiArea_->currentSubWindow())->getDocument();
+    }
+
+    QList<TreeDocument*> getNonActiveDocuments();
+
+    TreeSubWindow* getActiveSubWindow()
+    {
+      return dynamic_cast<TreeSubWindow*>(mdiArea_->currentSubWindow());
+    }
+
+    void submitCommand(QUndoCommand* cmd)
+    {
+      manager_.activeStack()->push(cmd);
+    }
+
+    TreeDocument* createNewDocument(Tree* tree);
+
+    MouseActionListener* getMouseActionListener()
+    {
+      return new MouseActionListener(this);
+    }
+
+    QString getMouseLeftButtonActionType() const { return leftButton_->currentText(); }
+    QString getMouseMiddleButtonActionType() const { return middleButton_->currentText(); }
+    QString getMouseRightButtonActionType() const { return rightButton_->currentText(); }
+
+    void controlerTakesAction();
+    
+    void readTree(const QString& path, const string& format);
+
+  protected:
+    void closeEvent(QCloseEvent* event);
+
+  private slots:
+    void openTree();
+    bool saveTree();
+    bool saveTreeAs();
+    void closeTree();
+    void exportTree();
+    void printTree();
+    void exit();
+    void about();
+    void aboutBpp();
+    void updateStatusBar();
+    void setCurrentSubWindow(TreeSubWindow* tsw);
+    void setCurrentSubWindow(QMdiSubWindow *msw)
+    {
+      TreeSubWindow* tsw = dynamic_cast<TreeSubWindow*>(msw);
+      if (tsw) setCurrentSubWindow(tsw);
+    }
+
+    void updateStatistics()
+    {
+      statsBox_->updateTree(*getActiveDocument()->getTree());
+    }
+    void setLengths();
+    void initLengthsGrafen();
+    void computeLengthsGrafen();
+    void convertToClockTree();
+    void midpointRooting();
+    void translateNames();
+
+    void attachData();
+    void saveData();
+    void addData();
+    void removeData();
+    void renameData();
+    void duplicateDownSelection();
+    void snapData();
+    void searchText();
+    void searchResultSelected();
+
+    void clearSearchResults() {
+      searchResults_->clear();
+      searchResultsItems_.clear();
+    }
+
+  private:
+    void initGui_();
+    void createActions_();
+    void createMenus_();
+    void createStatusBar_();
+
+    void createStatsPanel_();
+    void createDisplayPanel_();
+    void createBrlenPanel_();
+    void createMouseControlPanel_();
+    void createDataPanel_();
+    void createSearchPanel_();
+
+};
+
+
+
+
+int main(int argc, char *argv[]);
+
diff --git a/bppPhyView/TreeCommands.cpp b/bppPhyView/TreeCommands.cpp
new file mode 100644
index 0000000..096cc72
--- /dev/null
+++ b/bppPhyView/TreeCommands.cpp
@@ -0,0 +1,149 @@
+//
+// File: TreeCommands.cpp
+// Created by: Julien Dutheil
+// Created on: Fri Oct 13 21:25 2006
+//
+
+/*
+Copyright or © or Copr. Bio++ Development Team, (November 16, 2004)
+
+This software is a computer program whose purpose is to provide classes
+for phylogenetic data analysis.
+
+This software is governed by the CeCILL  license under French law and
+abiding by the rules of distribution of free software.  You can  use, 
+modify and/ or redistribute the software under the terms of the CeCILL
+license as circulated by CEA, CNRS and INRIA at the following URL
+"http://www.cecill.info". 
+
+As a counterpart to the access to the source code and  rights to copy,
+modify and redistribute granted by the license, users are provided only
+with a limited warranty  and the software's author,  the holder of the
+economic rights,  and the successive licensors  have only  limited
+liability. 
+
+In this respect, the user's attention is drawn to the risks associated
+with loading,  using,  modifying and/or developing or reproducing the
+software by the user in light of its specific status of free software,
+that may mean  that it is complicated to manipulate,  and  that  also
+therefore means  that it is reserved for developers  and  experienced
+professionals having in-depth computer knowledge. Users are therefore
+encouraged to load and test the software's suitability as regards their
+requirements in conditions enabling the security of their systems and/or 
+data to be ensured and,  more generally, to use and operate it in the 
+same conditions as regards security. 
+
+The fact that you are presently reading this means that you have had
+knowledge of the CeCILL license and that you accept its terms.
+*/
+
+#include "TreeCommands.h"
+
+using namespace std;
+
+TranslateNodeNamesCommand::TranslateNodeNamesCommand(TreeDocument* doc, const DataTable& table, unsigned int from, unsigned int to):
+  AbstractCommand(QtTools::toQt("Translates nodes names from " + table.getColumnName(from) + " to " + table.getColumnName(to) + "."), doc)
+{
+  new_ = new TreeTemplate<Node>(*old_);
+  //Build translation:
+  map<string, string> tln;
+  for(unsigned int i = 0; i < table.getNumberOfRows(); ++i) {
+    tln[table(i, from)] = table(i, to);
+  }
+  vector<Node*> nodes = new_->getNodes();
+  for (unsigned int i = 0; i < nodes.size(); i++) {
+    if (nodes[i]->hasName()) {
+      map<string,string>::iterator it = tln.find(nodes[i]->getName());
+      if (it != tln.end()) {
+        nodes[i]->setName(it->second);
+      }
+    }
+  }
+}
+
+AttachDataCommand::AttachDataCommand(TreeDocument* doc, const DataTable& data, unsigned int index, bool useNames):
+  AbstractCommand(QtTools::toQt("Attach data to tree."), doc)
+{
+  new_ = new TreeTemplate<Node>(*old_);
+  addProperties_(new_->getRootNode(), data, index, useNames);
+}
+
+void AttachDataCommand::addProperties_(Node* node, const DataTable& data, unsigned int index, bool useNames)
+{
+  if (!useNames) {
+    //Use id
+    string id = TextTools::toString(node->getId());
+    for (unsigned int i = 0; i < data.getNumberOfRows(); ++i) {
+      if (data(i, index) == id) {
+        for (unsigned int j = 0; j < data.getNumberOfColumns(); ++j) {
+          if (j != index) {
+            node->setNodeProperty(data.getColumnName(j), BppString(data(i, j)));
+          }
+        }
+      }
+    }
+  } else {
+    //Use name:
+    if (node->hasName()) {
+      string name = node->getName();
+      for (unsigned int i = 0; i < data.getNumberOfRows(); ++i) {
+        if (data(i, index) == name) {
+          for (unsigned int j = 0; j < data.getNumberOfColumns(); ++j) {
+            if (j != index) {
+              node->setNodeProperty(data.getColumnName(j), BppString(data(i, j)));
+            }
+          }
+        }
+      }
+    }
+  }
+  for (unsigned int i = 0; i < node->getNumberOfSons(); ++i)
+    addProperties_(node->getSon(i), data, index, useNames);
+}
+
+AddDataCommand::AddDataCommand(TreeDocument* doc, const QString& name):
+  AbstractCommand(QString("Add data '") + name + QString("' to tree."), doc)
+{
+  new_ = new TreeTemplate<Node>(*old_);
+  addProperty_(new_->getRootNode(), name);
+}
+
+void AddDataCommand::addProperty_(Node* node, const QString& name)
+{
+  node->setNodeProperty(name.toStdString(), BppString(""));
+  for (unsigned int i = 0; i < node->getNumberOfSons(); ++i)
+    addProperty_(node->getSon(i), name);
+}
+
+RemoveDataCommand::RemoveDataCommand(TreeDocument* doc, const QString& name):
+  AbstractCommand(QString("Remove data '") + name + QString("' from tree."), doc)
+{
+  new_ = new TreeTemplate<Node>(*old_);
+  removeProperty_(new_->getRootNode(), name);
+}
+
+void RemoveDataCommand::removeProperty_(Node* node, const QString& name)
+{
+  node->deleteNodeProperty(name.toStdString());
+  for (unsigned int i = 0; i < node->getNumberOfSons(); ++i)
+    removeProperty_(node->getSon(i), name);
+}
+
+RenameDataCommand::RenameDataCommand(TreeDocument* doc, const QString& oldName, const QString& newName):
+  AbstractCommand(QString("Rename data '") + oldName + QString("' to '" + newName + "' from tree."), doc)
+{
+  new_ = new TreeTemplate<Node>(*old_);
+  renameProperty_(new_->getRootNode(), oldName, newName);
+}
+
+void RenameDataCommand::renameProperty_(Node* node, const QString& oldName, const QString& newName)
+{
+  if (node->hasNodeProperty(oldName.toStdString())) {
+    Clonable* property = node->removeNodeProperty(oldName.toStdString());
+    node->setNodeProperty(newName.toStdString(), *property);
+    delete property;
+  }
+  for (unsigned int i = 0; i < node->getNumberOfSons(); ++i)
+    renameProperty_(node->getSon(i), oldName, newName);
+}
+
diff --git a/bppPhyView/TreeCommands.h b/bppPhyView/TreeCommands.h
new file mode 100644
index 0000000..2c5f259
--- /dev/null
+++ b/bppPhyView/TreeCommands.h
@@ -0,0 +1,339 @@
+//
+// File: TreeCommands.h
+// Created by: Julien Dutheil
+// Created on: Fri Oct 13 21:25 2006
+//
+
+/*
+Copyright or � or Copr. Bio++ Development Team, (November 16, 2004)
+
+This software is a computer program whose purpose is to provide classes
+for phylogenetic data analysis.
+
+This software is governed by the CeCILL  license under French law and
+abiding by the rules of distribution of free software.  You can  use, 
+modify and/ or redistribute the software under the terms of the CeCILL
+license as circulated by CEA, CNRS and INRIA at the following URL
+"http://www.cecill.info". 
+
+As a counterpart to the access to the source code and  rights to copy,
+modify and redistribute granted by the license, users are provided only
+with a limited warranty  and the software's author,  the holder of the
+economic rights,  and the successive licensors  have only  limited
+liability. 
+
+In this respect, the user's attention is drawn to the risks associated
+with loading,  using,  modifying and/or developing or reproducing the
+software by the user in light of its specific status of free software,
+that may mean  that it is complicated to manipulate,  and  that  also
+therefore means  that it is reserved for developers  and  experienced
+professionals having in-depth computer knowledge. Users are therefore
+encouraged to load and test the software's suitability as regards their
+requirements in conditions enabling the security of their systems and/or 
+data to be ensured and,  more generally, to use and operate it in the 
+same conditions as regards security. 
+
+The fact that you are presently reading this means that you have had
+knowledge of the CeCILL license and that you accept its terms.
+*/
+
+#ifndef _COMMANDS_H_
+#define _COMMANDS_H_
+
+#include "TreeDocument.h"
+
+#include <Bpp/Text/TextTools.h>
+#include <Bpp/Numeric/DataTable.h>
+
+//From PhylLib:
+#include <Bpp/Phyl/TreeTools.h>
+
+//From Qt:
+#include <QUndoCommand>
+#include <QTime>
+
+//From bpp-qt:
+#include <Bpp/Qt/QtTools.h>
+
+//From the STL:
+#include <vector>
+
+class AbstractCommand: public QUndoCommand
+{
+  protected:
+    TreeDocument* doc_;
+    TreeTemplate<Node>* old_;
+    TreeTemplate<Node>* new_;
+
+  public:
+    AbstractCommand(const QString& name, TreeDocument* doc):
+      QUndoCommand(name),
+      doc_(doc),
+      old_(new TreeTemplate<Node>(*doc->getTree())),
+      new_(0)
+    {}
+
+    virtual ~AbstractCommand()
+    {
+      if (old_) delete old_;
+      if (new_) delete new_;
+    }
+
+  public:
+    void redo() { doOrUndo(); }
+    void undo() { doOrUndo(); }
+    
+    virtual void doOrUndo()
+    {
+      doc_->setTree(*new_);
+      doc_->modified(true);
+      doc_->updateAllViews();
+      TreeTemplate<Node>* tmp = new_;
+      new_ = old_;
+      old_ = tmp;
+    }  
+};
+
+class SetLengthCommand: public AbstractCommand
+{
+  public:
+    SetLengthCommand(TreeDocument* doc, double length):
+      AbstractCommand(QtTools::toQt("Set all lengths to " + TextTools::toString(length) + "."), doc)
+    {
+      new_ = new TreeTemplate<Node>(*old_);
+      new_->setBranchLengths(length);
+    }
+};
+
+class InitGrafenCommand: public AbstractCommand
+{
+  public:
+    InitGrafenCommand(TreeDocument* doc):
+      AbstractCommand("Init branch lengths (Grafen)", doc)
+    {
+      new_ = new TreeTemplate<Node>(*old_);
+      TreeTools::initBranchLengthsGrafen(*new_);
+    }
+};
+
+class ComputeGrafenCommand: public AbstractCommand
+{
+  public:
+    ComputeGrafenCommand(TreeDocument* doc, double power):
+      AbstractCommand(QtTools::toQt("Compute branch lengths (Grafen), power=" + TextTools::toString(power) + "."), doc)
+    {
+      new_ = new TreeTemplate<Node>(*old_);
+      TreeTools::computeBranchLengthsGrafen(*new_, power, false);
+    }
+};
+
+class ConvertToClockTreeCommand: public AbstractCommand
+{
+  public:
+    ConvertToClockTreeCommand(TreeDocument* doc):
+      AbstractCommand(QtTools::toQt("Convert to clock tree"), doc)
+    {
+      new_ = new TreeTemplate<Node>(*old_);
+      TreeTools::convertToClockTree(*new_, new_->getRootId(), true);
+    }
+};
+
+class SwapCommand: public AbstractCommand
+{
+  public:
+    SwapCommand(TreeDocument* doc, int nodeId, unsigned int i1, unsigned int i2, int id1, int id2):
+      AbstractCommand(QtTools::toQt("Swap nodes " + TextTools::toString(id1) + " and " + TextTools::toString(id2) + "."), doc)
+    {
+      new_ = new TreeTemplate<Node>(*old_);
+      new_->swapNodes(nodeId, i1, i2);
+    }
+};
+
+class OrderCommand: public AbstractCommand
+{
+  public:
+    OrderCommand(TreeDocument* doc, int nodeId, bool downward):
+      AbstractCommand(QtTools::toQt("Order nodes in subtree " + TextTools::toString(nodeId) + "."), doc)
+    {
+      new_ = new TreeTemplate<Node>(*old_);
+      TreeTemplateTools::orderTree(*new_->getNode(nodeId), downward);
+    }
+};
+
+class RerootCommand: public AbstractCommand
+{
+  public:
+    RerootCommand(TreeDocument* doc, int nodeId):
+      AbstractCommand(QtTools::toQt("Reroot at " + TextTools::toString(nodeId) + "."), doc)
+    {
+      new_ = new TreeTemplate<Node>(*old_);
+      new_->rootAt(nodeId);
+    }
+};
+
+class OutgroupCommand: public AbstractCommand
+{
+  public:
+    OutgroupCommand(TreeDocument* doc, int nodeId):
+      AbstractCommand(QtTools::toQt("New outgroup: " + TextTools::toString(nodeId) + "."), doc)
+    {
+      new_ = new TreeTemplate<Node>(*old_);
+      new_->newOutGroup(nodeId);
+    }
+};
+
+class MidpointRootingCommand: public AbstractCommand
+{
+  public:
+    MidpointRootingCommand(TreeDocument* doc) :
+      AbstractCommand(QtTools::toQt("Midpoint rooting"), doc)
+    {
+      new_ = new TreeTemplate<Node>(*old_);
+      TreeTools::midpointRooting(*new_);
+    }
+};
+
+class DeleteSubtreeCommand: public AbstractCommand
+{
+  public:
+    DeleteSubtreeCommand(TreeDocument* doc, int nodeId):
+      AbstractCommand(QtTools::toQt("Delete substree " + TextTools::toString(nodeId) + "."), doc)
+    {
+      new_ = new TreeTemplate<Node>(*old_);
+      Node* node = new_->getNode(nodeId);
+      TreeTemplateTools::dropSubtree(*new_, node);
+    }
+};
+
+class InsertSubtreeAtNodeCommand: public AbstractCommand
+{
+  public:
+    InsertSubtreeAtNodeCommand(TreeDocument* doc, int nodeId, Node* subtree):
+      AbstractCommand(QtTools::toQt("Insert substree at " + TextTools::toString(nodeId) + "."), doc)
+    {
+      new_ = new TreeTemplate<Node>(*old_);
+      Node* node = new_->getNode(nodeId);
+      node->addSon(subtree);
+      new_->resetNodesId();
+    }
+};
+
+class InsertSubtreeOnBranchCommand: public AbstractCommand
+{
+  public:
+    InsertSubtreeOnBranchCommand(TreeDocument* doc, int nodeId, Node* subtree):
+      AbstractCommand(QtTools::toQt("Insert substree below " + TextTools::toString(nodeId) + "."), doc)
+    {
+      new_ = new TreeTemplate<Node>(*old_);
+      Node* node = new_->getNode(nodeId);
+      if (!node->hasFather())
+      {
+        //Need to change root:
+        Node* father = new Node();
+        node->addSon(new_->getRootNode());
+        node->addSon(subtree);
+        new_->setRootNode(father);
+      }
+      else
+      {
+        Node* father = node->getFather();
+        father->removeSon(node);
+        Node* base = new Node();
+        base->addSon(node);
+        base->addSon(subtree);
+        father->addSon(base);
+      }
+      new_->resetNodesId();
+    }
+};
+
+class ChangeBranchLengthCommand: public AbstractCommand
+{
+  public:
+    ChangeBranchLengthCommand(TreeDocument* doc, int nodeId, double newLength):
+      AbstractCommand(QtTools::toQt("Change length of node " + TextTools::toString(nodeId) + " to " + TextTools::toString(newLength) + "."), doc)
+    {
+      new_ = new TreeTemplate<Node>(*old_);
+      Node* node = new_->getNode(nodeId);
+      node->setDistanceToFather(newLength);
+    }
+};
+
+class ChangeNodeNameCommand: public AbstractCommand
+{
+  public:
+    ChangeNodeNameCommand(TreeDocument* doc, int nodeId, const string& newName):
+      AbstractCommand(QtTools::toQt("Change name of node " + TextTools::toString(nodeId) + " to " + newName + "."), doc)
+    {
+      new_ = new TreeTemplate<Node>(*old_);
+      Node* node = new_->getNode(nodeId);
+      node->setName(newName);
+    }
+};
+
+class TranslateNodeNamesCommand: public AbstractCommand
+{
+  public:
+    TranslateNodeNamesCommand(TreeDocument* doc, const DataTable& table, unsigned int from, unsigned int to);
+};
+
+class AttachDataCommand: public AbstractCommand
+{
+  public:
+    AttachDataCommand(TreeDocument* doc, const DataTable& data, unsigned int index, bool useNames);
+
+  private:
+    static void addProperties_(Node* node, const DataTable& data, unsigned int index, bool useNames);
+};
+
+class AddDataCommand: public AbstractCommand
+{
+  public:
+    AddDataCommand(TreeDocument* doc, const QString& name);
+
+  private:
+    static void addProperty_(Node* node, const QString& name);
+};
+
+class RemoveDataCommand: public AbstractCommand
+{
+  public:
+    RemoveDataCommand(TreeDocument* doc, const QString& name);
+
+  private:
+    static void removeProperty_(Node* node, const QString& name);
+};
+
+class RenameDataCommand: public AbstractCommand
+{
+  public:
+    RenameDataCommand(TreeDocument* doc, const QString& oldName, const QString& newName);
+
+  private:
+    static void renameProperty_(Node* node, const QString& oldName, const QString& newName);
+};
+
+class SampleSubtreeCommand: public AbstractCommand
+{
+  public:
+    SampleSubtreeCommand(TreeDocument* doc, int nodeId, unsigned int size):
+      AbstractCommand(QtTools::toQt("Sample subtree " + TextTools::toString(nodeId) + " to " + TextTools::toString(size) + " leaves."), doc)
+    {
+      new_ = new TreeTemplate<Node>(*old_);
+      Node* node = new_->getNode(nodeId);
+      TreeTemplateTools::sampleSubtree(*new_, TreeTemplateTools::getLeavesNames(*node), size);
+    }
+};
+
+class SnapCommand: public AbstractCommand
+{
+  public:
+    SnapCommand(TreeDocument* doc):
+      AbstractCommand(QString("Tree snapshot (saved at ") + QTime::currentTime().toString("hh:mm:ss") + QString(")"), doc)
+    {
+      new_ = new TreeTemplate<Node>(*old_);
+    }
+};
+
+#endif //_COMMANDS_H_
+
diff --git a/bppPhyView/TreeDocument.h b/bppPhyView/TreeDocument.h
new file mode 100644
index 0000000..43e23d4
--- /dev/null
+++ b/bppPhyView/TreeDocument.h
@@ -0,0 +1,142 @@
+//
+// File: TreeDocument.h
+// Created by: Julien Dutheil
+// Created on: Tue Oct 5 22:05 2006
+//
+
+/*
+Copyright or � or Copr. Bio++ Development Team, (November 16, 2004)
+
+This software is a computer program whose purpose is to provide classes
+for phylogenetic data analysis.
+
+This software is governed by the CeCILL  license under French law and
+abiding by the rules of distribution of free software.  You can  use, 
+modify and/ or redistribute the software under the terms of the CeCILL
+license as circulated by CEA, CNRS and INRIA at the following URL
+"http://www.cecill.info". 
+
+As a counterpart to the access to the source code and  rights to copy,
+modify and redistribute granted by the license, users are provided only
+with a limited warranty  and the software's author,  the holder of the
+economic rights,  and the successive licensors  have only  limited
+liability. 
+
+In this respect, the user's attention is drawn to the risks associated
+with loading,  using,  modifying and/or developing or reproducing the
+software by the user in light of its specific status of free software,
+that may mean  that it is complicated to manipulate,  and  that  also
+therefore means  that it is reserved for developers  and  experienced
+professionals having in-depth computer knowledge. Users are therefore
+encouraged to load and test the software's suitability as regards their
+requirements in conditions enabling the security of their systems and/or 
+data to be ensured and,  more generally, to use and operate it in the 
+same conditions as regards security. 
+
+The fact that you are presently reading this means that you have had
+knowledge of the CeCILL license and that you accept its terms.
+*/
+
+#ifndef _TREEDOCUMENT_H_
+#define _TREEDOCUMENT_H_
+
+#include <Bpp/Io/FileTools.h>
+
+//From PhylLib:
+#include <Bpp/Phyl/Tree.h>
+#include <Bpp/Phyl/Io.all>
+
+//From the STL:
+#include <string>
+
+//From Qt:
+#include <QUndoStack>
+
+using namespace bpp;
+using namespace std;
+
+/**
+ * @brief Interface for document viewers.
+ */
+class DocumentView
+{
+  public:
+    virtual ~DocumentView() {}
+
+  public:
+    virtual void updateView() = 0;
+};
+
+/**
+ * Contains a tree and all associated data, if any.
+ * Also contains a path where to write, and a format,
+ * which are use for actions like "save", "save as", "save a copy".
+ */
+class TreeDocument
+{
+  private:
+    TreeTemplate<Node>* tree_;
+    std::string documentName_;
+    bool modified_;
+    std::string currentFilePath_;
+    std::string currentFileFormat_;
+    QUndoStack undoStack_;
+    vector<DocumentView*> viewers_;
+
+  public:
+    TreeDocument():
+      tree_(0),
+      documentName_(),
+      modified_(false),
+      currentFilePath_(),
+      currentFileFormat_(),
+      undoStack_()
+    {}
+
+    virtual ~TreeDocument()
+    {
+      if (tree_) delete tree_;
+    }
+    
+  public:
+    const TreeTemplate<Node>* getTree() const { return tree_; }
+    
+    TreeTemplate<Node>* getTree() { return tree_; }
+    
+    void setTree(const Tree& tree)
+    {
+      if (tree_) delete tree_;
+      tree_ = new TreeTemplate<Node>(tree);
+    }
+
+    const std::string& getName() const { return documentName_; }
+
+    void setFile(const string& filePath, const string& fileFormat)
+    {
+      currentFilePath_   = filePath;
+      currentFileFormat_ = fileFormat;
+      documentName_      = FileTools::getFileName(filePath);
+    }
+    
+    const string& getFilePath() const { return currentFilePath_; }
+    const string& getFileFormat() const { return currentFileFormat_; }
+      
+    void modified(bool yn) { modified_ = yn; }
+    bool modified() const { return modified_; }
+
+    QUndoStack& getUndoStack() { return undoStack_; }
+
+    void addView(DocumentView* viewer)
+    {
+      viewers_.push_back(viewer);
+    }
+
+    void updateAllViews()
+    {
+      for (unsigned int i = 0; i < viewers_.size(); i++)
+        viewers_[i]->updateView();
+    }
+};
+
+#endif //_TREEDOCUMENT_H_
+
diff --git a/bppPhyView/TreeSubWindow.cpp b/bppPhyView/TreeSubWindow.cpp
new file mode 100644
index 0000000..7475cca
--- /dev/null
+++ b/bppPhyView/TreeSubWindow.cpp
@@ -0,0 +1,232 @@
+//
+// File: TreeSubWindow.cpp
+// Created by: Julien Dutheil
+// Created on: Tue Aug 11 13:34 2009
+//
+
+/*
+Copyright or © or Copr. Bio++ Development Team, (November 16, 2004)
+
+This software is a computer program whose purpose is to provide
+graphic components to develop bioinformatics applications.
+
+This software is governed by the CeCILL  license under French law and
+abiding by the rules of distribution of free software.  You can  use, 
+modify and/ or redistribute the software under the terms of the CeCILL
+license as circulated by CEA, CNRS and INRIA at the following URL
+"http://www.cecill.info". 
+
+As a counterpart to the access to the source code and  rights to copy,
+modify and redistribute granted by the license, users are provided only
+with a limited warranty  and the software's author,  the holder of the
+economic rights,  and the successive licensors  have only  limited
+liability. 
+
+In this respect, the user's attention is drawn to the risks associated
+with loading,  using,  modifying and/or developing or reproducing the
+software by the user in light of its specific status of free software,
+that may mean  that it is complicated to manipulate,  and  that  also
+therefore means  that it is reserved for developers  and  experienced
+professionals having in-depth computer knowledge. Users are therefore
+encouraged to load and test the software's suitability as regards their
+requirements in conditions enabling the security of their systems and/or 
+data to be ensured and,  more generally, to use and operate it in the 
+same conditions as regards security. 
+
+The fact that you are presently reading this means that you have had
+knowledge of the CeCILL license and that you accept its terms.
+*/
+
+#include "TreeSubWindow.h"
+#include "PhyView.h"
+
+//From Qt:
+#include <QScrollArea>
+#include <QMessageBox>
+
+//From bpp-qt:
+#include <Bpp/Qt/QtTools.h>
+
+TreeSubWindow::TreeSubWindow(PhyView* phyview, TreeDocument* document, TreeDrawing* td):
+  phyview_(phyview), treeDocument_(document), treeCanvas_()
+{
+  setAttribute(Qt::WA_DeleteOnClose);
+  setWindowFilePath(QtTools::toQt(treeDocument_->getFilePath()));
+  treeDocument_->addView(this);
+  treeCanvas_ = new TreeCanvas();
+  treeCanvas_->setTree(treeDocument_->getTree());
+  treeCanvas_->setTreeDrawing(*td);
+  treeCanvas_->setMinimumSize(400,400);
+  treeCanvas_->addMouseListener(reinterpret_cast<MouseListener*>(phyview_->getMouseActionListener()));
+  connect(treeCanvas_, SIGNAL(drawingChanged()), phyview, SLOT(clearSearchResults()));
+
+  nodeEditor_ = new QTableWidget();
+  nodeEditor_->setColumnCount(3);
+  connect(nodeEditor_, SIGNAL(itemChanged(QTableWidgetItem *)), this, SLOT(nodeEditorHasChanged(QTableWidgetItem*)));
+  QStringList labels;
+  labels.append(tr("Id"));
+  labels.append(tr("Name"));
+  labels.append(tr("Branch length")); 
+  nodeEditor_->setHorizontalHeaderLabels(labels);
+  splitter_ = new QSplitter(this);
+  splitter_->addWidget(treeCanvas_);
+  splitter_->addWidget(nodeEditor_);
+  splitter_->setCollapsible(0, true);
+  splitter_->setCollapsible(1, true);
+
+  setMinimumSize(400, 400);
+  setWidget(splitter_);
+  updateTable();
+}
+
+QTableWidgetItem* TreeSubWindow::getTableWigetItem_(Clonable* property)
+{
+  QTableWidgetItem* propItem = 0;
+  BppString* str = dynamic_cast<BppString*>(property);
+  if (str) {
+    propItem = new QTableWidgetItem();
+    propItem->setText(QtTools::toQt(*str));
+  } else {
+    Number<double>* num = dynamic_cast<Number<double>*>(property);
+    if (num) {
+      propItem = new QTableWidgetItem();
+      propItem->setText(QtTools::toQt(*num));
+    }
+  }
+  return propItem;
+}
+
+void TreeSubWindow::updateTable()
+{
+  stopSignal_ = true;
+  nodes_ = treeDocument_->getTree()->getNodes();
+  nodeEditor_->clearContents();
+  nodeEditor_->setRowCount(nodes_.size());
+
+  vector<string> nodeProperties;
+  TreeTemplateTools::getNodePropertyNames(*treeDocument_->getTree()->getRootNode(), nodeProperties);
+  vector<string> branchProperties;
+  TreeTemplateTools::getBranchPropertyNames(*treeDocument_->getTree()->getRootNode(), branchProperties);
+  QStringList labels;
+  labels.append(tr("Id"));
+  labels.append(tr("Name"));
+  labels.append(tr("Branch length"));
+  for (unsigned int i = 0; i < nodeProperties.size(); ++i)
+    labels.append(QtTools::toQt(nodeProperties[i]));
+  for (unsigned int i = 0; i < branchProperties.size(); ++i)
+    labels.append(QtTools::toQt(branchProperties[i]));
+  nodeEditor_->setColumnCount(labels.size());
+  nodeEditor_->setHorizontalHeaderLabels(labels);
+
+  for (unsigned int i = 0; i < nodes_.size(); ++i) {
+    QTableWidgetItem* idItem = new QTableWidgetItem(QtTools::toQt(TextTools::toString(nodes_[i]->getId())));
+    idItem->setFlags(!Qt::ItemIsEditable);
+    nodeEditor_->setItem(i, 0, idItem);
+
+    QTableWidgetItem* nameItem = new QTableWidgetItem();
+    if (nodes_[i]->hasName()) nameItem->setText(QtTools::toQt(nodes_[i]->getName()));
+    nodeEditor_->setItem(i, 1, nameItem);
+
+    QTableWidgetItem* brlenItem = new QTableWidgetItem();
+    if (nodes_[i]->hasDistanceToFather()) brlenItem->setText(QtTools::toQt(TextTools::toString(nodes_[i]->getDistanceToFather())));
+    nodeEditor_->setItem(i, 2, brlenItem);
+
+    for (unsigned int j = 0; j < nodeProperties.size(); ++j) {
+      QTableWidgetItem* item = 0; 
+      if (nodes_[i]->hasNodeProperty(nodeProperties[j])) {
+        item = getTableWigetItem_(nodes_[i]->getNodeProperty(nodeProperties[j]));
+      } else {
+        item = new QTableWidgetItem();
+      }
+      nodeEditor_->setItem(i, 3 + j, item);
+    }
+
+    for (unsigned int j = 0; j < branchProperties.size(); ++j) {
+      QTableWidgetItem* item = 0; 
+      if (nodes_[i]->hasBranchProperty(branchProperties[j])) {
+        item = getTableWigetItem_(nodes_[i]->getBranchProperty(branchProperties[j]));
+      } else {
+        item = new QTableWidgetItem();
+      }
+      nodeEditor_->setItem(i, 3 + nodeProperties.size() + j, item);
+    }
+  }
+  stopSignal_ = false;
+}
+
+void TreeSubWindow::writeTableToFile(const string& file, const string& sep)
+{
+  ofstream out(file.c_str(), ios::out);
+  for (int j = 0; j < nodeEditor_->columnCount(); ++j) {
+    QTableWidgetItem* hitem = nodeEditor_->horizontalHeaderItem(j);
+    out << (j > 0 ? sep : "") << (hitem ? hitem->text().toStdString() : "");
+  }
+  out << endl;
+  for (int i = 0; i < nodeEditor_->rowCount(); ++i) {
+    for (int j = 0; j < nodeEditor_->columnCount(); ++j) {
+      QTableWidgetItem* item = nodeEditor_->item(i, j);
+      out << (j > 0 ? sep : "") << (item ? item->text().toStdString() : 0);
+    }
+    out << endl;
+  }
+  out.close();
+}
+
+void TreeSubWindow::nodeEditorHasChanged(QTableWidgetItem* item)
+{
+  if (stopSignal_) return;
+  if (item->column() == 1) {
+    //Change name:
+    phyview_->submitCommand(new ChangeNodeNameCommand(treeDocument_, nodes_[item->row()]->getId(), item->text().toStdString()));
+  } else if (item->column() == 2) {
+    //Change branch length:
+    phyview_->submitCommand(new ChangeBranchLengthCommand(treeDocument_, nodes_[item->row()]->getId(), item->text().toDouble()));
+  } else {
+    //Change node property:
+    nodes_[item->row()]->setNodeProperty(nodeEditor_->horizontalHeaderItem(item->column())->text().toStdString(), BppString(item->text().toStdString()));
+  }
+  treeCanvas_->setTree(treeDocument_->getTree());
+}
+
+void TreeSubWindow::duplicateDownSelection(unsigned int rep)
+{
+  QList<QTableWidgetSelectionRange> selection = nodeEditor_->selectedRanges();
+  if (selection.size() == 0) {
+    QMessageBox::critical(phyview_, QString("Oups..."), QString("No selection."));
+    return;
+  }
+  //Perform some checking:
+  int row = -1;
+  for (int i = 0; i < selection.size(); ++i) {
+    QTableWidgetSelectionRange range = selection[i];
+    if (range.rowCount() != 1) {
+      QMessageBox::critical(phyview_, QString("Oups..."), QString("Only one row can be selected."));
+      return;
+    }
+    if (i == 0) {
+      row = range.topRow();
+    } else {
+      if (range.topRow() != row) {
+        QMessageBox::critical(phyview_, QString("Oups..."), QString("Only one row can be selected."));
+        return;
+      }
+    }
+  }
+  //Ok, if we reach this stage, then everything is ok...
+  int j;
+  for (j = row + 1; j < nodeEditor_->rowCount() && j - row <= static_cast<int>(rep); ++j) {
+    for (int i = 0; i < selection.size(); ++i) {
+      QTableWidgetSelectionRange range = selection[i];
+      for (int k = range.leftColumn(); k <= range.rightColumn(); ++k) {
+        nodeEditor_->setItem(j, k, nodeEditor_->item(row, k)->clone());
+      }
+    }
+  }
+  //Shift selection:
+  for (int i = 0; i < selection.size(); ++i) {
+    QTableWidgetSelectionRange range = selection[i];
+    nodeEditor_->setRangeSelected(range, false);
+    nodeEditor_->setRangeSelected(QTableWidgetSelectionRange(j - 1, range.leftColumn(), j - 1, range.rightColumn()), true);
+  }
+}
+
diff --git a/bppPhyView/TreeSubWindow.h b/bppPhyView/TreeSubWindow.h
new file mode 100644
index 0000000..bab9624
--- /dev/null
+++ b/bppPhyView/TreeSubWindow.h
@@ -0,0 +1,111 @@
+//
+// File: TreeSubWindow.h
+// Created by: Julien Dutheil
+// Created on: Tue Aug 11 13:34 2009
+//
+
+/*
+Copyright or © or Copr. Bio++ Development Team, (November 16, 2004)
+
+This software is a computer program whose purpose is to provide
+graphic components to develop bioinformatics applications.
+
+This software is governed by the CeCILL  license under French law and
+abiding by the rules of distribution of free software.  You can  use, 
+modify and/ or redistribute the software under the terms of the CeCILL
+license as circulated by CEA, CNRS and INRIA at the following URL
+"http://www.cecill.info". 
+
+As a counterpart to the access to the source code and  rights to copy,
+modify and redistribute granted by the license, users are provided only
+with a limited warranty  and the software's author,  the holder of the
+economic rights,  and the successive licensors  have only  limited
+liability. 
+
+In this respect, the user's attention is drawn to the risks associated
+with loading,  using,  modifying and/or developing or reproducing the
+software by the user in light of its specific status of free software,
+that may mean  that it is complicated to manipulate,  and  that  also
+therefore means  that it is reserved for developers  and  experienced
+professionals having in-depth computer knowledge. Users are therefore
+encouraged to load and test the software's suitability as regards their
+requirements in conditions enabling the security of their systems and/or 
+data to be ensured and,  more generally, to use and operate it in the 
+same conditions as regards security. 
+
+The fact that you are presently reading this means that you have had
+knowledge of the CeCILL license and that you accept its terms.
+*/
+
+#ifndef _TREESUBWINDOW_H_
+#define _TREESUBWINDOW_H_
+
+#include "TreeDocument.h"
+
+//From Qt:
+#include <QMdiSubWindow>
+#include <QSplitter>
+#include <QTableWidget>
+
+//From PhylLib:
+#include <Bpp/Phyl/Graphics/TreeDrawing.h>
+
+//From Bpp-Qt
+#include <Bpp/Qt/Tree/TreeCanvas.h>
+
+using namespace bpp;
+
+class PhyView;
+
+class TreeSubWindow:
+  public QMdiSubWindow,
+  public DocumentView
+{
+  Q_OBJECT
+
+  private:
+    PhyView* phyview_;
+    TreeDocument* treeDocument_;
+    TreeCanvas* treeCanvas_;
+    QSplitter* splitter_;
+    QTableWidget* nodeEditor_;
+    std::vector<Node*> nodes_;
+    bool stopSignal_;
+
+  public:
+    TreeSubWindow(PhyView* phyview, TreeDocument* document, TreeDrawing* td);
+
+    virtual ~TreeSubWindow()
+    {
+      delete treeDocument_;
+      delete splitter_;
+    }
+
+  public:
+    TreeDocument* getDocument() { return treeDocument_; }
+    const Tree& getTree() const { return *treeDocument_->getTree(); }
+    const TreeCanvas& getTreeCanvas() const { return *treeCanvas_; }
+    TreeCanvas& getTreeCanvas() { return *treeCanvas_; }
+
+    void duplicateDownSelection(unsigned int rep);
+
+    void updateView()
+    {
+      treeCanvas_->setTree(treeDocument_->getTree());
+      updateTable();
+    }
+    
+    void updateTable();
+
+    void writeTableToFile(const string& file, const string& sep);
+
+  private:
+    QTableWidgetItem* getTableWigetItem_(Clonable* property);
+
+  private slots:
+    void nodeEditorHasChanged(QTableWidgetItem* item);
+
+};
+
+#endif //_TREESUBWINDOW_H_
+
diff --git a/debian/bppphyview.manpages b/debian/bppphyview.manpages
new file mode 100644
index 0000000..a69bf35
--- /dev/null
+++ b/debian/bppphyview.manpages
@@ -0,0 +1 @@
+man/phyview.1.gz
diff --git a/debian/changelog b/debian/changelog
new file mode 100644
index 0000000..50b922f
--- /dev/null
+++ b/debian/changelog
@@ -0,0 +1,13 @@
+bppphyview (0.2.0-1) unstable; urgency=low
+
+  * RFP: Bio++ -- The Bio++ bioinformatics libraries. (Closes: #616373).
+  * Packages are now non-native.
+
+ -- Julien Dutheil <julien.dutheil at univ-montp2.fr>  Thu, 09 Jun 2011 11:00:00 +0100
+
+bppphyview (0.1.0) unstable; urgency=low
+
+  * Initial release.
+
+ -- Julien Dutheil <julien.dutheil at univ-montp2.fr>  Mon, 28 Feb 2011 09:00:00 +0100
+
diff --git a/debian/compat b/debian/compat
new file mode 100644
index 0000000..7ed6ff8
--- /dev/null
+++ b/debian/compat
@@ -0,0 +1 @@
+5
diff --git a/debian/control b/debian/control
new file mode 100644
index 0000000..e4ac94b
--- /dev/null
+++ b/debian/control
@@ -0,0 +1,17 @@
+Source: bppphyview
+Section: science
+Priority: optional
+Maintainer: Loic Dachary <loic at dachary.org>
+Uploaders: Julien Dutheil <julien.dutheil at univ-montp2.fr>
+Build-Depends: debhelper (>= 5), cmake (>= 2.6),
+  qt4-qmake (>= 4.6.0), libqt4-dev (>= 4.6.0),
+  libbpp-qt-dev (>= 2.0.0)
+Standards-Version: 3.9.1
+
+Package: bppphyview
+Architecture: any
+Depends: ${shlibs:Depends}, ${misc:Depends},
+  libbpp-qt1 (>= 2.0.0), libqtcore4 (>= 4.6.0), libqtgui4 (>= 4.6.0) 
+Description: Bio++ Phylogenetic Viewer
+ A phylogenetic tree editor developed using Bio++ and Qt.
+
diff --git a/debian/copyright b/debian/copyright
new file mode 100644
index 0000000..c724823
--- /dev/null
+++ b/debian/copyright
@@ -0,0 +1,62 @@
+This package was debianized by Julien Dutheil <julien.dutheil at univ-montp2.fr> on
+Mon, 28 Feb 2011 09:00:00 +0100.
+
+It was downloaded from <http://biopp.univ-montp2.fr/Repositories/sources>
+
+Upstream Author(s): 
+
+    Julien Dutheil <julien.dutheil at univ-montp2.fr>
+
+Copyright: 
+
+    Copyright (C) 2011 Bio++ Development Team
+
+License:
+
+    This package 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 package 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 package; if not, write to the Free Software
+    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
+
+The Debian packaging is (C) 2011, Julien Dutheil <julien.dutheil at univ-montp2.fr> and
+is licensed under the GPL, see `/usr/share/common-licenses/GPL'.
+
+The provided software is distributed under the CeCILL license:
+
+    This software is governed by the CeCILL license under French law and
+    abiding by the rules of distribution of free software.  You can  use, 
+    modify and/ or redistribute the software under the terms of the CeCILL
+    license as circulated by CEA, CNRS and INRIA at the following URL
+    "http://www.cecill.info". 
+
+    As a counterpart to the access to the source code and  rights to copy,
+    modify and redistribute granted by the license, users are provided only
+    with a limited warranty  and the software's author,  the holder of the
+    economic rights,  and the successive licensors  have only  limited
+    liability. 
+
+    In this respect, the user's attention is drawn to the risks associated
+    with loading,  using,  modifying and/or developing or reproducing the
+    software by the user in light of its specific status of free software,
+    that may mean  that it is complicated to manipulate,  and  that  also
+    therefore means  that it is reserved for developers  and  experienced
+    professionals having in-depth computer knowledge. Users are therefore
+    encouraged to load and test the software's suitability as regards their
+    requirements in conditions enabling the security of their systems and/or 
+    data to be ensured and,  more generally, to use and operate it in the 
+    same conditions as regards security. 
+
+    The fact that you are presently reading this means that you have had
+    knowledge of the CeCILL license and that you accept its terms.
+    
+The complete text of the license may be found here:
+http://www.cecill.info/licences/Licence_CeCILL_V2-en.html
diff --git a/debian/rules b/debian/rules
new file mode 100755
index 0000000..0cefd6d
--- /dev/null
+++ b/debian/rules
@@ -0,0 +1,147 @@
+#!/usr/bin/make -f
+# -*- makefile -*-
+# Sample debian/rules that uses debhelper.
+#
+# This file was originally written by Joey Hess and Craig Small.
+# As a special exception, when this file is copied by dh-make into a
+# dh-make output file, you may use that output file without restriction.
+# This special exception was added by Craig Small in version 0.37 of dh-make.
+#
+# Modified to make a template file for a multi-binary package with separated
+# build-arch and build-indep targets  by Bill Allombert 2001
+
+# 25/03/10 Modification for use with CMake by Julien Dutheil.
+
+# Uncomment this to turn on verbose mode.
+#export DH_VERBOSE=1
+
+# This has to be exported to make some magic below work.
+export DH_OPTIONS
+
+# These are used for cross-compiling and for saving the configure script
+# from having to guess our platform (since we know it already)
+DEB_HOST_GNU_TYPE   ?= $(shell dpkg-architecture -qDEB_HOST_GNU_TYPE)
+DEB_BUILD_GNU_TYPE  ?= $(shell dpkg-architecture -qDEB_BUILD_GNU_TYPE)
+
+
+CFLAGS = -Wall -g
+
+ifneq (,$(findstring noopt,$(DEB_BUILD_OPTIONS)))
+	CFLAGS += -O0
+else
+	CFLAGS += -O2
+endif
+
+configure:
+	cmake -DCMAKE_INSTALL_PREFIX=/usr .
+
+config.status: configure
+	dh_testdir
+
+#Architecture 
+build: build-arch build-indep
+
+build-arch: build-arch-stamp
+build-arch-stamp:  config.status
+
+	# Add here commands to compile the arch part of the package.
+	#$(MAKE) 
+	touch $@
+
+build-indep: build-indep-stamp
+build-indep-stamp:  config.status
+
+	# Add here commands to compile the indep part of the package.
+	#$(MAKE) doc
+	touch $@
+
+clean:
+	dh_testdir
+	dh_testroot
+	rm -f build-arch-stamp build-indep-stamp #CONFIGURE-STAMP#
+	rm -f CMakeCache.txt
+
+	# Add here commands to clean up after the build process.
+	[ ! -f Makefile ] || $(MAKE) clean;
+	[ ! -f Makefile ] || rm Makefile;
+	[ ! -f Makefile ] || rm bppphyview/Makefile;
+	rm -f config.sub config.guess
+	rm -f build-stamp
+	rm -f CMakeCache.txt
+	rm -f *.cmake
+	rm -f src/*.cmake
+	#rm -f test/*.cmake
+	rm -rf CMakeFiles
+	rm -rf src/CMakeFiles
+	#rm -rf test/CMakeFiles
+	rm -rf _CPack_Packages
+	#rm -rf Testing
+	#rm -f DartConfiguration.tcl
+
+	dh_clean 
+
+install: install-indep install-arch
+install-indep:
+	dh_testdir
+	dh_testroot
+	dh_prep -i 
+	dh_installdirs -i
+
+	# Add here commands to install the indep part of the package into
+	# debian/<package>-doc.
+	#INSTALLDOC#
+
+	dh_install -i
+
+install-arch:
+	dh_testdir
+	dh_testroot
+	dh_prep -s 
+	dh_installdirs -s
+
+	# Add here commands to install the arch part of the package into 
+	# debian/tmp.
+	$(MAKE) DESTDIR=$(CURDIR)/debian/bppphyview man install
+
+	dh_install -s
+# Must not depend on anything. This is to be called by
+# binary-arch/binary-indep
+# in another 'make' thread.
+binary-common:
+	dh_testdir
+	dh_testroot
+	dh_installchangelogs ChangeLog
+	dh_installdocs
+	dh_installexamples
+#	dh_installmenu
+#	dh_installdebconf	
+#	dh_installlogrotate	
+#	dh_installemacsen
+#	dh_installpam
+#	dh_installmime
+#	dh_python
+#	dh_installinit
+#	dh_installcron
+	dh_installinfo
+	dh_installman
+	dh_link
+	dh_strip
+	dh_compress 
+	dh_fixperms
+#	dh_perl
+#	dh_makeshlibs
+	dh_installdeb
+	dh_shlibdeps
+	dh_gencontrol
+	dh_md5sums
+	dh_builddeb
+# Build architecture independant packages using the common target.
+binary-indep: build-indep install-indep
+	$(MAKE) -f debian/rules DH_OPTIONS=-i binary-common
+
+# Build architecture dependant packages using the common target.
+binary-arch: build-arch install-arch
+	$(MAKE) -f debian/rules DH_OPTIONS=-s binary-common
+
+binary: binary-arch binary-indep
+.PHONY: build clean binary-indep binary-arch binary install install-indep install-arch 
diff --git a/debian/source/format b/debian/source/format
new file mode 100644
index 0000000..163aaf8
--- /dev/null
+++ b/debian/source/format
@@ -0,0 +1 @@
+3.0 (quilt)
diff --git a/man/CMakeLists.txt b/man/CMakeLists.txt
new file mode 100644
index 0000000..4235389
--- /dev/null
+++ b/man/CMakeLists.txt
@@ -0,0 +1,7 @@
+# CMake script for PhyView.
+# Author: Julien Dutheil
+# Created: 22/08/2009
+
+IF(MAN)
+  INSTALL(FILES phyview.1.gz DESTINATION share/man/man1)
+ENDIF(MAN)
diff --git a/man/phyview.1.txt b/man/phyview.1.txt
new file mode 100644
index 0000000..8a760ec
--- /dev/null
+++ b/man/phyview.1.txt
@@ -0,0 +1,47 @@
+.TH PHYVIEW 1 LOCAL
+
+.SH NAME
+
+bppml - Phylogenetic viewer and editor written with Bio++
+
+.SH SYNOPSIS
+
+.B phyview [arguments]
+
+.SH AVAILABILITY
+
+All UNIX flavors
+
+.SH DESCRIPTION
+
+phyview allows you to visualize, edit, print and output phylogenetic trees and associated data.
+
+.SH OPTIONS
+
+.TP 5
+
+file
+
+A tree file to open. By default, in the newick format.
+
+.TP
+
+--nhx
+
+switch to input format 'NHX'
+
+.TP
+
+--nexus
+
+switch to input format 'nexus'
+
+.TP
+
+--enc [text codec]
+
+specify the file name encoding, if different from the system default. See the Qt documentation for a list of available encodings.
+
+.SH AUTHOR
+
+The Bio++ Development Team.

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/debian-med/bppphyview.git



More information about the debian-med-commit mailing list