[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