commit cfccedd9c8db3af36d7c5635ca212fa170bb6ff5
Author: Timothy Pearson <kb9vqf@pearsoncomputing.net>
Date:   1327976424 -0600

    Part 2 of prior commit

diff --git a/kdecachegrind/AUTHORS b/kdecachegrind/AUTHORS
new file mode 100644
index 0000000..ded6005
--- /dev/null
+++ b/kdecachegrind/AUTHORS
@@ -0,0 +1 @@
+Josef Weidendorfer <Josef.Weidendorfer@gmx.de>
diff --git a/kdecachegrind/COPYING b/kdecachegrind/COPYING
new file mode 100644
index 0000000..c13faf0
--- /dev/null
+++ b/kdecachegrind/COPYING
@@ -0,0 +1,340 @@
+		    GNU GENERAL PUBLIC LICENSE
+		       Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+                       51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  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., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  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/kdecachegrind/ChangeLog b/kdecachegrind/ChangeLog
new file mode 100644
index 0000000..05f3081
--- /dev/null
+++ b/kdecachegrind/ChangeLog
@@ -0,0 +1,89 @@
+2004/06/30
+	* Leak fixes
+	* Crash fixes on reload (make setData() synchroneous)
+	* Some update fixes in the data model (tracedata.cpp)
+	* Fix update problems in Function Profile
+	* Reselect active function on refresh in function profile
+	  with grouping on
+
+2004/04/28
+	* toplevel.h/cpp, kdecachegrindui.rc
+	  - Switching Layouts
+	* multiview.cpp: Removed some qDebug's
+	* Same term fixes
+
+2004/04/26
+	* cachegrindloader.cpp, fixcost.cpp:
+	  - Allow Ranges in Subposition Spec, currently not used
+	  - Correctly parse "Desc: Trigger:"
+	  - Allow Event Spec (Long Name, Formula) with "event:"
+	* listutils.cpp:
+	  - make level meters for costs only 1 bar
+	    (2 with upper from 0..50%, lower 50%..100% is really confusing)
+	  - Besides from Call graph and Tree maps, truncate bars to
+	    only use needed size (removes lots of empty rectangles)
+	* CallGraphView:
+	  - some fixes when no data is loaded
+	* functionselection.cpp (Function Profile)
+	  - activation on mouse release to allow for context menu
+	* tracedata.cpp
+	  - more robust parsing of events lists
+	  - Introduction of Ranges (not currently used)
+	* utils.cpp:
+	  - more robust parsing functions	
+
+2004/04/05
+	* CallGraphView:
+	  - Add Context menu item "Export as Image"
+	  - Hide Birdseye-View if call-graph fits into widget
+	  - Error messages in Canvas when something goes wrong
+        * Some Fixes, qDebug->kdDebug
+
+2004/04/02
+	* In most views columns for 2nd Event Type added
+	* Context menus modified to allow quick change of 2nd Event Type
+	* Toolbar simplified (only most used actions)
+	* Terminology fixes ("cost type"->"event type",
+          "trace data"->"profile data", long names of Ir,Dr,...)
+	* Sorting costs in lists is always descending now
+	* New File menu item: "Add..." other profile data to current window
+        * Detect Cachegrind format by "events:" content, not file name
+	  Allows for arbitrary names of profile data files.
+
+2004/03/25
+	* New Class Addr as wrapper for memory addresses. Use 64bit
+	  to allow loading of data produced on 64bit architectures
+
+2004/03/17
+
+	* costtypeview.cpp, tracedata.h/cpp:
+	  Fixed deletion of custom types
+	* cachegrindloader.cpp, tracedata.h/cpp:
+	  Moved String compression handling in Cachegrind files
+	  to CachegrindLoader
+	* Do not show inclusive cost column in FunctionSelection
+	  side bar if not available
+	* Remove "isPartOfTrace" from Loader interface
+	  (we allow parts from multiple experiments for comp.)
+	* partview.cpp, partlistitem.h/cpp:
+	  Remove Column Callees, add Trigger
+
+2003/05/10
+
+	* Status progress on loading and cycle calculation
+	* Corrected order of trace parts (PID/PartNo/ThreadID)
+	* Allow adding traces (BUGGY...)
+
+2003/02/06
+
+	* Version 0.3a
+	* Bugfixes:
+	  - Compiles with KDE 3.0.x
+	  - Always select a first cost type
+	  - Loading from another directory
+
+
+2002/11/28
+
+	* Version 0.3
+	
diff --git a/kdecachegrind/INSTALL b/kdecachegrind/INSTALL
new file mode 100644
index 0000000..02a4a07
--- /dev/null
+++ b/kdecachegrind/INSTALL
@@ -0,0 +1,167 @@
+Basic Installation
+==================
+
+   These are generic installation instructions.
+
+   The `configure' shell script attempts to guess correct values for
+various system-dependent variables used during compilation.  It uses
+those values to create a `Makefile' in each directory of the package.
+It may also create one or more `.h' files containing system-dependent
+definitions.  Finally, it creates a shell script `config.status' that
+you can run in the future to recreate the current configuration, a file
+`config.cache' that saves the results of its tests to speed up
+reconfiguring, and a file `config.log' containing compiler output
+(useful mainly for debugging `configure').
+
+   If you need to do unusual things to compile the package, please try
+to figure out how `configure' could check whether to do them, and mail
+diffs or instructions to the address given in the `README' so they can
+be considered for the next release.  If at some point `config.cache'
+contains results you don't want to keep, you may remove or edit it.
+
+   The file `configure.in' is used to create `configure' by a program
+called `autoconf'.  You only need `configure.in' if you want to change
+it or regenerate `configure' using a newer version of `autoconf'.
+
+The simplest way to compile this package is:
+
+  1. `cd' to the directory containing the package's source code and type
+     `./configure' to configure the package for your system.  If you're
+     using `csh' on an old version of System V, you might need to type
+     `sh ./configure' instead to prevent `csh' from trying to execute
+     `configure' itself.
+
+     Running `configure' takes a while.  While running, it prints some
+     messages telling which features it is checking for.
+
+  2. Type `make' to compile the package.
+
+  3. Type `make install' to install the programs and any data files and
+     documentation.
+
+  4. You can remove the program binaries and object files from the
+     source code directory by typing `make clean'.  
+
+Compilers and Options
+=====================
+
+   Some systems require unusual options for compilation or linking that
+the `configure' script does not know about.  You can give `configure'
+initial values for variables by setting them in the environment.  Using
+a Bourne-compatible shell, you can do that on the command line like
+this:
+     CC=c89 CFLAGS=-O2 LIBS=-lposix ./configure
+
+Or on systems that have the `env' program, you can do it like this:
+     env CPPFLAGS=-I/usr/local/include LDFLAGS=-s ./configure
+
+Compiling For Multiple Architectures
+====================================
+
+   You can compile the package for more than one kind of computer at the
+same time, by placing the object files for each architecture in their
+own directory.  To do this, you must use a version of `make' that
+supports the `VPATH' variable, such as GNU `make'.  `cd' to the
+directory where you want the object files and executables to go and run
+the `configure' script.  `configure' automatically checks for the
+source code in the directory that `configure' is in and in `..'.
+
+   If you have to use a `make' that does not supports the `VPATH'
+variable, you have to compile the package for one architecture at a time
+in the source code directory.  After you have installed the package for
+one architecture, use `make distclean' before reconfiguring for another
+architecture.
+
+Installation Names
+==================
+
+   By default, `make install' will install the package's files in
+`/usr/local/bin', `/usr/local/man', etc.  You can specify an
+installation prefix other than `/usr/local' by giving `configure' the
+option `--prefix=PATH'.
+
+   You can specify separate installation prefixes for
+architecture-specific files and architecture-independent files.  If you
+give `configure' the option `--exec-prefix=PATH', the package will use
+PATH as the prefix for installing programs and libraries.
+Documentation and other data files will still use the regular prefix.
+
+   If the package supports it, you can cause programs to be installed
+with an extra prefix or suffix on their names by giving `configure' the
+option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'.
+
+Optional Features
+=================
+
+   Some packages pay attention to `--enable-FEATURE' options to
+`configure', where FEATURE indicates an optional part of the package.
+They may also pay attention to `--with-PACKAGE' options, where PACKAGE
+is something like `gnu-as' or `x' (for the X Window System).  The
+`README' should mention any `--enable-' and `--with-' options that the
+package recognizes.
+
+   For packages that use the X Window System, `configure' can usually
+find the X include and library files automatically, but if it doesn't,
+you can use the `configure' options `--x-includes=DIR' and
+`--x-libraries=DIR' to specify their locations.
+
+Specifying the System Type
+==========================
+
+   There may be some features `configure' can not figure out
+automatically, but needs to determine by the type of host the package
+will run on.  Usually `configure' can figure that out, but if it prints
+a message saying it can not guess the host type, give it the
+`--host=TYPE' option.  TYPE can either be a short name for the system
+type, such as `sun4', or a canonical name with three fields:
+     CPU-COMPANY-SYSTEM
+
+See the file `config.sub' for the possible values of each field.  If
+`config.sub' isn't included in this package, then this package doesn't
+need to know the host type.
+
+   If you are building compiler tools for cross-compiling, you can also
+use the `--target=TYPE' option to select the type of system they will
+produce code for and the `--build=TYPE' option to select the type of
+system on which you are compiling the package.
+
+Sharing Defaults
+================
+
+   If you want to set default values for `configure' scripts to share,
+you can create a site shell script called `config.site' that gives
+default values for variables like `CC', `cache_file', and `prefix'.
+`configure' looks for `PREFIX/share/config.site' if it exists, then
+`PREFIX/etc/config.site' if it exists.  Or, you can set the
+`CONFIG_SITE' environment variable to the location of the site script.
+A warning: not all `configure' scripts look for a site script.
+
+Operation Controls
+==================
+
+   `configure' recognizes the following options to control how it
+operates.
+
+`--cache-file=FILE'
+     Use and save the results of the tests in FILE instead of
+     `./config.cache'.  Set FILE to `/dev/null' to disable caching, for
+     debugging `configure'.
+
+`--help'
+     Print a summary of the options to `configure', and exit.
+
+`--quiet'
+`--silent'
+`-q'
+     Do not print messages saying which checks are being made.
+
+`--srcdir=DIR'
+     Look for the package's source code in directory DIR.  Usually
+     `configure' can determine that directory automatically.
+
+`--version'
+     Print the version of Autoconf used to generate the `configure'
+     script, and exit.
+
+`configure' also accepts some other, not widely useful, options.
+
diff --git a/kdecachegrind/Makefile.am b/kdecachegrind/Makefile.am
new file mode 100644
index 0000000..e93f6af
--- /dev/null
+++ b/kdecachegrind/Makefile.am
@@ -0,0 +1,6 @@
+SUBDIRS = kdecachegrind pics converters
+
+EXTRA_DIST = \
+	AUTHORS COPYING NEWS ChangeLog INSTALL README TODO \
+	kdecachegrind.lsm kdecachegrind.spec version.h 
+
diff --git a/kdecachegrind/NEWS b/kdecachegrind/NEWS
new file mode 100644
index 0000000..e69de29
diff --git a/kdecachegrind/README b/kdecachegrind/README
new file mode 100644
index 0000000..0866eb8
--- /dev/null
+++ b/kdecachegrind/README
@@ -0,0 +1,62 @@
+KCachegrind
+===========
+
+
+What is all this about ?
+-------------------------
+
+Profiling, i.e. determinating most time consuming execution parts,
+is an important last step when developing applications.
+KCachegrind visualizes traces, generated by profiling, in various ways;  
+most notable is the TreeMap visualization of the calls happening
+and a condensed version of it, the Coverage analysis.
+KCachegrind is designed to allow fast browsing and to provide a quick
+overview of very large programs, such as KDE applications (but not
+limited to!). 
+  
+At the moment, it uses Cachegrind as profiling backend, which is using
+the excellent CPU simulator in Valgrind. Thus, profiling does not 
+need any preparation, can cope with shared libraries and plugin
+architectures, and allows for profile runs to not influence the measuring
+by the profile itself (all in contrast to e.g. GProf). Disadvantage is 
+slower profile runs, unfortunately. 
+ 
+For Cachegrind to provide call tree information, a patch is provided.  
+This enables the most interesting visualization features of KCachegrind. 
+
+
+Requirements
+------------
+
+A call-tree version of Cachegrind:
+  - X86 Linux
+  - Valgrind 1.0.x with call-tree patch from KCachegrind Website
+  - Valgrind 2.0.x with call-tree skin installed
+
+Cachegrind runs on x86 platforms, KCachegrind on all KDE enabled
+platforms (KDE 3.0.x). 
+
+
+Compilation and Installation
+----------------------------
+
+Simple do the command sequence
+
+  ./configure --prefix=<KDE base directory>
+  make
+  make install
+
+
+
+KCachegrind features
+--------------------
+
+Most important: TreeMap calltree visualisation.
+For the rest, see the detailed "What's this?" help for
+each part of KCachegrind and the quick starter on the
+WWW page ( http://kcachegrind.sourceforge.net/cgi-bin/show.cgi )
+
+
+
+Happy Profiling,
+ Josef Weidendorfer
diff --git a/kdecachegrind/TODO b/kdecachegrind/TODO
new file mode 100644
index 0000000..1eca67e
--- /dev/null
+++ b/kdecachegrind/TODO
@@ -0,0 +1,100 @@
+TODO/Wishlist Items
+===================
+
+
+KCachegrind
+-----------
+
+All cost Lists:
+* Show up to a number of items, not down to a threadshold.
+  If more, add a "..." with number of items not shown, and context option
+  to show more
+* "Copy from Top" converts lists into ASCII, puts into clipboard
+
+
+Configuration:
+ Source dirs per ELF object
+
+Layout:
+* 1/2/3/4 vertical/horizontal FunctionInfos
+  with Shift/Wraparound selection mode
+* Inside each FunctionInfo different Layouts
+ - tabbed layout
+ - top: info, bottom left: calls/coverage, bottom right: graph/source
+* Long/short info tab
+
+General:
+* Selected Item can be a object/file/class/function/line
+* Configuration Dlg
+ - Local config (?)
+ - Cost Types
+ - function colors
+ - Try to reload source after config.
+* Session Management
+
+
+
+Annotation Views:
+
+ BUGS:
+  * Draw problem with multiple srcs to one target
+  * REP case...
+
+ TODO:
+  * Selectable Jumps (Arrows)
+  * Tooltip for Jumps (Kind, from/to, jump count) 
+  * Show direction (arrows) on jump lines
+
+ Source view TODO:
+  * Implicit jumps (green) [needs support from the tool?]
+
+
+
+Callgraph:
+* Fix Arrows for back-arcs
+* Less "Jumps" for minimap
+* Correct Keyboard navigation (how?)
+
+Types:
+* Ratios
+* Automatic subtypes
+
+WISHS:
+* Support for Data tracing
+  Which variables are touched how often from which function?
+  - Some graphical visualisation...
+
+* GCC -pg (gmon.out) as Profiling Backend
+* Demangler (use c++filt)
+* Calculation of call weights (if not given)
+* OProfile, DynaProf
+
+Support for KCachegrind in Calltree
+-----------------------------------
+
+WISHS:
+- store more details of calltree
+  - for every function call: executed from shared lib
+    (Not needed, if function names are unique in whole app)
+  - adaptive call chain context (Really needed ? MUCH Data!)
+- dump at
+  - breakpoints
+  - watchpoints (with data tracing!)
+  - every xxx BBs (DONE)
+- dump around
+  - function invocation
+  - KAction event
+  - DCOP event
+
+- data accesses from (instr address/count)
+  stack:   -> (function, stackframe-offset)
+  dynamic: -> (mem region start, [type], offset)
+              type can be get when a constructor is called for region
+  static:  -> (mem region start, type, offset)
+
+* Generate full instr/data access trace for offline analysis.
+
+* Appending mode
+
+
+
diff --git a/kdecachegrind/configure.in.in b/kdecachegrind/configure.in.in
new file mode 100644
index 0000000..dfc8508
--- /dev/null
+++ b/kdecachegrind/configure.in.in
@@ -0,0 +1,8 @@
+KCACHEGRIND_VERSION=0.4.6kde
+AC_SUBST(KCACHEGRIND_VERSION)
+
+AC_FUNC_MMAP
+
+dnl AC_OUTPUT( kdecachegrind/version.h )
+dnl AC_OUTPUT( kdecachegrind/kdecachegrind.spec )
+dnl AC_OUTPUT( kdecachegrind/kdecachegrind.lsm )
diff --git a/kdecachegrind/converters/Makefile.am b/kdecachegrind/converters/Makefile.am
new file mode 100644
index 0000000..08b3696
--- /dev/null
+++ b/kdecachegrind/converters/Makefile.am
@@ -0,0 +1,2 @@
+bin_SCRIPTS = hotshot2calltree op2calltree pprof2calltree dprof2calltree \
+	memprof2calltree
diff --git a/kdecachegrind/converters/README b/kdecachegrind/converters/README
new file mode 100644
index 0000000..c27d3c6
--- /dev/null
+++ b/kdecachegrind/converters/README
@@ -0,0 +1,24 @@
+This directory contains some scripts to convert output of different
+profiling tools into the format which can be loaded by KCachegrind.
+See the comment at start of every script for details.
+
+In the long run, these should be replaced by import filters in
+KCachegrind directly, but I can't promise anything. Partly, this
+is because some scripts are provided as contribution from others.
+
+hotshot2calltree   Converter from Python Hotshot Profiler.
+op2calltree        Converter from OProfile sampling data. 
+dprof2calltree     Converter from PERL::DProf Profiler.
+pprof2calltree     Converter from APD PHP Profiler.
+
+Thanks go to
+* George Schlossnagle <george@omniti.com> for
+  dprof2calltree and pprof2calltree,
+* J�rg Beyer <job@webde-ag.de> for
+  hotshot2calltree
+
+If you want to write a converter, have a look at the calltree format
+description on the web site (kdecachegrind.sf.net).
+
+Josef
+
diff --git a/kdecachegrind/converters/dprof2calltree b/kdecachegrind/converters/dprof2calltree
new file mode 100644
index 0000000..f276e18
--- /dev/null
+++ b/kdecachegrind/converters/dprof2calltree
@@ -0,0 +1,199 @@
+#!/usr/bin/perl
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are met:
+# 
+# - Redistributions of source code must retain the above copyright notice,
+# this list of conditions and the following disclaimer.
+# 
+# - Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+# 
+# - All advertising materials mentioning features or use of this software
+# must display the following acknowledgement: This product includes software
+# developed by OmniTI Computer Consulting.
+# 
+# - Neither name of the company nor the names of its contributors may be
+# used to endorse or promote products derived from this software without
+# specific prior written permission.
+# 
+# THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS `AS IS'' AND ANY
+# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+# DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
+# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+# Copyright (c) 2004 OmniTI Computer Consulting 
+# All rights reserved
+# The following code was written by George Schlossnagle <george@omniti.com>
+# and is provided completely free and without any warranty.
+#
+
+#
+# This script is designed to convert the tmon.out output emitted 
+# from Perl's Devel::DProf profiling package.  To use this:
+#
+# 1) Run your perl script as 
+#    > perl -d:DProf yoursript.pl
+#    This will create a file called tmon.out.  If you want to
+#    inspect it on the command line, look at the man page
+#    for dprofp for details.
+#
+# 2) Run  
+#    > dprof2calltree -f tmon.out
+#    or
+#    > dprof2calltree -f tmon.out -o cachegrind.out.foo
+#
+#    This creates a cachegrind-style file called cachgrind.out.tmon.out or
+#    cachegrind.out.foo, respecitvely.
+#
+# 3) Run kdecachegrind cachegrind.out.foo
+#
+# 4) Enjoy!
+
+use strict;
+use Config;
+use Getopt::Std;
+use IO::File;
+
+my @callstack;
+my %function_info;
+my $tree = {};
+my $total_cost = 0;
+my %opts;
+
+getopt('f:o:', \%opts);
+
+my $infd;
+usage() unless ($opts{'f'} && ($infd = IO::File->new($opts{'f'}, "r")));
+
+my $outfd;
+my $outfile = $opts{'o'};
+unless($outfile) {
+  $opts{'f'} =~ m!([^/]+)$!;
+  $outfile = "cachegrind.out.$1";
+}
+$outfd = new IO::File $outfile, "w";
+usage() unless defined $outfd;
+  
+while(<$infd>) {
+  last if /^PART2/;
+}
+while(<$infd>) {
+  chomp;
+  my @args = split;
+  if($args[0] eq '@') {
+    # record timing event
+    my $call_element = pop @callstack;
+    if($call_element) {
+      $call_element->{'cost'} += $args[3];
+      $call_element->{'cumm_cost'} += $args[3];
+      $total_cost += $args[3];
+      push @callstack, $call_element;
+    }
+  }
+  elsif($args[0] eq '&') {  
+    # declare function
+    $function_info{$args[1]}->{'package'} = $args[2];
+    if($args[2] ne 'main') {
+      $function_info{$args[1]}->{'name'} = $args[2]."::".$args[3];
+    } else {
+      $function_info{$args[1]}->{'name'} = $args[3];
+    }
+  }
+  elsif($args[0] eq '+') {
+    # push myself onto the stack
+    my $call_element = { 'specifier' => $args[1], 'cost' => 0 };
+    push @callstack, $call_element;
+  }
+  elsif($args[0] eq '-') {
+    my $called = pop @callstack;
+    my $called_id = $called->{'specifier'};
+    my $caller = pop @callstack;
+    if (exists $tree->{$called_id}) {
+      $tree->{$called_id}->{'cost'} += $called->{'cost'};
+    }
+    else {
+      $tree->{$called_id} = $called;
+    } 
+    if($caller) {
+      $caller->{'child_calls'}++;
+      my $caller_id = $caller->{'specifier'};
+      if(! exists $tree->{$caller_id} ) {
+        $tree->{$caller_id} = { 'specifier' => $caller_id, 'cost' => 0 };
+#        $tree->{$caller_id} = $caller;
+      }
+      $caller->{'cumm_cost'} += $called->{'cumm_cost'};
+      $tree->{$caller_id}->{'called_funcs'}->[$tree->{$caller_id}->{'call_counter'}++]->{$called_id} += $called->{'cumm_cost'};
+      push @callstack, $caller;
+    }
+  }
+  elsif($args[0] eq '*') {
+    # goto &func
+    # replace last caller with self
+    my $call_element = pop @callstack;
+    $call_element->{'specifier'} = $args[1];
+    push @callstack, $call_element;
+  }
+  else {print STDERR "Unexpected line: $_\n";}
+}
+
+#
+# Generate output
+#
+my $output = '';
+$output .= "events: Tick\n";
+$output .= "summary: $total_cost\n";
+$output .= "cmd: your script\n\n";
+foreach my $specifier ( keys %$tree ) {
+  my $caller_package = $function_info{$specifier}->{'package'} || '???';
+  my $caller_name = $function_info{$specifier}->{'name'} || '???';
+  my $include = find_include($caller_package);
+  $output .= "ob=\n";
+  $output .= sprintf "fl=%s\n", find_include($caller_package);
+  $output .= sprintf "fn=%s\n", $caller_name;
+  $output .= sprintf "1 %d\n", $tree->{$specifier}->{'cost'};
+  if(exists $tree->{$specifier}->{'called_funcs'}) {
+    foreach my $items (@{$tree->{$specifier}->{'called_funcs'}}) {
+      while(my ($child_specifier, $costs) = each %$items) {
+        $output .= sprintf "cfn=%s\n", $function_info{$child_specifier}->{'name'};
+        $output .= sprintf "cfi=%s\n", find_include($function_info{$child_specifier}->{'package'});
+        $output .= "calls=1\n";
+        $output .= sprintf "1 %d\n", $costs;
+      }
+    }
+  }
+  $output .= "\n";
+}
+print STDERR "Writing kdecachegrind output to $outfile\n";
+$outfd->print($output);
+
+
+
+sub find_include {
+  my $module = shift;
+  $module =~ s!::!/!g;
+  for (@INC) {
+    if ( -f "$_/$module.pm" ) {
+      return "$_/$module.pm";
+    }
+    if ( -f "$_/$module.so" ) {
+      return "$_/$module.so";
+    }
+  }
+  return "???";
+}
+
+sub usage() {
+  print STDERR "dprof2calltree -f <tmon.out> [-o outfile]\n";
+  exit -1;
+}
+
+
+# vim: set sts=2 ts=2 bs ai expandtab :
diff --git a/kdecachegrind/converters/hotshot2calltree b/kdecachegrind/converters/hotshot2calltree
new file mode 100644
index 0000000..f62a46e
--- /dev/null
+++ b/kdecachegrind/converters/hotshot2calltree
@@ -0,0 +1,394 @@
+#!/usr/bin/env python
+# _*_ coding: latin1 _*_
+
+#
+# Copyright (c) 2003 by WEB.DE, Karlsruhe
+# Autor: J�rg Beyer <job@webde-ag.de>
+#
+# hotshot2cachegrind 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, version 2.
+#
+# 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; see the file COPYING.  If not, write to
+# the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+# Boston, MA 02110-1301, USA.
+#
+#
+# This script transforms the pstat output of the hotshot
+# python profiler into the input of kdecachegrind. 
+#
+# example usage:
+# modify you python script to run this code:
+#
+# import hotshot
+# filename = "pythongrind.prof"
+# prof = hotshot.Profile(filename, lineevents=1)
+# prof.runcall(run) # assuming that "run" should be called.
+# prof.close()
+#
+# it will run the "run"-method under profiling and write
+# the results in a file, called "pythongrind.prof".
+#
+# then call this script:
+# hotshot2cachegrind -o <output> <input>
+# or here:
+# hotshot2cachegrind cachegrind.out.0 pythongrind.prof
+#
+# then call kdecachegrind:
+# kdecachegrind cachegrind.out.0
+#
+# TODO: 
+#  * es gibt Probleme mit rekursiven (direkt und indirekt) Aufrufen - dann
+#    stimmen die Kosten nicht.
+#
+#  * einige Funktionen werden mit "?" als Name angezeigt. Evtl sind
+#    das nur die C/C++ extensions.
+#
+#  * es fehlt noch ein Funktionsnamen Mangling, dass die Filenamen ber�cksichtigt,
+#    zZ sind alle __init__'s und alle run's schwer unterscheidbar :-(
+#
+version = "$Revision$"
+progname = "hotshot2cachegrind"
+
+import os, sys
+from hotshot import stats,log
+import os.path 
+
+file_limit=0
+
+what2text = { 
+    log.WHAT_ADD_INFO    : "ADD_INFO", 
+    log.WHAT_DEFINE_FUNC : "DEFINE_FUNC", 
+    log.WHAT_DEFINE_FILE : "DEFINE_FILE", 
+    log.WHAT_LINENO      : "LINENO", 
+    log.WHAT_EXIT        : "EXIT", 
+    log.WHAT_ENTER       : "ENTER"}
+
+# a pseudo caller on the caller stack. This represents
+# the Python interpreter that executes the given python 
+# code.
+root_caller = ("PythonInterpreter",0,"execute")
+
+class CallStack:
+    """A tiny Stack implementation, based on python lists"""
+    def __init__(self):
+       self.stack = []
+       self.recursion_counter = {}
+    def push(self, elem):
+        """put something on the stack"""
+        self.stack.append(elem)
+        rc = self.recursion_counter.get(elem, 0)
+        self.recursion_counter[elem] = rc + 1
+
+    def pop(self):
+        """get the head element of the stack and remove it from teh stack"""
+        elem = self.stack[-1:][0]
+        rc = self.recursion_counter.get(elem) - 1
+        if rc>0:
+            self.recursion_counter[elem] = rc
+        else:
+            del self.recursion_counter[elem]
+        return self.stack.pop()
+
+    def top(self):
+        """get the head element of the stack, stack is unchanged."""
+        return self.stack[-1:][0]
+    def handleLineCost(self, tdelta):
+        p, c = self.stack.pop()
+        self.stack.append( (p,c + tdelta) )
+    def size(self):
+        """ return how many elements the stack has"""
+        return len(self.stack)
+
+    def __str__(self):
+        return "[stack: %s]" % self.stack
+
+    def recursion(self, pos):
+        return self.recursion_counter.get(pos, 0)
+        #return self.recursion_dict.has_key((entry[0][0], entry[0][2]))
+
+def return_from_call(caller_stack, call_dict, cost_now):
+    """return from a function call
+       remove the function from the caller stack,
+       add the costs to the calling function.
+    """
+    called, cost_at_enter = caller_stack.pop()
+    caller, caller_cost = caller_stack.top()
+
+    #print "return_from_call: %s ruft %s" % (caller, called,)
+
+    per_file_dict = call_dict.get(called[0], {})
+    per_caller_dict = per_file_dict.get(called[2], {})
+    cost_so_far, call_counter = per_caller_dict.get(caller, (0, 0))
+
+    if caller_stack.recursion(called):
+        per_caller_dict[caller] = (cost_so_far, call_counter + 1)
+    else:
+        per_caller_dict[caller] = (cost_so_far + cost_now - cost_at_enter, call_counter + 1)
+
+    per_file_dict[called[2]] = per_caller_dict
+    call_dict[called[0]] = per_file_dict
+
+
+def updateStatus(filecount):
+    sys.stdout.write("reading File #%d    \r" % filecount)
+    sys.stdout.flush()
+def convertProfFiles(output, inputfilenames):
+    """convert all the given input files into one kdecachegrind 
+       input file.
+    """
+    call_dict = {}
+    cost_per_pos = {}
+    cost_per_function = {}
+    caller_stack = CallStack()
+    caller_stack.push((root_caller, 0))
+
+    total_cost = 0
+    filecount = 1
+    number_of_files = len(inputfilenames)
+    for inputfilename in inputfilenames:
+        updateStatus(filecount)
+        cost, filecount = convertHandleFilename(inputfilename, caller_stack, call_dict, cost_per_pos, cost_per_function, filecount)
+        total_cost += cost
+        if (file_limit > 0) and (filecount > file_limit):
+            break
+    
+    print
+    print "total_cost: % d Ticks",total_cost
+    dumpResults(output, call_dict, total_cost, cost_per_pos, cost_per_function)
+
+def convertHandleFilename(inputfilename, caller_stack, call_dict, cost_per_pos, cost_per_function, filecount):
+    updateStatus(filecount)
+    if not ((file_limit > 0) and (filecount > file_limit)):
+        if os.path.isdir(inputfilename):
+            cost, filecount = convertProfDir(inputfilename, caller_stack, call_dict, cost_per_pos, cost_per_function, filecount)
+        elif os.path.isfile(inputfilename):
+            cost = convertProfFile(inputfilename, caller_stack, call_dict, cost_per_pos, cost_per_function)
+            filecount += 1 
+        else:
+            sys.stderr.write("warn: ignoring '%s', is no file and no directory\n" % inputfilename)
+            cost = 0
+    return (cost, filecount)
+
+def convertProfDir(start, caller_stack, call_dict, cost_per_pos, cost_per_function, filecount):
+    cost = 0
+    filenames = os.listdir(start)
+    for f in filenames:
+        if (file_limit > 0) and (filecount > file_limit): 
+            break
+        full = os.path.join(start, f)
+        c, filecount = convertHandleFilename(full, caller_stack, call_dict, cost_per_pos, cost_per_function, filecount)
+        cost += c;
+    return (cost, filecount)
+
+def handleCostPerPos(cost_per_pos, pos, current_cost):
+    """
+       the cost per source position are managed in a dict in a dict.
+
+       the cost are handled per file and there per function.
+       so, the per-file-dict contains some per-function-dicts
+       which sum up the cost per line (in this function and in 
+       this file).
+    """
+    filename  = pos[0]
+    lineno    = pos[1]
+    funcname  = pos[2]
+    file_dict = cost_per_pos.get(filename, {})
+    func_dict = file_dict.get(funcname, {})
+    func_dict.setdefault(lineno, 0)
+    func_dict[lineno] += current_cost
+    file_dict[funcname] = func_dict
+    cost_per_pos[filename] = file_dict
+
+def convertProfFile(inputfilename, caller_stack, call_dict, cost_per_pos, cost_per_function):
+    """convert a single input file into one kdecachegrind
+       data.
+
+       this is the most expensive function in this python source :-)
+    """
+
+    total_cost = 0
+    try:
+        logreader = log.LogReader(inputfilename)
+        current_cost = 0
+        hc = handleCostPerPos # shortcut
+        for item in logreader:
+            what, pos ,tdelta = item
+            (file, lineno, func) = pos
+            #line = "%s %s %d %s %d" % (what2text[what], file, lineno, func, tdelta)
+            #print line
+            # most common cases first
+            if what == log.WHAT_LINENO:
+                # add the current cost to the current function
+                hc(cost_per_pos, pos, tdelta)
+                total_cost += tdelta
+            elif what == log.WHAT_ENTER:
+                caller_stack.push((pos, total_cost))
+                hc(cost_per_pos, pos, tdelta)
+                total_cost += tdelta
+            elif what == log.WHAT_EXIT:
+                hc(cost_per_pos, pos, tdelta)
+                total_cost += tdelta
+                return_from_call(caller_stack, call_dict, total_cost)
+            else:
+                assert 0, "duh: %d" % what
+
+
+        # I have no idea, why sometimes the stack is not empty - we
+        # have to rewind the stack to get 100% for the root_caller
+        while caller_stack.size() > 1:
+            return_from_call(caller_stack, call_dict, total_cost)
+
+    except IOError:
+        print "could not open inputfile '%s', ignore this." % inputfilename
+    except EOFError, m:
+        print "EOF: %s" % (m,)
+    return total_cost
+
+def pretty_name(file, function):
+    #pfile = os.path.splitext(os.path.basename(file)) [0]
+    #return "%s_[%s]" % (function, file)
+    return "%s" % function
+    #return "%s::%s" % (file, function)
+    #return "%s_%s" % (pfile, function)
+
+class TagWriter:
+    def __init__(self, output):
+        self.output = output
+        self.last_values = {}
+
+    def clearTag(self, tag):
+        if self.last_values.has_key(tag):
+            del self.last_values[ tag ]
+    def clear(self):
+        self.last_values = {}
+
+    def write(self, tag, value):
+        self.output.write("%s=%s\n" % (tag, value))
+        #if (not self.last_values.has_key(tag)) or self.last_values[tag] != value:
+        #    self.last_values[ tag ] = value
+        #    self.output.write("%s=%s\n" % (tag, value))
+
+def dumpResults(output, call_dict, total_cost, cost_per_pos, cost_per_function):
+    """write the collected results in the format kdecachegrind
+       could read.
+    """
+    # the intro
+    output.write("events: Tick\n")
+    output.write("summary: %d\n" % total_cost)
+    output.write("cmd: your python script\n")
+    output.write("\n")
+    tagwriter = TagWriter(output)
+
+    # now the costs per line
+    for file in cost_per_pos.keys():
+        func_dict = cost_per_pos[file]
+        for func in func_dict.keys():
+            line_dict = func_dict[func]
+            tagwriter.write("ob", file)
+            tagwriter.write("fn", func)# pretty_name(file, func)) ; output.write("# ^--- 2\n")
+            tagwriter.write("fl", file)
+            for line in line_dict:
+                output.write("%d %d\n" %( line, line_dict[line] ))
+
+    output.write("\n\n")
+    # now the function calls. For each caller all the called
+    # functions and their costs are written.
+    for file in call_dict.keys():
+        per_file_dict = call_dict[file]
+        #print "file %s -> %s" % (file, per_file_dict)
+        for called_x in per_file_dict.keys():
+            #print "called_x:",called_x
+            per_caller_dict = per_file_dict[called_x]
+            #print "called_x %s wird gerufen von: %s" % (called_x, per_caller_dict)
+            for caller_x in per_caller_dict.keys():
+                tagwriter.write("ob", caller_x[0])
+                tagwriter.write("fn", caller_x[2])# pretty_name(caller_x[2], caller_x[0])) ; output.write("# ^--- 1\n")
+                tagwriter.write("fl", caller_x[0])
+                tagwriter.write("cob", file)
+                tagwriter.write("cfn", called_x) #pretty_name(file, called_x))
+                tagwriter.write("cfl", file)
+                cost, count = per_caller_dict[caller_x]
+                #print "called_x:",called_x
+                output.write("calls=%d\n%d %d\n" % (count, caller_x[1], cost))
+                tagwriter.clear()
+                #tagwriter.clearTag("cob")
+                # is it a bug in kdecachegrind, that the "cob=xxx" line has
+                # to be rewritten after a calls entry with costline ?
+                #assert cost <= total_cost, "caller_x: %s, per_caller_dict: %s " % (caller_x, per_caller_dict, )
+                #output.write("calls=%d\n%d %d\n" % (count, caller_x[1], cost))
+                output.write("\n")
+
+def run_without_optparse():
+    """parse the options without optparse, use sys.argv"""
+    if  len(sys.argv) < 4 or sys.argv[1] != "-o" :
+        print "usage: hotshot2cachegrind -o outputfile in1 [in2 [in3 [...]]]"
+        return
+    outputfilename = sys.argv[2]
+    try:
+        output = file(outputfilename, "w")
+        args = sys.argv[3:]
+        convertProfFiles(output, args)
+        output.close()
+    except IOError:
+        print "could not open '%s' for writing." % outputfilename
+
+def run_with_optparse():
+    """parse the options with optparse"""
+
+    global file_limit
+
+    versiontext = "%s version: %s" % ( progname, version.split()[1], )
+    parser = OptionParser(version=versiontext)
+    parser.add_option("-o", "--output",
+      action="store", type="string", dest="outputfilename",
+      help="write output into FILE")
+    parser.add_option("--file-limit",
+      action="store", dest="file_limit", default=0,
+      help="stop after given number of input files")
+    output = sys.stdout
+    close_output = 0
+    (options, args) = parser.parse_args()
+    file_limit = int(options.file_limit)
+    try:
+        if options.outputfilename and options.outputfilename != "-":
+            output = file(options.outputfilename, "w")
+            close_output = 1
+    except IOError:
+        print "could not open '%s' for writing." % options.outputfilename
+    if output:
+        convertProfFiles(output, args)
+        if close_output:
+            output.close()
+
+
+def profile_myself():
+    import hotshot
+    filename = "self.prof"
+    if not os.path.exists(filename):
+        prof = hotshot.Profile(filename, lineevents=1)
+        prof.runcall(run)
+        prof.close()
+    else:
+        print "not profiling myself, since '%s' exists, running normal" % filename
+        run()
+
+# check if optparse is available.
+try:
+    from optparse import OptionParser
+    run = run_with_optparse
+except ImportError:
+    run = run_without_optparse
+
+if __name__ == "__main__":
+    try:
+        run()
+        #profile_myself()
+    except KeyboardInterrupt:
+        sys.exit(1)
diff --git a/kdecachegrind/converters/memprof2calltree b/kdecachegrind/converters/memprof2calltree
new file mode 100755
index 0000000..e82d6e8
--- /dev/null
+++ b/kdecachegrind/converters/memprof2calltree
@@ -0,0 +1,38 @@
+#!/usr/bin/perl
+#
+# Convert the memory profiles of memprof to calltree format,
+# loadable with KCachegrind
+#
+# (C) 2004, Josef Weidendorfer
+
+print "events: Allocated\n";
+
+while(<>) {
+  if (/^(\S.*)$/) {
+    $next = 0;
+    print "\nfn=$1\n";
+    next;
+  }
+  if (/^  children:/) {
+    $next = 1; #children
+    next;
+  }
+  if (/^  inherited:/) {
+    $next = 2; #inherited
+    next;
+  }
+  if (/^  total:/) {
+    # ignore, is calculated
+    next;
+  }
+  if (/^  self:\s*(\d+)/) {
+    if ($1 ne "0") {
+      print "0 $1\n";
+    }
+    next;
+  }
+  if (/^\s+(\S.*?):\s*(\d+)$/) {
+    if ($next < 2) { next; }
+    print "cfn=$1\ncalls=0 0\n0 $2\n";
+  }
+}
diff --git a/kdecachegrind/converters/op2calltree b/kdecachegrind/converters/op2calltree
new file mode 100755
index 0000000..ca121a2
--- /dev/null
+++ b/kdecachegrind/converters/op2calltree
@@ -0,0 +1,238 @@
+#!/usr/bin/perl
+#
+# Copyright (c) 2004
+# Author: Josef Weidendorfer <Josef.Weidendorfer@gmx.de>
+#
+# op2calltree 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, version 2.
+#
+# 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; see the file COPYING.  If not, write to
+# the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+# Boston, MA 02110-1301, USA.
+#
+#
+# Converter from OProfile's output of "opreport -gdf" (v 0.8)
+# into callgrind format.
+#
+# Generate a OProfile report with opreport and flags -gdf
+# and pipe this as standard input into this script.
+# This will generate separate cachegrind files for every application.
+#
+
+
+# parse symbol line. example (with 1 event type, $has_image==0):
+#   308  0.1491  /path/source.c:6 /path/app main
+sub parseSymSpec {
+  $e = 0;
+  while($e < $eventCount) {
+    ($line) = ($line =~ /\d+\s+\S+\s+(.*)/);
+    $e++;
+  }
+  if ($line =~ s/^\(no location information\)\s+//) {
+    $file = "???";
+    $linenr = 0;
+  }
+  else {
+    ($file,$linenr) = ($line =~ s/(\S+?):(\d+)\s+//);
+  }
+  if ($has_image) {
+    if ($line =~ s/^(\S+)\s+//) { $img = $1; }
+  }
+  if ($has_app) {
+    if ($line =~ s/^(\S+)\s+//) { $app = $1; }
+    if (!$has_image) { $img = $app; }
+  }
+  $sym = $line;
+
+  $app =~ s/^.*\///;
+  if ($sym eq "(no symbols)") { $sym = "???"; }
+  $file{$sym} = $file;
+  $linenr{$sym} = $linenr;
+  $app{$sym} = $app;
+  $img{$app,$sym} = $img;
+  $syms{$app}++;
+
+  if ($app ne $oldApp) {
+    $oldApp = $app;
+    print "\n\nApp $app\n";
+  }
+  print " Symbol $sym (Image $img)\n";
+}
+
+
+
+$eventCount = 0;
+$descCount = 0;
+$lnr = 0;
+$has_image = 0;
+$has_app = 0;
+$app = "unnamed";
+$img = "???";
+
+# first loop till first symbol specification
+while(<>) {
+  $lnr++;
+  chomp;
+  if (/^CPU:/) {
+    $desc[$descCount++] = $_;
+    next;
+  }
+  if (/^Counted\s*(\S+)/) {
+    $desc[$descCount++] = $_;
+    $eventCount++;
+    $events[$eventCount] = $1;
+    next;
+  }
+  if (/^(Profiling through timer.*)/) {
+    $desc[$descCount++] = $_;
+    $eventCount++;
+    $events[$eventCount] = "Timer";
+    next;
+  }
+  if (/^vma/) {
+    # title row: adapt to separation options of OProfile
+    if (/image/) { $has_image = 1; }
+    if (/app/) { $has_app = 1; }
+    next;
+  }
+  if (/^([0-9a-fA-F]+)\s*(.*)$/) {
+    $vmaSym = $1;
+    $line = $2;
+    last;
+  }
+}
+
+if ($eventCount == 0) {
+  die "No Events found";
+}
+
+print "Description:\n";
+foreach $d (@desc) { print " $d\n"; }
+print "\n";
+
+print "Events:";
+foreach $e (@events) { print " $e"; }
+print "\n";
+
+parseSymSpec;
+
+while(<>) {
+  $lnr++;
+  if (/^([0-9a-fA-F]+)\s*(.*)$/) {
+    $vmaSym = $1;
+    $line = $2;
+
+    parseSymSpec;
+    next;
+  }
+  if (/^\s+([0-9a-fA-F]+)\s*(.*)$/) {
+
+    $sampleCount{$app,$sym}++;
+    $sc = $sampleCount{$app,$sym};
+
+    $vma{$app,$sym,$sc} = $1;
+    $line = $2;
+
+    $e = 1;
+    while($e <= $eventCount) {
+      ($cost, $line) = ($line =~ /(\d+)\s+\S+\s+(.*)/);
+      $summary{$app,$e} += $cost;
+      $cost{"$app,$sym,$sc,$e"} = $cost;
+      $e++;
+    }
+    if ($line =~ /\(no location information\)/) {
+      $file = "???";
+      $linenr = 0;
+    }
+    else {
+      ($file,$linenr) = ($line =~ /(\S+?):(\d+)/);
+    }
+    $sFile{$app,$sym,$sc} = $file;
+    $linenr{$app,$sym,$sc} = $linenr;
+
+    $file =~ s/^.*\///;
+    print "  Sample $sc: $vma{$app,$sym,$sc} ($file:$linenr):";
+    foreach $e (1 .. $eventCount) { $c = $cost{"$app,$sym,$sc,$e"} ; print " $c"; }
+    print "\n";
+    next;
+  }
+  die "ERROR: Reading line $lnr '$_'\n";
+}
+
+foreach $app (keys %syms) {
+  if ($app eq "") { next; }
+  print "Generating dump for App '$app'...\n";
+
+  $out = "# Generated by op2cg, using OProfile with opreport -gdf\n";
+  $out .= "positions: instr line\n";
+
+  $out .= "events:";
+  foreach $e (@events) { $out .= " $e"; }
+  $out .= "\n";
+
+  $out .= "summary:";
+  foreach $e (1 .. $eventCount) { $out .= " $summary{$app,$e}"; }
+  $out .= "\n\n";
+
+  %fileNum = ();
+  $fileNum = 1;
+  $sf = "";
+
+  $img = "";
+
+  foreach $sym (keys %file) {
+    if ($sampleCount{$app,$sym} eq "") { next; }
+
+    if ($img{$app,$sym} ne $img) {
+      $img = $img{$app,$sym};
+      $out .= "ob=$img\n";
+    }
+
+    $file = $file{$sym};
+    if ($sf ne $file) {
+      if ($fileNum{$file} eq "") {
+	$fileNum{$file} = $fileNum;
+	$out .= "fl=($fileNum) $file\n";
+	$fileNum++;
+      }
+      else {
+	$out .= "fl=($fileNum{$file})\n";
+      }
+      $sf = $file;
+    }
+
+    $out .= "fn=$sym\n";
+    foreach $sc (1 .. $sampleCount{$app,$sym}) {
+      if ($sf ne $sFile{$app,$sym,$sc}) {
+	$sf = $sFile{$app,$sym,$sc};
+	if ($sf eq $file) {
+	  $out .= "fe=($fileNum{$file})\n";
+	}
+	else {
+	  if ($fileNum{$sf} eq "") {
+	    $fileNum{$sf} = $fileNum;
+	    $out .= "fi=($fileNum) $sf\n";
+	    $fileNum++;
+	  }
+	  else {
+	    $out .= "fi=($fileNum{$sf})\n";
+	  }
+	}
+      }
+      $out .= "0x$vma{$app,$sym,$sc} $linenr{$app,$sym,$sc}";
+      foreach $e (1 .. $eventCount) { $c = $cost{"$app,$sym,$sc,$e"} ; $out .= " $c"; }
+      $out .= "\n";
+    }
+  }
+
+  open OUT, ">oprof.out.$app";
+  print OUT $out;
+  close OUT;
+}
diff --git a/kdecachegrind/converters/pprof2calltree b/kdecachegrind/converters/pprof2calltree
new file mode 100644
index 0000000..0e70e1c
--- /dev/null
+++ b/kdecachegrind/converters/pprof2calltree
@@ -0,0 +1,218 @@
+#!/usr/bin/env php
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are met:
+#
+# - Redistributions of source code must retain the above copyright notice,
+# this list of conditions and the following disclaimer.
+#
+# - Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+#
+# - All advertising materials mentioning features or use of this software
+# must display the following acknowledgement: This product includes software
+# developed by OmniTI Computer Consulting.
+#
+# - Neither name of the company nor the names of its contributors may be
+# used to endorse or promote products derived from this software without
+# specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS `AS IS'' AND ANY
+# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+# DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
+# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+# Copyright (c) 2004 OmniTI Computer Consulting
+# All rights reserved
+# The following code was written by George Schlossnagle <george@omniti.com>
+# and is provided completely free and without any warranty.
+#
+# This script is designed to convert the pprof output from 
+# APD (http://pecl.php.net/apd/) to one readable by kdecachegrind. To use
+# this script:
+#
+# 1) Install APD.
+# 2) Profile your script with APD accordingto the directions in it's
+#    README file.
+# 3) Take the pprof trace file for your script (pprof.XXXXX.Y) and run it 
+#    through this script as follows:
+#    > pprof2calltree -f pprof.12345.1 
+#    This creates a new file cachegrind.out.12345.1
+# 4) View your trace with pprof2calltree cachegrind.out.12345.1
+
+<?php
+
+require "Console/Getopt.php";
+
+$con = new Console_Getopt;
+$args = $con->readPHPArgv();
+array_shift($args);
+$shortoptions = 'f:';
+$retval = $con->getopt( $args, $shortoptions);
+if(is_object($retval)) {
+	usage();
+}
+foreach ($retval[0] as $kv_array) {
+    $opt[$kv_array[0]] = $kv_array[1];
+}
+if(!$opt['f']) {
+	usage();
+}
+if(!file_exists($opt['f'])) {
+	print "Trace file ${opt['f']} does not exist\n";
+	exit;
+}
+$IN = fopen($opt['f'], "r");
+if(!$IN) {
+	print "Trace file ${opt['f']} could not be opened\n";
+	exit;
+}
+
+$path_parts = pathinfo($opt['f']);
+$outfile = "cachegrind.out.".$path_parts['basename'];
+$OUT = fopen($outfile, "w");
+if(!$OUT) {
+	print "Destination file $outfile could not be opened.\n";
+	exit;
+}
+
+while(($line = fgets($IN)) !== false) {
+	$line = rtrim($line);
+	if($line == "END_HEADER") {
+		break;
+	}
+}
+$tree = array();
+$callstack = array();
+while(($line = fgets($IN)) !== false) {
+	$line = rtrim($line);
+	$args = explode(" ", $line);
+	if($args[0] == '!') {
+		$file_lookup[$args[1]] = $args[2];
+	}
+	else if($args[0] == '&') {
+		$function_lookup[$args[1]] = $args[2];
+		$function_type[$args[1]] = ($args[3] == 2)?"USER":"INTERNAL";
+	}
+	else if($args[0] == '+') {
+		$val = array(function_id => $args[1], 
+		             file_id => $args[2],
+					 line => $args[3], 
+					 cost => 0);
+		array_push($callstack, $val);
+	}
+	else if($args[0] == '-') {
+		// retrieve $called to discard
+		$called = array_pop($callstack);
+		// retrieve $caller for reference
+		$caller = array_pop($callstack);
+		$called_id = $called['function_id'];
+		
+		// Set meta data if not already set'
+		if(!array_key_exists($called_id, $tree)) {
+			$tree[$called_id] = $called;
+			// initialize these to 0
+			$tree[$called_id]['cost_per_line'] = array();
+		}
+		if($caller !== null) {
+			$caller['child_calls']++;
+			$caller_id = $caller['function_id'];
+			if(!array_key_exists($caller_id, $tree)) {
+				$tree[$caller_id] = $caller;
+			}
+			$caller['cost'] += $called['cost'];
+			$tree[$caller_id]['called_funcs'][$tree[$caller_id]['call_counter']++][$called_id][$called['file_id']][$called['line']] += $called['cost'];
+			array_push($callstack, $caller);
+		}
+		if(is_array($called['cost_per_line'])) {
+			foreach($called[cost_per_line] as $file => $lines) {
+				foreach($lines as $line => $cost) {
+					$tree[$called_id]['cost_per_line'][$file][$line] += $cost;
+				}
+			}
+		}
+	}
+	else if($args[0] == '@') {
+		$called = array_pop($callstack);
+		switch(count($args)) {
+			// support new and old-style pprof data
+			case 6:
+				$file = $args[1];
+				$line = $args[2];
+				$real_tm = $args[5];
+				break;
+			case 4:
+				$file = $called['file_id'];
+				$line = $called['line'];
+				$real_tm = $args[3];
+				break;
+				
+		}
+		$called['cost_per_line'][$file][$line] += $real_tm;
+		$called['cost'] += $real_tm;
+		$total_cost += $real_tm;
+		array_push($callstack, $called);
+	}
+}
+
+ob_start();
+print "events: Tick\n";
+print "summary: $total_cost\n";
+printf("cmd: %s\n", $file_lookup[1]);
+print "\n";
+
+foreach($tree as $caller => $data) {
+	$filename = $file_lookup[$data['file_id']]?$file_lookup[$data['file_id']]:"???";
+	printf("ob=%s\n", $function_type[$caller]);
+	printf("fl=%s\n", $filename);
+	printf("fn=%s\n", $function_lookup[$caller]);
+	if(is_array($data['cost_per_line'])) {
+		foreach($data['cost_per_line'] as $file => $lines) {
+			foreach($lines as $line => $cost) {
+				print "$line $cost\n";
+			}
+		}
+	}
+	else if ($data['cost']) {
+		printf("COST %s %s\n", $items['line'], $items['cost']);
+	}
+	else {
+		print_r($items);
+	}
+	if(is_array($data['called_funcs'])) {
+		foreach($data['called_funcs'] as $counter => $items) {
+			foreach($items as $called_id => $costs) {
+				if(is_array($costs)) {
+					printf("cfn=%s\n", $function_lookup[$called_id]);
+					foreach($costs as $file => $lines) {
+						printf("cfi=%s\ncalls=1\n", $file_lookup[$file]);
+						foreach($lines as $line => $cost) {
+							print "$line $cost\n";
+						}
+					}
+				}
+			}
+		}
+	}
+	print "\n";
+}
+print "\ntotals=$total_cost\n";
+$buffer = ob_get_clean();
+print "Writing kdecachegrind compatible output to $outfile\n";
+fwrite($OUT, $buffer);
+
+function usage()
+{
+	print <<<EOD
+pprof2calltree -f <tracefile>
+
+EOD;
+	exit(1);
+}
+?>
diff --git a/kdecachegrind/pics/Makefile.am b/kdecachegrind/pics/Makefile.am
new file mode 100644
index 0000000..f4a3186
--- /dev/null
+++ b/kdecachegrind/pics/Makefile.am
@@ -0,0 +1,3 @@
+kdecachegrindicondir = $(kde_datadir)/kdecachegrind/icons
+kdecachegrindicon_ICON = AUTO
+SUBDIRS = hicolor
diff --git a/kdecachegrind/pics/hicolor/Makefile.am b/kdecachegrind/pics/hicolor/Makefile.am
new file mode 100644
index 0000000..068e319
--- /dev/null
+++ b/kdecachegrind/pics/hicolor/Makefile.am
@@ -0,0 +1,2 @@
+kdecachegrindicondir = $(kde_datadir)/kdecachegrind/icons
+kdecachegrindicon_ICON = AUTO
diff --git a/kdecachegrind/pics/hicolor/hi16-action-fromrec.png b/kdecachegrind/pics/hicolor/hi16-action-fromrec.png
new file mode 100644
index 0000000..a5cb430
Binary files /dev/null and b/kdecachegrind/pics/hicolor/hi16-action-fromrec.png differ
diff --git a/kdecachegrind/pics/hicolor/hi16-action-percent.png b/kdecachegrind/pics/hicolor/hi16-action-percent.png
new file mode 100644
index 0000000..7a4ba47
Binary files /dev/null and b/kdecachegrind/pics/hicolor/hi16-action-percent.png differ
diff --git a/kdecachegrind/pics/hicolor/hi16-action-recrec.png b/kdecachegrind/pics/hicolor/hi16-action-recrec.png
new file mode 100644
index 0000000..ec11bfa
Binary files /dev/null and b/kdecachegrind/pics/hicolor/hi16-action-recrec.png differ
diff --git a/kdecachegrind/pics/hicolor/hi16-action-torec.png b/kdecachegrind/pics/hicolor/hi16-action-torec.png
new file mode 100644
index 0000000..c092c01
Binary files /dev/null and b/kdecachegrind/pics/hicolor/hi16-action-torec.png differ
diff --git a/kdecachegrind/pics/hicolor/hi22-action-percent.png b/kdecachegrind/pics/hicolor/hi22-action-percent.png
new file mode 100644
index 0000000..c64a378
Binary files /dev/null and b/kdecachegrind/pics/hicolor/hi22-action-percent.png differ
diff --git a/kdecachegrind/pics/hicolor/hi32-action-percent.png b/kdecachegrind/pics/hicolor/hi32-action-percent.png
new file mode 100644
index 0000000..e876c30
Binary files /dev/null and b/kdecachegrind/pics/hicolor/hi32-action-percent.png differ
diff --git a/kdecachegrind/kdecachegrind.lsm.in b/kdecachegrind/kdecachegrind.lsm.in
new file mode 100644
index 0000000..fab7ced
--- /dev/null
+++ b/kdecachegrind/kdecachegrind.lsm.in
@@ -0,0 +1,11 @@
+Begin3
+Title:          kdecachegrind
+Version:        @KCACHEGRIND_VERSION@
+Description:    KDE Profiling Visualisation Tool
+Keywords:       Profiling, Performance Analysis, Visualisation, Development
+Author:         Josef Weidendorfer <Josef.Weidendorfer@gmx.de> 
+Maintained-by:  Josef Weidendorfer <Josef.Weidendorfer@gmx.de> 
+Home-page:      http://kcachegrind.sourceforge.net
+Platforms:      Linux and other Unices
+Copying-policy: GNU Public License
+End
diff --git a/kdecachegrind/kdecachegrind.spec.in b/kdecachegrind/kdecachegrind.spec.in
new file mode 100644
index 0000000..42b3e24
--- /dev/null
+++ b/kdecachegrind/kdecachegrind.spec.in
@@ -0,0 +1,55 @@
+Summary:   KDE Profiling Visualisation Tool
+Name:      kdecachegrind
+Version:   @KCACHEGRIND_VERSION@
+Release:   1
+Copyright: GPL
+Group:     Development/Tools
+Vendor:    (none)
+URL:       http://kcachegrind.sourceforge.net
+Packager:  Josef Weidendorfer <Josef.Weidendorfer@gmx.de>
+Source:    kdecachegrind-@KCACHEGRIND_VERSION@.tar.gz
+BuildRoot: /var/tmp/build
+
+%description
+KCachegrind is a GPL'd tool for quick browsing in and visualisation
+of performance data of an application run. This data is produced by
+profiling tools and typically includes distribution of cost events
+to source code ranges (instructions, source lines, functions, C++ classes)
+and call relationship of functions.
+KCachegrind has a list of functions sorted according to different cost
+types, and can provide various performance views for a function like
+direct/indirect callers/callees, TreeMap visualisation of cost distribution
+among callees, call graph sectors centered around the function and
+annotated source/assembler.
+Currently, KCachegrind depends on data delivered by the profiling tool
+calltree, powered by the Valgrind runtime instrumentation framework.
+
+%prep
+%setup
+CFLAGS="$RPM_OPT_FLAGS" CXXFLAGS="$RPM_OPT_FLAGS" ./configure \
+                 \
+                $LOCALFLAGS
+%build
+# Setup for parallel builds
+numprocs=`egrep -c ^cpu[0-9]+ /proc/stat || :`
+if [ "$numprocs" = "0" ]; then
+  numprocs=1
+fi
+
+make -j$numprocs
+
+%install
+make install-strip DESTDIR=$RPM_BUILD_ROOT
+
+cd $RPM_BUILD_ROOT
+find . -type d | sed '1,2d;s,^\.,\%attr(-\,root\,root) \%dir ,' > $RPM_BUILD_DIR/file.list.kdecachegrind
+find . -type f | sed 's,^\.,\%attr(-\,root\,root) ,' >> $RPM_BUILD_DIR/file.list.kdecachegrind
+find . -type l | sed 's,^\.,\%attr(-\,root\,root) ,' >> $RPM_BUILD_DIR/file.list.kdecachegrind
+
+%clean
+rm -rf $RPM_BUILD_ROOT/*
+rm -rf $RPM_BUILD_DIR/kdecachegrind
+rm -rf ../file.list.kdecachegrind
+
+
+%files -f ../file.list.kdecachegrind
diff --git a/kdecachegrind/kdecachegrind/Doxyfile b/kdecachegrind/kdecachegrind/Doxyfile
new file mode 100644
index 0000000..9d5d050
--- /dev/null
+++ b/kdecachegrind/kdecachegrind/Doxyfile
@@ -0,0 +1,157 @@
+# Doxygen configuration generated by Doxywizard version 0.1
+#---------------------------------------------------------------------------
+# General configuration options
+#---------------------------------------------------------------------------
+PROJECT_NAME           = kdecachegrind
+PROJECT_NUMBER         = 
+OUTPUT_DIRECTORY       = 
+OUTPUT_LANGUAGE        = English
+EXTRACT_ALL            = YES
+EXTRACT_PRIVATE        = YES
+EXTRACT_STATIC         = YES
+HIDE_UNDOC_MEMBERS     = 
+HIDE_UNDOC_CLASSES     = 
+BRIEF_MEMBER_DESC      = 
+REPEAT_BRIEF           = 
+ALWAYS_DETAILED_SEC    = 
+FULL_PATH_NAMES        = 
+STRIP_FROM_PATH        = 
+INTERNAL_DOCS          = 
+CLASS_DIAGRAMS         = 
+SOURCE_BROWSER         = 
+INLINE_SOURCES         = 
+STRIP_CODE_COMMENTS    = 
+CASE_SENSE_NAMES       = 
+SHORT_NAMES            = 
+HIDE_SCOPE_NAMES       = 
+VERBATIM_HEADERS       = 
+SHOW_INCLUDE_FILES     = 
+JAVADOC_AUTOBRIEF      = 
+INHERIT_DOCS           = 
+INLINE_INFO            = 
+SORT_MEMBER_DOCS       = 
+DISTRIBUTE_GROUP_DOC   = 
+TAB_SIZE               = 
+ENABLED_SECTIONS       = 
+GENERATE_TODOLIST      = 
+GENERATE_TESTLIST      = 
+GENERATE_BUGLIST       = 
+ALIASES                = 
+MAX_INITIALIZER_LINES  = 
+OPTIMIZE_OUTPUT_FOR_C  = 
+SHOW_USED_FILES        = 
+#---------------------------------------------------------------------------
+# configuration options related to warning and progress messages
+#---------------------------------------------------------------------------
+QUIET                  = 
+WARNINGS               = 
+WARN_IF_UNDOCUMENTED   = 
+WARN_FORMAT            = "$file:$line: $text"
+WARN_LOGFILE           = 
+#---------------------------------------------------------------------------
+# configuration options related to the input files
+#---------------------------------------------------------------------------
+INPUT                  = .
+FILE_PATTERNS          = *.cpp \
+                         *.h
+RECURSIVE              = no
+EXCLUDE                = 
+EXCLUDE_PATTERNS       = 
+EXAMPLE_PATH           = 
+EXAMPLE_PATTERNS       = 
+IMAGE_PATH             = 
+INPUT_FILTER           = 
+FILTER_SOURCE_FILES    = 
+#---------------------------------------------------------------------------
+# configuration options related to the alphabetical class index
+#---------------------------------------------------------------------------
+ALPHABETICAL_INDEX     = 
+COLS_IN_ALPHA_INDEX    = 
+IGNORE_PREFIX          = 
+#---------------------------------------------------------------------------
+# configuration options related to the HTML output
+#---------------------------------------------------------------------------
+GENERATE_HTML          = 
+HTML_OUTPUT            = html
+HTML_HEADER            = 
+HTML_FOOTER            = 
+HTML_STYLESHEET        = 
+HTML_ALIGN_MEMBERS     = 
+GENERATE_HTMLHELP      = 
+GENERATE_CHI           = 
+BINARY_TOC             = 
+TOC_EXPAND             = 
+DISABLE_INDEX          = 
+ENUM_VALUES_PER_LINE   = 
+GENERATE_TREEVIEW      = 
+TREEVIEW_WIDTH         = 
+#---------------------------------------------------------------------------
+# configuration options related to the LaTeX output
+#---------------------------------------------------------------------------
+GENERATE_LATEX         = NO
+LATEX_OUTPUT           = latex
+COMPACT_LATEX          = 
+PAPER_TYPE             = a4wide
+EXTRA_PACKAGES         = 
+LATEX_HEADER           = 
+PDF_HYPERLINKS         = 
+USE_PDFLATEX           = 
+LATEX_BATCHMODE        = 
+#---------------------------------------------------------------------------
+# configuration options related to the RTF output
+#---------------------------------------------------------------------------
+GENERATE_RTF           = NO
+RTF_OUTPUT             = rtf
+COMPACT_RTF            = 
+RTF_HYPERLINKS         = 
+RTF_STYLESHEET_FILE    = 
+RTF_EXTENSIONS_FILE    = 
+#---------------------------------------------------------------------------
+# configuration options related to the man page output
+#---------------------------------------------------------------------------
+GENERATE_MAN           = NO
+MAN_OUTPUT             = man
+MAN_EXTENSION          = .3
+MAN_LINKS              = 
+#---------------------------------------------------------------------------
+# Configuration options related to the preprocessor   
+#---------------------------------------------------------------------------
+ENABLE_PREPROCESSING   = 
+MACRO_EXPANSION        = 
+EXPAND_ONLY_PREDEF     = 
+SEARCH_INCLUDES        = 
+INCLUDE_PATH           = 
+INCLUDE_FILE_PATTERNS  = 
+PREDEFINED             = 
+EXPAND_AS_DEFINED      = 
+#---------------------------------------------------------------------------
+# Configuration::addtions related to external references   
+#---------------------------------------------------------------------------
+TAGFILES               = 
+GENERATE_TAGFILE       = 
+ALLEXTERNALS           = 
+PERL_PATH              = /usr/bin/perl
+#---------------------------------------------------------------------------
+# Configuration options related to the dot tool   
+#---------------------------------------------------------------------------
+HAVE_DOT               = 
+CLASS_GRAPH            = 
+COLLABORATION_GRAPH    = 
+INCLUDE_GRAPH          = 
+INCLUDED_BY_GRAPH      = 
+GRAPHICAL_HIERARCHY    = 
+DOT_PATH               = 
+MAX_DOT_GRAPH_WIDTH    = 
+MAX_DOT_GRAPH_HEIGHT   = 
+GENERATE_LEGEND        = 
+DOT_CLEANUP            = 
+#---------------------------------------------------------------------------
+# Configuration::addtions related to the search engine   
+#---------------------------------------------------------------------------
+SEARCHENGINE           = 
+CGI_NAME               = search.cgi
+CGI_URL                = 
+DOC_URL                = 
+DOC_ABSPATH            = 
+BIN_ABSPATH            = /usr/local/bin/
+EXT_DOC_PATHS          = 
diff --git a/kdecachegrind/kdecachegrind/Makefile.am b/kdecachegrind/kdecachegrind/Makefile.am
new file mode 100644
index 0000000..53cd35d
--- /dev/null
+++ b/kdecachegrind/kdecachegrind/Makefile.am
@@ -0,0 +1,62 @@
+bin_PROGRAMS = kdecachegrind
+
+kdecachegrind_SOURCES = \
+ functionselectionbase.ui \
+ stackselectionbase.ui \
+ partselectionbase.ui \
+ configdlgbase.ui \
+ loader.cpp cachegrindloader.cpp treemap.cpp pool.cpp \
+ main.cpp configuration.cpp \
+ functionselection.cpp coverage.cpp partgraph.cpp \
+ toplevel.cpp stackselection.cpp stackbrowser.cpp \
+ subcost.cpp tracedata.cpp partselection.cpp configdlg.cpp \
+ utils.cpp fixcost.cpp \
+ traceitemview.cpp instrview.cpp tabview.cpp \
+ sourceview.cpp callmapview.cpp callview.cpp \
+ coverageview.cpp costtypeview.cpp partview.cpp \
+ listutils.cpp costtypeitem.cpp multiview.cpp \
+ callitem.cpp coverageitem.cpp sourceitem.cpp \
+ costlistitem.cpp partlistitem.cpp functionitem.cpp \
+ instritem.cpp stackitem.cpp callgraphview.cpp
+
+kdecachegrind_COMPILE_FIRST = ../version.h
+
+kdecachegrind_LDADD   =  $(LIB_KIO)
+
+KDE_ICON = AUTO
+
+xdg_apps_DATA = kdecachegrind.desktop
+
+mimeapplicationdir = $(kde_mimedir)/application
+mimeapplication_DATA = x-kcachegrind.desktop
+
+EXTRA_DIST =              \
+ kdecachegrind.desktop      \
+ x-kcachegrind.desktop    \
+ hi32-app-kcachegrind.png \
+ hi48-app-kcachegrind.png \
+ Doxyfile                 \
+ kdecachegrindui.rc
+
+# set the include path for X, qt and KDE
+INCLUDES= $(all_includes)
+
+METASOURCES = AUTO
+
+# the library search path. 
+kdecachegrind_LDFLAGS = $(all_libraries) $(KDE_RPATH) $(LIB_QT) -lDCOP $(LIB_KDECORE) $(LIB_KDEUI) -lkdefx $(LIB_KIO) -lktexteditor
+
+rcdir = $(kde_datadir)/kdecachegrind
+rc_DATA = kdecachegrindui.rc
+
+tipdir = $(kde_datadir)/kdecachegrind
+tip_DATA = tips
+
+messages: rc.cpp
+	$(PREPARETIPS) > tips.txt
+	LIST=`find . -name \*.h -o -name \*.cpp -o -name \*.txt`; \
+	if test -n "$$LIST"; then \
+	 $(XGETTEXT) $$LIST -o $(podir)/kdecachegrind.pot; \
+	fi
+	rm -f tips.txt
+
diff --git a/kdecachegrind/kdecachegrind/cachegrindloader.cpp b/kdecachegrind/kdecachegrind/cachegrindloader.cpp
new file mode 100644
index 0000000..4fe57d3
--- /dev/null
+++ b/kdecachegrind/kdecachegrind/cachegrindloader.cpp
@@ -0,0 +1,1323 @@
+/* This file is part of KCachegrind.
+   Copyright (C) 2002, 2003 Josef Weidendorfer <Josef.Weidendorfer@gmx.de>
+
+   KCachegrind 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, version 2.
+
+   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; see the file COPYING.  If not, write to
+   the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+   Boston, MA 02110-1301, USA.
+*/
+
+#include <errno.h>
+
+#include <tqfile.h>
+#include <tqcstring.h>
+
+#include <klocale.h>
+#include <kdebug.h>
+
+#include "loader.h"
+#include "tracedata.h"
+#include "utils.h"
+#include "fixcost.h"
+
+
+#define TRACE_LOADER 0
+
+/*
+ * Loader for Callgrind Profile data (format based on Cachegrind format).
+ * See Callgrind documentation for the file format.
+ */
+
+class CachegrindLoader: public Loader
+{
+public:
+  CachegrindLoader();
+  
+  bool canLoadTrace(TQFile* file);  
+  bool loadTrace(TracePart*);
+  bool isPartOfTrace(TQString file, TraceData*);
+  
+private:
+  bool loadTraceInternal(TracePart*);
+
+  enum lineType { SelfCost, CallCost, BoringJump, CondJump };
+  
+  bool parsePosition(FixString& s, PositionSpec& newPos);
+
+  // position setters
+  void clearPosition();
+  void ensureObject();
+  void ensureFile();
+  void ensureFunction();
+  void setObject(const TQString&);
+  void setCalledObject(const TQString&);
+  void setFile(const TQString&);
+  void setCalledFile(const TQString&);
+  void setFunction(const TQString&);
+  void setCalledFunction(const TQString&);
+
+  TQString _emptyString;
+  
+  // current line in file to read in
+  TQString _filename;
+  int _lineNo;
+
+  TraceSubMapping* subMapping;
+  TraceData* _data;
+  TracePart* _part;
+
+  // current position
+  lineType nextLineType;
+  bool hasLineInfo, hasAddrInfo;
+  PositionSpec currentPos;
+  
+    // current function/line
+  TraceObject* currentObject;
+  TracePartObject* currentPartObject;
+  TraceFile* currentFile;
+  TracePartFile* currentPartFile;
+  TraceFunction* currentFunction;
+  TracePartFunction* currentPartFunction;
+  TraceFunctionSource* currentFunctionSource;
+  TraceInstr* currentInstr;
+  TracePartInstr* currentPartInstr;
+  TraceLine* currentLine;
+  TracePartLine* currentPartLine;
+
+  // current call
+  TraceObject* currentCalledObject;
+  TracePartObject* currentCalledPartObject;
+  TraceFile* currentCalledFile;
+  TracePartFile* currentCalledPartFile;
+  TraceFunction* currentCalledFunction;
+  TracePartFunction* currentCalledPartFunction;
+  SubCost currentCallCount;
+  
+  // current jump
+  TraceFile* currentJumpToFile;
+  TraceFunction* currentJumpToFunction;
+  PositionSpec targetPos;
+  SubCost jumpsFollowed, jumpsExecuted;
+  
+  /** Support for compressed string format
+   * This uses the following string compression model
+   * for objects, files, functions:
+   * If the name matches
+   *   "(<Integer>) Name": this is a compression specification,
+   *                       mapping the integer number to Name and using Name.
+   *   "(<Integer>)"     : this is a compression reference.
+   *                       Assumes previous compression specification of the
+   *                       integer number to a name, uses this name.
+   *   "Name"            : Regular name
+   */
+  void clearCompression();
+  const TQString& checkUnknown(const TQString& n);
+  TraceObject* compressedObject(const TQString& name);
+  TraceFile* compressedFile(const TQString& name);
+  TraceFunction* compressedFunction(const TQString& name,
+                                    TraceFile*, TraceObject*);
+
+  TQPtrVector<TraceCostItem> _objectVector, _fileVector, _functionVector;
+};
+
+
+
+/**********************************************************
+ * Loader
+ */
+
+
+CachegrindLoader::CachegrindLoader()
+  : Loader("Callgrind",
+           i18n( "Import filter for Cachegrind/Callgrind generated profile data files") )
+{
+    _emptyString = TQString("");
+}
+
+bool CachegrindLoader::canLoadTrace(TQFile* file)
+{
+  if (!file) return false;
+
+  if (!file->isOpen()) {
+    if (!file->open( IO_ReadOnly ) ) {
+      kdDebug() << TQFile::encodeName(_filename).data() << ": "
+		<< strerror( errno ) << endl;
+      return false;
+    }
+  }
+
+  /* 
+   * We recognize this as cachegrind/callgrind format if in the first
+   * 2047 bytes we see the string "\nevents:"
+   */
+  char buf[2048];
+  int read = file->readBlock(buf,2047);
+  if (read < 0)
+	return false;
+  buf[read] = 0;
+
+  TQCString s;
+  s.setRawData(buf, read+1);
+  int pos = s.find("events:");
+  if (pos>0 && buf[pos-1] != '\n') pos = -1;
+  s.resetRawData(buf, read+1);
+  return (pos>=0);
+}
+
+bool CachegrindLoader::loadTrace(TracePart* p)
+{
+  /* do the loading in a new object so parallel load
+   * operations do not interfere each other.
+   */
+  CachegrindLoader l;
+
+  /* emit progress signals via the singleton loader */
+  connect(&l, TQT_SIGNAL(updateStatus(TQString, int)),
+	  this, TQT_SIGNAL(updateStatus(TQString, int)));
+
+  return l.loadTraceInternal(p);
+}
+
+Loader* createCachegrindLoader()
+{
+  return new CachegrindLoader();
+}
+
+
+
+/**
+ * Return false if this is no position specification
+ */
+bool CachegrindLoader::parsePosition(FixString& line,
+				     PositionSpec& newPos)
+{
+    char c;
+    uint diff;
+
+    if (hasAddrInfo) {
+      
+      if (!line.first(c)) return false;
+
+      if (c == '*') {
+	// nothing changed
+	line.stripFirst(c);
+	newPos.fromAddr = currentPos.fromAddr;
+	newPos.toAddr = currentPos.toAddr;
+      }
+      else if (c == '+') {
+	line.stripFirst(c);
+	line.stripUInt(diff, false);
+	newPos.fromAddr = currentPos.fromAddr + diff;
+	newPos.toAddr = newPos.fromAddr;
+      }
+      else if (c == '-') {
+	line.stripFirst(c);
+	line.stripUInt(diff, false);
+	newPos.fromAddr = currentPos.fromAddr - diff;
+	newPos.toAddr = newPos.fromAddr;
+      }
+      else if (c >= '0') {
+	uint64 v;
+	line.stripUInt64(v, false);
+	newPos.fromAddr = Addr(v);
+	newPos.toAddr = newPos.fromAddr;
+      }
+      else return false;
+
+      // Range specification
+      if (line.first(c)) {
+	if (c == '+') {
+	  line.stripFirst(c);
+	  line.stripUInt(diff);
+	  newPos.toAddr = newPos.fromAddr + diff;
+	}
+	else if ((c == '-') || (c == ':')) {
+	  line.stripFirst(c);
+	  uint64 v;
+	  line.stripUInt64(v);
+	  newPos.toAddr = Addr(v);
+	}
+      }
+      line.stripSpaces();
+
+#if TRACE_LOADER
+      if (newPos.fromAddr == newPos.toAddr)
+	kdDebug() << " Got Addr " << newPos.fromAddr.toString() << endl;
+      else
+	kdDebug() << " Got AddrRange " << newPos.fromAddr.toString()
+		  << ":" << newPos.toAddr.toString() << endl;
+#endif
+
+    }
+    
+    if (hasLineInfo) {
+
+      if (!line.first(c)) return false;
+
+      if (c > '9') return false;
+      else if (c == '*') {
+	// nothing changed
+	line.stripFirst(c);
+	newPos.fromLine = currentPos.fromLine;
+	newPos.toLine   = currentPos.toLine;
+      }
+      else if (c == '+') {
+	line.stripFirst(c);
+	line.stripUInt(diff, false);
+	newPos.fromLine = currentPos.fromLine + diff;
+	newPos.toLine = newPos.fromLine;
+      }
+      else if (c == '-') {
+	line.stripFirst(c);
+	line.stripUInt(diff, false);
+	if (currentPos.fromLine < diff) {
+	    kdError() << _filename << ":" << _lineNo
+		      << " - Negative line number "
+		      << (int)currentPos.fromLine - (int)diff << endl;
+	  diff = currentPos.fromLine;
+	}
+	newPos.fromLine = currentPos.fromLine - diff;
+	newPos.toLine = newPos.fromLine;
+      }
+      else if (c >= '0') {
+	line.stripUInt(newPos.fromLine, false);
+	newPos.toLine = newPos.fromLine;
+      }
+      else return false;
+
+      // Range specification
+      if (line.first(c)) {
+	if (c == '+') {
+	  line.stripFirst(c);
+	  line.stripUInt(diff);
+	  newPos.toLine = newPos.fromLine + diff;
+	}
+	else if ((c == '-') || (c == ':')) {
+	  line.stripFirst(c);
+	  line.stripUInt(newPos.toLine);
+	}
+      }
+      line.stripSpaces();
+
+#if TRACE_LOADER
+      if (newPos.fromLine == newPos.toLine)
+	kdDebug() << " Got Line " << newPos.fromLine << endl;
+      else
+	kdDebug() << " Got LineRange " << newPos.fromLine
+		  << ":" << newPos.toLine << endl;
+#endif
+
+    }
+
+    return true;
+}
+
+// Support for compressed strings
+void CachegrindLoader::clearCompression()
+{
+  // this doesn't delete previous contained objects
+  _objectVector.clear();
+  _fileVector.clear();
+  _functionVector.clear();
+
+  // reset to reasonable init size. We double lengths if needed.
+  _objectVector.resize(100);
+  _fileVector.resize(1000);
+  _functionVector.resize(10000);
+}
+
+const TQString& CachegrindLoader::checkUnknown(const TQString& n)
+{
+    if (n == "???") return _emptyString;
+    return n;
+}
+
+TraceObject* CachegrindLoader::compressedObject(const TQString& name)
+{
+  if ((name[0] != '(') || !name[1].isDigit()) return _data->object(checkUnknown(name));
+
+  // compressed format using _objectVector
+  int p = name.find(')');
+  if (p<2) {
+      kdError() << _filename << ":" << _lineNo
+		<< " - Invalid compressed ELF object ('" 
+		<< name << "')" << endl;
+    return 0;
+  }
+  unsigned index = name.mid(1, p-1).toInt();
+  TraceObject* o = 0;
+  p++;
+  if ((int)name.length()>p) {
+    while(name.at(p).isSpace()) p++;
+
+    if (_objectVector.size() <= index) {
+      int newSize = index * 2;
+#if TRACE_LOADER
+      kdDebug() << " CachegrindLoader: objectVector enlarged to "
+		<< newSize << endl;
+#endif
+      _objectVector.resize(newSize);
+    }
+
+    TQString realName = checkUnknown(name.mid(p));
+    o = (TraceObject*) _objectVector.at(index);
+    if (o && (o->name() != realName)) {
+	kdError() << _filename << ":" << _lineNo
+		  << " - Redefinition of compressed ELF object index " << index
+		  << " (was '" << o->name()
+		  << "') to '" << realName << "'" << endl;
+    }
+
+    o = _data->object(realName);
+    _objectVector.insert(index, o);
+  }
+  else {
+    if ((_objectVector.size() <= index) ||
+	( (o=(TraceObject*)_objectVector.at(index)) == 0)) {
+	kdError() << _filename << ":" << _lineNo
+		  << " - Undefined compressed ELF object index " << index << endl;
+      return 0;
+    }    
+  }
+
+  return o;
+}
+
+
+// Note: Callgrind sometimes gives different IDs for same file
+// (when references to same source file come from different ELF objects)
+TraceFile* CachegrindLoader::compressedFile(const TQString& name)
+{
+  if ((name[0] != '(') || !name[1].isDigit()) return _data->file(checkUnknown(name));
+
+  // compressed format using _fileVector
+  int p = name.find(')');
+  if (p<2) {
+      kdError() << _filename << ":" << _lineNo
+		<< " - Invalid compressed file ('" 
+		<< name << "')" << endl;
+    return 0;
+  }
+  unsigned int index = name.mid(1, p-1).toUInt();
+  TraceFile* f = 0;
+  p++;
+  if ((int)name.length()>p) {
+    while(name.at(p).isSpace()) p++;
+
+    if (_fileVector.size() <= index) {
+      int newSize = index * 2;
+#if TRACE_LOADER
+      kdDebug() << " CachegrindLoader::fileVector enlarged to "
+		<< newSize << endl;
+#endif
+      _fileVector.resize(newSize);
+    }
+
+    TQString realName = checkUnknown(name.mid(p));
+    f = (TraceFile*) _fileVector.at(index);
+    if (f && (f->name() != realName)) {
+	kdError() << _filename << ":" << _lineNo
+		  << " - Redefinition of compressed file index " << index
+		  << " (was '" << f->name()
+		  << "') to '" << realName << "'" << endl;
+    }
+
+    f = _data->file(realName);
+    _fileVector.insert(index, f);
+  }
+  else {
+    if ((_fileVector.size() <= index) ||
+	( (f=(TraceFile*)_fileVector.at(index)) == 0)) {
+	kdError() << _filename << ":" << _lineNo
+		  << " - Undefined compressed file index " << index << endl;
+      return 0;
+    }
+  }
+
+  return f;
+}
+
+// Note: Callgrind gives different IDs even for same function
+// when parts of the function are from different source files.
+// Thus, it is no error when multiple indexes map to same function.
+TraceFunction* CachegrindLoader::compressedFunction(const TQString& name,
+						    TraceFile* file,
+						    TraceObject* object)
+{
+  if ((name[0] != '(') || !name[1].isDigit())
+    return _data->function(checkUnknown(name), file, object);
+
+  // compressed format using _functionVector
+  int p = name.find(')');
+  if (p<2) {
+      kdError() << _filename << ":" << _lineNo
+		<< " - Invalid compressed function ('" 
+		<< name << "')" << endl;
+    return 0;
+  }
+
+
+  unsigned int index = name.mid(1, p-1).toUInt();
+  TraceFunction* f = 0;
+  p++;
+  if ((int)name.length()>p) {
+    while(name.at(p).isSpace()) p++;
+
+    if (_functionVector.size() <= index) {
+      int newSize = index * 2;
+#if TRACE_LOADER
+      kdDebug() << " CachegrindLoader::functionVector enlarged to "
+		<< newSize << endl;
+#endif
+      _functionVector.resize(newSize);
+    }
+
+    TQString realName = checkUnknown(name.mid(p));
+    f = (TraceFunction*) _functionVector.at(index);
+    if (f && (f->name() != realName)) {
+	    kdError() << _filename << ":" << _lineNo
+		      << " - Redefinition of compressed function index " << index
+		      << " (was '" << f->name()
+		      << "') to '" << realName << "'" << endl;
+    }
+
+    f = _data->function(realName, file, object);
+    _functionVector.insert(index, f);
+
+#if TRACE_LOADER
+    kdDebug() << "compressedFunction: Inserted at Index " << index
+	      << "\n  " << f->fullName()
+	      << "\n  in " << f->cls()->fullName()
+	      << "\n  in " << f->file()->fullName()
+	      << "\n  in " << f->object()->fullName() << endl;
+#endif
+  }
+  else {
+    if ((_functionVector.size() <= index) ||
+	( (f=(TraceFunction*)_functionVector.at(index)) == 0)) {
+	    kdError() << _filename << ":" << _lineNo
+		      << " - Undefined compressed function index " 
+		      << index << endl;
+      return 0;
+    }
+
+    // there was a check if the used function (returned from KCachegrinds
+    // model) has the same object and file as here given to us, but that was wrong:
+    // that holds only if we make this assumption on the model...
+  }
+
+  return f;
+}
+
+
+// make sure that a valid object is set, at least dummy with empty name
+void CachegrindLoader::ensureObject()
+{
+  if (currentObject) return;
+
+  currentObject = _data->object(_emptyString);
+  currentPartObject = currentObject->partObject(_part);
+}
+
+void CachegrindLoader::setObject(const TQString& name)
+{
+  currentObject = compressedObject(name);
+  if (!currentObject) {
+    kdError() << _filename << ":" << _lineNo
+	      << " - Invalid object specification, setting to unknown" << endl;
+
+    currentObject = _data->object(_emptyString);
+  }
+
+  currentPartObject = currentObject->partObject(_part);
+  currentFunction = 0;
+  currentPartFunction = 0;
+}
+
+void CachegrindLoader::setCalledObject(const TQString& name)
+{
+  currentCalledObject = compressedObject(name);
+
+  if (!currentCalledObject) {
+    kdError() << _filename << ":" << _lineNo
+	      << " - Invalid called specification, setting to unknown" << endl;
+
+    currentCalledObject = _data->object(_emptyString);
+  }
+
+  currentCalledPartObject = currentCalledObject->partObject(_part);
+}
+
+
+// make sure that a valid file is set, at least dummy with empty name
+void CachegrindLoader::ensureFile()
+{
+  if (currentFile) return;
+
+  currentFile = _data->file(_emptyString);
+  currentPartFile = currentFile->partFile(_part);
+}
+
+void CachegrindLoader::setFile(const TQString& name)
+{
+  currentFile = compressedFile(name);
+
+  if (!currentFile) {
+    kdWarning() << _filename << ":" << _lineNo
+		<< " - Invalid file specification, setting to unknown" << endl;
+
+    currentFile = _data->file(_emptyString);
+  }
+
+  currentPartFile = currentFile->partFile(_part);
+  currentLine = 0;
+  currentPartLine = 0;
+}
+
+void CachegrindLoader::setCalledFile(const TQString& name)
+{
+  currentCalledFile = compressedFile(name);
+
+  if (!currentCalledFile) {
+    kdError() << _filename << ":" << _lineNo
+	      << " - Invalid called file specification, setting to unknown" << endl;
+
+    currentCalledFile = _data->file(_emptyString);
+  }
+
+  currentCalledPartFile = currentCalledFile->partFile(_part);
+}
+
+// make sure that a valid function is set, at least dummy with empty name
+void CachegrindLoader::ensureFunction()
+{
+  if (currentFunction) return;
+
+  kdWarning() << _filename << ":" << _lineNo
+	      << " - Function name not set" << endl;
+
+  ensureFile();
+  ensureObject();
+
+  currentFunction = _data->function(_emptyString,
+				    currentFile,
+				    currentObject);
+  currentPartFunction = currentFunction->partFunction(_part,
+						      currentPartFile,
+						      currentPartObject);
+}
+
+void CachegrindLoader::setFunction(const TQString& name)
+{
+  ensureFile();
+  ensureObject();
+  
+  currentFunction = compressedFunction( name,
+					currentFile,
+					currentObject);
+
+  if (!currentFunction) {
+    kdWarning() << _filename << ":" << _lineNo
+		<< " - Invalid function, setting to unknown" << endl;
+
+    currentFunction = _data->function(_emptyString,
+				      currentFile,
+				      currentObject);
+  }
+
+  currentPartFunction = currentFunction->partFunction(_part,
+						      currentPartFile,
+						      currentPartObject);
+
+  currentFunctionSource = 0;
+  currentLine = 0;
+  currentPartLine = 0;
+}
+
+void CachegrindLoader::setCalledFunction(const TQString& name)
+{
+  // if called object/file not set, use current object/file
+  if (!currentCalledObject) {
+    currentCalledObject = currentObject;
+    currentCalledPartObject = currentPartObject;
+  }
+
+  if (!currentCalledFile) {
+    // !=0 as functions needs file
+    currentCalledFile = currentFile;
+    currentCalledPartFile = currentPartFile;
+  }
+
+  currentCalledFunction = compressedFunction(name,
+					     currentCalledFile,
+					     currentCalledObject);
+  if (!currentCalledFunction) {
+    kdWarning() << _filename << ":" << _lineNo
+		<< " - Invalid called function, setting to unknown" << endl;
+
+    currentCalledFunction = _data->function(_emptyString,
+					    currentCalledFile,
+					    currentCalledObject);
+  }
+
+  currentCalledPartFunction =
+    currentCalledFunction->partFunction(_part,
+					currentCalledPartFile,
+					currentCalledPartObject);
+}
+
+
+void CachegrindLoader::clearPosition()
+{
+  currentPos = PositionSpec();
+
+  // current function/line
+  currentFunction = 0;
+  currentPartFunction = 0;
+  currentFunctionSource = 0;
+  currentFile = 0;
+  currentPartFile = 0;
+  currentObject = 0;
+  currentPartObject = 0;
+  currentLine = 0;
+  currentPartLine = 0;
+  currentInstr = 0;
+  currentPartInstr = 0;
+
+  // current call
+  currentCalledObject = 0;
+  currentCalledPartObject = 0;
+  currentCalledFile = 0;
+  currentCalledPartFile = 0;
+  currentCalledFunction = 0;
+  currentCalledPartFunction = 0;
+  currentCallCount = 0;
+
+  // current jump
+  currentJumpToFile = 0;
+  currentJumpToFunction = 0;
+  targetPos = PositionSpec();
+  jumpsFollowed = 0;
+  jumpsExecuted = 0;
+
+  subMapping = 0;
+}
+
+
+/**
+ * The main import function...
+ */
+bool CachegrindLoader::loadTraceInternal(TracePart* part)
+{
+  clearCompression();
+  clearPosition();
+
+  _part     = part;
+  _data     = part->data();
+  TQFile* pFile = part->file();
+
+  if (!pFile) return false;
+    
+  _filename = pFile->name();
+
+  FixFile file(pFile);
+  if (!file.exists()) {
+    kdError() << "File doesn't exist\n" << endl;
+    return false;
+  }
+  kdDebug() << "Loading " << _filename << " ..." << endl;
+  TQString statusMsg = i18n("Loading %1").arg(_filename);
+  int statusProgress = 0;
+  emit updateStatus(statusMsg,statusProgress);
+
+
+#if USE_FIXCOST
+  // FixCost Memory Pool
+  FixPool* pool = _data->fixPool();
+#endif
+
+  _lineNo = 0;
+  FixString line;
+  char c;
+  bool totalsSet = false;
+
+  // current position
+  nextLineType  = SelfCost;
+  // default if there's no "positions:" line
+  hasLineInfo = true;
+  hasAddrInfo = false;
+
+  while (file.nextLine(line)) {
+
+      _lineNo++;
+
+#if TRACE_LOADER
+      kdDebug() << "[CachegrindLoader] " << _filename << ":" << _lineNo
+		<< " - '" << TQString(line) << "'" << endl;
+#endif
+
+      // if we cannot strip a character, this was an empty line
+      if (!line.first(c)) continue;
+
+      if (c <= '9') {
+
+	  if (c == '#') continue;
+
+	  // parse position(s)
+	  if (!parsePosition(line, currentPos)) {
+	      kdError() << _filename << ":" << _lineNo
+			<< " - Invalid position specification ('"
+			<< TQString(line) << "')" << endl;
+	      continue;
+	  }
+
+	  // go through after big switch
+      }
+      else { // if (c > '9')
+
+	line.stripFirst(c);
+
+	/* in order of probability */
+	switch(c) {
+
+	case 'f':
+
+	    // fl=, fi=, fe=
+	    if (line.stripPrefix("l=") ||
+		line.stripPrefix("i=") ||
+		line.stripPrefix("e=")) {
+
+	      setFile(line);
+	      continue;
+	    }
+
+	    // fn=
+	    if (line.stripPrefix("n=")) {
+
+	      setFunction(line);
+
+	      // on a new function, update status
+	      int progress = (int)(100.0 * file.current() / file.len() +.5);
+	      if (progress != statusProgress) {
+		statusProgress = progress;
+
+		/* When this signal is connected, it most probably
+		 * should lead to GUI update. Thus, when multiple
+		 * "long operations" (like file loading) are in progress,
+		 * this can temporarly switch to another operation.
+		 */
+		emit updateStatus(statusMsg,statusProgress);
+	      }
+
+	      continue;
+	    }
+
+	    break;
+
+	case 'c':
+	    // cob=
+	    if (line.stripPrefix("ob=")) {
+	      setCalledObject(line);
+	      continue;
+	    }
+
+	    // cfi= / cfl=
+	    if (line.stripPrefix("fl=") ||
+		line.stripPrefix("fi=")) {
+	      setCalledFile(line);
+	      continue;
+	    }
+
+	    // cfn=
+	    if (line.stripPrefix("fn=")) {
+
+	      setCalledFunction(line);
+	      continue;
+	    }
+
+	    // calls=
+	    if (line.stripPrefix("alls=")) {
+		// ignore long lines...
+		line.stripUInt64(currentCallCount);
+		nextLineType = CallCost;
+		continue;
+	    }
+
+	    // cmd:
+	    if (line.stripPrefix("md:")) {
+		TQString command = TQString(line).stripWhiteSpace();
+		if (!_data->command().isEmpty() &&
+		    _data->command() != command) {
+
+		  kdWarning() << _filename << ":" << _lineNo
+			      << " - Redefined command, was '"
+			      << _data->command()
+			      << "'" << endl;
+		}
+		_data->setCommand(command);
+		continue;
+	    }
+
+	    // creator:
+	    if (line.stripPrefix("reator:")) {
+		// ignore ...
+	        continue;
+	    }
+
+	    break;
+
+	case 'j':
+
+	    // jcnd=
+	    if (line.stripPrefix("cnd=")) {
+		bool valid;
+
+		valid = line.stripUInt64(jumpsFollowed) &&
+		    line.stripPrefix("/") &&
+		    line.stripUInt64(jumpsExecuted) &&
+		    parsePosition(line, targetPos);
+
+		if (!valid) {
+		  kdError() << _filename << ":" << _lineNo
+			    << " - Invalid jcnd line" << endl;
+		}
+		else
+		    nextLineType = CondJump;
+		continue;
+	    }
+
+	    if (line.stripPrefix("ump=")) {
+		bool valid;
+
+		valid = line.stripUInt64(jumpsExecuted) &&
+		    parsePosition(line, targetPos);
+
+		if (!valid) {
+		  kdError() << _filename << ":" << _lineNo
+			    << " - Invalid jump line" << endl;
+		}
+		else
+		    nextLineType = BoringJump;
+		continue;
+	    }
+
+	    // jfi=
+	    if (line.stripPrefix("fi=")) {
+		currentJumpToFile = compressedFile(line);
+		continue;
+	    }
+
+	    // jfn=
+	    if (line.stripPrefix("fn=")) {
+
+		if (!currentJumpToFile) {
+		    // !=0 as functions needs file
+		    currentJumpToFile = currentFile;
+		}
+
+		currentJumpToFunction =
+		    compressedFunction(line,
+				       currentJumpToFile,
+				       currentObject);
+		continue;
+	    }
+
+	    break;
+
+	case 'o':
+
+	    // ob=
+	    if (line.stripPrefix("b=")) {
+	      setObject(line);
+	      continue;
+	    }
+
+	    break;
+
+	case '#':
+	    continue;
+
+	case 't':
+
+	    // totals:
+	    if (line.stripPrefix("otals:")) continue;
+
+	    // thread:
+	    if (line.stripPrefix("hread:")) {
+		part->setThreadID(TQString(line).toInt());
+		continue;
+	    }
+
+	    // timeframe (BB):
+	    if (line.stripPrefix("imeframe (BB):")) {
+		part->setTimeframe(line);
+		continue;
+	    }
+
+	    break;
+
+	case 'd':
+
+	    // desc:
+	    if (line.stripPrefix("esc:")) {
+
+	      line.stripSurroundingSpaces();
+
+	      // desc: Trigger:
+	      if (line.stripPrefix("Trigger:")) {
+		part->setTrigger(line);
+	      }
+	      
+	      continue;
+	    }
+	    break;
+
+	case 'e':
+
+	    // events:
+	    if (line.stripPrefix("vents:")) {
+		subMapping = _data->mapping()->subMapping(line);
+                part->setFixSubMapping(subMapping);
+		continue;
+	    }
+
+	    // event:<name>[=<formula>][:<long name>]
+	    if (line.stripPrefix("vent:")) {
+	      line.stripSurroundingSpaces();
+
+	      FixString e, f, l;
+	      if (!line.stripName(e)) {
+		kdError() << _filename << ":" << _lineNo
+			  << " - Invalid event" << endl;
+		continue;
+	      }
+	      line.stripSpaces();
+	      if (!line.stripFirst(c)) continue;
+
+	      if (c=='=') f = line.stripUntil(':');
+	      line.stripSpaces();
+
+	      // add to known cost types
+	      if (line.isEmpty()) line = e;
+	      TraceCostType::add(new TraceCostType(e,line,f));
+	      continue;
+	    }
+	    break;
+
+	case 'p':
+
+	    // part:
+	    if (line.stripPrefix("art:")) {
+		part->setPartNumber(TQString(line).toInt());
+		continue;
+	    }
+
+	    // pid:
+	    if (line.stripPrefix("id:")) {
+		part->setProcessID(TQString(line).toInt());
+		continue;
+	    }
+
+	    // positions:
+	    if (line.stripPrefix("ositions:")) {
+		TQString positions(line);
+		hasLineInfo = (positions.find("line")>=0);
+		hasAddrInfo = (positions.find("instr")>=0);
+		continue;
+	    }
+	    break;
+
+	case 'v':
+
+	    // version:
+	    if (line.stripPrefix("ersion:")) {
+		part->setVersion(line);
+		continue;
+	    }
+	    break;
+
+	case 's':
+
+	    // summary:
+	    if (line.stripPrefix("ummary:")) {
+		if (!subMapping) {
+		  kdError() << "No event line found. Skipping '" << _filename << endl;
+		  return false;
+		}
+
+		part->totals()->set(subMapping, line);
+		continue;
+	    }
+
+	case 'r':
+
+	    // rcalls= (deprecated)
+	    if (line.stripPrefix("calls=")) {
+		// handle like normal calls: we need the sum of call count
+		// recursive cost is discarded in cycle detection
+		line.stripUInt64(currentCallCount);
+		nextLineType = CallCost;
+
+		kdDebug() << "WARNING: This trace dump was generated by an old "
+		  "version\n of the call-tree skin. Use a new one!" << endl;
+
+		continue;
+	    }
+	    break;
+
+	default:
+	    break;
+	}
+
+	kdError() << _filename << ":" << _lineNo
+		  << " - Invalid line '" << c << TQString(line) << "'" << endl;
+	continue;
+      }
+
+      if (!subMapping) {
+	kdError() << "No event line found. Skipping '" << _filename << "'" << endl;
+	return false;
+      }
+
+      // for a cost line, we always need a current function
+      ensureFunction();
+
+
+#if USE_FIXCOST
+      if (!currentFunctionSource ||
+	  (currentFunctionSource->file() != currentFile))
+	  currentFunctionSource = currentFunction->sourceFile(currentFile,
+							      true);
+#else
+      if (hasAddrInfo) {
+	  if (!currentInstr ||
+	      (currentInstr->addr() != currentPos.fromAddr)) {
+	      currentInstr = currentFunction->instr(currentPos.fromAddr,
+						    true);
+
+	      if (!currentInstr) {
+		kdError() << _filename << ":" << _lineNo
+			  << " - Invalid address "
+			  << currentPos.fromAddr.toString() << endl;
+
+		continue;
+	      }
+
+	      currentPartInstr = currentInstr->partInstr(part,
+							 currentPartFunction);
+	  }
+      }
+
+      if (hasLineInfo) {
+	  if (!currentLine ||
+	      (currentLine->lineno() != currentPos.fromLine)) {
+	    
+	    currentLine = currentFunction->line(currentFile,
+						currentPos.fromLine,
+						true);
+	    currentPartLine = currentLine->partLine(part,
+						    currentPartFunction);
+	  }
+	  if (hasAddrInfo && currentInstr)
+	      currentInstr->setLine(currentLine);
+      }
+#endif
+
+#if TRACE_LOADER
+      kdDebug() << _filename << ":" << _lineNo
+		<< endl << "  currentInstr "
+		<< (currentInstr ? currentInstr->toString().ascii() : ".")
+		<< endl << "  currentLine "
+		<< (currentLine ? currentLine->toString().ascii() : ".")
+		<< "( file " << currentFile->name() << ")"
+		<< endl << "  currentFunction "
+		<< currentFunction->prettyName().ascii()
+		<< endl << "  currentCalled "
+		<< (currentCalledFunction ? currentCalledFunction->prettyName().ascii() : ".")
+		<< endl;
+#endif
+
+    // create cost item
+
+    if (nextLineType == SelfCost) {
+
+#if USE_FIXCOST
+      new (pool) FixCost(part, pool,
+			 currentFunctionSource,
+			 currentPos,
+                         currentPartFunction,
+                         line);
+#else
+      if (hasAddrInfo) {
+	  TracePartInstr* partInstr;
+	  partInstr = currentInstr->partInstr(part, currentPartFunction);
+
+	  if (hasLineInfo) {
+	      // we need to set <line> back after reading for the line
+	      int l = line.len();
+	      const char* s = line.ascii();
+
+	      partInstr->addCost(subMapping, line);
+	      line.set(s,l);
+	  }
+	  else
+	      partInstr->addCost(subMapping, line);
+      }
+
+      if (hasLineInfo) {
+	  TracePartLine* partLine;
+	  partLine = currentLine->partLine(part, currentPartFunction);
+	  partLine->addCost(subMapping, line);
+      }
+#endif
+
+      if (!line.isEmpty()) {
+	kdError() << _filename << ":" << _lineNo
+		  << " - Garbage at end of cost line ('" 
+		  << TQString(line) << "')" << endl;
+      }
+    }
+    else if (nextLineType == CallCost) {
+      nextLineType = SelfCost;
+
+      TraceCall* calling = currentFunction->calling(currentCalledFunction);
+      TracePartCall* partCalling =
+        calling->partCall(part, currentPartFunction,
+                          currentCalledPartFunction);
+
+#if USE_FIXCOST
+      FixCallCost* fcc;
+      fcc = new (pool) FixCallCost(part, pool,
+				   currentFunctionSource,
+				   hasLineInfo ? currentPos.fromLine : 0,
+				   hasAddrInfo ? currentPos.fromAddr : Addr(0),
+				   partCalling,
+				   currentCallCount, line);
+      fcc->setMax(_data->callMax());
+#else
+      if (hasAddrInfo) {
+	  TraceInstrCall* instrCall;
+	  TracePartInstrCall* partInstrCall;
+
+	  instrCall = calling->instrCall(currentInstr);
+	  partInstrCall = instrCall->partInstrCall(part, partCalling);
+	  partInstrCall->addCallCount(currentCallCount);
+
+	  if (hasLineInfo) {
+	      // we need to set <line> back after reading for the line
+	      int l = line.len();
+	      const char* s = line.ascii();
+
+	      partInstrCall->addCost(subMapping, line);
+	      line.set(s,l);
+	  }
+	  else
+	      partInstrCall->addCost(subMapping, line);
+
+	  // update maximum of call cost
+	  _data->callMax()->maxCost(partInstrCall);
+      }
+
+      if (hasLineInfo) {
+	  TraceLineCall* lineCall;
+	  TracePartLineCall* partLineCall;
+
+	  lineCall = calling->lineCall(currentLine);
+	  partLineCall = lineCall->partLineCall(part, partCalling);
+
+	  partLineCall->addCallCount(currentCallCount);
+	  partLineCall->addCost(subMapping, line);
+
+	  // update maximum of call cost
+	  _data->callMax()->maxCost(partLineCall);
+      }
+#endif
+      currentCalledFile = 0;
+      currentCalledPartFile = 0;
+      currentCalledObject = 0;
+      currentCalledPartObject = 0;
+      currentCallCount = 0;
+
+      if (!line.isEmpty()) {
+	kdError() << _filename << ":" << _lineNo
+		  << " - Garbage at end of call cost line ('"
+		  << TQString(line) << "')" << endl;
+      }
+    }
+    else { // (nextLineType == BoringJump || nextLineType == CondJump)
+
+	TraceFunctionSource* targetSource;
+
+	if (!currentJumpToFunction)
+	    currentJumpToFunction = currentFunction;
+
+	targetSource = (currentJumpToFile) ?
+	    currentJumpToFunction->sourceFile(currentJumpToFile, true) :
+	    currentFunctionSource;
+
+#if USE_FIXCOST
+      new (pool) FixJump(part, pool,
+			 /* source */
+			 hasLineInfo ? currentPos.fromLine : 0,
+			 hasAddrInfo ? currentPos.fromAddr : 0,
+			 currentPartFunction,
+			 currentFunctionSource,
+			 /* target */
+			 hasLineInfo ? targetPos.fromLine : 0,
+			 hasAddrInfo ? targetPos.fromAddr : Addr(0),
+			 currentJumpToFunction,
+			 targetSource,
+			 (nextLineType == CondJump),
+			 jumpsExecuted, jumpsFollowed);
+#endif
+
+      if (0) {
+	kdDebug() << _filename << ":" << _lineNo
+		  << " - jump from 0x" << currentPos.fromAddr.toString()
+		  << " (line " << currentPos.fromLine
+		  << ") to 0x" << targetPos.fromAddr.toString()
+		  << " (line " << targetPos.fromLine << ")" << endl;
+
+	if (nextLineType == BoringJump)
+	  kdDebug() << " Boring Jump, count " << jumpsExecuted.pretty() << endl;
+	else
+	  kdDebug() << " Cond. Jump, followed " << jumpsFollowed.pretty()
+		    << ", executed " << jumpsExecuted.pretty() << endl;
+      }
+
+      nextLineType = SelfCost;
+      currentJumpToFunction = 0;
+      currentJumpToFile = 0;
+
+      if (!line.isEmpty()) {
+	kdError() << _filename << ":" << _lineNo
+		  << " - Garbage at end of jump cost line ('"
+		  << TQString(line) << "')" << endl;
+      }
+
+    }
+  }
+
+
+  emit updateStatus(statusMsg,100);
+
+  _part->invalidate();
+  if (!totalsSet) {
+    _part->totals()->clear();
+    _part->totals()->addCost(_part);
+  }
+  
+  pFile->close();
+
+  return true;
+}
+
diff --git a/kdecachegrind/kdecachegrind/callgraphview.cpp b/kdecachegrind/kdecachegrind/callgraphview.cpp
new file mode 100644
index 0000000..bc01da8
--- /dev/null
+++ b/kdecachegrind/kdecachegrind/callgraphview.cpp
@@ -0,0 +1,2734 @@
+/* This file is part of KCachegrind.
+   Copyright (C) 2003 Josef Weidendorfer <Josef.Weidendorfer@gmx.de>
+
+   KCachegrind 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, version 2.
+
+   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; see the file COPYING.  If not, write to
+   the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+   Boston, MA 02110-1301, USA.
+*/
+
+/*
+ * Callgraph View
+ */
+
+#include <stdlib.h>
+#include <math.h>
+
+#include <tqtooltip.h>
+#include <tqfile.h>
+#include <tqtextstream.h>
+#include <tqwhatsthis.h>
+#include <tqcanvas.h>
+#include <tqwmatrix.h>
+#include <tqpair.h>
+#include <tqpainter.h>
+#include <tqpopupmenu.h>
+#include <tqstyle.h>
+#include <tqprocess.h>
+
+#include <kdebug.h>
+#include <klocale.h>
+#include <kconfig.h>
+#include <ktempfile.h>
+#include <kapplication.h>
+#include <kiconloader.h>
+#include <kfiledialog.h>
+
+#include "configuration.h"
+#include "callgraphview.h"
+#include "toplevel.h"
+#include "listutils.h"
+
+
+/*
+ * TODO:
+ * - Zooming option for work canvas? (e.g. 1:1 - 1:3)
+ */
+
+#define DEBUG_GRAPH 0
+
+// CallGraphView defaults
+
+#define DEFAULT_FUNCLIMIT   .05
+#define DEFAULT_CALLLIMIT   .05
+#define DEFAULT_MAXCALLER    2
+#define DEFAULT_MAXCALLING   -1
+#define DEFAULT_SHOWSKIPPED  false
+#define DEFAULT_EXPANDCYCLES false
+#define DEFAULT_CLUSTERGROUPS false
+#define DEFAULT_DETAILLEVEL  1
+#define DEFAULT_LAYOUT       GraphOptions::TopDown
+#define DEFAULT_ZOOMPOS      Auto
+
+
+//
+// GraphEdgeList
+//
+
+GraphEdgeList::GraphEdgeList()
+    : _sortCallerPos(true)
+{}
+
+int GraphEdgeList::compareItems(Item item1, Item item2)
+{
+    CanvasEdge* e1 = ((GraphEdge*)item1)->canvasEdge();
+    CanvasEdge* e2 = ((GraphEdge*)item2)->canvasEdge();
+
+    // edges without arrow visualisations are sorted as low
+    if (!e1) return -1;
+    if (!e2) return 1;
+
+    int dx1, dy1, dx2, dy2;
+    int x, y;
+    if (_sortCallerPos) {
+	e1->controlPoints().point(0,&x,&y);
+	e2->controlPoints().point(0,&dx1,&dy1);
+	dx1 -= x; dy1 -= y;
+    }
+    else {
+	TQPointArray a1 = e1->controlPoints();
+	TQPointArray a2 = e2->controlPoints();
+	a1.point(a1.count()-2,&x,&y);
+	a2.point(a2.count()-1,&dx2,&dy2);
+	dx2 -= x; dy2 -= y;
+    }
+    double at1 = atan2(double(dx1), double(dy1));
+    double at2 = atan2(double(dx2), double(dy2));
+
+    return (at1 < at2) ? 1:-1;
+}
+
+
+
+
+//
+// GraphNode
+//
+
+GraphNode::GraphNode()
+{
+    _f=0;
+    self = incl = 0;
+    _cn = 0;
+
+    _visible = false;
+    _lastCallerIndex = _lastCallingIndex = -1;
+
+    callers.setSortCallerPos(false);
+    callings.setSortCallerPos(true);
+    _lastFromCaller = true;
+}
+
+TraceCall* GraphNode::visibleCaller()
+{
+    if (0) qDebug("GraphNode::visibleCaller %s: last %d, count %d",
+		  _f->prettyName().ascii(), _lastCallerIndex, callers.count());
+
+    GraphEdge* e = callers.at(_lastCallerIndex);
+    if (e && !e->isVisible()) e = 0;
+    if (!e) {
+	double maxCost = 0.0;
+	GraphEdge* maxEdge = 0;
+	int idx = 0;
+	for(e = callers.first();e; e=callers.next(),idx++)
+	    if (e->isVisible() && (e->cost > maxCost)) {
+		maxCost = e->cost;
+		maxEdge = e;
+		_lastCallerIndex = idx;
+	    }
+	e = maxEdge;
+    }
+    return e ? e->call() : 0;
+}
+
+TraceCall* GraphNode::visibleCalling()
+{
+    if (0) qDebug("GraphNode::visibleCalling %s: last %d, count %d",
+		  _f->prettyName().ascii(), _lastCallingIndex, callings.count());
+
+    GraphEdge* e = callings.at(_lastCallingIndex);
+    if (e && !e->isVisible()) e = 0;
+    if (!e) {
+	double maxCost = 0.0;
+	GraphEdge* maxEdge = 0;
+	int idx = 0;
+	for(e = callings.first();e; e=callings.next(),idx++)
+	    if (e->isVisible() && (e->cost > maxCost)) {
+		maxCost = e->cost;
+		maxEdge = e;
+		_lastCallingIndex = idx;
+	    }
+	e = maxEdge;
+    }
+    return e ? e->call() : 0;
+}
+
+void GraphNode::setCalling(GraphEdge* e)
+{
+    _lastCallingIndex = callings.findRef(e);
+    _lastFromCaller = false;
+}
+
+void GraphNode::setCaller(GraphEdge* e)
+{
+    _lastCallerIndex = callers.findRef(e);
+    _lastFromCaller = true;
+}
+
+TraceFunction* GraphNode::nextVisible()
+{
+  TraceCall* c;
+  if (_lastFromCaller) {
+    c = nextVisibleCaller(callers.at(_lastCallerIndex));
+    if (c) return c->called(true);
+    c = nextVisibleCalling(callings.at(_lastCallingIndex));
+    if (c) return c->caller(true);
+  }
+  else {
+    c = nextVisibleCalling(callings.at(_lastCallingIndex));
+    if (c) return c->caller(true);
+    c = nextVisibleCaller(callers.at(_lastCallerIndex));
+    if (c) return c->called(true);
+  }
+  return 0;
+}
+
+TraceFunction* GraphNode::priorVisible()
+{
+  TraceCall* c;
+  if (_lastFromCaller) {
+    c = priorVisibleCaller(callers.at(_lastCallerIndex));
+    if (c) return c->called(true);
+    c = priorVisibleCalling(callings.at(_lastCallingIndex));
+    if (c) return c->caller(true);
+  }
+  else {
+    c = priorVisibleCalling(callings.at(_lastCallingIndex));
+    if (c) return c->caller(true);
+    c = priorVisibleCaller(callers.at(_lastCallerIndex));
+    if (c) return c->called(true);
+  }
+  return 0;
+}
+
+TraceCall* GraphNode::nextVisibleCaller(GraphEdge* last)
+{
+    GraphEdge* e;
+    bool found = false;
+    int idx = 0;
+    for(e = callers.first();e; e=callers.next(),idx++) {
+	if (found && e->isVisible()) {
+	    _lastCallerIndex = idx;
+	    return e->call();
+	}
+	if (e == last) found = true;
+    }
+    return 0;
+}
+
+TraceCall* GraphNode::nextVisibleCalling(GraphEdge* last)
+{
+    GraphEdge* e;
+    bool found = false;
+    int idx = 0;
+    for(e = callings.first();e; e=callings.next(),idx++) {
+	if (found && e->isVisible()) {
+	    _lastCallingIndex = idx;
+	    return e->call();
+	}
+	if (e == last) found = true;
+    }
+    return 0;
+}
+
+TraceCall* GraphNode::priorVisibleCaller(GraphEdge* last)
+{
+    GraphEdge *e, *prev = 0;
+    int prevIdx = -1, idx = 0;
+    for(e = callers.first(); e; e=callers.next(),idx++) {
+	if (e == last) {
+	    _lastCallerIndex = prevIdx;
+	    return prev ? prev->call() : 0;
+	}
+	if (e->isVisible()) {
+	    prev = e;
+	    prevIdx = idx;
+	}
+    }
+    return 0;
+}
+
+TraceCall* GraphNode::priorVisibleCalling(GraphEdge* last)
+{
+    GraphEdge *e, *prev = 0;
+    int prevIdx = -1, idx = 0;
+    for(e = callings.first(); e; e=callings.next(),idx++) {
+	if (e == last) {
+	    _lastCallingIndex = prevIdx;
+	    return prev ? prev->call() : 0;
+	}
+	if (e->isVisible()) {
+	    prev = e;
+	    prevIdx = idx;
+	}
+    }
+    return 0;
+}
+
+//
+// GraphEdge
+//
+
+GraphEdge::GraphEdge()
+{
+    _c=0;
+    _from = _to = 0;
+    _fromNode = _toNode = 0;
+    cost = count = 0;
+    _ce = 0;
+
+    _visible = false;
+    _lastFromCaller = true;
+}
+
+TQString GraphEdge::prettyName()
+{
+    if (_c) return _c->prettyName();
+    if (_from) return i18n("Call(s) from %1").arg(_from->prettyName());
+    if (_to) return i18n("Call(s) to %1").arg(_to->prettyName());
+    return i18n("(unknown call)");
+}
+
+
+TraceFunction* GraphEdge::visibleCaller()
+{
+    if (_from) {
+	_lastFromCaller = true;
+	if (_fromNode) _fromNode->setCalling(this);
+	return _from;
+    }
+    return 0;
+}
+
+TraceFunction* GraphEdge::visibleCalling()
+{
+    if (_to) {
+	_lastFromCaller = false;
+	if (_toNode) _toNode->setCaller(this);
+	return _to;
+    }
+    return 0;
+}
+
+TraceCall* GraphEdge::nextVisible()
+{
+    TraceCall* res = 0;
+
+    if (_lastFromCaller && _fromNode) {
+	res = _fromNode->nextVisibleCalling(this);
+	if (!res && _toNode)
+	    res = _toNode->nextVisibleCaller(this);
+    }
+    else if (_toNode) {
+	res = _toNode->nextVisibleCaller(this);
+	if (!res && _fromNode)
+	    res = _fromNode->nextVisibleCalling(this);
+    }
+    return res;
+}
+
+TraceCall* GraphEdge::priorVisible()
+{
+    TraceCall* res = 0;
+
+    if (_lastFromCaller && _fromNode) {
+	res = _fromNode->priorVisibleCalling(this);
+	if (!res && _toNode)
+	    res = _toNode->priorVisibleCaller(this);
+    }
+    else if (_toNode) {
+	res = _toNode->priorVisibleCaller(this);
+	if (!res && _fromNode)
+	    res = _fromNode->priorVisibleCalling(this);
+    }
+    return res;
+}
+
+
+
+//
+// GraphOptions
+//
+
+TQString GraphOptions::layoutString(Layout l)
+{
+    if (l == Circular) return TQString("Circular");
+    if (l == LeftRight) return TQString("LeftRight");
+    return TQString("TopDown");
+}
+
+GraphOptions::Layout GraphOptions::layout(TQString s)
+{
+    if (s == TQString("Circular")) return Circular;
+    if (s == TQString("LeftRight")) return LeftRight;
+    return TopDown;
+}
+
+
+//
+// StorableGraphOptions
+//
+
+StorableGraphOptions::StorableGraphOptions()
+{
+  // default options
+  _funcLimit         = DEFAULT_FUNCLIMIT;
+  _callLimit         = DEFAULT_CALLLIMIT;
+  _maxCallerDepth    = DEFAULT_MAXCALLER;
+  _maxCallingDepth   = DEFAULT_MAXCALLING;
+  _showSkipped       = DEFAULT_SHOWSKIPPED;
+  _expandCycles      = DEFAULT_EXPANDCYCLES;
+  _detailLevel       = DEFAULT_DETAILLEVEL;
+  _layout            = DEFAULT_LAYOUT;
+}
+
+
+
+
+//
+// GraphExporter
+//
+
+GraphExporter::GraphExporter()
+{
+    _go = this;
+    _tmpFile = 0;
+    _item = 0;
+    reset(0, 0, 0, TraceItem::NoCostType, TQString());
+}
+
+
+GraphExporter::GraphExporter(TraceData* d, TraceFunction* f, TraceCostType* ct,
+                             TraceItem::CostType gt, TQString filename)
+{
+    _go = this;
+    _tmpFile = 0;
+    _item = 0;
+    reset(d, f, ct, gt, filename);
+}
+
+
+GraphExporter::~GraphExporter()
+{
+  if (_item && _tmpFile) {
+#if DEBUG_GRAPH
+    _tmpFile->unlink();
+#endif
+    delete _tmpFile;
+  }
+}
+
+
+void GraphExporter::reset(TraceData*, TraceItem* i, TraceCostType* ct,
+                          TraceItem::CostType gt, TQString filename)
+{
+  _graphCreated = false;
+  _nodeMap.clear();
+  _edgeMap.clear();
+
+  if (_item && _tmpFile) {
+    _tmpFile->unlink();
+    delete _tmpFile;
+  }
+
+  if (i) {
+    switch(i->type()) {
+    case TraceItem::Function:
+    case TraceItem::FunctionCycle:
+    case TraceItem::Call:
+      break;
+    default:
+      i = 0;
+    }
+  }
+
+  _item = i;
+  _costType = ct;
+  _groupType = gt;
+  if (!i) return;
+
+  if (filename.isEmpty()) {
+    _tmpFile = new KTempFile(TQString(), ".dot");
+    _dotName = _tmpFile->name();
+    _useBox = true;
+  }
+  else {
+    _tmpFile = 0;
+    _dotName = filename;
+    _useBox = false;
+  }
+}
+
+
+
+void GraphExporter::setGraphOptions(GraphOptions* go)
+{
+    if (go == 0) go = this;
+    _go = go;
+}
+
+void GraphExporter::createGraph()
+{
+  if (!_item) return;
+  if (_graphCreated) return;
+  _graphCreated = true;
+
+  if ((_item->type() == TraceItem::Function) ||
+      (_item->type() == TraceItem::FunctionCycle)) {
+    TraceFunction* f = (TraceFunction*) _item;
+
+    double incl = f->inclusive()->subCost(_costType);
+    _realFuncLimit = incl * _go->funcLimit();
+    _realCallLimit = incl * _go->callLimit();
+
+    buildGraph(f, 0, true, 1.0); // down to callings
+
+    // set costs of function back to 0, as it will be added again
+    GraphNode& n = _nodeMap[f];
+    n.self = n.incl = 0.0;
+
+    buildGraph(f, 0, false, 1.0); // up to callers
+  }
+  else {
+    TraceCall* c = (TraceCall*) _item;
+
+    double incl = c->subCost(_costType);
+    _realFuncLimit = incl * _go->funcLimit();
+    _realCallLimit = incl * _go->callLimit();
+
+    // create edge
+    TraceFunction *caller, *called;
+    caller = c->caller(false);
+    called = c->called(false);
+    TQPair<TraceFunction*,TraceFunction*> p(caller, called);
+    GraphEdge& e = _edgeMap[p];
+    e.setCall(c);
+    e.setCaller(p.first);
+    e.setCalling(p.second);
+    e.cost  = c->subCost(_costType);
+    e.count = c->callCount();
+
+    SubCost s = called->inclusive()->subCost(_costType);
+    buildGraph(called, 0, true,  e.cost / s); // down to callings
+    s = caller->inclusive()->subCost(_costType);
+    buildGraph(caller, 0, false, e.cost / s); // up to callers
+  }
+}
+
+void GraphExporter::writeDot()
+{
+  if (!_item) return;
+
+  TQFile* file = 0;
+  TQTextStream* stream = 0;
+
+  if (_tmpFile)
+    stream = _tmpFile->textStream();
+  else {
+    file = new TQFile(_dotName);
+    if ( !file->open( IO_WriteOnly ) ) {
+      kdError() << "Can't write dot file '" << _dotName << "'" << endl;
+      return;
+    }
+    stream = new TQTextStream(file);
+  }
+
+  if (!_graphCreated) createGraph();
+
+  /* Generate dot format...
+   * When used for the CallGraphView (in contrast to "Export Callgraph..."),
+   * the labels are only dummy placeholders to reserve space for our own
+   * drawings.
+   */
+
+  *stream << "digraph \"callgraph\" {\n";
+
+  if (_go->layout() == LeftRight) {
+      *stream << TQString("  rankdir=LR;\n");
+  }
+  else if (_go->layout() == Circular) {
+    TraceFunction *f = 0;
+    switch(_item->type()) {
+    case TraceItem::Function:
+    case TraceItem::FunctionCycle:
+      f = (TraceFunction*) _item;
+      break;
+    case TraceItem::Call:
+      f = ((TraceCall*)_item)->caller(true);
+      break;
+    default:
+      break;
+    }
+    if (f)
+      *stream << TQString("  center=F%1;\n").arg((long)f, 0, 16);
+    *stream << TQString("  overlap=false;\n  splines=true;\n");
+  }
+
+  // for clustering
+  TQMap<TraceCostItem*,TQPtrList<GraphNode> > nLists;
+
+  GraphNodeMap::Iterator nit;
+  for ( nit = _nodeMap.begin();
+        nit != _nodeMap.end(); ++nit ) {
+    GraphNode& n = *nit;
+
+    if (n.incl <= _realFuncLimit) continue;
+
+    // for clustering: get cost item group of function
+    TraceCostItem* g;
+    TraceFunction* f = n.function();
+    switch(_groupType) {
+    case TraceItem::Object: g = f->object(); break;
+    case TraceItem::Class:  g = f->cls(); break;
+    case TraceItem::File:   g = f->file(); break;
+    case TraceItem::FunctionCycle: g = f->cycle();  break;
+    default: g = 0; break;
+    }
+    nLists[g].append(&n);
+  }
+
+  TQMap<TraceCostItem*,TQPtrList<GraphNode> >::Iterator lit;
+  int cluster = 0;
+  for ( lit = nLists.begin();
+        lit != nLists.end(); ++lit, cluster++ ) {
+    TQPtrList<GraphNode>& l = lit.data();
+    TraceCostItem* i = lit.key();
+
+    if (_go->clusterGroups() && i) {
+      TQString iabr = i->prettyName();
+      if ((int)iabr.length() > Configuration::maxSymbolLength())
+	iabr = iabr.left(Configuration::maxSymbolLength()) + "...";
+
+      *stream << TQString("subgraph \"cluster%1\" { label=\"%2\";\n")
+	.arg(cluster).arg(iabr);
+    }
+
+    GraphNode* np;
+    for(np = l.first(); np; np = l.next() ) {
+      TraceFunction* f = np->function();
+
+      TQString abr = f->prettyName();
+      if ((int)abr.length() > Configuration::maxSymbolLength())
+	abr = abr.left(Configuration::maxSymbolLength()) + "...";
+      
+      *stream << TQString("  F%1 [").arg((long)f, 0, 16);
+      if (_useBox) {
+	// make label 3 lines for CallGraphView
+	*stream << TQString("shape=box,label=\"** %1 **\\n**\\n%2\"];\n")
+	  .arg(abr)
+	  .arg(SubCost(np->incl).pretty());
+      }
+      else
+	*stream << TQString("label=\"%1\\n%2\"];\n")
+	  .arg(abr)
+	  .arg(SubCost(np->incl).pretty());
+    }
+
+    if (_go->clusterGroups() && i)
+      *stream << TQString("}\n");
+  }
+
+  GraphEdgeMap::Iterator eit;
+  for ( eit = _edgeMap.begin();
+        eit != _edgeMap.end(); ++eit ) {
+    GraphEdge& e = *eit;
+
+    if (e.cost < _realCallLimit) continue;
+    if (!_go->expandCycles()) {
+      // don't show inner cycle calls
+      if (e.call()->inCycle()>0) continue;
+    }
+
+
+    GraphNode& from = _nodeMap[e.from()];
+    GraphNode& to   = _nodeMap[e.to()];
+
+    e.setCallerNode(&from);
+    e.setCallingNode(&to);
+
+    if ((from.incl <= _realFuncLimit) ||
+        (to.incl <= _realFuncLimit)) continue;
+
+    // remove dumped edges from n.callers/n.callings
+    from.callings.removeRef(&e);
+    to.callers.removeRef(&e);
+    from.callingSet.remove(&e);
+    to.callerSet.remove(&e);
+
+    *stream << TQString("  F%1 -> F%2 [weight=%3")
+      .arg((long)e.from(), 0, 16)
+      .arg((long)e.to(), 0, 16)
+      .arg((long)log(log(e.cost)));
+
+    if (_go->detailLevel() ==1)
+	*stream << TQString(",label=\"%1\"")
+	    .arg(SubCost(e.cost).pretty());
+    else if (_go->detailLevel() ==2)
+	*stream << TQString(",label=\"%3\\n%4 x\"")
+	    .arg(SubCost(e.cost).pretty())
+	    .arg(SubCost(e.count).pretty());
+
+    *stream << TQString("];\n");
+  }
+
+  if (_go->showSkipped()) {
+
+      // Create sum-edges for skipped edges
+      GraphEdge* e;
+      double costSum, countSum;
+      for ( nit = _nodeMap.begin();
+	    nit != _nodeMap.end(); ++nit ) {
+	  GraphNode& n = *nit;
+	  if (n.incl <= _realFuncLimit) continue;
+
+	  costSum = countSum = 0.0;
+	  for (e=n.callers.first();e;e=n.callers.next()) {
+	      costSum += e->cost;
+	      countSum += e->count;
+	  }
+	  if (costSum > _realCallLimit) {
+
+	      TQPair<TraceFunction*,TraceFunction*> p(0, n.function());
+	      e = &(_edgeMap[p]);
+	      e->setCalling(p.second);
+	      e->cost = costSum;
+	      e->count = countSum;
+
+	      *stream << TQString("  R%1 [shape=point,label=\"\"];\n")
+		  .arg((long)n.function(), 0, 16);
+	      *stream << TQString("  R%1 -> F%2 [label=\"%3\\n%4 x\",weight=%5];\n")
+		  .arg((long)n.function(), 0, 16)
+		  .arg((long)n.function(), 0, 16)
+		  .arg(SubCost(costSum).pretty())
+		  .arg(SubCost(countSum).pretty())
+		  .arg((int)log(costSum));
+	  }
+
+	  costSum = countSum = 0.0;
+	  for (e=n.callings.first();e;e=n.callings.next()) {
+	      costSum += e->cost;
+	      countSum += e->count;
+	  }
+	  if (costSum > _realCallLimit) {
+
+	      TQPair<TraceFunction*,TraceFunction*> p(n.function(), 0);
+	      e = &(_edgeMap[p]);
+	      e->setCaller(p.first);
+	      e->cost = costSum;
+	      e->count = countSum;
+
+	      *stream << TQString("  S%1 [shape=point,label=\"\"];\n")
+		  .arg((long)n.function(), 0, 16);
+	      *stream << TQString("  F%1 -> S%2 [label=\"%3\\n%4 x\",weight=%5];\n")
+		  .arg((long)n.function(), 0, 16)
+		  .arg((long)n.function(), 0, 16)
+		  .arg(SubCost(costSum).pretty())
+		  .arg(SubCost(countSum).pretty())
+		  .arg((int)log(costSum));
+	  }
+      }
+  }
+
+  // clear edges here completely.
+  // Visible edges are inserted again on parsing in CallGraphView::refresh
+  for ( nit = _nodeMap.begin();
+	nit != _nodeMap.end(); ++nit ) {
+      GraphNode& n = *nit;
+      n.callers.clear();
+      n.callings.clear();
+      n.callerSet.clear();
+      n.callingSet.clear();
+  }
+
+  *stream << "}\n";
+
+  if (_tmpFile) {
+    _tmpFile->close();
+  }
+  else {
+    file->close();
+    delete file;
+    delete stream;
+  }
+}
+
+void GraphExporter::sortEdges()
+{
+    GraphNodeMap::Iterator nit;
+    for ( nit = _nodeMap.begin();
+	  nit != _nodeMap.end(); ++nit ) {
+	GraphNode& n = *nit;
+
+	n.callers.sort();
+	n.callings.sort();
+  }
+}
+
+TraceFunction* GraphExporter::toFunc(TQString s)
+{
+  if (s[0] != 'F') return 0;
+  bool ok;
+  TraceFunction* f = (TraceFunction*) s.mid(1).toULong(&ok, 16);
+  if (!ok) return 0;
+
+  return f;
+}
+
+GraphNode* GraphExporter::node(TraceFunction* f)
+{
+  if (!f) return 0;
+
+  GraphNodeMap::Iterator it = _nodeMap.find(f);
+  if (it == _nodeMap.end()) return 0;
+
+  return &(*it);
+}
+
+GraphEdge* GraphExporter::edge(TraceFunction* f1, TraceFunction* f2)
+{
+  GraphEdgeMap::Iterator it = _edgeMap.find(tqMakePair(f1, f2));
+  if (it == _edgeMap.end()) return 0;
+
+  return &(*it);
+}
+
+
+/**
+ * We do a DFS and don't stop on already visited nodes/edges,
+ * but add up costs. We only stop if limits/max depth is reached.
+ *
+ * For a node/edge, it can happen that the first time visited the
+ * cost will below the limit, so the search is stopped.
+ * If on a further visit of the node/edge the limit is reached,
+ * we use the whole node/edge cost and continue search.
+ */
+void GraphExporter::buildGraph(TraceFunction* f, int d,
+                               bool toCallings, double factor)
+{
+#if DEBUG_GRAPH
+  kdDebug() << "buildGraph(" << f->prettyName() << "," << d << "," << factor
+	    << ") [to " << (toCallings ? "Callings":"Callers") << "]" << endl;
+#endif
+
+  double oldIncl = 0.0;
+  GraphNode& n = _nodeMap[f];
+  if (n.function() == 0) {
+    n.setFunction(f);
+  }
+  else
+    oldIncl = n.incl;
+
+  double incl = f->inclusive()->subCost(_costType) * factor;
+  n.incl  += incl;
+  n.self += f->subCost(_costType) * factor;
+  if (0) qDebug("  Added Incl. %f, now %f", incl, n.incl);
+
+  // A negative depth limit means "unlimited"
+  int maxDepth = toCallings ? _go->maxCallingDepth() : _go->maxCallerDepth();
+  if ((maxDepth>=0) && (d >= maxDepth)) {
+    if (0) qDebug("  Cutoff, max depth reached");
+    return;
+  }
+
+  // if we just reached the limit by summing, do a DFS
+  // from here with full incl. cost because of previous cutoffs
+  if ((n.incl >= _realFuncLimit) && (oldIncl < _realFuncLimit)) incl = n.incl;
+
+  if (f->cycle()) {
+    // for cycles members, we never stop on first visit, but always on 2nd
+    // note: a 2nd visit never should happen, as we don't follow inner-cycle
+    //       calls
+    if (oldIncl > 0.0) {
+      if (0) qDebug("  Cutoff, 2nd visit to Cycle Member");
+      // and takeback cost addition, as it's added twice
+      n.incl  = oldIncl;
+      n.self -= f->subCost(_costType) * factor;
+      return;
+    }
+  }
+  else if (incl <= _realFuncLimit) {
+    if (0) qDebug("  Cutoff, below limit");
+    return;
+  }
+
+  TraceCall* call;
+  TraceFunction* f2;
+
+
+  // on entering a cycle, only go the FunctionCycle
+  TraceCallList l = toCallings ?
+    f->callings(false) : f->callers(false);
+
+  for (call=l.first();call;call=l.next()) {
+
+    f2 = toCallings ? call->called(false) : call->caller(false);
+
+    double count = call->callCount() * factor;
+    double cost = call->subCost(_costType) * factor;
+
+    // ignore function calls with absolute cost < 3 per call
+    // No: This would skip a lot of functions e.g. with L2 cache misses
+    // if (count>0.0 && (cost/count < 3)) continue;
+
+    double oldCost = 0.0;
+    TQPair<TraceFunction*,TraceFunction*> p(toCallings ? f:f2,
+					   toCallings ? f2:f);
+    GraphEdge& e = _edgeMap[p];
+    if (e.call() == 0) {
+      e.setCall(call);
+      e.setCaller(p.first);
+      e.setCalling(p.second);
+    }
+    else
+      oldCost = e.cost;
+
+    e.cost  += cost;
+    e.count += count;
+    if (0) qDebug("  Edge to %s, added cost %f, now %f",
+                  f2->prettyName().ascii(), cost, e.cost);
+
+    // if this call goes into a FunctionCycle, we also show the real call
+    if (f2->cycle() == f2) {
+      TraceFunction* realF;
+      realF = toCallings ? call->called(true) : call->caller(true);
+      TQPair<TraceFunction*,TraceFunction*> realP(toCallings ? f:realF,
+						 toCallings ? realF:f);
+      GraphEdge& e = _edgeMap[realP];
+      if (e.call() == 0) {
+	e.setCall(call);
+	e.setCaller(realP.first);
+	e.setCalling(realP.second);
+      }
+      e.cost  += cost;
+      e.count += count;
+    }
+
+    // - don't do a DFS on calls in recursion/cycle
+    if (call->inCycle()>0) continue;
+    if (call->isRecursion()) continue;
+
+    if (toCallings) {
+	GraphEdgeSet::Iterator it = n.callingSet.find(&e);
+	if (it == n.callingSet.end()) {
+	    n.callings.append(&e);
+	    n.callingSet.insert(&e, 1 );
+	}
+    }
+    else {
+	GraphEdgeSet::Iterator it = n.callerSet.find(&e);
+	if (it == n.callerSet.end()) {
+	    n.callers.append(&e);
+	    n.callerSet.insert(&e, 1 );
+	}
+    }
+
+    // if we just reached the call limit (=func limit by summing, do a DFS
+    // from here with full incl. cost because of previous cutoffs
+    if ((e.cost >= _realCallLimit) && (oldCost < _realCallLimit)) cost = e.cost;
+    if (cost < _realCallLimit) {
+      if (0) qDebug("  Edge Cutoff, limit not reached");
+      continue;
+    }
+
+    SubCost s;
+    if (call->inCycle())
+      s = f2->cycle()->inclusive()->subCost(_costType);
+    else
+      s = f2->inclusive()->subCost(_costType);
+    SubCost v = call->subCost(_costType);
+    buildGraph(f2, d+1, toCallings, factor * v / s);
+  }
+}
+
+
+//
+// PannerView
+//
+PannerView::PannerView(TQWidget * parent, const char * name)
+  : TQCanvasView(parent, name, WNoAutoErase | WStaticContents)
+{
+  _movingZoomRect = false;
+
+  // why doesn't this avoid flicker ?
+  viewport()->setBackgroundMode(TQt::NoBackground);
+  setBackgroundMode(TQt::NoBackground);
+}
+
+void PannerView::setZoomRect(TQRect r)
+{
+  TQRect oldRect = _zoomRect;
+  _zoomRect = r;
+  updateContents(oldRect);
+  updateContents(_zoomRect);
+}
+
+void PannerView::drawContents(TQPainter * p, int clipx, int clipy, int clipw, int cliph)
+{
+  // save/restore around TQCanvasView::drawContents seems to be needed
+  // for QT 3.0 to get the red rectangle drawn correct
+  p->save();
+  TQCanvasView::drawContents(p,clipx,clipy,clipw,cliph);
+  p->restore();
+  if (_zoomRect.isValid()) {
+    p->setPen(red.dark());
+    p->drawRect(_zoomRect);
+    p->setPen(red);
+    p->drawRect(TQRect(_zoomRect.x()+1, _zoomRect.y()+1,
+		      _zoomRect.width()-2, _zoomRect.height()-2));
+  }
+}
+
+void PannerView::contentsMousePressEvent(TQMouseEvent* e)
+{
+  if (_zoomRect.isValid()) {
+    if (!_zoomRect.contains(e->pos()))
+      emit zoomRectMoved(e->pos().x() - _zoomRect.center().x(),
+                         e->pos().y() - _zoomRect.center().y());
+
+    _movingZoomRect = true;
+    _lastPos = e->pos();
+  }
+}
+
+void PannerView::contentsMouseMoveEvent(TQMouseEvent* e)
+{
+  if (_movingZoomRect) {
+    emit zoomRectMoved(e->pos().x() - _lastPos.x(), e->pos().y() - _lastPos.y());
+    _lastPos = e->pos();
+  }
+}
+
+void PannerView::contentsMouseReleaseEvent(TQMouseEvent*)
+{
+    _movingZoomRect = false;
+    emit zoomRectMoveFinished();
+}
+
+
+
+
+
+//
+// CanvasNode
+//
+
+CanvasNode::CanvasNode(CallGraphView* v, GraphNode* n,
+		       int x, int y, int w, int h, TQCanvas* c)
+    : TQCanvasRectangle(x, y, w, h, c), _node(n), _view(v)
+{
+    setPosition(0, DrawParams::TopCenter);
+    setPosition(1, DrawParams::BottomCenter);
+
+    updateGroup();
+
+    if (!_node || !_view) return;
+
+    if (_node->function())
+	setText(0, _node->function()->prettyName());
+
+    TraceCost* totalCost;
+    if (_view->topLevel()->showExpanded()) {
+      if (_view->activeFunction()) {
+        if (_view->activeFunction()->cycle())
+          totalCost = _view->activeFunction()->cycle()->inclusive();
+        else
+          totalCost = _view->activeFunction()->inclusive();
+      }
+      else
+        totalCost = (TraceCost*) _view->activeItem();
+    }
+    else
+	totalCost = _view->TraceItemView::data();
+    double total = totalCost->subCost(_view->costType());
+    double inclP  = 100.0 * n->incl / total;
+    if (_view->topLevel()->showPercentage())
+	setText(1, TQString("%1 %")
+		.arg(inclP, 0, 'f', Configuration::percentPrecision()));
+    else
+	setText(1, SubCost(n->incl).pretty());
+    setPixmap(1, percentagePixmap(25,10,(int)(inclP+.5), TQt::blue, true));
+}
+
+void CanvasNode::setSelected(bool s)
+{
+  StoredDrawParams::setSelected(s);
+  update();
+}
+
+void CanvasNode::updateGroup()
+{
+    if (!_view || !_node) return;
+
+    TQColor c = Configuration::functionColor(_view->groupType(),
+					    _node->function());
+    setBackColor(c);
+    update();
+}
+
+void CanvasNode::drawShape(TQPainter& p)
+{
+    TQRect r = rect(), origRect = r;
+
+  r.setRect(r.x()+1, r.y()+1, r.width()-2, r.height()-2);
+
+  RectDrawing d(r);
+  d.drawBack(&p, this);
+  r.setRect(r.x()+2, r.y()+2, r.width()-4, r.height()-4);
+
+  if (StoredDrawParams::selected() && _view->hasFocus()) {
+    _view->style().tqdrawPrimitive( TQStyle::PE_FocusRect, &p, r,
+				  _view->colorGroup());
+  }
+
+  // draw afterwards to always get a frame even when zoomed
+  p.setPen(StoredDrawParams::selected() ? red : black);
+  p.drawRect(origRect);
+
+  d.setRect(r);
+  d.drawField(&p, 0, this);
+  d.drawField(&p, 1, this);
+}
+
+
+//
+// CanvasEdgeLabel
+//
+
+CanvasEdgeLabel::CanvasEdgeLabel(CallGraphView* v, CanvasEdge* ce,
+                                 int x, int y, int w, int h, TQCanvas* c)
+    : TQCanvasRectangle(x, y, w, h, c), _ce(ce), _view(v)
+{
+    GraphEdge* e = ce->edge();
+    if (!e) return;
+
+    setPosition(1, DrawParams::TopCenter);
+    setText(1, TQString("%1 x").arg(SubCost(e->count).pretty()));
+
+    setPosition(0, DrawParams::BottomCenter);
+
+    TraceCost* totalCost;
+    if (_view->topLevel()->showExpanded()) {
+      if (_view->activeFunction()) {
+        if (_view->activeFunction()->cycle())
+          totalCost = _view->activeFunction()->cycle()->inclusive();
+        else
+          totalCost = _view->activeFunction()->inclusive();
+      }
+      else
+        totalCost = (TraceCost*) _view->activeItem();
+    }
+    else
+        totalCost = _view->TraceItemView::data();
+    double total = totalCost->subCost(_view->costType());
+    double inclP  = 100.0 * e->cost / total;
+    if (_view->topLevel()->showPercentage())
+        setText(0, TQString("%1 %")
+		.arg(inclP, 0, 'f', Configuration::percentPrecision()));
+    else
+        setText(0, SubCost(e->cost).pretty());
+    setPixmap(0, percentagePixmap(25,10,(int)(inclP+.5), TQt::blue, true));
+
+    if (e->call() && (e->call()->isRecursion() || e->call()->inCycle())) {
+	TQString icon = "undo";
+	KIconLoader* loader = KApplication::kApplication()->iconLoader();
+	TQPixmap p= loader->loadIcon(icon, KIcon::Small, 0,
+				      KIcon::DefaultState, 0, true);
+	setPixmap(0, p);
+    }
+}
+
+void CanvasEdgeLabel::drawShape(TQPainter& p)
+{
+  TQRect r = rect();
+  //p.setPen(blue);
+  //p.drawRect(r);
+  RectDrawing d(r);
+  d.drawField(&p, 0, this);
+  d.drawField(&p, 1, this);
+}
+
+//
+// CanvasEdgeArrow
+
+CanvasEdgeArrow::CanvasEdgeArrow(CanvasEdge* ce, TQCanvas* c)
+    : TQCanvasPolygon(c), _ce(ce)
+{}
+
+void CanvasEdgeArrow::drawShape(TQPainter& p)
+{
+    if (_ce->isSelected()) p.setBrush(TQt::red);
+
+    TQCanvasPolygon::drawShape(p);
+}
+
+//
+// CanvasEdge
+//
+
+CanvasEdge::CanvasEdge(GraphEdge* e, TQCanvas* c)
+  : TQCanvasSpline(c), _edge(e)
+{
+    _label = 0;
+    _arrow = 0;
+}
+
+void CanvasEdge::setSelected(bool s)
+{
+    TQCanvasItem::setSelected(s);
+    update();
+    if (_arrow) _arrow->setSelected(s);
+}
+
+TQPointArray CanvasEdge::areaPoints() const
+{
+  int minX = poly[0].x(), minY = poly[0].y();
+  int maxX = minX, maxY = minY;
+  int i;
+
+  if (0) qDebug("CanvasEdge::areaPoints\n  P 0: %d/%d", minX, minY);
+  int len = poly.count();
+  for (i=1;i<len;i++) {
+    if (poly[i].x() < minX) minX = poly[i].x();
+    if (poly[i].y() < minY) minY = poly[i].y();
+    if (poly[i].x() > maxX) maxX = poly[i].x();
+    if (poly[i].y() > maxY) maxY = poly[i].y();
+    if (0) qDebug("  P %d: %d/%d", i, poly[i].x(), poly[i].y());
+  }
+  TQPointArray a = poly.copy(),  b = poly.copy();
+  if (minX == maxX) {
+    a.translate(-2, 0);
+    b.translate(2, 0);
+  }
+  else {
+    a.translate(0, -2);
+    b.translate(0, 2);
+  }
+  a.resize(2*len);
+  for (i=0;i<len;i++)
+    a[2 * len - 1 -i] = b[i];
+
+  if (0) {
+      qDebug(" Result:");
+      for (i=0;i<2*len;i++)
+	  qDebug("  P %d: %d/%d", i, a[i].x(), a[i].y());
+  }
+
+  return a;
+}
+
+void CanvasEdge::drawShape(TQPainter& p)
+{
+    if (isSelected()) p.setPen(TQt::red);
+
+    p.drawPolyline(poly);
+}
+
+
+//
+// CanvasFrame
+//
+
+TQPixmap* CanvasFrame::_p = 0;
+
+CanvasFrame::CanvasFrame(CanvasNode* n, TQCanvas* c)
+ : TQCanvasRectangle(c)
+{
+  if (!_p) {
+
+    int d = 5;
+    float v1 = 130.0, v2 = 10.0, v = v1, f = 1.03;
+
+    // calculate pix size
+    TQRect r(0, 0, 30, 30);
+    while (v>v2) {
+      r.setRect(r.x()-d, r.y()-d, r.width()+2*d, r.height()+2*d);
+      v /= f;
+    }
+
+    _p = new TQPixmap(r.size());
+    _p->fill(TQt::white);
+    TQPainter p(_p);
+    p.setPen(TQt::NoPen);
+
+    r.moveBy(-r.x(), -r.y());
+
+    while (v<v1) {
+      v *= f;
+      p.setBrush(TQColor(265-(int)v, 265-(int)v, 265-(int)v));
+
+      p.drawRect(TQRect(r.x(), r.y(), r.width(), d));
+      p.drawRect(TQRect(r.x(), r.bottom()-d, r.width(), d));
+      p.drawRect(TQRect(r.x(), r.y()+d, d, r.height()-2*d));
+      p.drawRect(TQRect(r.right()-d, r.y()+d, d, r.height()-2*d));
+
+      r.setRect(r.x()+d, r.y()+d, r.width()-2*d, r.height()-2*d);
+    }
+  }
+
+  setSize(_p->width(), _p->height());
+  move(n->rect().center().x()-_p->width()/2,
+       n->rect().center().y()-_p->height()/2);
+}
+
+
+void CanvasFrame::drawShape(TQPainter& p)
+{
+  p.drawPixmap( int(x()), int(y()), *_p );
+}
+
+
+
+
+//
+// Tooltips for CallGraphView
+//
+
+class CallGraphTip: public TQToolTip
+{
+public:
+  CallGraphTip( TQWidget* p ):TQToolTip(p) {}
+
+protected:
+    void maybeTip( const TQPoint & );
+};
+
+void CallGraphTip::maybeTip( const TQPoint& pos )
+{
+  if (!parentWidget()->inherits( "CallGraphView" )) return;
+  CallGraphView* cgv = (CallGraphView*)parentWidget();
+
+  TQPoint cPos = cgv->viewportToContents(pos);
+
+  if (0) qDebug("CallGraphTip for (%d/%d) -> (%d/%d) ?",
+		pos.x(), pos.y(), cPos.x(), cPos.y());
+
+  TQCanvasItemList l = cgv->canvas()->collisions(cPos);
+  if (l.count() == 0) return;
+  TQCanvasItem* i = l.first();
+
+  if (i->rtti() == CANVAS_NODE) {
+      CanvasNode* cn = (CanvasNode*)i;
+      GraphNode* n = cn->node();
+      if (0) qDebug("CallGraphTip: Mouse on Node '%s'",
+		    n->function()->prettyName().ascii());
+
+      TQString tipStr = TQString("%1 (%2)").arg(cn->text(0)).arg(cn->text(1));
+      TQPoint vPosTL = cgv->contentsToViewport(i->boundingRect().topLeft());
+      TQPoint vPosBR = cgv->contentsToViewport(i->boundingRect().bottomRight());
+      tip(TQRect(vPosTL, vPosBR), tipStr);
+
+      return;
+  }
+
+  // redirect from label / arrow to edge
+  if (i->rtti() == CANVAS_EDGELABEL)
+      i = ((CanvasEdgeLabel*)i)->canvasEdge();
+  if (i->rtti() == CANVAS_EDGEARROW)
+      i = ((CanvasEdgeArrow*)i)->canvasEdge();
+
+  if (i->rtti() == CANVAS_EDGE) {
+      CanvasEdge* ce = (CanvasEdge*)i;
+      GraphEdge* e = ce->edge();
+      if (0) qDebug("CallGraphTip: Mouse on Edge '%s'",
+		    e->prettyName().ascii());
+
+      TQString tipStr;
+      if (!ce->label())
+	  tipStr = e->prettyName();
+      else
+	  tipStr = TQString("%1 (%2)")
+	      .arg(ce->label()->text(0)).arg(ce->label()->text(1));
+      tip(TQRect(pos.x()-5,pos.y()-5,pos.x()+5,pos.y()+5), tipStr);
+  }
+}
+
+
+
+
+//
+// CallGraphView
+//
+CallGraphView::CallGraphView(TraceItemView* parentView,
+                             TQWidget* parent, const char* name)
+  : TQCanvasView(parent, name), TraceItemView(parentView)
+{
+    _zoomPosition = DEFAULT_ZOOMPOS;
+    _lastAutoPosition = TopLeft;
+
+  _canvas = 0;
+  _xMargin = _yMargin = 0;
+  _completeView = new PannerView(this);
+  _cvZoom = 1;
+  _selectedNode = 0;
+  _selectedEdge = 0;
+
+  _exporter.setGraphOptions(this);
+
+  _completeView->setVScrollBarMode(TQScrollView::AlwaysOff);
+  _completeView->setHScrollBarMode(TQScrollView::AlwaysOff);
+  _completeView->raise();
+  _completeView->hide();
+
+  setFocusPolicy(TQ_StrongFocus);
+  setBackgroundMode(TQt::NoBackground);
+
+  connect(this, TQT_SIGNAL(contentsMoving(int,int)),
+          this, TQT_SLOT(contentsMovingSlot(int,int)));
+  connect(_completeView, TQT_SIGNAL(zoomRectMoved(int,int)),
+          this, TQT_SLOT(zoomRectMoved(int,int)));
+  connect(_completeView, TQT_SIGNAL(zoomRectMoveFinished()),
+          this, TQT_SLOT(zoomRectMoveFinished()));
+
+  TQWhatsThis::add( this, whatsThis() );
+
+  // tooltips...
+  _tip = new CallGraphTip(this);
+
+  _renderProcess = 0;
+  _prevSelectedNode = 0;
+  connect(&_renderTimer, TQT_SIGNAL(timeout()),
+          this, TQT_SLOT(showRenderWarning()));
+}
+
+CallGraphView::~CallGraphView()
+{
+  delete _completeView;
+  delete _tip;
+
+  if (_canvas) {
+    setCanvas(0);
+    delete _canvas;
+  }
+}
+
+TQString CallGraphView::whatsThis() const
+{
+    return i18n( "<b>Call Graph around active Function</b>"
+                 "<p>Depending on configuration, this view shows "
+                 "the call graph environment of the active function. "
+		 "Note: the shown cost is <b>only</b> the cost which is "
+		 "spent while the active function was actually running; "
+		 "i.e. the cost shown for main() - if it's visible - should "
+		 "be the same as the cost of the active function, as that's "
+		 "the part of inclusive cost of main() spent while the active "
+		 "function was running.</p>"
+		 "<p>For cycles, blue call arrows indicate that this is an "
+		 "artificial call added for correct drawing which "
+		 "actually never happened.</p>"
+                 "<p>If the graph is larger than the widget area, an overview "
+                 "panner is shown in one edge. "
+                 "There are similar visualization options to the "
+                 "Call Treemap; the selected function is highlighted.<p>");
+}
+
+void CallGraphView::updateSizes(TQSize s)
+{
+  if (!_canvas) return;
+
+    if (s == TQSize(0,0)) s = size();
+
+    // the part of the canvas that should be visible
+    int cWidth  = _canvas->width()  - 2*_xMargin + 100;
+    int cHeight = _canvas->height() - 2*_yMargin + 100;
+
+    // hide birds eye view if no overview needed
+    if (!_data || !_activeItem ||
+	((cWidth < s.width()) && cHeight < s.height())) {
+      _completeView->hide();
+      return;
+    }
+    _completeView->show();
+
+    // first, assume use of 1/3 of width/height (possible larger)
+    double zoom = .33 * s.width() / cWidth;
+    if (zoom * cHeight < .33 * s.height()) zoom = .33 * s.height() / cHeight;
+
+    // fit to widget size
+    if (cWidth  * zoom  > s.width())   zoom = s.width() / (double)cWidth;
+    if (cHeight * zoom  > s.height())  zoom = s.height() / (double)cHeight;
+
+    // scale to never use full height/width
+    zoom = zoom * 3/4;
+
+    // at most a zoom of 1/3
+    if (zoom > .33) zoom = .33;
+
+    if (zoom != _cvZoom) {
+      _cvZoom = zoom;
+      if (0) qDebug("Canvas Size: %dx%d, Visible: %dx%d, Zoom: %f",
+		    _canvas->width(), _canvas->height(),
+		    cWidth, cHeight, zoom);
+
+      TQWMatrix wm;
+      wm.scale( zoom, zoom );
+      _completeView->setWorldMatrix(wm);
+
+      // make it a little bigger to compensate for widget frame
+      _completeView->resize(int(cWidth * zoom) + 4,
+                            int(cHeight * zoom) + 4);
+
+      // update ZoomRect in completeView
+      contentsMovingSlot(contentsX(), contentsY());
+    }
+
+    _completeView->setContentsPos(int(zoom*(_xMargin-50)),
+				  int(zoom*(_yMargin-50)));
+
+    int cvW = _completeView->width();
+    int cvH = _completeView->height();
+    int x = width()- cvW - verticalScrollBar()->width()    -2;
+    int y = height()-cvH - horizontalScrollBar()->height() -2;
+    TQPoint oldZoomPos = _completeView->pos();
+    TQPoint newZoomPos = TQPoint(0,0);
+    ZoomPosition zp = _zoomPosition;
+    if (zp == Auto) {
+	TQPoint tl1Pos = viewportToContents(TQPoint(0,0));
+	TQPoint tl2Pos = viewportToContents(TQPoint(cvW,cvH));
+	TQPoint tr1Pos = viewportToContents(TQPoint(x,0));
+	TQPoint tr2Pos = viewportToContents(TQPoint(x+cvW,cvH));
+	TQPoint bl1Pos = viewportToContents(TQPoint(0,y));
+	TQPoint bl2Pos = viewportToContents(TQPoint(cvW,y+cvH));
+	TQPoint br1Pos = viewportToContents(TQPoint(x,y));
+	TQPoint br2Pos = viewportToContents(TQPoint(x+cvW,y+cvH));
+	int tlCols = _canvas->collisions(TQRect(tl1Pos,tl2Pos)).count();
+	int trCols = _canvas->collisions(TQRect(tr1Pos,tr2Pos)).count();
+	int blCols = _canvas->collisions(TQRect(bl1Pos,bl2Pos)).count();
+	int brCols = _canvas->collisions(TQRect(br1Pos,br2Pos)).count();
+	int minCols = tlCols;
+	zp = _lastAutoPosition;
+	switch(zp) {
+	case TopRight:    minCols = trCols; break;
+	case BottomLeft:  minCols = blCols; break;
+	case BottomRight: minCols = brCols; break;
+	default:
+	case TopLeft:     minCols = tlCols; break;
+	}
+	if (minCols > tlCols) { minCols = tlCols; zp = TopLeft; }
+	if (minCols > trCols) { minCols = trCols; zp = TopRight; }
+	if (minCols > blCols) { minCols = blCols; zp = BottomLeft; }
+	if (minCols > brCols) { minCols = brCols; zp = BottomRight; }
+
+	_lastAutoPosition = zp;
+    }
+
+    switch(zp) {
+    case TopRight:
+	newZoomPos = TQPoint(x,0);
+	break;
+    case BottomLeft:
+	newZoomPos = TQPoint(0,y);
+	break;
+    case BottomRight:
+	newZoomPos = TQPoint(x,y);
+	break;
+    default:
+	break;
+    }
+    if (newZoomPos != oldZoomPos) _completeView->move(newZoomPos);
+}
+
+void CallGraphView::focusInEvent(TQFocusEvent*)
+{
+    if (!_canvas) return;
+
+    if (_selectedNode && _selectedNode->canvasNode()) {
+	_selectedNode->canvasNode()->setSelected(true); // requests item update
+	_canvas->update();
+    }
+}
+
+void CallGraphView::focusOutEvent(TQFocusEvent* e)
+{
+    // trigger updates as in focusInEvent
+    focusInEvent(e);
+}
+
+void CallGraphView::keyPressEvent(TQKeyEvent* e)
+{
+    if (!_canvas) {
+	e->ignore();
+	return;
+    }
+
+    if ((e->key() == Key_Return) ||
+	(e->key() == Key_Space)) {
+	if (_selectedNode)
+	    activated(_selectedNode->function());
+	else if (_selectedEdge && _selectedEdge->call())
+	    activated(_selectedEdge->call());
+	return;
+    }
+
+    // move selected node/edge
+    if (!(e->state() & (ShiftButton | ControlButton)) &&
+	(_selectedNode || _selectedEdge) &&
+	((e->key() == Key_Up) ||
+	 (e->key() == Key_Down) ||
+	 (e->key() == Key_Left) ||
+	 (e->key() == Key_Right))) {
+
+	TraceFunction* f = 0;
+	TraceCall* c = 0;
+
+	// rotate arrow key meaning for LeftRight layout
+	int key = e->key();
+	if (_layout == LeftRight) {
+	    switch(key) {
+	    case Key_Up:    key = Key_Left; break;
+	    case Key_Down:  key = Key_Right; break;
+	    case Key_Left:  key = Key_Up; break;
+	    case Key_Right: key = Key_Down; break;
+	    default: break;
+	    }
+	}
+
+	if (_selectedNode) {
+	    if (key == Key_Up)    c = _selectedNode->visibleCaller();
+	    if (key == Key_Down)  c = _selectedNode->visibleCalling();
+	    if (key == Key_Right) f = _selectedNode->nextVisible();
+	    if (key == Key_Left)  f = _selectedNode->priorVisible();
+	}
+	else if (_selectedEdge) {
+	    if (key == Key_Up)    f = _selectedEdge->visibleCaller();
+	    if (key == Key_Down)  f = _selectedEdge->visibleCalling();
+	    if (key == Key_Right) c = _selectedEdge->nextVisible();
+	    if (key == Key_Left)  c = _selectedEdge->priorVisible();
+	}
+
+	if (c) selected(c);
+	if (f) selected(f);
+	return;
+    }
+
+    // move canvas...
+    if (e->key() == Key_Home)
+	scrollBy(-_canvas->width(),0);
+    else if (e->key() == Key_End)
+	scrollBy(_canvas->width(),0);
+    else if (e->key() == Key_Prior)
+	scrollBy(0,-visibleHeight()/2);
+    else if (e->key() == Key_Next)
+	scrollBy(0,visibleHeight()/2);
+    else if (e->key() == Key_Left)
+	scrollBy(-visibleWidth()/10,0);
+    else if (e->key() == Key_Right)
+	scrollBy(visibleWidth()/10,0);
+    else if (e->key() == Key_Down)
+	scrollBy(0,visibleHeight()/10);
+    else if (e->key() == Key_Up)
+	scrollBy(0,-visibleHeight()/10);
+    else e->ignore();
+}
+
+void CallGraphView::resizeEvent(TQResizeEvent* e)
+{
+  TQCanvasView::resizeEvent(e);
+  if (_canvas) updateSizes(e->size());
+}
+
+TraceItem* CallGraphView::canShow(TraceItem* i)
+{
+  if (i) {
+    switch(i->type()) {
+    case TraceItem::Function:
+    case TraceItem::FunctionCycle:
+    case TraceItem::Call:
+      return i;
+    default:
+      break;
+    }
+  }
+  return 0;
+}
+
+void CallGraphView::doUpdate(int changeType)
+{
+  // Special case ?
+  if (changeType == costType2Changed) return;
+
+  if (changeType == selectedItemChanged) {
+    if (!_canvas) return;
+
+    if (!_selectedItem) return;
+
+    GraphNode* n = 0;
+    GraphEdge* e = 0;
+    if ((_selectedItem->type() == TraceItem::Function) ||
+        (_selectedItem->type() == TraceItem::FunctionCycle)) {
+	n = _exporter.node((TraceFunction*)_selectedItem);
+	if (n == _selectedNode) return;
+    }
+    else if (_selectedItem->type() == TraceItem::Call) {
+	TraceCall* c = (TraceCall*)_selectedItem;
+	e = _exporter.edge(c->caller(false), c->called(false));
+	if (e == _selectedEdge) return;
+    }
+
+    // unselected any selected item
+    if (_selectedNode && _selectedNode->canvasNode()) {
+	_selectedNode->canvasNode()->setSelected(false);
+    }
+    _selectedNode = 0;
+    if (_selectedEdge && _selectedEdge->canvasEdge()) {
+	_selectedEdge->canvasEdge()->setSelected(false);
+    }
+    _selectedEdge = 0;
+
+    // select
+    CanvasNode* sNode = 0;
+    if (n && n->canvasNode()) {
+	_selectedNode = n;
+	_selectedNode->canvasNode()->setSelected(true);
+
+	if (!_isMoving) sNode = _selectedNode->canvasNode();
+    }
+    if (e && e->canvasEdge()) {
+	_selectedEdge = e;
+	_selectedEdge->canvasEdge()->setSelected(true);
+
+#if 0 // don't change position when selecting edge
+	if (!_isMoving) {
+	    if (_selectedEdge->fromNode())
+		sNode = _selectedEdge->fromNode()->canvasNode();
+	    if (!sNode && _selectedEdge->toNode())
+		sNode = _selectedEdge->toNode()->canvasNode();
+	}
+#endif
+    }
+    if (sNode) {
+	double x = sNode->x() + sNode->width()/2;
+	double y = sNode->y() + sNode->height()/2;
+
+	ensureVisible(int(x),int(y),
+                      sNode->width()/2+50, sNode->height()/2+50);
+    }
+
+    _canvas->update();
+    return;
+  }
+
+  if (changeType == groupTypeChanged) {
+    if (!_canvas) return;
+
+    if (_clusterGroups) { 
+      refresh(); 
+      return;
+    }
+
+    TQCanvasItemList l = _canvas->allItems();
+    TQCanvasItemList::iterator it;
+    for (it = l.begin();it != l.end(); ++it)
+	if ((*it)->rtti() == CANVAS_NODE)
+	    ((CanvasNode*) (*it))->updateGroup();
+
+    _canvas->update();
+    return;
+  }
+
+  if (changeType & dataChanged) {
+      // invalidate old selection and graph part
+    _exporter.reset(_data, _activeItem, _costType, _groupType);
+      _selectedNode = 0;
+      _selectedEdge = 0;
+  }
+
+  refresh();
+}
+
+void CallGraphView::clear()
+{
+  if (!_canvas) return;
+
+  delete _canvas;
+  _canvas = 0;
+  _completeView->setCanvas(0);
+  setCanvas(0);
+}
+
+void CallGraphView::showText(TQString s)
+{
+  clear();
+  _renderTimer.stop();
+
+  _canvas = new TQCanvas(TQApplication::desktop()->width(),
+			TQApplication::desktop()->height());
+
+  TQCanvasText* t = new TQCanvasText(s, _canvas);
+  t->move(5, 5);
+  t->show();
+  center(0,0);
+  setCanvas(_canvas);
+  _canvas->update();
+  _completeView->hide();
+}
+
+void CallGraphView::showRenderWarning()
+{
+  TQString s;
+
+  if (_renderProcess)
+    s =i18n("Warning: a long lasting graph layouting is in progress.\n"
+	    "Reduce node/edge limits for speedup.\n");
+  else
+    s = i18n("Layouting stopped.\n");
+  
+  s.append(i18n("The call graph has %1 nodes and %2 edges.\n")
+	   .arg(_exporter.nodeCount())
+	   .arg(_exporter.edgeCount()));
+
+  showText(s);
+}
+
+void CallGraphView::stopRendering()
+{
+  if (!_renderProcess) return;
+
+  _renderProcess->kill();
+  delete _renderProcess;
+  _renderProcess = 0;
+  _unparsedOutput = TQString();
+
+  _renderTimer.start(200, true);
+}
+
+void CallGraphView::refresh()
+{
+  // trigger start of background rendering
+  if (_renderProcess) stopRendering();
+
+  // we want to keep a selected node item at the same global position
+  _prevSelectedNode = _selectedNode;
+  _prevSelectedPos = TQPoint(-1,-1);
+  if (_selectedNode) {
+    TQPoint center = _selectedNode->canvasNode()->boundingRect().center();
+    _prevSelectedPos  = contentsToViewport(center);
+  }
+
+  if (!_data || !_activeItem) {
+    showText(i18n("No item activated for which to draw the call graph."));
+    return;
+  }
+
+  TraceItem::CostType t = _activeItem->type();
+  switch(t) {
+  case TraceItem::Function:
+  case TraceItem::FunctionCycle:
+  case TraceItem::Call:
+    break;
+  default:
+    showText(i18n("No call graph can be drawn for the active item."));
+    return;
+  }
+
+  if (1) kdDebug() << "CallGraphView::refresh" << endl;
+
+  _selectedNode = 0;
+  _selectedEdge = 0;
+  _exporter.reset(_data, _activeItem, _costType, _groupType);
+  _exporter.writeDot();
+
+  _renderProcess = new TQProcess(TQT_TQOBJECT(this));
+  if (_layout == GraphOptions::Circular)
+    _renderProcess->addArgument( "twopi" );
+  else
+    _renderProcess->addArgument( "dot" );
+  _renderProcess->addArgument(_exporter.filename());
+  _renderProcess->addArgument( "-Tplain" );
+
+  connect( _renderProcess, TQT_SIGNAL(readyReadStdout()),
+	   this, TQT_SLOT(readDotOutput()) );
+  connect( _renderProcess, TQT_SIGNAL(processExited()),
+	   this, TQT_SLOT(dotExited()) );
+
+  if (1) kdDebug() << "Running '" 
+		   << _renderProcess->arguments().join(" ")
+		   << "'..." << endl;
+
+  if ( !_renderProcess->start() ) {
+    TQString e = i18n("No call graph is available because the following\n"
+		     "command cannot be run:\n'%1'\n")
+      .arg(_renderProcess->arguments().join(" "));
+    e += i18n("Please check that 'dot' is installed (package GraphViz).");
+    showText(e);
+
+    delete _renderProcess;
+    _renderProcess = 0;
+
+    return;
+  }
+
+  _unparsedOutput = TQString();
+
+  // layouting of more than seconds is dubious
+  _renderTimer.start(1000, true);  
+}
+
+void CallGraphView::readDotOutput()
+{
+  _unparsedOutput.append( _renderProcess->readStdout() );
+}
+
+void CallGraphView::dotExited()
+{
+  TQString line, cmd;
+  CanvasNode *rItem;
+  TQCanvasEllipse* eItem;
+  CanvasEdge* sItem;
+  CanvasEdgeLabel* lItem;
+  TQTextStream* dotStream;
+  double scale = 1.0, scaleX = 1.0, scaleY = 1.0;
+  double dotWidth, dotHeight;
+  GraphNode* activeNode = 0;
+  GraphEdge* activeEdge = 0;
+
+  _renderTimer.stop();
+  viewport()->setUpdatesEnabled(false);
+  clear();
+  dotStream = new TQTextStream(_unparsedOutput, IO_ReadOnly);
+
+  int lineno = 0;
+  while (1) {
+    line = dotStream->readLine();
+    if (line.isNull()) break;
+    lineno++;
+    if (line.isEmpty()) continue;
+
+    TQTextStream lineStream(line, IO_ReadOnly);
+    lineStream >> cmd;
+
+    if (0) qDebug("%s:%d - line '%s', cmd '%s'",
+                  _exporter.filename().ascii(), lineno,
+                  line.ascii(), cmd.ascii());
+
+    if (cmd == "stop") break;
+
+    if (cmd == "graph") {
+      TQString dotWidthString, dotHeightString;
+      lineStream >> scale >> dotWidthString >> dotHeightString;
+      dotWidth = dotWidthString.toDouble();
+      dotHeight = dotHeightString.toDouble();
+
+      if (_detailLevel == 0)      { scaleX = scale * 70; scaleY = scale * 40; }
+      else if (_detailLevel == 1) { scaleX = scale * 80; scaleY = scale * 70; }
+      else                        { scaleX = scale * 60; scaleY = scale * 100; }
+
+      if (!_canvas) {
+        int w = (int)(scaleX * dotWidth);
+        int h = (int)(scaleY * dotHeight);
+
+	// We use as minimum canvas size the desktop size.
+	// Otherwise, the canvas would have to be resized on widget resize.
+	_xMargin = 50;
+	if (w < TQApplication::desktop()->width())
+	    _xMargin += (TQApplication::desktop()->width()-w)/2;
+
+	_yMargin = 50;
+	if (h < TQApplication::desktop()->height())
+	    _yMargin += (TQApplication::desktop()->height()-h)/2;
+
+        _canvas = new TQCanvas(int(w+2*_xMargin), int(h+2*_yMargin));
+
+#if DEBUG_GRAPH
+        kdDebug() << _exporter.filename().ascii() << ":" << lineno
+		  << " - graph (" << dotWidth << " x " << dotHeight
+		  << ") => (" << w << " x " << h << ")" << endl;
+#endif
+      }
+      else
+        kdWarning() << "Ignoring 2nd 'graph' from dot ("
+		    << _exporter.filename() << ":" << lineno << ")" << endl;
+      continue;
+    }
+
+    if ((cmd != "node") && (cmd != "edge")) {
+      kdWarning() << "Ignoring unknown command '" << cmd << "' from dot ("
+		    << _exporter.filename() << ":" << lineno << ")" << endl;
+      continue;
+    }
+
+    if (_canvas == 0) {
+      kdWarning() << "Ignoring '" << cmd << "' without 'graph' from dot ("
+		  << _exporter.filename() << ":" << lineno << ")" << endl;
+      continue;
+    }
+
+    if (cmd == "node") {
+      // x, y are centered in node
+      TQString nodeName, label, nodeX, nodeY, nodeWidth, nodeHeight;
+      double x, y, width, height;
+      lineStream >> nodeName >> nodeX >> nodeY >> nodeWidth >> nodeHeight;
+      x = nodeX.toDouble();
+      y = nodeY.toDouble();
+      width = nodeWidth.toDouble();
+      height = nodeHeight.toDouble();
+
+      GraphNode* n = _exporter.node(_exporter.toFunc(nodeName));
+
+      int xx = (int)(scaleX * x + _xMargin);
+      int yy = (int)(scaleY * (dotHeight - y) + _yMargin);
+      int w = (int)(scaleX * width);
+      int h = (int)(scaleY * height);
+
+#if DEBUG_GRAPH
+      kdDebug() << _exporter.filename() << ":" << lineno
+		<< " - node '" << nodeName << "' ( "
+		<< x << "/" << y << " - "
+		<< width << "x" << height << " ) => ("
+		<< xx-w/2 << "/" << yy-h/2 << " - "
+		<< w << "x" << h << ")" << endl;
+#endif
+
+
+      // Unnamed nodes with collapsed edges (with 'R' and 'S')
+      if (nodeName[0] == 'R' || nodeName[0] == 'S') {
+	  w = 10, h = 10;
+        eItem = new TQCanvasEllipse(w, h, _canvas);
+        eItem->move(xx, yy);
+        eItem->setBrush(TQt::gray);
+        eItem->setZ(1.0);
+        eItem->show();
+        continue;
+      }
+
+      if (!n) {
+	  qDebug("Warning: Unknown function '%s' ?!", nodeName.ascii());
+	  continue;
+      }
+      n->setVisible(true);
+
+      rItem = new CanvasNode(this, n, xx-w/2, yy-h/2, w, h, _canvas);
+      n->setCanvasNode(rItem);
+
+      if (n) {
+        if (n->function() == activeItem()) activeNode = n;
+        if (n->function() == selectedItem()) _selectedNode = n;
+        rItem->setSelected(n == _selectedNode);
+      }
+
+      rItem->setZ(1.0);
+      rItem->show();
+
+      continue;
+    }
+
+    // edge
+
+    TQString node1Name, node2Name, label, edgeX, edgeY;
+    double x, y;
+    TQPointArray pa;
+    int points, i;
+    lineStream >> node1Name >> node2Name >> points;
+
+    GraphEdge* e = _exporter.edge(_exporter.toFunc(node1Name),
+                                  _exporter.toFunc(node2Name));
+    if (!e) {
+      kdWarning() << "Unknown edge '" << node1Name << "'-'"
+		  << node2Name << "' from dot ("
+		  << _exporter.filename() << ":" << lineno << ")" << endl;
+      continue;
+    }
+    e->setVisible(true);
+    if (e->fromNode()) e->fromNode()->callings.append(e);
+    if (e->toNode()) e->toNode()->callers.append(e);
+
+    if (0) qDebug("  Edge with %d points:", points);
+
+    pa.resize(points);
+    for (i=0;i<points;i++) {
+      if (lineStream.atEnd()) break;
+      lineStream >> edgeX >> edgeY;
+      x = edgeX.toDouble();
+      y = edgeY.toDouble();
+
+      int xx = (int)(scaleX * x + _xMargin);
+      int yy = (int)(scaleY * (dotHeight - y) + _yMargin);
+
+      if (0) qDebug("   P %d: ( %f / %f ) => ( %d / %d)",
+                    i, x, y, xx, yy);
+
+      pa.setPoint(i, xx, yy);
+    }
+    if (i < points) {
+      qDebug("CallGraphView: Can't read %d spline points (%s:%d)",
+             points, _exporter.filename().ascii(), lineno);
+      continue;
+    }
+
+    // calls into/out of cycles are special: make them blue
+    TQColor arrowColor = TQt::black;
+    TraceFunction* caller = e->fromNode() ? e->fromNode()->function() : 0;
+    TraceFunction* called = e->toNode() ? e->toNode()->function() : 0;
+    if ( (caller && (caller->cycle() == caller)) ||
+         (called && (called->cycle() == called)) ) arrowColor = TQt::blue;
+
+    sItem = new CanvasEdge(e, _canvas);
+    e->setCanvasEdge(sItem);
+    sItem->setControlPoints(pa, false);
+    sItem->setPen(TQPen(arrowColor, 1 /*(int)log(log(e->cost))*/ ));
+    sItem->setZ(0.5);
+    sItem->show();
+
+    if (e->call() == selectedItem()) _selectedEdge = e;
+    if (e->call() == activeItem()) activeEdge = e;
+    sItem->setSelected(e == _selectedEdge);
+
+    // Arrow head
+    TQPoint arrowDir;
+    int indexHead = -1;
+
+    // check if head is at start of spline...
+    // this is needed because dot always gives points from top to bottom
+    CanvasNode* fromNode = e->fromNode() ? e->fromNode()->canvasNode() : 0;
+    if (fromNode) {
+      TQPoint toCenter = fromNode->rect().center();
+      int dx0 = pa.point(0).x() - toCenter.x();
+      int dy0 = pa.point(0).y() - toCenter.y();
+      int dx1 = pa.point(points-1).x() - toCenter.x();
+      int dy1 = pa.point(points-1).y() - toCenter.y();
+      if (dx0*dx0+dy0*dy0 > dx1*dx1+dy1*dy1) {
+	// start of spline is nearer to call target node
+	indexHead=-1;
+	while(arrowDir.isNull() && (indexHead<points-2)) {
+	  indexHead++;
+	  arrowDir = pa.point(indexHead) - pa.point(indexHead+1);
+	}
+      }
+    }
+
+    if (arrowDir.isNull()) {
+      indexHead = points;
+      // sometimes the last spline points from dot are the same...
+      while(arrowDir.isNull() && (indexHead>1)) {
+	indexHead--;
+	arrowDir = pa.point(indexHead) - pa.point(indexHead-1);
+      }
+    }
+
+    if (!arrowDir.isNull()) {
+	// arrow around pa.point(indexHead) with direction arrowDir
+	arrowDir *= 10.0/sqrt(double(arrowDir.x()*arrowDir.x() +
+			             arrowDir.y()*arrowDir.y()));
+	TQPointArray a(3);
+	a.setPoint(0, pa.point(indexHead) + arrowDir);
+	a.setPoint(1, pa.point(indexHead) + TQPoint(arrowDir.y()/2,
+						   -arrowDir.x()/2));
+	a.setPoint(2, pa.point(indexHead) + TQPoint(-arrowDir.y()/2,
+						   arrowDir.x()/2));
+
+	if (0) qDebug("  Arrow: ( %d/%d, %d/%d, %d/%d)",
+		      a.point(0).x(), a.point(0).y(),
+		      a.point(1).x(), a.point(1).y(),
+		      a.point(2).x(), a.point(2).y());
+
+	CanvasEdgeArrow* aItem = new CanvasEdgeArrow(sItem,_canvas);
+	aItem->setPoints(a);
+	aItem->setBrush(arrowColor);
+	aItem->setZ(1.5);
+	aItem->show();
+
+	sItem->setArrow(aItem);
+    }
+
+    if (lineStream.atEnd()) continue;
+
+    // parse quoted label
+    TQChar c;
+    lineStream >> c;
+    while (c.isSpace()) lineStream >> c;
+    if (c != '\"') {
+      lineStream >> label;
+      label = c + label;
+    }
+    else {
+      lineStream >> c;
+      while(!c.isNull() && (c != '\"')) {
+        //if (c == '\\') lineStream >> c;
+
+        label += c;
+        lineStream >> c;
+      }
+    }
+    lineStream >> edgeX >> edgeY;
+    x = edgeX.toDouble();
+    y = edgeY.toDouble();
+
+    int xx = (int)(scaleX * x + _xMargin);
+    int yy = (int)(scaleY * (dotHeight - y) + _yMargin);
+
+    if (0) qDebug("   Label '%s': ( %f / %f ) => ( %d / %d)",
+                  label.ascii(), x, y, xx, yy);
+
+    // Fixed Dimensions for Label: 100 x 40
+    int w = 100;
+    int h = _detailLevel * 20;
+    lItem = new CanvasEdgeLabel(this, sItem, xx-w/2, yy-h/2, w, h, _canvas);
+    // edge labels above nodes
+    lItem->setZ(1.5);
+    sItem->setLabel(lItem);
+    if (h>0) lItem->show();
+
+  }
+  delete dotStream;
+
+  // for keyboard navigation
+  // TODO: Edge sorting. Better keep left-to-right edge order from dot now
+  // _exporter.sortEdges();
+
+  if (!_canvas) {
+    _canvas = new TQCanvas(size().width(),size().height());
+    TQString s = i18n("Error running the graph layouting tool.\n");
+    s += i18n("Please check that 'dot' is installed (package GraphViz).");
+    TQCanvasText* t = new TQCanvasText(s, _canvas);
+    t->move(5, 5);
+    t->show();
+    center(0,0);
+  }
+  else if (!activeNode && !activeEdge) {
+    TQString s = i18n("There is no call graph available for function\n"
+		     "\t'%1'\n"
+		     "because it has no cost of the selected event type.");
+    TQCanvasText* t = new TQCanvasText(s.arg(_activeItem->name()), _canvas);
+    //    t->setTextFlags(TQt::AlignHCenter | TQt::AlignVCenter);
+    t->move(5,5);
+    t->show();
+    center(0,0);
+  }
+
+  _completeView->setCanvas(_canvas);
+  setCanvas(_canvas);
+
+  // if we don't have a selection, or the old selection is not
+  // in visible graph, make active function selected for this view
+  if ((!_selectedNode || !_selectedNode->canvasNode()) &&
+      (!_selectedEdge || !_selectedEdge->canvasEdge())) {
+    if (activeNode) {
+      _selectedNode = activeNode;
+      _selectedNode->canvasNode()->setSelected(true);
+    }
+    else if (activeEdge) {
+      _selectedEdge = activeEdge;
+      _selectedEdge->canvasEdge()->setSelected(true);
+    }
+  }
+
+  CanvasNode* sNode = 0;
+  if (_selectedNode)
+      sNode = _selectedNode->canvasNode();
+  else if (_selectedEdge) {
+      if (_selectedEdge->fromNode())
+	  sNode = _selectedEdge->fromNode()->canvasNode();
+      if (!sNode && _selectedEdge->toNode())
+	  sNode = _selectedEdge->toNode()->canvasNode();
+  }
+  if (sNode) {
+      int x = int(sNode->x() + sNode->width()/2);
+      int y = int(sNode->y() + sNode->height()/2);
+
+      if (_prevSelectedNode) {
+	  if (rect().contains(_prevSelectedPos))
+	      setContentsPos(x-_prevSelectedPos.x(),
+                             y-_prevSelectedPos.y());
+	  else
+	      ensureVisible(x,y,
+                            sNode->width()/2+50, sNode->height()/2+50);
+      }
+      else center(x,y);
+  }
+
+  if (activeNode) {
+    CanvasNode* cn = activeNode->canvasNode();
+    CanvasFrame* f = new CanvasFrame(cn, _canvas);
+    f->setZ(-1);
+    f->show();
+  }
+
+  _cvZoom = 0;
+  updateSizes();
+
+  _canvas->update();
+  viewport()->setUpdatesEnabled(true);
+
+  delete _renderProcess;
+  _renderProcess = 0;
+}
+
+void CallGraphView::contentsMovingSlot(int x, int y)
+{
+  TQRect z(int(x * _cvZoom), int(y * _cvZoom),
+          int(visibleWidth() * _cvZoom)-1, int(visibleHeight() * _cvZoom)-1);
+  if (0) qDebug("moving: (%d,%d) => (%d/%d - %dx%d)",
+                x, y, z.x(), z.y(), z.width(), z.height());
+  _completeView->setZoomRect(z);
+}
+
+void CallGraphView::zoomRectMoved(int dx, int dy)
+{
+  if (leftMargin()>0) dx = 0;
+  if (topMargin()>0) dy = 0;
+  scrollBy(int(dx/_cvZoom),int(dy/_cvZoom));
+}
+
+void CallGraphView::zoomRectMoveFinished()
+{
+    if (_zoomPosition == Auto) updateSizes();
+}
+
+void CallGraphView::contentsMousePressEvent(TQMouseEvent* e)
+{
+    // clicking on the viewport sets focus
+    setFocus();
+
+  _isMoving = true;
+
+  TQCanvasItemList l = canvas()->collisions(e->pos());
+  if (l.count()>0) {
+    TQCanvasItem* i = l.first();
+
+    if (i->rtti() == CANVAS_NODE) {
+      GraphNode* n = ((CanvasNode*)i)->node();
+      if (0) qDebug("CallGraphView: Got Node '%s'",
+                    n->function()->prettyName().ascii());
+
+      selected(n->function());
+    }
+
+    // redirect from label / arrow to edge
+    if (i->rtti() == CANVAS_EDGELABEL)
+	i = ((CanvasEdgeLabel*)i)->canvasEdge();
+    if (i->rtti() == CANVAS_EDGEARROW)
+	i = ((CanvasEdgeArrow*)i)->canvasEdge();
+
+    if (i->rtti() == CANVAS_EDGE) {
+      GraphEdge* e = ((CanvasEdge*)i)->edge();
+      if (0) qDebug("CallGraphView: Got Edge '%s'",
+                    e->prettyName().ascii());
+
+      if (e->call()) selected(e->call());
+    }
+  }
+  _lastPos = e->globalPos();
+}
+
+void CallGraphView::contentsMouseMoveEvent(TQMouseEvent* e)
+{
+  if (_isMoving) {
+    int dx = e->globalPos().x() - _lastPos.x();
+    int dy = e->globalPos().y() - _lastPos.y();
+    scrollBy(-dx, -dy);
+    _lastPos = e->globalPos();
+  }
+}
+
+void CallGraphView::contentsMouseReleaseEvent(TQMouseEvent*)
+{
+  _isMoving = false;
+  if (_zoomPosition == Auto) updateSizes();
+}
+
+void CallGraphView::contentsMouseDoubleClickEvent(TQMouseEvent* e)
+{
+  TQCanvasItemList l = canvas()->collisions(e->pos());
+  if (l.count() == 0) return;
+  TQCanvasItem* i = l.first();
+
+  if (i->rtti() == CANVAS_NODE) {
+    GraphNode* n = ((CanvasNode*)i)->node();
+    if (0) qDebug("CallGraphView: Double Clicked on Node '%s'",
+		  n->function()->prettyName().ascii());
+
+    activated(n->function());
+  }
+
+  // redirect from label / arrow to edge
+  if (i->rtti() == CANVAS_EDGELABEL)
+      i = ((CanvasEdgeLabel*)i)->canvasEdge();
+  if (i->rtti() == CANVAS_EDGEARROW)
+      i = ((CanvasEdgeArrow*)i)->canvasEdge();
+
+  if (i->rtti() == CANVAS_EDGE) {
+    GraphEdge* e = ((CanvasEdge*)i)->edge();
+    if (e->call()) {
+      if (0) qDebug("CallGraphView: Double Clicked On Edge '%s'",
+		    e->call()->prettyName().ascii());
+
+      activated(e->call());
+    }
+  }
+}
+
+void CallGraphView::contentsContextMenuEvent(TQContextMenuEvent* e)
+{
+  TQCanvasItemList l = canvas()->collisions(e->pos());
+  TQCanvasItem* i = (l.count() == 0) ? 0 : l.first();
+
+  TQPopupMenu popup;
+  TraceFunction *f = 0, *cycle = 0;
+  TraceCall* c = 0;
+
+  if (i) {
+    if (i->rtti() == CANVAS_NODE) {
+      GraphNode* n = ((CanvasNode*)i)->node();
+      if (0) qDebug("CallGraphView: Menu on Node '%s'",
+		    n->function()->prettyName().ascii());
+      f = n->function();
+      cycle = f->cycle();
+
+      TQString name = f->prettyName();
+      popup.insertItem(i18n("Go to '%1'")
+		     .arg(Configuration::shortenSymbol(name)), 93);
+      if (cycle && (cycle != f)) {
+	name = Configuration::shortenSymbol(cycle->prettyName());
+	popup.insertItem(i18n("Go to '%1'").arg(name), 94);
+      }
+      popup.insertSeparator();
+    }
+
+    // redirect from label / arrow to edge
+    if (i->rtti() == CANVAS_EDGELABEL)
+	i = ((CanvasEdgeLabel*)i)->canvasEdge();
+    if (i->rtti() == CANVAS_EDGEARROW)
+	i = ((CanvasEdgeArrow*)i)->canvasEdge();
+
+    if (i->rtti() == CANVAS_EDGE) {
+      GraphEdge* e = ((CanvasEdge*)i)->edge();
+      if (0) qDebug("CallGraphView: Menu on Edge '%s'",
+		    e->prettyName().ascii());
+      c = e->call();
+      if (c) {
+	  TQString name = c->prettyName();
+	  popup.insertItem(i18n("Go to '%1'")
+			   .arg(Configuration::shortenSymbol(name)), 95);
+
+	  popup.insertSeparator();
+      }
+    }
+  }
+
+  if (_renderProcess) {
+    popup.insertItem(i18n("Stop Layouting"), 999);
+    popup.insertSeparator();
+  }
+
+  addGoMenu(&popup);
+  popup.insertSeparator();
+
+  TQPopupMenu epopup;
+  epopup.insertItem(i18n("As PostScript"), 201);
+  epopup.insertItem(i18n("As Image ..."), 202);
+
+  popup.insertItem(i18n("Export Graph"), &epopup, 200);
+  popup.insertSeparator();
+
+  TQPopupMenu gpopup1;
+  gpopup1.setCheckable(true);
+  gpopup1.insertItem(i18n("Unlimited"), 100);
+  gpopup1.setItemEnabled(100, (_funcLimit>0.005));
+  gpopup1.insertSeparator();
+  gpopup1.insertItem(i18n("None"), 101);
+  gpopup1.insertItem(i18n("max. 2"), 102);
+  gpopup1.insertItem(i18n("max. 5"), 103);
+  gpopup1.insertItem(i18n("max. 10"), 104);
+  gpopup1.insertItem(i18n("max. 15"), 105);
+  if (_maxCallerDepth<-1) _maxCallerDepth=-1;
+  switch(_maxCallerDepth) {
+  case -1: gpopup1.setItemChecked(100,true); break;
+  case  0: gpopup1.setItemChecked(101,true); break;
+  case  2: gpopup1.setItemChecked(102,true); break;
+  case  5: gpopup1.setItemChecked(103,true); break;
+  case 10: gpopup1.setItemChecked(104,true); break;
+  case 15: gpopup1.setItemChecked(105,true); break;
+  default:
+    gpopup1.insertItem(i18n("< %1").arg(_maxCallerDepth), 106);
+    gpopup1.setItemChecked(106,true); break;
+  }
+
+  TQPopupMenu gpopup2;
+  gpopup2.setCheckable(true);
+  gpopup2.insertItem(i18n("Unlimited"), 110);
+  gpopup2.setItemEnabled(110, (_funcLimit>0.005));
+  gpopup2.insertSeparator();
+  gpopup2.insertItem(i18n("None"), 111);
+  gpopup2.insertItem(i18n("max. 2"), 112);
+  gpopup2.insertItem(i18n("max. 5"), 113);
+  gpopup2.insertItem(i18n("max. 10"), 114);
+  gpopup2.insertItem(i18n("max. 15"), 115);
+  if (_maxCallingDepth<-1) _maxCallingDepth=-1;
+  switch(_maxCallingDepth) {
+  case -1: gpopup2.setItemChecked(110,true); break;
+  case  0: gpopup2.setItemChecked(111,true); break;
+  case  2: gpopup2.setItemChecked(112,true); break;
+  case  5: gpopup2.setItemChecked(113,true); break;
+  case 10: gpopup2.setItemChecked(114,true); break;
+  case 15: gpopup2.setItemChecked(115,true); break;
+  default:
+    gpopup2.insertItem(i18n("< %1").arg(_maxCallingDepth), 116);
+    gpopup2.setItemChecked(116,true); break;
+  }
+
+  TQPopupMenu gpopup3;
+  gpopup3.setCheckable(true);
+  gpopup3.insertItem(i18n("No Minimum"), 120);
+  gpopup3.setItemEnabled(120,
+                         (_maxCallerDepth>=0) && (_maxCallingDepth>=0));
+  gpopup3.insertSeparator();
+  gpopup3.insertItem(i18n("50 %"), 121);
+  gpopup3.insertItem(i18n("20 %"), 122);
+  gpopup3.insertItem(i18n("10 %"), 123);
+  gpopup3.insertItem(i18n("5 %"), 124);
+  gpopup3.insertItem(i18n("3 %"), 125);
+  gpopup3.insertItem(i18n("2 %"), 126);
+  gpopup3.insertItem(i18n("1.5 %"), 127);
+  gpopup3.insertItem(i18n("1 %"), 128);
+  if (_funcLimit<0) _funcLimit = DEFAULT_FUNCLIMIT;
+  if (_funcLimit>.5) _funcLimit = .5;
+  if (_funcLimit == 0.0) gpopup3.setItemChecked(120,true);
+  else if (_funcLimit >= 0.5) gpopup3.setItemChecked(121,true);
+  else if (_funcLimit >= 0.2) gpopup3.setItemChecked(122,true);
+  else if (_funcLimit >= 0.1) gpopup3.setItemChecked(123,true);
+  else if (_funcLimit >= 0.05) gpopup3.setItemChecked(124,true);
+  else if (_funcLimit >= 0.03) gpopup3.setItemChecked(125,true);
+  else if (_funcLimit >= 0.02) gpopup3.setItemChecked(126,true);
+  else if (_funcLimit >= 0.015) gpopup3.setItemChecked(127,true);
+  else gpopup3.setItemChecked(128,true);
+  double oldFuncLimit = _funcLimit;
+
+  TQPopupMenu gpopup4;
+  gpopup4.setCheckable(true);
+  gpopup4.insertItem(i18n("Same as Node"), 160);
+  gpopup4.insertItem(i18n("50 % of Node"), 161);
+  gpopup4.insertItem(i18n("20 % of Node"), 162);
+  gpopup4.insertItem(i18n("10 % of Node"), 163);
+  if (_callLimit<0) _callLimit = DEFAULT_CALLLIMIT;
+  if (_callLimit >= _funcLimit) _callLimit = _funcLimit;
+  if (_callLimit == _funcLimit) gpopup4.setItemChecked(160,true);
+  else if (_callLimit >= 0.5 * _funcLimit) gpopup4.setItemChecked(161,true);
+  else if (_callLimit >= 0.2 * _funcLimit) gpopup4.setItemChecked(162,true);
+  else gpopup4.setItemChecked(163,true);
+
+  TQPopupMenu gpopup;
+  gpopup.setCheckable(true);
+  gpopup.insertItem(i18n("Caller Depth"), &gpopup1, 80);
+  gpopup.insertItem(i18n("Callee Depth"), &gpopup2, 81);
+  gpopup.insertItem(i18n("Min. Node Cost"), &gpopup3, 82);
+  gpopup.insertItem(i18n("Min. Call Cost"), &gpopup4, 83);
+  gpopup.insertSeparator();
+  gpopup.insertItem(i18n("Arrows for Skipped Calls"), 130);
+  gpopup.setItemChecked(130,_showSkipped);
+  gpopup.insertItem(i18n("Inner-cycle Calls"), 131);
+  gpopup.setItemChecked(131,_expandCycles);
+  gpopup.insertItem(i18n("Cluster Groups"), 132);
+  gpopup.setItemChecked(132,_clusterGroups);
+
+  TQPopupMenu vpopup;
+  vpopup.setCheckable(true);
+  vpopup.insertItem(i18n("Compact"), 140);
+  vpopup.insertItem(i18n("Normal"), 141);
+  vpopup.insertItem(i18n("Tall"), 142);
+  vpopup.setItemChecked(140,_detailLevel == 0);
+  vpopup.setItemChecked(141,_detailLevel == 1);
+  vpopup.setItemChecked(142,_detailLevel == 2);
+  vpopup.insertSeparator();
+  vpopup.insertItem(i18n("Top to Down"), 150);
+  vpopup.insertItem(i18n("Left to Right"), 151);
+  vpopup.insertItem(i18n("Circular"), 152);
+  vpopup.setItemChecked(150,_layout == TopDown);
+  vpopup.setItemChecked(151,_layout == LeftRight);
+  vpopup.setItemChecked(152,_layout == Circular);
+
+  TQPopupMenu opopup;
+  opopup.insertItem(i18n("TopLeft"), 170);
+  opopup.insertItem(i18n("TopRight"), 171);
+  opopup.insertItem(i18n("BottomLeft"), 172);
+  opopup.insertItem(i18n("BottomRight"), 173);
+  opopup.insertItem(i18n("Automatic"), 174);
+  opopup.setItemChecked(170,_zoomPosition == TopLeft);
+  opopup.setItemChecked(171,_zoomPosition == TopRight);
+  opopup.setItemChecked(172,_zoomPosition == BottomLeft);
+  opopup.setItemChecked(173,_zoomPosition == BottomRight);
+  opopup.setItemChecked(174,_zoomPosition == Auto);
+
+  popup.insertItem(i18n("Graph"), &gpopup, 70);
+  popup.insertItem(i18n("Visualization"), &vpopup, 71);
+  popup.insertItem(i18n("Birds-eye View"), &opopup, 72);
+
+  int r = popup.exec(e->globalPos());
+
+  switch(r) {
+  case 93: activated(f); break;
+  case 94: activated(cycle); break;
+  case 95: activated(c); break;
+
+  case 999: stopRendering(); break;
+
+  case 201:
+      {
+	  TraceFunction* f = activeFunction();
+	  if (!f) break;
+
+	  GraphExporter ge(TraceItemView::data(), f, costType(), groupType(),
+			   TQString("callgraph.dot"));
+	  ge.setGraphOptions(this);
+	  ge.writeDot();
+
+	  system("(dot callgraph.dot -Tps > callgraph.ps; kghostview callgraph.ps)&");
+      }
+      break;
+
+  case 202:    
+      // write current content of canvas as image to file
+      {
+	if (!_canvas) return;
+
+	TQString fn = KFileDialog::getSaveFileName(":","*.png");
+
+	if (!fn.isEmpty()) {
+	  TQPixmap pix(_canvas->size());
+	  TQPainter p(&pix);
+	  _canvas->drawArea( _canvas->rect(), &p );
+	  pix.save(fn,"PNG");
+	}
+      }
+      break;
+
+  case 100: _maxCallerDepth = -1; break;
+  case 101: _maxCallerDepth = 0; break;
+  case 102: _maxCallerDepth = 2; break;
+  case 103: _maxCallerDepth = 5; break;
+  case 104: _maxCallerDepth = 10; break;
+  case 105: _maxCallerDepth = 15; break;
+
+  case 110: _maxCallingDepth = -1; break;
+  case 111: _maxCallingDepth = 0; break;
+  case 112: _maxCallingDepth = 2; break;
+  case 113: _maxCallingDepth = 5; break;
+  case 114: _maxCallingDepth = 10; break;
+  case 115: _maxCallingDepth = 15; break;
+
+  case 120: _funcLimit = 0; break;
+  case 121: _funcLimit = 0.5; break;
+  case 122: _funcLimit = 0.2; break;
+  case 123: _funcLimit = 0.1; break;
+  case 124: _funcLimit = 0.05; break;
+  case 125: _funcLimit = 0.03; break;
+  case 126: _funcLimit = 0.02; break;
+  case 127: _funcLimit = 0.015; break;
+  case 128: _funcLimit = 0.01; break;
+
+  case 130: _showSkipped = !_showSkipped; break;
+  case 131: _expandCycles = !_expandCycles; break;
+  case 132: _clusterGroups = !_clusterGroups; break;
+
+  case 140: _detailLevel = 0; break;
+  case 141: _detailLevel = 1; break;
+  case 142: _detailLevel = 2; break;
+
+  case 150: _layout = TopDown; break;
+  case 151: _layout = LeftRight; break;
+  case 152: _layout = Circular; break;
+
+  case 160: _callLimit = _funcLimit; break;
+  case 161: _callLimit = .5 * _funcLimit; break;
+  case 162: _callLimit = .2 * _funcLimit; break;
+  case 163: _callLimit = .1 * _funcLimit; break;
+
+  case 170: _zoomPosition = TopLeft; break;
+  case 171: _zoomPosition = TopRight; break;
+  case 172: _zoomPosition = BottomLeft; break;
+  case 173: _zoomPosition = BottomRight; break;
+  case 174: _zoomPosition = Auto; break;
+
+  default: break;
+  }
+  if (r>=120 && r<130) _callLimit *= _funcLimit / oldFuncLimit;
+
+  if (r>99 && r<170) refresh();
+  if (r>169 && r<180) updateSizes();
+}
+
+CallGraphView::ZoomPosition CallGraphView::zoomPos(TQString s)
+{
+    if (s == TQString("TopLeft")) return TopLeft;
+    if (s == TQString("TopRight")) return TopRight;
+    if (s == TQString("BottomLeft")) return BottomLeft;
+    if (s == TQString("BottomRight")) return BottomRight;
+    if (s == TQString("Automatic")) return Auto;
+
+    return DEFAULT_ZOOMPOS;
+}
+
+TQString CallGraphView::zoomPosString(ZoomPosition p)
+{
+    if (p == TopRight) return TQString("TopRight");
+    if (p == BottomLeft) return TQString("BottomLeft");
+    if (p == BottomRight) return TQString("BottomRight");
+    if (p == Auto) return TQString("Automatic");
+
+    return TQString("TopLeft");
+}
+
+void CallGraphView::readViewConfig(KConfig* c, 
+				   TQString prefix, TQString postfix, bool)
+{
+    KConfigGroup* g = configGroup(c, prefix, postfix);
+
+    if (0) qDebug("CallGraphView::readViewConfig");
+
+    _maxCallerDepth  = g->readNumEntry("MaxCaller", DEFAULT_MAXCALLER);
+    _maxCallingDepth = g->readNumEntry("MaxCalling", DEFAULT_MAXCALLING);
+    _funcLimit       = g->readDoubleNumEntry("FuncLimit", DEFAULT_FUNCLIMIT);
+    _callLimit       = g->readDoubleNumEntry("CallLimit", DEFAULT_CALLLIMIT);
+    _showSkipped     = g->readBoolEntry("ShowSkipped", DEFAULT_SHOWSKIPPED);
+    _expandCycles    = g->readBoolEntry("ExpandCycles", DEFAULT_EXPANDCYCLES);
+    _clusterGroups   = g->readBoolEntry("ClusterGroups",
+					DEFAULT_CLUSTERGROUPS);
+    _detailLevel     = g->readNumEntry("DetailLevel", DEFAULT_DETAILLEVEL);
+    _layout          = GraphOptions::layout(g->readEntry("Layout",
+					   layoutString(DEFAULT_LAYOUT)));
+    _zoomPosition    = zoomPos(g->readEntry("ZoomPosition",
+					    zoomPosString(DEFAULT_ZOOMPOS)));
+
+    delete g;
+}
+
+void CallGraphView::saveViewConfig(KConfig* c,
+				   TQString prefix, TQString postfix, bool)
+{
+    KConfigGroup g(c, (prefix+postfix).ascii());
+
+    writeConfigEntry(&g, "MaxCaller", _maxCallerDepth, DEFAULT_MAXCALLER);
+    writeConfigEntry(&g, "MaxCalling", _maxCallingDepth, DEFAULT_MAXCALLING);
+    writeConfigEntry(&g, "FuncLimit", _funcLimit, DEFAULT_FUNCLIMIT);
+    writeConfigEntry(&g, "CallLimit", _callLimit, DEFAULT_CALLLIMIT);
+    writeConfigEntry(&g, "ShowSkipped", _showSkipped, DEFAULT_SHOWSKIPPED);
+    writeConfigEntry(&g, "ExpandCycles", _expandCycles, DEFAULT_EXPANDCYCLES);
+    writeConfigEntry(&g, "ClusterGroups", _clusterGroups,
+		     DEFAULT_CLUSTERGROUPS);
+    writeConfigEntry(&g, "DetailLevel", _detailLevel, DEFAULT_DETAILLEVEL);
+    writeConfigEntry(&g, "Layout",
+		     layoutString(_layout), layoutString(DEFAULT_LAYOUT).utf8().data());
+    writeConfigEntry(&g, "ZoomPosition",
+		     zoomPosString(_zoomPosition),
+		     zoomPosString(DEFAULT_ZOOMPOS).utf8().data());
+}
+
+#include "callgraphview.moc"
+
diff --git a/kdecachegrind/kdecachegrind/callgraphview.h b/kdecachegrind/kdecachegrind/callgraphview.h
new file mode 100644
index 0000000..4db619d
--- /dev/null
+++ b/kdecachegrind/kdecachegrind/callgraphview.h
@@ -0,0 +1,501 @@
+/* This file is part of KCachegrind.
+   Copyright (C) 2003 Josef Weidendorfer <Josef.Weidendorfer@gmx.de>
+
+   KCachegrind 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, version 2.
+
+   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; see the file COPYING.  If not, write to
+   the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+   Boston, MA 02110-1301, USA.
+*/
+
+/*
+ * Callgraph View
+ */
+
+#ifndef CALLGRAPHVIEW_H
+#define CALLGRAPHVIEW_H
+
+#include <tqcanvas.h>
+#include <tqwidget.h>
+#include <tqmap.h>
+#include <tqtimer.h>
+
+#include "treemap.h" // for DrawParams
+#include "tracedata.h"
+#include "traceitemview.h"
+
+class TQProcess;
+
+class KTempFile;
+class CanvasNode;
+class CanvasEdge;
+class GraphEdge;
+class CallGraphView;
+
+// sorts according start/end position of a call arc
+// this depends on attached CanvasEdge's !
+class GraphEdgeList: public TQPtrList<GraphEdge>
+{
+ public:
+    GraphEdgeList();
+    void setSortCallerPos(bool b) { _sortCallerPos = b; }
+
+ protected:
+    int compareItems ( Item item1, Item item2 );
+
+ private:
+    bool _sortCallerPos;
+};
+
+
+typedef TQMap<GraphEdge*, int> GraphEdgeSet;
+
+// temporary parts of call graph to be shown
+class GraphNode
+{
+public:
+    GraphNode();
+
+  TraceFunction* function() { return _f; }
+  void setFunction(TraceFunction* f) { _f = f; }
+
+  CanvasNode* canvasNode() { return _cn; }
+  void setCanvasNode(CanvasNode* cn) { _cn = cn; }
+
+  bool isVisible() { return _visible; }
+  void setVisible(bool v) { _visible = v; }
+
+  // keyboard navigation
+  TraceCall* visibleCaller();
+  TraceCall* visibleCalling();
+  void setCalling(GraphEdge*);
+  void setCaller(GraphEdge*);
+  TraceFunction* nextVisible();
+  TraceFunction* priorVisible();
+  TraceCall* nextVisibleCaller(GraphEdge*);
+  TraceCall* nextVisibleCalling(GraphEdge*);
+  TraceCall* priorVisibleCaller(GraphEdge*);
+  TraceCall* priorVisibleCalling(GraphEdge*);
+
+  double self, incl;
+  GraphEdgeList callers, callings;
+  // for fast unique insertion of GraphEdges in above lists
+  GraphEdgeSet callerSet, callingSet;
+
+ private:
+  TraceFunction* _f;
+  CanvasNode* _cn;
+  bool _visible;
+
+  // for keyboard navigation
+  int _lastCallerIndex, _lastCallingIndex;
+  bool _lastFromCaller;
+};
+
+class GraphEdge
+{
+public:
+    GraphEdge();
+
+  CanvasEdge* canvasEdge() { return _ce; }
+  void setCanvasEdge(CanvasEdge* ce) { _ce = ce; }
+
+  TraceCall* call() { return _c; }
+  void setCall(TraceCall* c) { _c = c; }
+
+  bool isVisible() { return _visible; }
+  void setVisible(bool v) { _visible = v; }
+
+  GraphNode* fromNode() { return _fromNode; }
+  GraphNode* toNode() { return _toNode; }
+  TraceFunction* from() { return _from; }
+  TraceFunction* to() { return _to; }
+
+  // has special cases for collapsed edges
+  TQString prettyName();
+
+  void setCaller(TraceFunction* f) { _from = f; }
+  void setCalling(TraceFunction* f) { _to = f; }
+  void setCallerNode(GraphNode* n) { _fromNode = n; }
+  void setCallingNode(GraphNode* n) { _toNode = n; }
+
+  // keyboard navigation
+  TraceFunction* visibleCaller();
+  TraceFunction* visibleCalling();
+  TraceCall* nextVisible();
+  TraceCall* priorVisible();
+
+  double cost, count;
+
+ private:
+  // we have a _c *and* _from/_to because for collapsed edges,
+  // only _to or _from will be unequal NULL
+  TraceCall* _c;
+  TraceFunction * _from, * _to;
+  GraphNode *_fromNode, *_toNode;
+  CanvasEdge* _ce;
+  bool _visible;
+  // for keyboard navigation: have we last reached this edge via a caller?
+  bool _lastFromCaller;
+
+};
+
+
+typedef TQMap<TraceFunction*, GraphNode> GraphNodeMap;
+typedef TQMap<TQPair<TraceFunction*, TraceFunction*>, GraphEdge> GraphEdgeMap;
+
+
+/* Abstract Interface for graph options */
+class GraphOptions
+{
+ public:
+    enum Layout { TopDown, LeftRight, Circular};
+
+    virtual double funcLimit() = 0;
+    virtual double callLimit() = 0;
+    virtual int maxCallerDepth() = 0;
+    virtual int maxCallingDepth() = 0;
+    virtual bool showSkipped() = 0;
+    virtual bool expandCycles() = 0;
+    virtual bool clusterGroups() = 0;
+    virtual int detailLevel() = 0;
+    virtual Layout layout() = 0;
+
+    static TQString layoutString(Layout);
+    static Layout layout(TQString);
+};
+
+/* Graph Options Storage */
+class StorableGraphOptions: public GraphOptions
+{
+ public:
+    StorableGraphOptions();
+
+    // implementation of getters
+    virtual double funcLimit() { return _funcLimit; }
+    virtual double callLimit() { return _callLimit; }
+    virtual int maxCallerDepth() { return _maxCallerDepth; }
+    virtual int maxCallingDepth() { return _maxCallingDepth; }
+    virtual bool showSkipped() { return _showSkipped; }
+    virtual bool expandCycles() { return _expandCycles; }
+    virtual bool clusterGroups() { return _clusterGroups; }
+    virtual int detailLevel() { return _detailLevel; }
+    virtual Layout layout() { return _layout; }
+
+    // setters
+    void setMaxCallerDepth(int d) { _maxCallerDepth = d; }
+    void setMaxCallingDepth(int d) { _maxCallingDepth = d; }
+    void setFuncLimit(double l) { _funcLimit = l; }
+    void setCallLimit(double l) { _callLimit = l; }
+    void setShowSkipped(bool b) { _showSkipped = b; }
+    void setExpandCycles(bool b) { _expandCycles = b; }
+    void setClusterGroups(bool b) { _clusterGroups = b; }
+    void setDetailLevel(int l) { _detailLevel = l; }
+    void setLayout(Layout l) { _layout = l; }
+
+ protected:
+    double _funcLimit, _callLimit;
+    int _maxCallerDepth, _maxCallingDepth;
+    bool _showSkipped, _expandCycles, _clusterGroups;
+    int _detailLevel;
+    Layout _layout;
+};
+
+/**
+ * GraphExporter
+ *
+ * Generates a graph file for "dot"
+ * Create an instance and
+ */
+class GraphExporter: public StorableGraphOptions
+{
+public:
+  GraphExporter();
+  GraphExporter(TraceData*, TraceFunction*, TraceCostType*,
+		TraceItem::CostType, TQString filename = TQString());
+  virtual ~GraphExporter();
+
+  void reset(TraceData*, TraceItem*, TraceCostType*,
+	     TraceItem::CostType, TQString filename = TQString());
+
+  TQString filename() { return _dotName; }
+  int edgeCount() { return _edgeMap.count(); }
+  int nodeCount() { return _nodeMap.count(); }
+
+  // Set the object from which to get graph options for creation.
+  // Default is this object itself (supply 0 for default)
+  void setGraphOptions(GraphOptions* go = 0);
+
+  // Create a subgraph with given limits/maxDepths
+  void createGraph();
+
+  // calls createGraph before dumping of not already created
+  void writeDot();
+
+  // to map back to structures when parsing a layouted graph
+
+  /* <toFunc> is a helper for node() and edge().
+   * Don't use the returned pointer directly, but only with
+   * node() or edge(), because it could be a dangling pointer.
+   */
+  TraceFunction* toFunc(TQString);
+  GraphNode* node(TraceFunction*);
+  GraphEdge* edge(TraceFunction*, TraceFunction*);
+
+  /* After CanvasEdges are attached to GraphEdges, we can
+   * sort the incoming and outgoing edges of all nodes
+   * regarding start/end points for keyboard navigation
+   */
+  void sortEdges();
+
+private:
+  void buildGraph(TraceFunction*, int, bool, double);
+
+  TQString _dotName;
+  TraceItem* _item;
+  TraceCostType* _costType;
+  TraceItem::CostType _groupType;
+  KTempFile* _tmpFile;
+  double _realFuncLimit, _realCallLimit;
+  int _maxDepth;
+  bool _graphCreated;
+
+  GraphOptions* _go;
+
+  // optional graph attributes
+  bool _useBox;
+
+  // graph parts written to file
+  GraphNodeMap _nodeMap;
+  GraphEdgeMap _edgeMap;
+};
+
+/**
+ * A panner layed over a TQCanvas
+ */
+class PannerView: public TQCanvasView
+{
+  Q_OBJECT
+  TQ_OBJECT
+
+public:
+  PannerView(TQWidget * parent = 0, const char * name = 0);
+
+  void setZoomRect(TQRect r);
+
+signals:
+  void zoomRectMoved(int dx, int dy);
+  void zoomRectMoveFinished();
+
+protected:
+  void contentsMousePressEvent(TQMouseEvent*);
+  void contentsMouseMoveEvent(TQMouseEvent*);
+  void contentsMouseReleaseEvent(TQMouseEvent*);
+  void drawContents(TQPainter * p, int clipx, int clipy, int clipw, int cliph);
+
+  TQRect _zoomRect;
+  bool _movingZoomRect;
+  TQPoint _lastPos;
+};
+
+
+/*
+ * Canvas Items:
+ * - CanvasNode       (Rectangular Area)
+ * - CanvasEdge       (Spline curve)
+ * - CanvasEdgeLabel  (Label for edges)
+ * - CanvasEdgeArrow  (Arrows at the end of the edge spline)
+ * - CanvasFrame      (Grey background blending to show active node)
+ */
+
+enum {
+    CANVAS_NODE = 1122,
+    CANVAS_EDGE, CANVAS_EDGELABEL, CANVAS_EDGEARROW,
+    CANVAS_FRAME
+};
+
+class CanvasNode: public TQCanvasRectangle, public StoredDrawParams
+{
+public:
+  CanvasNode(CallGraphView*,GraphNode*, int, int, int, int, TQCanvas*);
+
+  void updateGroup();
+  void setSelected(bool);
+  void drawShape(TQPainter&);
+
+  GraphNode* node() { return _node; }
+  int rtti() const { return CANVAS_NODE; }
+
+private:
+  GraphNode* _node;
+  CallGraphView* _view;
+};
+
+class CanvasEdgeLabel: public TQCanvasRectangle, public StoredDrawParams
+{
+public:
+  CanvasEdgeLabel(CallGraphView*, CanvasEdge*, int, int, int, int, TQCanvas*);
+
+  void drawShape(TQPainter&);
+
+  CanvasEdge* canvasEdge() { return _ce; }
+  int rtti() const { return CANVAS_EDGELABEL; }
+
+private:
+  CanvasEdge* _ce;
+  CallGraphView* _view;
+};
+
+class CanvasEdgeArrow: public TQCanvasPolygon
+{
+public:
+  CanvasEdgeArrow(CanvasEdge*, TQCanvas*);
+
+  void drawShape(TQPainter&);
+
+  CanvasEdge* canvasEdge() { return _ce; }
+  int rtti() const { return CANVAS_EDGEARROW; }
+
+private:
+  CanvasEdge* _ce;
+};
+
+
+class CanvasEdge: public TQCanvasSpline
+{
+public:
+  CanvasEdge(GraphEdge*, TQCanvas*);
+
+  void setSelected(bool);
+  void drawShape(TQPainter&);
+  TQPointArray areaPoints() const;
+
+  CanvasEdgeLabel* label() { return _label; }
+  void setLabel(CanvasEdgeLabel* l) { _label = l; }
+  CanvasEdgeArrow* arrow() { return _arrow; }
+  void setArrow(CanvasEdgeArrow* a) { _arrow = a; }
+
+  GraphEdge* edge() { return _edge; }
+  int rtti() const { return CANVAS_EDGE; }
+
+private:
+  GraphEdge* _edge;
+  CanvasEdgeLabel* _label;
+  CanvasEdgeArrow* _arrow;
+};
+
+
+class CanvasFrame: public TQCanvasRectangle
+{
+public:
+  CanvasFrame( CanvasNode*, TQCanvas *canvas );
+  int rtti () const { return CANVAS_FRAME; }
+  bool hit( const TQPoint&) const { return false; }
+protected:
+    void drawShape( TQPainter & );
+private:
+    static TQPixmap* _p;
+};
+
+
+class CallGraphTip;
+
+/**
+ * A CanvasView showing a part of the call graph
+ * and another zoomed out CanvasView in a border acting as
+ * a panner to select to visible part (only if needed)
+ */
+class CallGraphView: public TQCanvasView,  public TraceItemView,
+		     public StorableGraphOptions
+{
+ Q_OBJECT
+  TQ_OBJECT
+
+public:
+ enum ZoomPosition { TopLeft, TopRight, BottomLeft, BottomRight, Auto };
+
+  CallGraphView(TraceItemView* parentView,
+                TQWidget* parent=0, const char* name=0);
+  ~CallGraphView();
+
+  void readViewConfig(KConfig*, TQString prefix, TQString postfix, bool);
+  void saveViewConfig(KConfig*, TQString prefix, TQString postfix, bool);
+
+  TQWidget* widget() { return this; }
+  TQString whatsThis() const;
+
+  ZoomPosition zoomPos() const { return _zoomPosition; }
+  static ZoomPosition zoomPos(TQString);
+  static TQString zoomPosString(ZoomPosition);
+
+public slots:
+  void contentsMovingSlot(int,int);
+  void zoomRectMoved(int,int);
+  void zoomRectMoveFinished();
+
+  void showRenderWarning();
+  void stopRendering();
+  void readDotOutput();
+  void dotExited();
+
+protected:
+  void resizeEvent(TQResizeEvent*);
+  void contentsMousePressEvent(TQMouseEvent*);
+  void contentsMouseMoveEvent(TQMouseEvent*);
+  void contentsMouseReleaseEvent(TQMouseEvent*);
+  void contentsMouseDoubleClickEvent(TQMouseEvent*);
+  void contentsContextMenuEvent(TQContextMenuEvent*);
+  void keyPressEvent(TQKeyEvent*);
+  void focusInEvent(TQFocusEvent*);
+  void focusOutEvent(TQFocusEvent*);
+
+private:
+  void updateSizes(TQSize s = TQSize(0,0));
+  TraceItem* canShow(TraceItem*);
+  void doUpdate(int);
+  void refresh();
+  void makeFrame(CanvasNode*, bool active);
+  void clear();
+  void showText(TQString);
+
+  TQCanvas *_canvas;
+  int _xMargin, _yMargin;
+  PannerView *_completeView;
+  double _cvZoom;
+
+  CallGraphTip* _tip;
+
+  bool _isMoving;
+  TQPoint _lastPos;
+
+  GraphExporter _exporter;
+
+  GraphNode* _selectedNode;
+  GraphEdge* _selectedEdge;
+
+  // widget options
+  ZoomPosition _zoomPosition, _lastAutoPosition;
+
+  // background rendering
+  TQProcess* _renderProcess;
+  TQTimer _renderTimer;
+  GraphNode* _prevSelectedNode;
+  TQPoint _prevSelectedPos;
+  TQString _unparsedOutput;
+};
+
+
+
+
+#endif
+
+
+
diff --git a/kdecachegrind/kdecachegrind/callitem.cpp b/kdecachegrind/kdecachegrind/callitem.cpp
new file mode 100644
index 0000000..ebca490
--- /dev/null
+++ b/kdecachegrind/kdecachegrind/callitem.cpp
@@ -0,0 +1,185 @@
+/* This file is part of KCachegrind.
+   Copyright (C) 2002, 2003 Josef Weidendorfer <Josef.Weidendorfer@gmx.de>
+
+   KCachegrind 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, version 2.
+
+   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; see the file COPYING.  If not, write to
+   the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+   Boston, MA 02110-1301, USA.
+*/
+
+/*
+ * Items for caller/callee view.
+ */
+
+#include <tqpixmap.h>
+#include <klocale.h>
+#include <kapplication.h>
+#include <kiconloader.h>
+
+#include "configuration.h"
+#include "listutils.h"
+#include "callitem.h"
+#include "callview.h"
+#include "toplevel.h"
+
+// CallItem
+
+
+CallItem::CallItem(CallView* view, TQListView* parent, TraceCall* c)
+    : TQListViewItem(parent)
+{
+  _call = c;
+  _view = view;
+
+  _active = _view->activeFunction();
+  bool baseIsCycle = (_active && (_active == _active->cycle()));
+
+  TQString fName;
+  if (_view->showCallers()) {
+      _shown = _call->caller(true);
+      fName  = c->callerName(!baseIsCycle);
+  }
+  else {
+      _shown = _call->called(true);
+      fName = c->calledName(!baseIsCycle);
+  }
+
+  _shown->addPrettyLocation(fName);
+
+  setText(3, fName);
+  updateGroup();
+  updateCost();
+}
+
+void  CallItem::updateGroup()
+{
+  TQColor c = Configuration::functionColor(_view->groupType(), _shown);
+  setPixmap(3, colorPixmap(10, 10, c));
+}
+
+void CallItem::updateCost()
+{
+    bool sameCycle = _shown->cycle() && (_active->cycle() == _shown->cycle());
+    bool shownIsCycle = (_shown == _shown->cycle());
+    bool selectedIsCycle = (_active == _active->cycle());
+    if (_call->isRecursion()) sameCycle=true;
+
+    TQString cStr;
+    if ((selectedIsCycle || shownIsCycle) && sameCycle)
+	cStr = "-";
+    else {
+	_cc  = _call->callCount();
+	if (_cc == 0)
+	    cStr = i18n("(active)");
+	else
+	    cStr = _call->prettyCallCount();
+    }
+    setText(2, cStr);
+
+    TraceCost* totalCost;
+    if (_view->topLevel()->showExpanded()) {
+      if (_active->cycle())
+        totalCost = _active->cycle()->inclusive();
+      else
+	totalCost = _active->inclusive();
+    }
+    else
+	totalCost = _active->data();
+
+    TraceCostType* ct = _view->costType();
+    _sum = _call->subCost(ct);
+    double total = totalCost->subCost(ct);
+
+    if (total == 0.0) {
+	TQString str = "-";
+
+	setText(0, str);
+	setPixmap(0, TQPixmap());
+    }
+    else {
+	double sum  = 100.0 * _sum / total;
+
+	if (_view->topLevel()->showPercentage())
+	    setText(0, TQString("%1")
+		    .arg(sum, 0, 'f', Configuration::percentPrecision()));
+	else
+	    setText(0, _call->prettySubCost(ct));
+
+	setPixmap(0, costPixmap(ct, _call, total, false));
+    }
+
+    // Cost Type 2
+    TraceCostType* ct2 = _view->costType2();
+    if (ct2) {
+      _sum2 = _call->subCost(ct2);
+      double total = totalCost->subCost(ct2);
+
+      if (total == 0.0) {
+	TQString str = "-";
+
+	setText(1, str);
+	setPixmap(1, TQPixmap());
+      }
+      else {
+	double sum  = 100.0 * _sum2 / total;
+	
+	if (_view->topLevel()->showPercentage())
+	  setText(1, TQString("%1")
+		  .arg(sum, 0, 'f', Configuration::percentPrecision()));
+	else
+	  setText(1, _call->prettySubCost(ct2));
+
+	setPixmap(1, costPixmap(ct2, _call, total, false));
+      }
+    }
+
+    TQPixmap p;
+    if (sameCycle && !selectedIsCycle && !shownIsCycle) {
+
+	TQString icon = "undo";
+	KIconLoader* loader = KApplication::kApplication()->iconLoader();
+	p= loader->loadIcon(icon, KIcon::Small, 0,
+			    KIcon::DefaultState, 0, true);
+    }
+    setPixmap(2, p);
+}
+
+
+int CallItem::compare(TQListViewItem * i, int col, bool ascending ) const
+{
+  const CallItem* ci1 = this;
+  const CallItem* ci2 = (CallItem*) i;
+
+  // we always want descending order
+  if (ascending) {
+    ci1 = ci2;
+    ci2 = this;
+  }
+
+  if (col==0) {
+    if (ci1->_sum < ci2->_sum) return -1;
+    if (ci1->_sum > ci2->_sum) return 1;
+    return 0;
+  }
+  if (col==1) {
+    if (ci1->_sum2 < ci2->_sum2) return -1;
+    if (ci1->_sum2 > ci2->_sum2) return 1;
+    return 0;
+  }
+  if (col==2) {
+    if (ci1->_cc < ci2->_cc) return -1;
+    if (ci1->_cc > ci2->_cc) return 1;
+    return 0;
+  }
+  return TQListViewItem::compare(i, col, ascending);
+}
+
diff --git a/kdecachegrind/kdecachegrind/callitem.h b/kdecachegrind/kdecachegrind/callitem.h
new file mode 100644
index 0000000..94191b8
--- /dev/null
+++ b/kdecachegrind/kdecachegrind/callitem.h
@@ -0,0 +1,50 @@
+/* This file is part of KCachegrind.
+   Copyright (C) 2003 Josef Weidendorfer <Josef.Weidendorfer@gmx.de>
+
+   KCachegrind 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, version 2.
+
+   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; see the file COPYING.  If not, write to
+   the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+   Boston, MA 02110-1301, USA.
+*/
+
+/*
+ * Items of call view.
+ */
+
+#ifndef CALLITEM_H
+#define CALLITEM_H
+
+#include <tqlistview.h>
+#include "tracedata.h"
+
+class CallView;
+
+class CallItem: public TQListViewItem
+{
+public:
+    CallItem(CallView*, TQListView*, TraceCall* c);
+
+    int compare(TQListViewItem * i, int col, bool ascending ) const;
+    TraceCall* call() { return _call; }
+    CallView* view() { return _view; }
+    void updateCost();
+    void updateGroup();
+
+private:
+    SubCost _sum, _sum2;
+    SubCost _cc;
+    TraceCall* _call;
+    CallView* _view;
+    TraceFunction *_active, *_shown;
+};
+
+#endif
diff --git a/kdecachegrind/kdecachegrind/callmapview.cpp b/kdecachegrind/kdecachegrind/callmapview.cpp
new file mode 100644
index 0000000..0e4d5e3
--- /dev/null
+++ b/kdecachegrind/kdecachegrind/callmapview.cpp
@@ -0,0 +1,999 @@
+/* This file is part of KCachegrind.
+   Copyright (C) 2003 Josef Weidendorfer <Josef.Weidendorfer@gmx.de>
+
+   KCachegrind 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, version 2.
+
+   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; see the file COPYING.  If not, write to
+   the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+   Boston, MA 02110-1301, USA.
+*/
+
+/*
+ * Call Map View
+ */
+
+#include <tqwhatsthis.h>
+#include <tqpopupmenu.h>
+
+#include <klocale.h>
+#include <kiconloader.h>
+#include <kapplication.h>
+#include <kconfig.h>
+
+#include "callmapview.h"
+#include "configuration.h"
+#include "listutils.h"
+#include "toplevel.h"
+
+//
+// CallMapView
+//
+
+
+// defaults
+#define DEFAULT_SPLITMODE    "Rows"
+#define DEFAULT_DRAWNAME     true
+#define DEFAULT_DRAWCOST     true
+#define DEFAULT_DRAWLOCATION false
+#define DEFAULT_DRAWCALLS    false
+#define DEFAULT_FORCESTRINGS false
+#define DEFAULT_ROTATION     true
+#define DEFAULT_SHADING      true
+#define DEFAULT_MAXAREA      100
+
+
+CallMapView::CallMapView(bool showCallers, TraceItemView* parentView,
+                         TQWidget* parent, const char* name)
+  : TreeMapWidget(new CallMapBaseItem(), parent, name),  TraceItemView(parentView)
+{
+  _showCallers = showCallers;
+
+  setFieldType(0, i18n( "Name" ));
+  setFieldType(1, i18n( "Cost" ));
+  setFieldType(2, i18n( "Location" ));
+  setFieldPosition(2, TreeMapItem::TopLeft);
+  setFieldType(3, i18n( "Calls" ));
+  setFieldPosition(3, TreeMapItem::TopRight);
+
+  setSplitMode(DEFAULT_SPLITMODE);
+  setFieldVisible(0, DEFAULT_DRAWNAME);
+  setFieldVisible(1, DEFAULT_DRAWCOST);
+  setFieldVisible(2, DEFAULT_DRAWLOCATION);
+  setFieldVisible(3, DEFAULT_DRAWCALLS);
+  setFieldForced(0, DEFAULT_FORCESTRINGS);
+  setFieldForced(1, DEFAULT_FORCESTRINGS);
+  setFieldForced(2, DEFAULT_FORCESTRINGS);
+  setFieldForced(3, DEFAULT_FORCESTRINGS);
+  setAllowRotation(DEFAULT_ROTATION);
+  setShadingEnabled(DEFAULT_SHADING);
+  setMinimalArea(DEFAULT_MAXAREA);
+
+  connect(this,
+          TQT_SIGNAL(doubleClicked(TreeMapItem*)),
+          TQT_SLOT(activatedSlot(TreeMapItem*)));
+  connect(this,
+          TQT_SIGNAL(returnPressed(TreeMapItem*)),
+          TQT_SLOT(activatedSlot(TreeMapItem*)));
+  connect(this,
+          TQT_SIGNAL(currentChanged(TreeMapItem*, bool)),
+          TQT_SLOT(selectedSlot(TreeMapItem*, bool)));
+  connect(this,
+          TQT_SIGNAL(contextMenuRequested(TreeMapItem*,const TQPoint &)),
+          TQT_SLOT(context(TreeMapItem*,const TQPoint &)));
+
+  TQWhatsThis::add( this, whatsThis());
+}
+
+TQString CallMapView::whatsThis() const
+{
+  TQString s = _showCallers ?
+              i18n( "<b>Caller Map</b>"
+                    "<p>This graph shows the nested hierarchy of "
+                    "all callers of the current activated function. "
+                    "Each colored rectangle represents a function; "
+                    "its size tries to be proportional to the cost spent "
+                    "therein while the active function is running "
+                    "(however, there are drawing constrains).</p>") :
+              i18n("<b>Call Map</b>"
+                   "<p>This graph shows the nested hierarchy of "
+                   "all callees of the current activated function. "
+                   "Each colored rectangle represents a function; "
+                   "its size tries to be proportional to the cost spent "
+                   "therein while the active function is running "
+                   "(however, there are drawing constrains).</p>");
+
+  s += i18n( "<p>Appearance options can be found in the "
+             "in the context menu. To get exact size proportions, "
+             "choose 'Hide incorrect borders'. As this mode can be "
+             "<em>very</em> time consuming, you may want to limit "
+             "the maximum drawn nesting level before. "
+             "'Best' determinates the split direction for children "
+             "from the aspect ratio of the parent. "
+             "'Always Best' decides on remaining space for each "
+             "sibling. "
+             "'Ignore Proportions' takes space for function name "
+             "drawing <em>before</em> drawing children. Note that "
+             "size proportions can get <em>heavily</em> wrong.</p>"
+
+             "<p>This is a <em>TreeMap</em> widget. "
+             "Keyboard navigation is available with the left/right arrow "
+             "keys for traversing siblings, and up/down arrow keys "
+             "to go a nesting level up/down. "
+             "<em>Return</em> activates the current item.</p>");
+
+  return s;
+}
+
+void CallMapView::setData(TraceData* d)
+{
+  TraceItemView::setData(d);
+
+  ((CallMapBaseItem*)base())->setFunction(0);
+}
+
+void CallMapView::context(TreeMapItem* i,const TQPoint & p)
+{
+  if (!i) return;
+
+  TQPopupMenu popup;
+  TQPopupMenu fpopup; // select function subpopup
+  TQPopupMenu vpopup; // visualisation subpopup
+  TQPopupMenu dpopup; // split direction
+  TQPopupMenu bpopup; // border subpopup
+  TQPopupMenu l1popup; // depth limit subpopup
+  TQPopupMenu l2popup; // function limit subpopup
+  TQPopupMenu l3popup; // area limit subpopup
+
+  TreeMapItem* item = i;
+  int count;
+
+  TQString shortCurrentName;
+  if (i) {
+    shortCurrentName = i->text(0);
+    if ((int)shortCurrentName.length() > Configuration::maxSymbolLength())
+      shortCurrentName =
+        shortCurrentName.left(Configuration::maxSymbolLength()) + "...";
+  }
+
+  if (item) {
+    popup.insertItem(i18n("Go To"), &fpopup, 100);
+    count = 0;
+    while (count<Configuration::maxSymbolCount() && item) {
+      TQString name = item->text(0);
+      if ((int)name.length()>Configuration::maxSymbolLength())
+        name = name.left(Configuration::maxSymbolLength()) + "...";
+      fpopup.insertItem(name, 101+count);
+      item = item->parent();
+      count++;
+    }
+    popup.insertSeparator();
+  }
+
+  addGoMenu(&popup);
+  popup.insertSeparator();
+
+  l1popup.setCheckable(true);
+  popup.insertItem(i18n("Stop at Depth"), &l1popup, 12);
+
+  int maxDepth = maxDrawingDepth();
+  l1popup.insertItem(i18n("No Depth Limit"), 50);
+  l1popup.setItemChecked(50, maxDepth==-1);
+  l1popup.insertSeparator();
+  l1popup.insertItem(i18n("Depth 10"), 51);
+  l1popup.setItemChecked(51, maxDepth==10);
+  l1popup.insertItem(i18n("Depth 15"), 52);
+  l1popup.setItemChecked(52, maxDepth==15);
+  l1popup.insertItem(i18n("Depth 20"), 53);
+  l1popup.setItemChecked(53, maxDepth==20);
+  if (i) {
+    l1popup.insertSeparator();
+    l1popup.insertItem(i18n("Depth of '%1' (%2)")
+                       .arg(shortCurrentName).arg(i->depth()), 55);
+    l1popup.setItemChecked(55, maxDepth == i->depth());
+  }
+  if (maxDepth>0) {
+    l1popup.insertSeparator();
+    l1popup.insertItem(i18n("Decrement Depth (to %1)").arg(maxDepth-1), 56);
+    l1popup.insertItem(i18n("Increment Depth (to %1)").arg(maxDepth+1), 57);
+  }
+
+  l2popup.setCheckable(true);
+  popup.insertItem(i18n("Stop at Function"), &l2popup, 13);
+  l2popup.insertItem(i18n("No Function Limit"), 200);
+  l2popup.setItemChecked(200, fieldStop(0).isEmpty());
+  bool foundStopName = false;
+  item = i;
+  if (i) {
+    l2popup.insertSeparator();
+    count = 0;
+    while (count<Configuration::maxSymbolCount() && item) {
+      TQString name = item->text(0);
+      if ((int)name.length()>Configuration::maxSymbolLength())
+        name = name.left(Configuration::maxSymbolLength()) + "...";
+      l2popup.insertItem(name, 201+count);
+      if (item->text(0) == fieldStop(0)) {
+        l2popup.setItemChecked(201+count, true);
+        foundStopName = true;
+      }
+      item = item->parent();
+      count++;
+    }
+  }
+  if (!foundStopName && !fieldStop(0).isEmpty()) {
+    l2popup.insertSeparator();
+    TQString name = fieldStop(0);
+    if ((int)name.length()>Configuration::maxSymbolLength())
+      name = name.left(Configuration::maxSymbolLength()) + "...";
+    l2popup.insertItem(name, 199);
+    l2popup.setItemChecked(199, true);
+  }
+
+  l3popup.setCheckable(true);
+  popup.insertItem(i18n("Stop at Area"), &l3popup, 14);
+
+  int mArea = minimalArea();
+  l3popup.insertItem(i18n("No Area Limit"), 60);
+  l3popup.setItemChecked(60, mArea ==-1);
+  l3popup.insertSeparator();
+  l3popup.insertItem(i18n("50 Pixels"), 63);
+  l3popup.setItemChecked(63, mArea==50);
+  l3popup.insertItem(i18n("100 Pixels"), 64);
+  l3popup.setItemChecked(64, mArea==100);
+  l3popup.insertItem(i18n("200 Pixels"), 65);
+  l3popup.setItemChecked(65, mArea==200);
+  l3popup.insertItem(i18n("500 Pixels"), 66);
+  l3popup.setItemChecked(66, mArea==500);
+  int currentArea = 0;
+  if (i) {
+    currentArea = i->width() * i->height();
+    l3popup.insertSeparator();
+    l3popup.insertItem(i18n("Area of '%1' (%2)")
+                       .arg(shortCurrentName).arg(currentArea), 67);
+    l3popup.setItemChecked(67, mArea == currentArea);
+  }
+  if (mArea>0) {
+    l3popup.insertSeparator();
+    l3popup.insertItem(i18n("Double Area Limit (to %1)")
+                       .arg(mArea*2), 68);
+    l3popup.insertItem(i18n("Half Area Limit (to %1)")
+                       .arg(mArea/2), 69);
+  }
+
+  popup.insertSeparator();
+
+  vpopup.setCheckable(true);
+  popup.insertItem(i18n("Visualisation"), &vpopup, 10);
+
+  TQPopupMenu splitpopup;
+  addSplitDirectionItems(&splitpopup, 1001);
+  vpopup.insertItem(i18n("Split Direction"), &splitpopup, 1000);
+
+  vpopup.insertItem(i18n("Skip Incorrect Borders"), 40);
+  vpopup.setItemEnabled(40, !_showCallers);
+  vpopup.setItemChecked(40, skipIncorrectBorder());
+
+  bpopup.setCheckable(true);
+  vpopup.insertItem(i18n("Border Width"), &bpopup, 41);
+  bpopup.insertItem(i18n("Border 0"), 42);
+  bpopup.setItemEnabled(42, !_showCallers);
+  bpopup.setItemChecked(42, borderWidth()==0);
+  bpopup.insertItem(i18n("Border 1"), 43);
+  bpopup.setItemChecked(43, borderWidth()==1);
+  bpopup.insertItem(i18n("Border 2"), 44);
+  bpopup.setItemChecked(44, borderWidth()==2);
+  bpopup.insertItem(i18n("Border 3"), 45);
+  bpopup.setItemChecked(45, borderWidth()==3);
+
+  vpopup.insertSeparator();
+
+  vpopup.insertItem(i18n("Draw Symbol Names"), 20);
+  vpopup.insertItem(i18n("Draw Cost"), 21);
+  vpopup.insertItem(i18n("Draw Location"), 22);
+  vpopup.insertItem(i18n("Draw Calls"), 23);
+  vpopup.insertSeparator();
+
+  vpopup.insertItem(i18n("Ignore Proportions"), 24);
+  vpopup.insertItem(i18n("Allow Rotation"), 25);
+  if (!fieldVisible(0) &&
+      !fieldVisible(1) &&
+      !fieldVisible(2) &&
+      !fieldVisible(3)) {
+    vpopup.setItemEnabled(24, false);
+    vpopup.setItemEnabled(25, false);
+  }
+  else {
+    vpopup.setItemChecked(20,fieldVisible(0));
+    vpopup.setItemChecked(21,fieldVisible(1));
+    vpopup.setItemChecked(22,fieldVisible(2));
+    vpopup.setItemChecked(23,fieldVisible(3));
+    vpopup.setItemChecked(24,fieldForced(0));
+    vpopup.setItemChecked(25,allowRotation());
+  }
+
+  vpopup.insertItem(i18n("Shading"), 26);
+  vpopup.setItemChecked(26,isShadingEnabled());
+
+  int r = popup.exec(mapToGlobal(p));
+
+  if (r>100 && r<150) {
+    r -= 100;
+    while (i && (r>1)) {
+      i=i->parent();
+      r--;
+    }
+    activatedSlot(i);
+    return;
+  }
+
+  if (r>200 && r<250) {
+    r -= 200;
+    while (i && (r>1)) {
+      i=i->parent();
+      r--;
+    }
+    if (i)
+      setFieldStop(0, i->text(0));
+
+    return;
+  }
+
+  switch(r) {
+  case 20:
+    setFieldVisible(0, !vpopup.isItemChecked(20));
+    break;
+
+  case 21:
+    setFieldVisible(1, !vpopup.isItemChecked(21));
+    break;
+
+  case 22:
+    setFieldVisible(2, !vpopup.isItemChecked(22));
+    break;
+
+  case 23:
+    setFieldVisible(3, !vpopup.isItemChecked(23));
+    break;
+
+  case 24:
+    setFieldForced(0, !vpopup.isItemChecked(24));
+    setFieldForced(1, !vpopup.isItemChecked(24));
+    setFieldForced(2, !vpopup.isItemChecked(24));
+    setFieldForced(3, !vpopup.isItemChecked(24));
+    break;
+
+  case 25: setAllowRotation(!vpopup.isItemChecked(25)); break;
+  case 26: setShadingEnabled(!vpopup.isItemChecked(26)); break;
+
+  case 40:
+    setSkipIncorrectBorder(!vpopup.isItemChecked(40));
+    break;
+
+  case 42: setBorderWidth(0); break;
+  case 43: setBorderWidth(1); break;
+  case 44: setBorderWidth(2); break;
+  case 45: setBorderWidth(3); break;
+
+  case 50: setMaxDrawingDepth(-1); break;
+  case 51: setMaxDrawingDepth(10); break;
+  case 52: setMaxDrawingDepth(15); break;
+  case 53: setMaxDrawingDepth(20); break;
+  case 55: setMaxDrawingDepth(i->depth()); break;
+  case 56: setMaxDrawingDepth(maxDepth-1); break;
+  case 57: setMaxDrawingDepth(maxDepth+1); break;
+
+  case 200: setFieldStop(0, TQString()); break;
+
+  case 60: setMinimalArea(-1); break;
+  case 61: setMinimalArea(10); break;
+  case 62: setMinimalArea(20); break;
+  case 63: setMinimalArea(50); break;
+  case 64: setMinimalArea(100); break;
+  case 65: setMinimalArea(200); break;
+  case 66: setMinimalArea(500); break;
+  case 67: setMinimalArea(currentArea); break;
+  case 68: setMinimalArea(mArea*2); break;
+  case 69: setMinimalArea(mArea/2); break;
+  }
+}
+
+void CallMapView::activatedSlot(TreeMapItem* item)
+{
+  if (!item) return;
+
+  if (item->rtti() == 1) {
+    CallMapBaseItem* bi = (CallMapBaseItem*)item;
+    activated(bi->function());
+  }
+  else if (item->rtti() == 2) {
+    CallMapCallingItem* ci = (CallMapCallingItem*)item;
+    activated(ci->function());
+  }
+  else if (item->rtti() == 3) {
+    CallMapCallerItem* ci = (CallMapCallerItem*)item;
+    activated(ci->function());
+  }
+}
+
+void CallMapView::selectedSlot(TreeMapItem* item, bool kbd)
+{
+  if (!item) return;
+  if (item->text(0).isEmpty()) return;
+
+  if (kbd) {
+      TQString msg = i18n("Call Map: Current is '%1'").arg(item->text(0));
+      if (_topLevel)
+	  _topLevel->showMessage(msg, 5000);
+  }
+
+  TraceFunction* f = 0;
+
+  if (item->rtti() == 1) {
+    CallMapBaseItem* bi = (CallMapBaseItem*)item;
+    f = bi->function();
+  }
+  else if (item->rtti() == 2) {
+    CallMapCallingItem* ci = (CallMapCallingItem*)item;
+    f = ci->function();
+  }
+  else if (item->rtti() == 3) {
+    CallMapCallerItem* ci = (CallMapCallerItem*)item;
+    f = ci->function();
+  }
+  if (f) {
+      // this avoids marking
+      _selectedItem = f;
+      selected(f);
+  }
+}
+
+TraceItem* CallMapView::canShow(TraceItem* i)
+{
+  TraceItem::CostType t = i ? i->type() : TraceItem::NoCostType;
+
+  switch(t) {
+  case TraceItem::Function:
+  case TraceItem::FunctionCycle:
+      return i;
+  default:
+      break;
+  }
+  return 0;
+}
+
+void CallMapView::doUpdate(int changeType)
+{
+    if (changeType == costType2Changed) return;
+
+    // if there is a selected item, always draw marking...
+    if (changeType & selectedItemChanged) {
+	TraceFunction* f = 0;
+
+	if (_selectedItem) {
+	    switch(_selectedItem->type()) {
+	    case TraceItem::Function:
+	    case TraceItem::FunctionCycle:
+		f = (TraceFunction*)_selectedItem;
+		break;
+	    default:
+		break;
+	    }
+	}
+	// if this is the only change...
+	if (changeType == selectedItemChanged) {
+	    setMarked(f ? 1:0, true);
+	    return;
+	}
+	setMarked(f ? 1:0, false);
+    }
+
+
+  if (changeType & activeItemChanged) {
+      TraceFunction* f = 0;
+
+      if (_activeItem) {
+	  switch(_activeItem->type()) {
+	  case TraceItem::Function:
+	  case TraceItem::FunctionCycle:
+	      f = (TraceFunction*)_activeItem;
+	      break;
+	  default:
+	      break;
+	  }
+      }
+      ((CallMapBaseItem*)base())->setFunction(f);
+  }
+  else if ( ((changeType & partsChanged) && Configuration::showCycles()) ||
+            (changeType & dataChanged) ||
+            (changeType & configChanged)) {
+    /* regenerates the treemap because traceitems were added/removed */
+    base()->refresh();
+  }
+  else if ((changeType & partsChanged) ||
+           (changeType & costTypeChanged)) {
+    /* we need to do the draw order sorting again as the values change */
+    resort();
+    redraw();
+  }
+  else
+    redraw();
+}
+
+
+
+TQColor CallMapView::groupColor(TraceFunction* f) const
+{
+  if (!f)
+    return colorGroup().button();
+
+  return Configuration::functionColor(_groupType, f);
+}
+
+
+TQString CallMapView::tipString(TreeMapItem* i) const
+{
+  TQString tip, itemTip;
+  int count = 0;
+
+  //qDebug("CallMapView::tipString for '%s'", i->text(0).ascii());
+
+  // first, SubPartItem's
+  while (i && count<Configuration::maxSymbolCount()) {
+    itemTip = i->text(0);
+    if ((int)itemTip.length()>Configuration::maxSymbolLength())
+      itemTip = itemTip.left(Configuration::maxSymbolLength()) + "...";
+
+    if (!i->text(1).isEmpty())
+      itemTip += " (" + i->text(1) + ")";
+
+    if (!tip.isEmpty()) tip += "\n";
+
+    tip += itemTip;
+    i = i->parent();
+    count++;
+  }
+  if (count == Configuration::maxSymbolCount()) tip += "\n...";
+
+  return tip;
+}
+
+
+TraceCost* CallMapView::totalCost()
+{
+  TraceFunction* f = ((CallMapBaseItem*)base())->function();
+  if (!f) return 0;
+
+  return Configuration::showExpanded() ? f->inclusive() : f->data();
+}
+
+
+
+
+// CallMapBaseItem
+
+CallMapBaseItem::CallMapBaseItem()
+{
+  _f = 0;
+}
+
+void CallMapBaseItem::setFunction(TraceFunction* f)
+{
+  if (f == _f) return;
+
+  _f = f;
+  refresh();
+}
+
+
+TQString CallMapBaseItem::text(int textNo) const
+{
+  if (textNo == 0) {
+    if (!_f)
+      return i18n("(no function)");
+
+    return _f->prettyName();
+  }
+
+  if (!_f) return TQString();
+
+  if (textNo == 2) return _f->prettyLocation();
+  if (textNo == 3) return _f->calledCount().pretty();
+  if (textNo != 1) return TQString();
+
+  TraceCostType* ct = ((CallMapView*)widget())->costType();
+  TraceCost* t      = ((CallMapView*)widget())->totalCost();
+
+  if (Configuration::showPercentage()) {
+      double sum, total = t->subCost(ct);
+      if (total == 0.0)
+	  sum = 100.0;
+      else
+	  sum = 100.0 * _f->inclusive()->subCost(ct) / total;
+
+      return TQString("%1 %")
+	  .arg(sum, 0, 'f', Configuration::percentPrecision());
+  }
+  return _f->inclusive()->prettySubCost(ct);
+}
+
+TQPixmap CallMapBaseItem::pixmap(int i) const
+{
+    if ((i != 1) || !_f) return TQPixmap();
+
+    TraceCostType* ct = ((CallMapView*)widget())->costType();
+    TraceCost* t      = ((CallMapView*)widget())->totalCost();
+
+    // colored level meter with frame
+    return costPixmap( ct, _f->inclusive(), (double) (t->subCost(ct)), true);
+}
+
+
+double CallMapBaseItem::value() const
+{
+  if (!_f) return 0.0;
+
+  TraceCostType* ct;
+  ct = ((CallMapView*)widget())->costType();
+  return (double) _f->inclusive()->subCost(ct);
+}
+
+
+double CallMapBaseItem::sum() const
+{
+  if (!_f) return 0.0;
+
+  CallMapView* w = (CallMapView*)widget();
+
+  if (w->showCallers())
+    return 0.0;
+  else
+    return (double) _f->inclusive()->subCost(w->costType());
+}
+
+
+bool CallMapBaseItem::isMarked(int) const
+{
+    return ((CallMapView*)widget())->selectedItem() == _f;
+}
+
+TreeMapItemList* CallMapBaseItem::children()
+{
+  if (_f && !initialized()) {
+    CallMapView* w = (CallMapView*)widget();
+
+    if (0) qDebug("Create Function %s (%s)",
+		  w->showCallers() ? "Callers":"Callees",
+		  text(0).ascii());
+
+    TraceCall* call;
+
+    setSorting(-1);
+    if (w->showCallers()) {
+      TraceCallList l = _f->callers();
+      for (call=l.first();call;call=l.next()) {
+
+        // don't show calls inside of a cycle
+        if (call->inCycle()>0) continue;
+        if (call->isRecursion()) continue;
+
+        addItem(new CallMapCallerItem(1.0, call));
+      }
+
+      setSum(0);
+    }
+    else {
+      TraceCallList l = _f->callings();
+      for (call=l.first();call;call=l.next()) {
+
+        // don't show calls inside of a cycle
+        if (call->inCycle()>0) continue;
+        if (call->isRecursion()) continue;
+
+        CallMapCallingItem* i = new CallMapCallingItem(1.0, call);
+        i->init();
+        addItem(i);
+      }
+
+      setSum(_f->inclusive()->subCost(w->costType()));
+    }
+    setSorting(-2, false);
+  }
+
+  return _children;
+}
+
+TQColor CallMapBaseItem::backColor() const
+{
+  return ((CallMapView*)widget())->groupColor(_f);
+}
+
+
+
+// CallMapCallingItems
+
+CallMapCallingItem::CallMapCallingItem(double factor, TraceCall* c)
+{
+  _factor = factor;
+  _c = c;
+}
+
+void CallMapCallingItem::init()
+{
+#if 0
+  // create assoziation: if not possible, i.e. an ass. already exists
+  // for the function, we need to draw the recursive version
+  _recursive = !setFunction(_c->called());
+  _valid = true;
+#endif
+}
+
+TQString CallMapCallingItem::text(int textNo) const
+{
+  if (textNo == 0) {
+    if (!_c)
+      return i18n("(no call)");
+
+    return _c->calledName();
+  }
+
+  if (textNo == 2) return _c->called()->prettyLocation();
+  if (textNo == 3) return SubCost(_factor * _c->callCount()).pretty();
+  if (textNo != 1) return TQString();
+
+  TraceCostType* ct;
+  ct = ((CallMapView*)widget())->costType();
+
+  SubCost val = SubCost(_factor * _c->subCost(ct));
+  if (Configuration::showPercentage()) {
+    // percentage relative to function cost
+    TraceCost* t = ((CallMapView*)widget())->totalCost();
+    double p  = 100.0 * _factor * _c->subCost(ct) / t->subCost(ct);
+    return TQString("%1 %")
+      .arg(p, 0, 'f', Configuration::percentPrecision());
+  }
+  return val.pretty();
+}
+
+TQPixmap CallMapCallingItem::pixmap(int i) const
+{
+    if (i != 1) return TQPixmap();
+
+    // Cost pixmap
+    TraceCostType* ct = ((CallMapView*)widget())->costType();
+    TraceCost* t      = ((CallMapView*)widget())->totalCost();
+
+    // colored level meter with frame
+    return costPixmap( ct, _c, t->subCost(ct) / _factor, true);
+}
+
+
+double CallMapCallingItem::value() const
+{
+  TraceCostType* ct;
+  ct = ((CallMapView*)widget())->costType();
+  return _factor * _c->subCost(ct);
+}
+
+double CallMapCallingItem::sum() const
+{
+  return value();
+}
+
+bool CallMapCallingItem::isMarked(int) const
+{
+    return ((CallMapView*)widget())->selectedItem() == _c->called();
+}
+
+
+TreeMapItemList* CallMapCallingItem::children()
+{
+  if (!initialized()) {
+    if (0) qDebug("Create Calling subitems (%s)", path(0).join("/").ascii());
+
+    TraceCostType* ct;
+    ct = ((CallMapView*)widget())->costType();
+
+    // same as sum()
+    SubCost s = _c->called()->inclusive()->subCost(ct);
+    SubCost v = _c->subCost(ct);
+    if (v>s) {
+      qDebug("Warning: CallingItem subVal %u > Sum %u (%s)",
+             (unsigned)v, (unsigned)s, _c->called()->prettyName().ascii());
+      v = s;
+    }
+    double newFactor = _factor * v / s;
+
+#if 0
+    qDebug("CallingItem: Subitems of %s => %s, factor %f * %d/%d => %f",
+               _c->caller()->prettyName().ascii(),
+               _c->called()->prettyName().ascii(),
+               _factor, v, s, newFactor);
+#endif
+    setSorting(-1);
+    TraceCall* call;
+    TraceCallList l = _c->called()->callings();
+    for (call=l.first();call;call=l.next()) {
+
+      // don't show calls inside of a cycle
+      if (call->inCycle()>0) continue;
+      if (call->isRecursion()) continue;
+
+      CallMapCallingItem* i = new CallMapCallingItem(newFactor, call);
+      i->init();
+      addItem(i);
+    }
+    setSorting(-2, false);
+  }
+
+  return _children;
+}
+
+
+TQColor CallMapCallingItem::backColor() const
+{
+  CallMapView* w = (CallMapView*)widget();
+  return w->groupColor(_c->called());
+}
+
+
+// CallMapCallerItem
+
+CallMapCallerItem::CallMapCallerItem(double factor, TraceCall* c)
+{
+  _factor = factor;
+  _c = c;
+}
+
+TQString CallMapCallerItem::text(int textNo) const
+{
+  if (textNo == 0) {
+    if (!_c)
+      return i18n("(no call)");
+
+    return _c->callerName();
+  }
+
+  if (textNo == 2) return _c->caller()->prettyLocation();
+  if (textNo == 3) return SubCost(_factor * _c->callCount()).pretty();
+  if (textNo != 1) return TQString();
+
+  TraceCostType* ct;
+  ct = ((CallMapView*)widget())->costType();
+
+  SubCost val = SubCost(_factor * _c->subCost(ct));
+  if (Configuration::showPercentage()) {
+    TraceCost* t = ((CallMapView*)widget())->totalCost();
+    double p  = 100.0 * _factor * _c->subCost(ct) / t->subCost(ct);
+    return TQString("%1 %")
+      .arg(p, 0, 'f', Configuration::percentPrecision());
+  }
+  return val.pretty();
+}
+
+
+TQPixmap CallMapCallerItem::pixmap(int i) const
+{
+    if (i != 1) return TQPixmap();
+
+    // Cost pixmap
+    TraceCostType* ct = ((CallMapView*)widget())->costType();
+    TraceCost* t      = ((CallMapView*)widget())->totalCost();
+
+    // colored level meter with frame
+    return costPixmap( ct, _c, t->subCost(ct) / _factor, true );
+}
+
+
+double CallMapCallerItem::value() const
+{
+  TraceCostType* ct;
+  ct = ((CallMapView*)widget())->costType();
+  return (double) _c->subCost(ct);
+}
+
+bool CallMapCallerItem::isMarked(int) const
+{
+    return ((CallMapView*)widget())->selectedItem() == _c->caller();
+}
+
+
+TreeMapItemList* CallMapCallerItem::children()
+{
+  if (!initialized()) {
+    //qDebug("Create Caller subitems (%s)", name().ascii());
+
+    TraceCostType* ct;
+    ct = ((CallMapView*)widget())->costType();
+
+    SubCost s = _c->caller()->inclusive()->subCost(ct);
+    SubCost v = _c->subCost(ct);
+    double newFactor = _factor * v / s;
+
+
+#if 0
+    qDebug("CallerItem: Subitems of %s => %s, factor %f * %d/%d => %f",
+           _c->caller()->prettyName().ascii(),
+           _c->called()->prettyName().ascii(),
+           _factor, v, s, newFactor);
+#endif
+    setSorting(-1);
+
+    TraceCall* call;
+    TraceCallList l = _c->caller()->callers();
+    for (call=l.first();call;call=l.next()) {
+
+      // don't show calls inside of a cycle
+      if (call->inCycle()>0) continue;
+      if (call->isRecursion()) continue;
+
+      TreeMapItem* i = new CallMapCallerItem(newFactor, call);
+      addItem(i);
+    }
+    setSorting(-2, false);
+  }
+
+  return _children;
+}
+
+TQColor CallMapCallerItem::backColor() const
+{
+  CallMapView* w = (CallMapView*)widget();
+  return w->groupColor(_c->caller());
+}
+
+void CallMapView::readViewConfig(KConfig* c,
+				 TQString prefix, TQString postfix, bool)
+{
+    KConfigGroup* g = configGroup(c, prefix, postfix);
+
+    setSplitMode(g->readEntry("SplitMode", DEFAULT_SPLITMODE));
+
+    setFieldVisible(0, g->readBoolEntry("DrawName", DEFAULT_DRAWNAME));
+    setFieldVisible(1, g->readBoolEntry("DrawCost", DEFAULT_DRAWCOST));
+    setFieldVisible(2, g->readBoolEntry("DrawLocation", DEFAULT_DRAWLOCATION));
+    setFieldVisible(3, g->readBoolEntry("DrawCalls", DEFAULT_DRAWCALLS));
+
+    bool enable = g->readBoolEntry("ForceStrings", DEFAULT_FORCESTRINGS);
+    setFieldForced(0, enable);
+    setFieldForced(1, enable);
+    setFieldForced(2, enable);
+    setFieldForced(3, enable);
+
+    setAllowRotation(g->readBoolEntry("AllowRotation", DEFAULT_ROTATION));
+    setShadingEnabled(g->readBoolEntry("Shading", DEFAULT_SHADING));
+    setFieldStop(0, g->readEntry("StopName"));
+    setMaxDrawingDepth(g->readNumEntry("MaxDepth", -1));
+    setMinimalArea(g->readNumEntry("MaxArea", DEFAULT_MAXAREA));
+
+    delete g;
+}
+
+void CallMapView::saveViewConfig(KConfig* c, 
+				 TQString prefix, TQString postfix, bool)
+{
+    KConfigGroup g(c, (prefix+postfix).ascii());
+
+    writeConfigEntry(&g, "SplitMode", splitModeString(), DEFAULT_SPLITMODE);
+    writeConfigEntry(&g, "DrawName", fieldVisible(0), DEFAULT_DRAWNAME);
+    writeConfigEntry(&g, "DrawCost", fieldVisible(1), DEFAULT_DRAWCOST);
+    writeConfigEntry(&g, "DrawLocation", fieldVisible(2), DEFAULT_DRAWLOCATION);
+    writeConfigEntry(&g, "DrawCalls", fieldVisible(3), DEFAULT_DRAWCALLS);
+    // when option for all text (0-3)
+    writeConfigEntry(&g, "ForceStrings", fieldForced(0), DEFAULT_FORCESTRINGS);
+
+    writeConfigEntry(&g, "AllowRotation", allowRotation(), DEFAULT_ROTATION);
+    writeConfigEntry(&g, "Shading", isShadingEnabled(), DEFAULT_SHADING);
+
+    writeConfigEntry(&g, "StopName", fieldStop(0), "");
+    writeConfigEntry(&g, "MaxDepth", maxDrawingDepth(), -1);
+    writeConfigEntry(&g, "MaxArea", minimalArea(), DEFAULT_MAXAREA);
+}
+
+#include "callmapview.moc"
diff --git a/kdecachegrind/kdecachegrind/callmapview.h b/kdecachegrind/kdecachegrind/callmapview.h
new file mode 100644
index 0000000..860743f
--- /dev/null
+++ b/kdecachegrind/kdecachegrind/callmapview.h
@@ -0,0 +1,130 @@
+/* This file is part of KCachegrind.
+   Copyright (C) 2003 Josef Weidendorfer <Josef.Weidendorfer@gmx.de>
+
+   KCachegrind 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, version 2.
+
+   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; see the file COPYING.  If not, write to
+   the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+   Boston, MA 02110-1301, USA.
+*/
+
+/*
+ * Call Map View
+ */
+
+#ifndef CALLMAPVIEW_H
+#define CALLMAPVIEW_H
+
+#include "treemap.h"
+#include "tracedata.h"
+#include "traceitemview.h"
+
+class CallMapView: public TreeMapWidget, public TraceItemView
+{
+  Q_OBJECT
+  TQ_OBJECT
+
+public:
+
+  CallMapView(bool showCallers, TraceItemView* parentView,
+              TQWidget* parent=0, const char* name=0);
+
+  TQWidget* widget() { return this; }
+  TQString whatsThis() const;
+  void setData(TraceData*);
+
+  void readViewConfig(KConfig*, TQString prefix, TQString postfix, bool);
+  void saveViewConfig(KConfig*, TQString prefix, TQString postfix, bool);
+
+  bool showCallers() const { return _showCallers; }
+  TraceCost* totalCost();
+  TQString tipString(TreeMapItem*) const;
+  TQColor groupColor(TraceFunction*) const;
+
+private slots:
+  void context(TreeMapItem*,const TQPoint &);
+  void selectedSlot(TreeMapItem*, bool);
+  void activatedSlot(TreeMapItem*);
+
+private:
+  TraceItem* canShow(TraceItem*);
+  void doUpdate(int);
+
+  bool _showCallers;
+};
+
+
+
+// Subitems of CallMap
+
+class CallMapBaseItem: public TreeMapItem
+{
+public:
+  CallMapBaseItem();
+
+  void setFunction(TraceFunction* f);
+  TraceFunction* function() { return _f; }
+  int rtti() const { return 1; }
+  double sum() const;
+  double value() const ;
+  bool isMarked(int) const;
+  TQString text(int) const;
+  TQPixmap pixmap(int) const;
+  TreeMapItemList* children();
+  TQColor backColor() const;
+
+private:
+  TraceFunction* _f;
+};
+
+
+class CallMapCallingItem: public TreeMapItem
+{
+public:
+  CallMapCallingItem(double factor, TraceCall* c);
+  void init();
+  int rtti() const { return 2; }
+  int borderWidth() const { return widget()->borderWidth(); }
+  TraceFunction* function() { return _c->called(); }
+  double value() const;
+  double sum() const;
+  bool isMarked(int) const;
+  TQString text(int) const;
+  TQPixmap pixmap(int) const;
+  TreeMapItemList* children();
+  TQColor backColor() const;
+
+private:
+  TraceCall* _c;
+  double _factor;
+};
+
+class CallMapCallerItem: public TreeMapItem
+{
+public:
+  CallMapCallerItem(double factor, TraceCall* c);
+  int rtti() const { return 3; }
+  int borderWidth() const { return widget()->borderWidth(); }
+  TraceFunction* function() { return _c->caller(); }
+  double value() const;
+  bool isMarked(int) const;
+  TQString text(int) const;
+  TQPixmap pixmap(int) const;
+  TreeMapItemList* children();
+  TQColor backColor() const;
+
+private:
+  TraceCall* _c;
+  double _factor;
+};
+
+
+#endif
diff --git a/kdecachegrind/kdecachegrind/callview.cpp b/kdecachegrind/kdecachegrind/callview.cpp
new file mode 100644
index 0000000..317d137
--- /dev/null
+++ b/kdecachegrind/kdecachegrind/callview.cpp
@@ -0,0 +1,256 @@
+/* This file is part of KCachegrind.
+   Copyright (C) 2003 Josef Weidendorfer <Josef.Weidendorfer@gmx.de>
+
+   KCachegrind 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, version 2.
+
+   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; see the file COPYING.  If not, write to
+   the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+   Boston, MA 02110-1301, USA.
+*/
+
+/*
+ * Call Views
+ */
+
+#include <tqwhatsthis.h>
+#include <tqpopupmenu.h>
+#include <klocale.h>
+
+#include "configuration.h"
+#include "callitem.h"
+#include "callview.h"
+
+
+
+//
+// CallView
+//
+
+
+CallView::CallView(bool showCallers, TraceItemView* parentView,
+		   TQWidget* parent, const char* name)
+  : TQListView(parent, name), TraceItemView(parentView)
+{
+    _showCallers = showCallers;
+
+    addColumn( i18n( "Cost" ) );
+    addColumn( i18n( "Cost 2" ) );
+    if (_showCallers) {
+	addColumn( i18n( "Count" ) );
+	addColumn( i18n( "Caller" ) );
+    }
+    else {
+	addColumn( i18n( "Count" ) );
+	addColumn( i18n( "Callee" ) );
+    }
+
+    setSorting(0,false);
+    setColumnAlignment(0, TQt::AlignRight);
+    setColumnAlignment(1, TQt::AlignRight);
+    setColumnAlignment(2, TQt::AlignRight);
+    setAllColumnsShowFocus(true);
+    setResizeMode(TQListView::LastColumn);
+    setMinimumHeight(50);
+
+    connect( this,
+	     TQT_SIGNAL( selectionChanged(TQListViewItem*) ),
+	     TQT_SLOT( selectedSlot(TQListViewItem*) ) );
+
+    connect( this,
+	     TQT_SIGNAL(contextMenuRequested(TQListViewItem*, const TQPoint &, int)),
+	     TQT_SLOT(context(TQListViewItem*, const TQPoint &, int)));
+
+    connect(this,
+	    TQT_SIGNAL(doubleClicked(TQListViewItem*)),
+	    TQT_SLOT(activatedSlot(TQListViewItem*)));
+
+    connect(this,
+	    TQT_SIGNAL(returnPressed(TQListViewItem*)),
+	    TQT_SLOT(activatedSlot(TQListViewItem*)));
+
+    TQWhatsThis::add( this, whatsThis() );
+}
+
+TQString CallView::whatsThis() const
+{
+    return _showCallers ?
+	i18n( "<b>List of direct Callers</b>"
+	      "<p>This list shows all functions calling the "
+	      "current selected one directly, together with "
+	      "a call count and the cost spent in the current "
+	      "selected function while being called from the "
+	      "function from the list.</p>"
+	      "<p>An icon instead of an inclusive cost specifies "
+	      "that this is a call inside of a recursive cycle. "
+	      "An inclusive cost makes no sense here.</p>"
+	      "<p>Selecting a function makes it the current selected "
+	      "one of this information panel. "
+	      "If there are two panels (Split mode), the "
+	      "function of the other panel is changed instead.</p>") :
+	i18n( "<b>List of direct Callees</b>"
+	      "<p>This list shows all functions called by the "
+	      "current selected one directly, together with "
+	      "a call count and the cost spent in this function "
+	      "while being called from the selected function.</p>"
+	      "<p>Selecting a function makes it the current selected "
+	      "one of this information panel. "
+	      "If there are two panels (Split mode), the "
+	      "function of the other panel is changed instead.</p>");
+}
+
+
+void CallView::context(TQListViewItem* i, const TQPoint & p, int col)
+{
+  TQPopupMenu popup;
+
+  // Menu entry:
+  TraceCall* c = i ? ((CallItem*) i)->call() : 0;
+  TraceFunction *f = 0, *cycle = 0;
+
+  if (c) {
+    TQString name  = _showCallers ? c->callerName(true) : c->calledName(true);
+    f = _showCallers ? c->caller(true) : c->called(true);
+    cycle = f->cycle();
+
+    popup.insertItem(i18n("Go to '%1'")
+		     .arg(Configuration::shortenSymbol(name)), 93);
+
+    if (cycle) {
+	name = Configuration::shortenSymbol(cycle->prettyName());
+	popup.insertItem(i18n("Go to '%1'").arg(name), 94);
+    }
+
+    popup.insertSeparator();
+  }
+
+  if ((col == 0) || (col == 1)) {
+    addCostMenu(&popup);
+    popup.insertSeparator();
+  }
+  addGoMenu(&popup);
+
+  int r = popup.exec(p);
+  if (r == 93) activated(f);
+  else if (r == 94) activated(cycle);
+}
+
+void CallView::selectedSlot(TQListViewItem * i)
+{
+  if (!i) return;
+  TraceCall* c = ((CallItem*) i)->call();
+  // Should we skip cycles here?
+  TraceItem* f = _showCallers ? c->caller(false) : c->called(false);
+
+  _selectedItem = f;
+  selected(f);
+}
+
+void CallView::activatedSlot(TQListViewItem * i)
+{
+  if (!i) return;
+  TraceCall* c = ((CallItem*) i)->call();
+  // skip cycles: use the context menu to get to the cycle...
+  TraceItem* f = _showCallers ? c->caller(true) : c->called(true);
+
+  activated(f);
+}
+
+TraceItem* CallView::canShow(TraceItem* i)
+{
+  TraceItem::CostType t = i ? i->type() : TraceItem::NoCostType;
+
+  switch(t) {
+  case TraceItem::Function:
+  case TraceItem::FunctionCycle:
+      return i;
+  default:
+      break;
+  }
+  return 0;
+}
+
+void CallView::doUpdate(int changeType)
+{
+    // Special case ?
+    if (changeType == selectedItemChanged) {
+
+	if (!_selectedItem) {
+	    clearSelection();
+	    return;
+	}
+
+	CallItem* ci = (CallItem*) TQListView::selectedItem();
+	TraceCall* c;
+	TraceItem* ti;
+	if (ci) {
+	    c = ci->call();
+	    ti = _showCallers ? c->caller() : c->called();
+	    if (ti == _selectedItem) return;
+	}
+
+	TQListViewItem *item;
+	for (item = firstChild();item;item = item->nextSibling()) {
+	    c = ((CallItem*) item)->call();
+	    ti = _showCallers ? c->caller() : c->called();
+	    if (ti == _selectedItem) {
+		ensureItemVisible(item);
+		setSelected(item,  true);
+		break;
+	    }
+	}
+        if (!item && ci) clearSelection();
+	return;
+    }
+    
+    if (changeType == groupTypeChanged) {
+	TQListViewItem *item;
+	for (item = firstChild();item;item = item->nextSibling())
+	    ((CallItem*)item)->updateGroup();
+	return;
+    }
+
+    refresh();
+}
+
+void CallView::refresh()
+{
+    clear();
+    setColumnWidth(0, 50);
+    setColumnWidth(1, _costType2 ? 50:0);
+    setColumnWidth(2, 50);
+    if (_costType)
+      setColumnText(0, _costType->name());
+    if (_costType2)
+      setColumnText(1, _costType2->name());
+
+    if (!_data || !_activeItem) return;
+
+    TraceFunction* f = activeFunction();
+    if (!f) return;
+
+    TraceCall* call;
+    // In the call lists, we skip cycles to show the real call relations
+    TraceCallList l = _showCallers ? f->callers(true) : f->callings(true);
+
+    // Allow resizing of column 1
+    setColumnWidthMode(1, TQListView::Maximum);
+
+    for (call=l.first();call;call=l.next())
+	if (call->subCost(_costType)>0)
+	    new CallItem(this, this, call);
+
+    if (!_costType2) {
+      setColumnWidthMode(1, TQListView::Manual);
+      setColumnWidth(1, 0);
+    }
+}
+
+#include "callview.moc"
diff --git a/kdecachegrind/kdecachegrind/callview.h b/kdecachegrind/kdecachegrind/callview.h
new file mode 100644
index 0000000..be644f9
--- /dev/null
+++ b/kdecachegrind/kdecachegrind/callview.h
@@ -0,0 +1,56 @@
+/* This file is part of KCachegrind.
+   Copyright (C) 2003 Josef Weidendorfer <Josef.Weidendorfer@gmx.de>
+
+   KCachegrind 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, version 2.
+
+   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; see the file COPYING.  If not, write to
+   the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+   Boston, MA 02110-1301, USA.
+*/
+
+/*
+ * Call Views
+ */
+
+#ifndef CALLVIEW_H
+#define CALLVIEW_H
+
+#include <tqlistview.h>
+#include "tracedata.h"
+#include "traceitemview.h"
+
+class CallView: public TQListView, public TraceItemView
+{
+  Q_OBJECT
+  TQ_OBJECT
+
+public:
+  CallView(bool showCallers, TraceItemView* parentView,
+	   TQWidget* parent=0, const char* name=0);
+
+  virtual TQWidget* widget() { return this; }
+  TQString whatsThis() const;
+  bool showCallers() const { return _showCallers; }
+
+private slots:
+  void context(TQListViewItem*,const TQPoint &, int);
+  void selectedSlot(TQListViewItem*);
+  void activatedSlot(TQListViewItem*);
+
+private:
+  TraceItem* canShow(TraceItem*);
+  void doUpdate(int);
+  void refresh();
+
+  bool _showCallers;
+};
+
+#endif
diff --git a/kdecachegrind/kdecachegrind/configdlg.cpp b/kdecachegrind/kdecachegrind/configdlg.cpp
new file mode 100644
index 0000000..e0b4547
--- /dev/null
+++ b/kdecachegrind/kdecachegrind/configdlg.cpp
@@ -0,0 +1,398 @@
+/* This file is part of KCachegrind.
+   Copyright (C) 2002, 2003 Josef Weidendorfer <Josef.Weidendorfer@gmx.de>
+
+   KCachegrind 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, version 2.
+
+   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; see the file COPYING.  If not, write to
+   the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+   Boston, MA 02110-1301, USA.
+*/
+
+/*
+ * Configuration Dialog for KCachegrind
+ */
+
+#include <tqcombobox.h>
+#include <tqcheckbox.h>
+#include <tqlineedit.h>
+#include <tqlistview.h>
+#include <tqdict.h>
+#include <tqmessagebox.h>
+
+#include <kcolorbutton.h>
+#include <kfiledialog.h>
+#include <klocale.h>
+#include <knumvalidator.h>
+
+#include "configdlg.h"
+#include "tracedata.h"
+#include "configuration.h"
+
+
+ConfigDlg::ConfigDlg(Configuration* c, TraceData* data,
+                     TQWidget* parent, const char* name)
+  :ConfigDlgBase(parent, name)
+{
+  _config = c;
+  _data = data;
+  _objectCS = 0;
+  _classCS = 0;
+  _fileCS = 0;
+  KIntValidator * numValidator = new KIntValidator( this );
+  maxListEdit->setValidator(numValidator );
+  symbolCount->setValidator(numValidator );
+  symbolLength->setValidator(numValidator );
+  precisionEdit->setValidator(numValidator );
+  contextEdit->setValidator(numValidator );
+
+#if 0
+  TQListViewItem *oItem, *fItem, *cItem, *fnItem;
+  oItem = new(colorList, i18n("ELF Objects"));
+
+  fItem = new(colorList, i18n("Source Files"));
+  cItem = new(colorList, i18n("C++ Classes"));
+  fnItem = new(colorList, i18n("Function (no Grouping)"));
+#endif
+
+  connect(objectCombo, TQT_SIGNAL(activated(const TQString &)),
+          this, TQT_SLOT(objectActivated(const TQString &)));
+  connect(objectCombo, TQT_SIGNAL(textChanged(const TQString &)),
+          this, TQT_SLOT(objectActivated(const TQString &)));
+  connect(objectCheck, TQT_SIGNAL(toggled(bool)),
+          this, TQT_SLOT(objectCheckChanged(bool)));
+  connect(objectColor, TQT_SIGNAL(changed(const TQColor &)),
+          this, TQT_SLOT(objectColorChanged(const TQColor &)));
+
+  connect(classCombo, TQT_SIGNAL(activated(const TQString &)),
+          this, TQT_SLOT(classActivated(const TQString &)));
+  connect(classCombo, TQT_SIGNAL(textChanged(const TQString &)),
+          this, TQT_SLOT(classActivated(const TQString &)));
+  connect(classCheck, TQT_SIGNAL(toggled(bool)),
+          this, TQT_SLOT(classCheckChanged(bool)));
+  connect(classColor, TQT_SIGNAL(changed(const TQColor &)),
+          this, TQT_SLOT(classColorChanged(const TQColor &)));
+
+  connect(fileCombo, TQT_SIGNAL(activated(const TQString &)),
+          this, TQT_SLOT(fileActivated(const TQString &)));
+  connect(fileCombo, TQT_SIGNAL(textChanged(const TQString &)),
+          this, TQT_SLOT(fileActivated(const TQString &)));
+  connect(fileCheck, TQT_SIGNAL(toggled(bool)),
+          this, TQT_SLOT(fileCheckChanged(bool)));
+  connect(fileColor, TQT_SIGNAL(changed(const TQColor &)),
+          this, TQT_SLOT(fileColorChanged(const TQColor &)));
+
+  TQString objectPrefix = TraceCost::typeName(TraceCost::Object);
+  TQString classPrefix = TraceCost::typeName(TraceCost::Class);
+  TQString filePrefix = TraceCost::typeName(TraceCost::File);
+
+  objectCombo->setDuplicatesEnabled(false);
+  classCombo->setDuplicatesEnabled(false);
+  fileCombo->setDuplicatesEnabled(false);
+  objectCombo->setAutoCompletion(true);
+  classCombo->setAutoCompletion(true);
+  fileCombo->setAutoCompletion(true);
+
+  // first unspecified cost items from data
+  TraceObjectMap::Iterator oit;
+  TQStringList oList;
+  for ( oit = data->objectMap().begin();
+        oit != data->objectMap().end(); ++oit )
+    oList.append((*oit).prettyName());
+
+  TraceClassMap::Iterator cit;
+  TQStringList cList;
+  for ( cit = data->classMap().begin();
+        cit != data->classMap().end(); ++cit )
+    cList.append((*cit).prettyName());
+
+  TraceFileMap::Iterator fit;
+  TQStringList fList;
+  for ( fit = data->fileMap().begin();
+        fit != data->fileMap().end(); ++fit )
+    fList.append((*fit).prettyName());
+
+  // then already defined colors (have to check for duplicates!)
+  TQDictIterator<Configuration::ColorSetting> it( c->_colors );
+  for( ; it.current(); ++it ) {
+    if ((*it)->automatic) continue;
+
+    TQString n = it.currentKey();
+    if (n.startsWith(objectPrefix)) {
+      n = n.remove(0, objectPrefix.length()+1);
+      if (oList.findIndex(n) == -1) oList.append(n);
+    }
+    else if (n.startsWith(classPrefix)) {
+      n = n.remove(0, classPrefix.length()+1);
+      if (cList.findIndex(n) == -1) cList.append(n);
+    }
+    else if (n.startsWith(filePrefix)) {
+      n = n.remove(0, filePrefix.length()+1);
+      if (fList.findIndex(n) == -1) fList.append(n);
+    }
+  }
+
+  oList.sort();
+  cList.sort();
+  fList.sort();
+  objectCombo->insertStringList(oList);
+  classCombo->insertStringList(cList);
+  fileCombo->insertStringList(fList);
+
+  objectActivated(objectCombo->currentText());
+  classActivated(classCombo->currentText());
+  fileActivated(fileCombo->currentText());
+
+  maxListEdit->setText(TQString::number(c->_maxListCount));
+
+  _dirItem = 0;
+
+  TQListViewItem* i = new TQListViewItem(dirList, i18n("(always)"));
+  i->setOpen(true);
+  TQStringList::Iterator sit = c->_generalSourceDirs.begin();
+  for(; sit != c->_generalSourceDirs.end(); ++sit ) {
+    TQString d = (*sit);
+    if (d.isEmpty()) d = "/";
+    new TQListViewItem(i, d);
+  }
+  for ( oit = data->objectMap().begin();
+        oit != data->objectMap().end(); ++oit ) {
+    TQString n = (*oit).name();
+    i = new TQListViewItem(dirList, n);
+    i->setOpen(true);
+    TQStringList* dirs = c->_objectSourceDirs[n];
+    if (!dirs) continue;
+
+    sit = dirs->begin();
+    for(; sit != dirs->end(); ++sit ) {
+      TQString d = (*sit);
+      if (d.isEmpty()) d = "/";
+      new TQListViewItem(i, d);
+    }
+  }
+
+  connect(dirList, TQT_SIGNAL(selectionChanged(TQListViewItem*)),
+          this, TQT_SLOT(dirsItemChanged(TQListViewItem*)));
+  connect(addDirButton, TQT_SIGNAL(clicked()),
+          this, TQT_SLOT(dirsAddPressed()));
+  connect(deleteDirButton, TQT_SIGNAL(clicked()),
+          this, TQT_SLOT(dirsDeletePressed()));
+  dirList->setSelected(dirList->firstChild(), true);
+
+  symbolCount->setText(TQString::number(c->_maxSymbolCount));
+  symbolLength->setText(TQString::number(c->_maxSymbolLength));
+  precisionEdit->setText(TQString::number(c->_percentPrecision));
+  contextEdit->setText(TQString::number(c->_context));
+}
+
+ConfigDlg::~ConfigDlg()
+{
+}
+
+bool ConfigDlg::configure(Configuration* c, TraceData* d, TQWidget* p)
+{
+  ConfigDlg dlg(c, d, p);
+
+  if (dlg.exec()) {
+
+    bool ok;
+    int newValue = dlg.maxListEdit->text().toUInt(&ok);
+    if (ok && newValue < 500)
+      c->_maxListCount = newValue;
+    else
+      TQMessageBox::warning(p, i18n("KCachegrind Configuration"),
+                           i18n("The Maximum Number of List Items should be below 500."
+                                "The previous set value (%1) will still be used.")
+                           .arg(TQString::number(c->_maxListCount)),
+                           TQMessageBox::Ok, 0);
+
+    c->_maxSymbolCount = dlg.symbolCount->text().toInt();
+    c->_maxSymbolLength = dlg.symbolLength->text().toInt();
+    c->_percentPrecision = dlg.precisionEdit->text().toInt();
+    c->_context = dlg.contextEdit->text().toInt();
+    return true;
+  }
+  return false;
+}
+
+void ConfigDlg::objectActivated(const TQString & s)
+{
+//  qDebug("objectActivated: %s", s.ascii());
+
+  if (s.isEmpty()) { _objectCS=0; return; }
+
+  TQString n = TraceCost::typeName(TraceCost::Object) + "-" + s;
+
+  Configuration* c = Configuration::config();
+  Configuration::ColorSetting* cs = c->_colors[n];
+  if (!cs)
+    cs = Configuration::color(n);
+//  else
+//    qDebug("found color %s", n.ascii());
+
+  _objectCS = cs;
+
+  objectCheck->setChecked(cs->automatic);
+  objectColor->setColor(cs->color);
+
+  /*
+  qDebug("Found Color %s, automatic to %s",
+         _objectCS->name.ascii(),
+         _objectCS->automatic ? "true":"false");
+  */
+}
+
+
+void ConfigDlg::objectCheckChanged(bool b)
+{
+  if (_objectCS) {
+    _objectCS->automatic = b;
+    /*
+    qDebug("Set Color %s automatic to %s",
+           _objectCS->name.ascii(),
+           _objectCS->automatic ? "true":"false");
+    */
+  }
+}
+
+void ConfigDlg::objectColorChanged(const TQColor & c)
+{
+  if (_objectCS) _objectCS->color = c;
+}
+
+void ConfigDlg::classActivated(const TQString & s)
+{
+//  qDebug("classActivated: %s", s.ascii());
+
+  if (s.isEmpty()) { _classCS=0; return; }
+
+  TQString n = TraceCost::typeName(TraceCost::Class) + "-" + s;
+
+  Configuration* c = Configuration::config();
+  Configuration::ColorSetting* cs = c->_colors[n];
+  if (!cs)
+    cs = Configuration::color(n);
+
+  _classCS = cs;
+
+  classCheck->setChecked(cs->automatic);
+  classColor->setColor(cs->color);
+
+}
+
+
+void ConfigDlg::classCheckChanged(bool b)
+{
+  if (_classCS) _classCS->automatic = b;
+}
+
+void ConfigDlg::classColorChanged(const TQColor & c)
+{
+  if (_classCS) _classCS->color = c;
+}
+
+
+void ConfigDlg::fileActivated(const TQString & s)
+{
+//  qDebug("fileActivated: %s", s.ascii());
+
+  if (s.isEmpty()) { _fileCS=0; return; }
+
+  TQString n = TraceCost::typeName(TraceCost::File) + "-" + s;
+
+  Configuration* c = Configuration::config();
+  Configuration::ColorSetting* cs = c->_colors[n];
+  if (!cs)
+    cs = Configuration::color(n);
+
+  _fileCS = cs;
+
+  fileCheck->setChecked(cs->automatic);
+  fileColor->setColor(cs->color);
+}
+
+
+void ConfigDlg::fileCheckChanged(bool b)
+{
+  if (_fileCS) _fileCS->automatic = b;
+}
+
+void ConfigDlg::fileColorChanged(const TQColor & c)
+{
+  if (_fileCS) _fileCS->color = c;
+}
+
+
+void ConfigDlg::dirsItemChanged(TQListViewItem* i)
+{
+  _dirItem = i;
+  deleteDirButton->setEnabled(i->depth() == 1);
+  addDirButton->setEnabled(i->depth() == 0);
+}
+
+void ConfigDlg::dirsDeletePressed()
+{
+  if (!_dirItem || (_dirItem->depth() == 0)) return;
+  TQListViewItem* p = _dirItem->parent();
+  if (!p) return;
+
+  Configuration* c = Configuration::config();
+  TQString objName = p->text(0);
+
+  TQStringList* dirs;
+  if (objName == i18n("(always)"))
+    dirs = &(c->_generalSourceDirs);
+  else
+    dirs = c->_objectSourceDirs[objName];
+  if (!dirs) return;
+
+  dirs->remove(_dirItem->text(0));
+  delete _dirItem;
+  _dirItem = 0;
+
+  deleteDirButton->setEnabled(false);
+}
+
+void ConfigDlg::dirsAddPressed()
+{
+  if (!_dirItem || (_dirItem->depth() >0)) return;
+
+  Configuration* c = Configuration::config();
+  TQString objName = _dirItem->text(0);
+
+  TQStringList* dirs;
+  if (objName == i18n("(always)"))
+    dirs = &(c->_generalSourceDirs);
+  else {
+    dirs = c->_objectSourceDirs[objName];
+    if (!dirs) {
+      dirs = new TQStringList;
+      c->_objectSourceDirs.insert(objName, dirs);
+    }
+  }
+
+  TQString newDir;
+  newDir = KFileDialog::getExistingDirectory(TQString(),
+                                             this,
+                                             i18n("Choose Source Folder"));
+  if (newDir.isEmpty()) return;
+
+  // even for "/", we strip the tailing slash
+  if (newDir.endsWith("/"))
+    newDir = newDir.left(newDir.length()-1);
+
+  if (dirs->findIndex(newDir)>=0) return;
+
+  dirs->append(newDir);
+  if (newDir.isEmpty()) newDir = TQString("/");
+  new TQListViewItem(_dirItem, newDir);
+}
+
+#include "configdlg.moc"
diff --git a/kdecachegrind/kdecachegrind/configdlg.h b/kdecachegrind/kdecachegrind/configdlg.h
new file mode 100644
index 0000000..5ef6bab
--- /dev/null
+++ b/kdecachegrind/kdecachegrind/configdlg.h
@@ -0,0 +1,65 @@
+/* This file is part of KCachegrind.
+   Copyright (C) 2002, 2003 Josef Weidendorfer <Josef.Weidendorfer@gmx.de>
+
+   KCachegrind 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, version 2.
+
+   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; see the file COPYING.  If not, write to
+   the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+   Boston, MA 02110-1301, USA.
+*/
+
+/*
+ * Configuration Dialog for KCachegrind
+ */
+
+#ifndef CONFIGDLG_H
+#define CONFIGDLG_H
+
+#include "configdlgbase.h"
+#include "configuration.h"
+
+class TraceData;
+
+class ConfigDlg : public ConfigDlgBase
+{
+  Q_OBJECT
+  TQ_OBJECT
+
+public:
+  ConfigDlg(Configuration*, TraceData*,
+            TQWidget* parent = 0, const char* name = 0);
+  ~ConfigDlg();
+
+  static bool configure(Configuration*, TraceData*, TQWidget*);
+
+protected slots:
+  void objectActivated(const TQString &);
+  void objectCheckChanged(bool);
+  void objectColorChanged(const TQColor &);
+  void classActivated(const TQString &);
+  void classCheckChanged(bool);
+  void classColorChanged(const TQColor &);
+  void fileActivated(const TQString &);
+  void fileCheckChanged(bool);
+  void fileColorChanged(const TQColor &);
+  void dirsItemChanged(TQListViewItem*);
+  void dirsDeletePressed();
+  void dirsAddPressed();
+
+private:
+  Configuration* _config;
+  TraceData* _data;
+
+  Configuration::ColorSetting *_objectCS, *_classCS, *_fileCS;
+  TQListViewItem* _dirItem;
+};
+
+#endif
diff --git a/kdecachegrind/kdecachegrind/configdlgbase.ui b/kdecachegrind/kdecachegrind/configdlgbase.ui
new file mode 100644
index 0000000..dc0ee9e
--- /dev/null
+++ b/kdecachegrind/kdecachegrind/configdlgbase.ui
@@ -0,0 +1,653 @@
+<!DOCTYPE UI><UI version="3.1" stdsetdef="1">
+<class>ConfigDlgBase</class>
+<widget class="TQDialog">
+    <property name="name">
+        <cstring>configDlgBase</cstring>
+    </property>
+    <property name="geometry">
+        <rect>
+            <x>0</x>
+            <y>0</y>
+            <width>447</width>
+            <height>378</height>
+        </rect>
+    </property>
+    <property name="caption">
+        <string>Configuration</string>
+    </property>
+    <vbox>
+        <property name="name">
+            <cstring>unnamed</cstring>
+        </property>
+        <property name="margin">
+            <number>11</number>
+        </property>
+        <property name="spacing">
+            <number>6</number>
+        </property>
+        <widget class="TQTabWidget">
+            <property name="name">
+                <cstring>tabWidget2</cstring>
+            </property>
+            <widget class="TQWidget">
+                <property name="name">
+                    <cstring>tab</cstring>
+                </property>
+                <attribute name="title">
+                    <string>General</string>
+                </attribute>
+                <vbox>
+                    <property name="name">
+                        <cstring>unnamed</cstring>
+                    </property>
+                    <widget class="TQLayoutWidget">
+                        <property name="name">
+                            <cstring>layout10</cstring>
+                        </property>
+                        <grid>
+                            <property name="name">
+                                <cstring>unnamed</cstring>
+                            </property>
+                            <widget class="TQLineEdit" row="3" column="2" rowspan="1" colspan="2">
+                                <property name="name">
+                                    <cstring>precisionEdit</cstring>
+                                </property>
+                                <property name="sizePolicy">
+                                    <sizepolicy>
+                                        <hsizetype>7</hsizetype>
+                                        <vsizetype>0</vsizetype>
+                                        <horstretch>2</horstretch>
+                                        <verstretch>0</verstretch>
+                                    </sizepolicy>
+                                </property>
+                            </widget>
+                            <widget class="TQLabel" row="2" column="1">
+                                <property name="name">
+                                    <cstring>TextLabel2</cstring>
+                                </property>
+                                <property name="text">
+                                    <string>Truncated when more/longer than:</string>
+                                </property>
+                            </widget>
+                            <widget class="TQLabel" row="3" column="0" rowspan="1" colspan="2">
+                                <property name="name">
+                                    <cstring>TextLabel4_3</cstring>
+                                </property>
+                                <property name="text">
+                                    <string>Precision of percentage values:</string>
+                                </property>
+                            </widget>
+                            <widget class="TQLabel" row="1" column="0" rowspan="1" colspan="3">
+                                <property name="name">
+                                    <cstring>TextLabel3</cstring>
+                                </property>
+                                <property name="text">
+                                    <string>Symbols in tooltips and context menus</string>
+                                </property>
+                            </widget>
+                            <widget class="TQLineEdit" row="2" column="3">
+                                <property name="name">
+                                    <cstring>symbolLength</cstring>
+                                </property>
+                                <property name="sizePolicy">
+                                    <sizepolicy>
+                                        <hsizetype>4</hsizetype>
+                                        <vsizetype>0</vsizetype>
+                                        <horstretch>0</horstretch>
+                                        <verstretch>0</verstretch>
+                                    </sizepolicy>
+                                </property>
+                            </widget>
+                            <spacer row="2" column="0">
+                                <property name="name">
+                                    <cstring>Spacer6_2_2_2</cstring>
+                                </property>
+                                <property name="orientation">
+                                    <enum>Horizontal</enum>
+                                </property>
+                                <property name="sizeType">
+                                    <enum>Fixed</enum>
+                                </property>
+                                <property name="sizeHint">
+                                    <size>
+                                        <width>16</width>
+                                        <height>20</height>
+                                    </size>
+                                </property>
+                            </spacer>
+                            <widget class="TQLineEdit" row="0" column="2" rowspan="1" colspan="2">
+                                <property name="name">
+                                    <cstring>maxListEdit</cstring>
+                                </property>
+                            </widget>
+                            <widget class="TQLineEdit" row="2" column="2">
+                                <property name="name">
+                                    <cstring>symbolCount</cstring>
+                                </property>
+                                <property name="sizePolicy">
+                                    <sizepolicy>
+                                        <hsizetype>4</hsizetype>
+                                        <vsizetype>0</vsizetype>
+                                        <horstretch>0</horstretch>
+                                        <verstretch>0</verstretch>
+                                    </sizepolicy>
+                                </property>
+                            </widget>
+                            <widget class="TQLabel" row="0" column="0" rowspan="1" colspan="2">
+                                <property name="name">
+                                    <cstring>TextLabel5</cstring>
+                                </property>
+                                <property name="text">
+                                    <string>Maximum number of items in lists:</string>
+                                </property>
+                            </widget>
+                        </grid>
+                    </widget>
+                    <widget class="TQLabel">
+                        <property name="name">
+                            <cstring>TextLabel1</cstring>
+                        </property>
+                        <property name="font">
+                            <font>
+                                <bold>1</bold>
+                            </font>
+                        </property>
+                        <property name="frameShape">
+                            <enum>NoFrame</enum>
+                        </property>
+                        <property name="frameShadow">
+                            <enum>Plain</enum>
+                        </property>
+                        <property name="text">
+                            <string>Cost Item Colors</string>
+                        </property>
+                    </widget>
+                    <widget class="TQLayoutWidget">
+                        <property name="name">
+                            <cstring>Layout9</cstring>
+                        </property>
+                        <grid>
+                            <property name="name">
+                                <cstring>unnamed</cstring>
+                            </property>
+                            <property name="margin">
+                                <number>0</number>
+                            </property>
+                            <property name="spacing">
+                                <number>6</number>
+                            </property>
+                            <spacer row="1" column="1">
+                                <property name="name">
+                                    <cstring>Spacer9</cstring>
+                                </property>
+                                <property name="orientation">
+                                    <enum>Vertical</enum>
+                                </property>
+                                <property name="sizeType">
+                                    <enum>Fixed</enum>
+                                </property>
+                                <property name="sizeHint">
+                                    <size>
+                                        <width>20</width>
+                                        <height>16</height>
+                                    </size>
+                                </property>
+                            </spacer>
+                            <spacer row="0" column="0">
+                                <property name="name">
+                                    <cstring>Spacer6</cstring>
+                                </property>
+                                <property name="orientation">
+                                    <enum>Horizontal</enum>
+                                </property>
+                                <property name="sizeType">
+                                    <enum>Fixed</enum>
+                                </property>
+                                <property name="sizeHint">
+                                    <size>
+                                        <width>16</width>
+                                        <height>20</height>
+                                    </size>
+                                </property>
+                            </spacer>
+                            <widget class="TQLayoutWidget" row="0" column="1">
+                                <property name="name">
+                                    <cstring>Layout9</cstring>
+                                </property>
+                                <grid>
+                                    <property name="name">
+                                        <cstring>unnamed</cstring>
+                                    </property>
+                                    <property name="margin">
+                                        <number>0</number>
+                                    </property>
+                                    <property name="spacing">
+                                        <number>6</number>
+                                    </property>
+                                    <widget class="TQComboBox" row="1" column="1">
+                                        <property name="name">
+                                            <cstring>classCombo</cstring>
+                                        </property>
+                                        <property name="maximumSize">
+                                            <size>
+                                                <width>300</width>
+                                                <height>32767</height>
+                                            </size>
+                                        </property>
+                                        <property name="editable">
+                                            <bool>true</bool>
+                                        </property>
+                                    </widget>
+                                    <widget class="TQCheckBox" row="2" column="2">
+                                        <property name="name">
+                                            <cstring>fileCheck</cstring>
+                                        </property>
+                                        <property name="text">
+                                            <string>Automatic</string>
+                                        </property>
+                                    </widget>
+                                    <widget class="TQLabel" row="0" column="0">
+                                        <property name="name">
+                                            <cstring>TextLabel4</cstring>
+                                        </property>
+                                        <property name="text">
+                                            <string>Object:</string>
+                                        </property>
+                                    </widget>
+                                    <widget class="TQLabel" row="1" column="0">
+                                        <property name="name">
+                                            <cstring>TextLabel4_2_2</cstring>
+                                        </property>
+                                        <property name="text">
+                                            <string>Class:</string>
+                                        </property>
+                                    </widget>
+                                    <widget class="KColorButton" row="2" column="3">
+                                        <property name="name">
+                                            <cstring>fileColor</cstring>
+                                        </property>
+                                        <property name="sizePolicy">
+                                            <sizepolicy>
+                                                <hsizetype>0</hsizetype>
+                                                <vsizetype>0</vsizetype>
+                                                <horstretch>0</horstretch>
+                                                <verstretch>0</verstretch>
+                                            </sizepolicy>
+                                        </property>
+                                        <property name="text">
+                                            <string></string>
+                                        </property>
+                                    </widget>
+                                    <widget class="TQCheckBox" row="1" column="2">
+                                        <property name="name">
+                                            <cstring>classCheck</cstring>
+                                        </property>
+                                        <property name="text">
+                                            <string>Automatic</string>
+                                        </property>
+                                    </widget>
+                                    <widget class="KColorButton" row="0" column="3">
+                                        <property name="name">
+                                            <cstring>objectColor</cstring>
+                                        </property>
+                                        <property name="text">
+                                            <string></string>
+                                        </property>
+                                    </widget>
+                                    <widget class="TQCheckBox" row="0" column="2">
+                                        <property name="name">
+                                            <cstring>objectCheck</cstring>
+                                        </property>
+                                        <property name="text">
+                                            <string>Automatic</string>
+                                        </property>
+                                    </widget>
+                                    <widget class="TQLabel" row="2" column="0">
+                                        <property name="name">
+                                            <cstring>TextLabel4_2</cstring>
+                                        </property>
+                                        <property name="text">
+                                            <string>File:</string>
+                                        </property>
+                                    </widget>
+                                    <widget class="KColorButton" row="1" column="3">
+                                        <property name="name">
+                                            <cstring>classColor</cstring>
+                                        </property>
+                                        <property name="sizePolicy">
+                                            <sizepolicy>
+                                                <hsizetype>0</hsizetype>
+                                                <vsizetype>0</vsizetype>
+                                                <horstretch>0</horstretch>
+                                                <verstretch>0</verstretch>
+                                            </sizepolicy>
+                                        </property>
+                                        <property name="text">
+                                            <string></string>
+                                        </property>
+                                    </widget>
+                                    <widget class="TQComboBox" row="2" column="1">
+                                        <property name="name">
+                                            <cstring>fileCombo</cstring>
+                                        </property>
+                                        <property name="maximumSize">
+                                            <size>
+                                                <width>300</width>
+                                                <height>32767</height>
+                                            </size>
+                                        </property>
+                                        <property name="editable">
+                                            <bool>true</bool>
+                                        </property>
+                                    </widget>
+                                    <widget class="TQComboBox" row="0" column="1">
+                                        <property name="name">
+                                            <cstring>objectCombo</cstring>
+                                        </property>
+                                        <property name="sizePolicy">
+                                            <sizepolicy>
+                                                <hsizetype>3</hsizetype>
+                                                <vsizetype>0</vsizetype>
+                                                <horstretch>0</horstretch>
+                                                <verstretch>0</verstretch>
+                                            </sizepolicy>
+                                        </property>
+                                        <property name="maximumSize">
+                                            <size>
+                                                <width>300</width>
+                                                <height>32767</height>
+                                            </size>
+                                        </property>
+                                        <property name="editable">
+                                            <bool>true</bool>
+                                        </property>
+                                    </widget>
+                                </grid>
+                            </widget>
+                        </grid>
+                    </widget>
+                </vbox>
+            </widget>
+            <widget class="TQWidget">
+                <property name="name">
+                    <cstring>tab</cstring>
+                </property>
+                <attribute name="title">
+                    <string>Annotations</string>
+                </attribute>
+                <vbox>
+                    <property name="name">
+                        <cstring>unnamed</cstring>
+                    </property>
+                    <widget class="TQLayoutWidget">
+                        <property name="name">
+                            <cstring>layout8</cstring>
+                        </property>
+                        <hbox>
+                            <property name="name">
+                                <cstring>unnamed</cstring>
+                            </property>
+                            <widget class="TQLabel">
+                                <property name="name">
+                                    <cstring>TextLabel4_3_2</cstring>
+                                </property>
+                                <property name="text">
+                                    <string>Context lines in annotations:</string>
+                                </property>
+                            </widget>
+                            <widget class="TQLineEdit">
+                                <property name="name">
+                                    <cstring>contextEdit</cstring>
+                                </property>
+                                <property name="sizePolicy">
+                                    <sizepolicy>
+                                        <hsizetype>7</hsizetype>
+                                        <vsizetype>0</vsizetype>
+                                        <horstretch>2</horstretch>
+                                        <verstretch>0</verstretch>
+                                    </sizepolicy>
+                                </property>
+                            </widget>
+                        </hbox>
+                    </widget>
+                    <widget class="TQLabel">
+                        <property name="name">
+                            <cstring>TextLabel1_2</cstring>
+                        </property>
+                        <property name="font">
+                            <font>
+                                <bold>1</bold>
+                            </font>
+                        </property>
+                        <property name="text">
+                            <string>Source Folders</string>
+                        </property>
+                    </widget>
+                    <widget class="TQLayoutWidget">
+                        <property name="name">
+                            <cstring>layout11</cstring>
+                        </property>
+                        <grid>
+                            <property name="name">
+                                <cstring>unnamed</cstring>
+                            </property>
+                            <spacer row="0" column="0">
+                                <property name="name">
+                                    <cstring>Spacer6_2</cstring>
+                                </property>
+                                <property name="orientation">
+                                    <enum>Horizontal</enum>
+                                </property>
+                                <property name="sizeType">
+                                    <enum>Fixed</enum>
+                                </property>
+                                <property name="sizeHint">
+                                    <size>
+                                        <width>16</width>
+                                        <height>20</height>
+                                    </size>
+                                </property>
+                            </spacer>
+                            <widget class="TQListView" row="0" column="1">
+                                <column>
+                                    <property name="text">
+                                        <string>Object / Related Source Base</string>
+                                    </property>
+                                    <property name="clickable">
+                                        <bool>true</bool>
+                                    </property>
+                                    <property name="resizable">
+                                        <bool>true</bool>
+                                    </property>
+                                </column>
+                                <property name="name">
+                                    <cstring>dirList</cstring>
+                                </property>
+                                <property name="rootIsDecorated">
+                                    <bool>true</bool>
+                                </property>
+                            </widget>
+                            <widget class="TQLayoutWidget" row="0" column="2">
+                                <property name="name">
+                                    <cstring>layout10</cstring>
+                                </property>
+                                <vbox>
+                                    <property name="name">
+                                        <cstring>unnamed</cstring>
+                                    </property>
+                                    <widget class="TQPushButton">
+                                        <property name="name">
+                                            <cstring>addDirButton</cstring>
+                                        </property>
+                                        <property name="text">
+                                            <string>Add...</string>
+                                        </property>
+                                    </widget>
+                                    <spacer>
+                                        <property name="name">
+                                            <cstring>Spacer5</cstring>
+                                        </property>
+                                        <property name="orientation">
+                                            <enum>Vertical</enum>
+                                        </property>
+                                        <property name="sizeType">
+                                            <enum>Expanding</enum>
+                                        </property>
+                                        <property name="sizeHint">
+                                            <size>
+                                                <width>16</width>
+                                                <height>49</height>
+                                            </size>
+                                        </property>
+                                    </spacer>
+                                    <widget class="TQPushButton">
+                                        <property name="name">
+                                            <cstring>deleteDirButton</cstring>
+                                        </property>
+                                        <property name="text">
+                                            <string>Delete</string>
+                                        </property>
+                                    </widget>
+                                </vbox>
+                            </widget>
+                            <spacer row="1" column="1">
+                                <property name="name">
+                                    <cstring>Spacer9_2</cstring>
+                                </property>
+                                <property name="orientation">
+                                    <enum>Vertical</enum>
+                                </property>
+                                <property name="sizeType">
+                                    <enum>Fixed</enum>
+                                </property>
+                                <property name="sizeHint">
+                                    <size>
+                                        <width>20</width>
+                                        <height>16</height>
+                                    </size>
+                                </property>
+                            </spacer>
+                        </grid>
+                    </widget>
+                </vbox>
+            </widget>
+        </widget>
+        <widget class="Line">
+            <property name="name">
+                <cstring>Line1</cstring>
+            </property>
+            <property name="frameShape">
+                <enum>HLine</enum>
+            </property>
+            <property name="frameShadow">
+                <enum>Sunken</enum>
+            </property>
+            <property name="orientation">
+                <enum>Horizontal</enum>
+            </property>
+        </widget>
+        <widget class="TQLayoutWidget">
+            <property name="name">
+                <cstring>Layout4</cstring>
+            </property>
+            <hbox>
+                <property name="name">
+                    <cstring>unnamed</cstring>
+                </property>
+                <property name="margin">
+                    <number>0</number>
+                </property>
+                <property name="spacing">
+                    <number>6</number>
+                </property>
+                <spacer>
+                    <property name="name">
+                        <cstring>Spacer2</cstring>
+                    </property>
+                    <property name="orientation">
+                        <enum>Horizontal</enum>
+                    </property>
+                    <property name="sizeType">
+                        <enum>Expanding</enum>
+                    </property>
+                    <property name="sizeHint">
+                        <size>
+                            <width>210</width>
+                            <height>0</height>
+                        </size>
+                    </property>
+                </spacer>
+                <widget class="TQPushButton">
+                    <property name="name">
+                        <cstring>PushButton2</cstring>
+                    </property>
+                    <property name="text">
+                        <string>&amp;OK</string>
+                    </property>
+                    <property name="default">
+                        <bool>true</bool>
+                    </property>
+                </widget>
+                <widget class="TQPushButton">
+                    <property name="name">
+                        <cstring>PushButton1</cstring>
+                    </property>
+                    <property name="text">
+                        <string>&amp;Cancel</string>
+                    </property>
+                </widget>
+            </hbox>
+        </widget>
+    </vbox>
+</widget>
+<connections>
+    <connection>
+        <sender>PushButton2</sender>
+        <signal>clicked()</signal>
+        <receiver>configDlgBase</receiver>
+        <slot>accept()</slot>
+    </connection>
+    <connection>
+        <sender>PushButton1</sender>
+        <signal>clicked()</signal>
+        <receiver>configDlgBase</receiver>
+        <slot>reject()</slot>
+    </connection>
+    <connection>
+        <sender>classCheck</sender>
+        <signal>toggled(bool)</signal>
+        <receiver>classColor</receiver>
+        <slot>setDisabled(bool)</slot>
+    </connection>
+    <connection>
+        <sender>fileCheck</sender>
+        <signal>toggled(bool)</signal>
+        <receiver>fileColor</receiver>
+        <slot>setDisabled(bool)</slot>
+    </connection>
+    <connection>
+        <sender>objectCheck</sender>
+        <signal>toggled(bool)</signal>
+        <receiver>objectColor</receiver>
+        <slot>setDisabled(bool)</slot>
+    </connection>
+</connections>
+<tabstops>
+    <tabstop>objectCombo</tabstop>
+    <tabstop>objectCheck</tabstop>
+    <tabstop>classCombo</tabstop>
+    <tabstop>classCheck</tabstop>
+    <tabstop>classColor</tabstop>
+    <tabstop>fileCombo</tabstop>
+    <tabstop>fileCheck</tabstop>
+    <tabstop>fileColor</tabstop>
+    <tabstop>maxListEdit</tabstop>
+    <tabstop>PushButton1</tabstop>
+    <tabstop>PushButton2</tabstop>
+</tabstops>
+<includes>
+    <include location="global" impldecl="in implementation">kcolorbutton.h</include>
+</includes>
+<pixmapinproject/>
+<layoutdefaults spacing="6" margin="11"/>
+</UI>
diff --git a/kdecachegrind/kdecachegrind/configuration.cpp b/kdecachegrind/kdecachegrind/configuration.cpp
new file mode 100644
index 0000000..02d5c09
--- /dev/null
+++ b/kdecachegrind/kdecachegrind/configuration.cpp
@@ -0,0 +1,490 @@
+/* This file is part of KCachegrind.
+   Copyright (C) 2002, 2003 Josef Weidendorfer <Josef.Weidendorfer@gmx.de>
+
+   KCachegrind 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, version 2.
+
+   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; see the file COPYING.  If not, write to
+   the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+   Boston, MA 02110-1301, USA.
+*/
+
+/*
+ * Configuration for KCachegrind
+ */
+
+#include <kconfig.h>
+#include <klocale.h>
+#include <kdebug.h>
+
+#include "configuration.h"
+#include "tracedata.h"
+#include "configdlgbase.h"
+
+#include "traceitemview.h"
+
+//
+// Some predefined cost types...
+//
+
+static TQStringList knownTypes()
+{
+  TQStringList l;
+
+  l << "Ir"   << "Dr"   << "Dw"
+    << "I1mr" << "D1mr" << "D1mw"
+    << "I2mr" << "D2mr" << "D2mw"
+
+    << "Smp"  << "Sys"  << "User"
+    << "L1m"  << "L2m"  << "CEst";
+
+  return l;
+}
+
+
+static TQString knownFormula(TQString name)
+{
+  if (name =="L1m") return TQString("I1mr + D1mr + D1mw");
+  if (name =="L2m") return TQString("I2mr + D2mr + D2mw");
+  if (name =="CEst") return TQString("Ir + 10 L1m + 100 L2m");
+
+  return TQString();
+}
+
+static TQString knownLongName(TQString name)
+{
+    if (name == "Ir") return i18n("Instruction Fetch");
+    if (name =="Dr") return i18n("Data Read Access");
+    if (name =="Dw") return i18n("Data Write Access");
+    if (name =="I1mr") return i18n("L1 Instr. Fetch Miss");
+    if (name =="D1mr") return i18n("L1 Data Read Miss");
+    if (name =="D1mw") return i18n("L1 Data Write Miss");
+    if (name =="I2mr") return i18n("L2 Instr. Fetch Miss");
+    if (name =="D2mr") return i18n("L2 Data Read Miss");
+    if (name =="D2mw") return i18n("L2 Data Write Miss");
+    if (name =="Smp") return i18n("Samples");
+    if (name =="Sys") return i18n("System Time");
+    if (name =="User") return i18n("User Time");
+    if (name =="L1m") return i18n("L1 Miss Sum");
+    if (name =="L2m") return i18n("L2 Miss Sum");
+    if (name =="CEst") return i18n("Cycle Estimation");
+
+    return TQString();
+}
+
+
+
+
+//
+// Configuration
+//
+
+Configuration* Configuration::_config = 0;
+
+Configuration::Configuration()
+  :_colors(517)
+{
+  _config = 0;
+
+  _colors.setAutoDelete(true);
+  _objectSourceDirs.setAutoDelete(true);
+
+  // defaults
+  _showPercentage = true;
+  _showExpanded = false;
+  _showCycles = true;
+  _cycleCut = 0.0;
+  _percentPrecision = 2;
+
+  // max symbol count/length in tooltip/popup
+  _maxSymbolLength = 30;
+  _maxSymbolCount = 10;
+  _maxListCount = 100;
+
+  // annotation behaviour
+  _context = 3;
+  _noCostInside   = 20;
+}
+
+Configuration* Configuration::config()
+{
+  if (!_config)
+    _config = new Configuration();
+
+  return _config;
+}
+
+
+void Configuration::saveOptions(KConfig* kconfig)
+{
+  Configuration* c = config();
+
+  // color options
+  KConfigGroup colorConfig(kconfig, TQCString("CostColors"));
+  TQDictIterator<ColorSetting> it( c->_colors );
+  int count = 1;
+  for( ; it.current(); ++it ) {
+    if ( !(*it)->automatic ) {
+      colorConfig.writeEntry( TQString("Name%1").arg(count),
+                              it.currentKey());
+      colorConfig.writeEntry( TQString("Color%1").arg(count),
+                              (*it)->color);
+      //qDebug("Written Color %s (%d)", it.currentKey().ascii(), count);
+
+      count++;
+    }
+  }
+  colorConfig.writeEntry( "Count", count-1);
+
+  // source options
+  KConfigGroup sourceConfig(kconfig, TQCString("Source"));
+  sourceConfig.writeEntry("Dirs", c->_generalSourceDirs, ':');
+  TQDictIterator<TQStringList> it2( c->_objectSourceDirs );
+  count = 1;
+  for( ; it2.current(); ++it2 ) {
+    sourceConfig.writeEntry( TQString("Object%1").arg(count),
+			     it2.currentKey());
+    sourceConfig.writeEntry( TQString("Dirs%1").arg(count),
+			     *(*it2), ':');
+    count++;
+  }
+  sourceConfig.writeEntry( "Count", count-1);
+
+  // general options
+  KConfigGroup generalConfig(kconfig, TQCString("General"));
+  generalConfig.writeEntry("ShowPercentage", c->_showPercentage);
+  generalConfig.writeEntry("ShowExpanded", c->_showExpanded);
+  generalConfig.writeEntry("ShowCycles", c->_showCycles);
+  generalConfig.writeEntry("CycleCut", c->_cycleCut);
+  generalConfig.writeEntry("MaxSymbolCount", c->_maxSymbolCount);
+  generalConfig.writeEntry("MaxListCount", c->_maxListCount);
+  generalConfig.writeEntry("MaxSymbolLength", c->_maxSymbolLength);
+  generalConfig.writeEntry("PercentPrecision", c->_percentPrecision);
+
+  generalConfig.writeEntry("Context", c->_context);
+  generalConfig.writeEntry("NoCostInside", c->_noCostInside);
+
+  KConfigGroup ctConfig(kconfig, TQCString("CostTypes"));
+  int ctCount = TraceCostType::knownTypeCount();
+  ctConfig.writeEntry( "Count", ctCount);
+  for (int i=0; i<ctCount; i++) {
+    TraceCostType* t = TraceCostType::knownType(i);
+    ctConfig.writeEntry( TQString("Name%1").arg(i+1), t->name());
+
+    // Use localized key
+    TraceItemView::writeConfigEntry(&ctConfig,
+                                    TQString("Longname%1").arg(i+1).ascii(),
+                                    t->longName(),
+                                    knownLongName(t->name()).utf8().data() /*, true */ );
+    TraceItemView::writeConfigEntry(&ctConfig,
+                                    TQString("Formula%1").arg(i+1).ascii(),
+                                    t->formula(), knownFormula(t->name()).utf8().data());
+  }
+}
+
+
+
+
+void Configuration::readOptions(KConfig* kconfig)
+{
+  int i, count;
+  Configuration* c = config();
+
+  // color options
+  c->_colors.clear();
+
+  // colors for default cost types:
+  //  red for L2 misses, green for L1 misses, blue for normal accesses
+  c->color("CostType-I2mr")->color = TQColor(240, 0, 0);
+  c->color("CostType-D2mr")->color = TQColor(180,40,40);
+  c->color("CostType-D2mw")->color = TQColor(120,80,80);
+
+  c->color("CostType-I1mr")->color = TQColor(0, 240, 0);
+  c->color("CostType-D1mr")->color = TQColor(40,180,40);
+  c->color("CostType-D1mw")->color = TQColor(80,120,80);
+
+  c->color("CostType-Ir")->color = TQColor(0, 0, 240);
+  c->color("CostType-Dr")->color = TQColor(40,40,180);
+  c->color("CostType-Dw")->color = TQColor(80,80,120);
+
+  KConfigGroup colorConfig(kconfig, TQCString("CostColors"));
+  count = colorConfig.readNumEntry("Count", 0);
+  for (i=1;i<=count;i++) {
+    TQString n = colorConfig.readEntry(TQString("Name%1").arg(i));
+    TQColor color = colorConfig.readColorEntry(TQString("Color%1").arg(i));
+
+    if (n.isEmpty()) continue;
+
+    ColorSetting* cs = new ColorSetting;
+    cs->name = n;
+    cs->automatic = false;
+    cs->color = color;
+
+    c->_colors.insert(n, cs);
+
+    //qDebug("Read Color %s", n.ascii());
+  }
+
+  // source options
+  KConfigGroup sourceConfig(kconfig, TQCString("Source"));
+  TQStringList dirs;
+  dirs = sourceConfig.readListEntry("Dirs", ':');
+  if (dirs.count()>0) c->_generalSourceDirs = dirs;
+  count = sourceConfig.readNumEntry("Count", 0);
+  c->_objectSourceDirs.clear();
+  if (count>17) c->_objectSourceDirs.resize(count);
+  for (i=1;i<=count;i++) {
+    TQString n = sourceConfig.readEntry(TQString("Object%1").arg(i));
+    dirs = sourceConfig.readListEntry(TQString("Dirs%1").arg(i), ':');
+
+    if (n.isEmpty() || (dirs.count()==0)) continue;
+
+    c->_objectSourceDirs.insert(n, new TQStringList(dirs));
+  }
+
+
+  // general options
+  KConfigGroup generalConfig(kconfig, TQCString("General"));
+  c->_showPercentage = generalConfig.readBoolEntry("ShowPercentage", true);
+  c->_showExpanded = generalConfig.readBoolEntry("ShowExpanded", false);
+  c->_showCycles = generalConfig.readBoolEntry("ShowCycles", true);
+  c->_cycleCut = generalConfig.readDoubleNumEntry("CycleCut", 0.0);
+  c->_maxSymbolCount = generalConfig.readNumEntry("MaxSymbolCount", 10);
+  c->_maxListCount = generalConfig.readNumEntry("MaxListCount", 100);
+  c->_maxSymbolLength = generalConfig.readNumEntry("MaxSymbolLength", 30);
+  c->_percentPrecision = generalConfig.readNumEntry("PercentPrecision", 2);
+
+  c->_context = generalConfig.readNumEntry("Context", 3);
+  c->_noCostInside   = generalConfig.readNumEntry("NoCostInside", 20);
+
+  // known cost types
+  if (TraceCostType::knownTypeCount()==0) {
+
+    KConfigGroup ctConfig(kconfig, TQCString("CostTypes"));
+    int ctCount = ctConfig.readNumEntry("Count", 0);
+    if (ctCount>0) {
+      for (int i=1;i<=ctCount;i++) {
+        TQString n = ctConfig.readEntry(TQString("Name%1").arg(i));
+        TQString l = ctConfig.readEntry(TQString("Longname%1").arg(i));
+	if (l.isEmpty()) l = knownLongName(n);
+        TQString f = ctConfig.readEntry(TQString("Formula%1").arg(i));
+	if (f.isEmpty()) f = knownFormula(n);
+
+        TraceCostType::add(new TraceCostType(n, l, f));
+      }
+    }
+    else {
+      // add default types
+
+      TQString longName, formula;
+      TraceCostType* ct;
+      TQStringList l = knownTypes();
+      for ( TQStringList::Iterator it = l.begin();
+            it != l.end(); ++it ) {
+        longName = knownLongName(*it);
+        formula  = knownFormula(*it);
+        ct = new TraceCostType(*it, longName, formula);
+        TraceCostType::add(ct);
+      }
+    }
+  }
+}
+
+TQColor Configuration::groupColor(TraceItem* cost)
+{
+   TQString n;
+
+  if (!cost)
+    n = TQString("default");
+  else
+    n = TraceCost::typeName(cost->type()) + "-" + cost->prettyName();
+
+  return color(n)->color;
+}
+
+TQColor Configuration::costTypeColor(TraceCostType* t)
+{
+   TQString n;
+
+   if (!t)
+     n = TQString("CostType-default");
+   else
+     n = TQString("CostType-%1").arg(t->name());
+
+   return color(n)->color;
+}
+
+TQColor Configuration::functionColor(TraceCost::CostType gt,
+                                    TraceFunction* f)
+{
+  TraceCost* group = f;
+  TQString n;
+
+  switch(gt) {
+  case TraceCost::Object: group = f->object(); break;
+  case TraceCost::Class:  group = f->cls(); break;
+  case TraceCost::File:   group = f->file(); break;
+  default:
+    break;
+  }
+
+  if (group != f) {
+    // first look for manual color of a function in a group
+    n = TraceCost::typeName(group->type()) +
+        "-" + group->prettyName() +
+        "-" + f->prettyName();
+
+    ColorSetting* cs = color(n, false);
+    if (cs) return cs->color;
+  }
+  return groupColor(group);
+}
+
+Configuration::ColorSetting* Configuration::color(TQString n, bool createNew)
+{
+//  qDebug("Color for %s", n.latin1());
+
+  // predefined ?
+  Configuration* c = config();
+  ColorSetting* cs = c->_colors[n];
+  if (cs || !createNew) return cs;
+
+  // automatic colors...
+  int h = 0, s = 100;
+  const char* str = n.ascii();
+  while (*str) {
+    h = (h * 37 + s* (unsigned)*str) % 256;
+    s = (s * 17 + h* (unsigned)*str) % 192;
+    str++;
+  }
+
+  //qDebug("New color for %s: H %d, S %d", n.ascii(), h, 64+s);
+  TQColor color = TQColor(h, 64+s, 192, TQColor::Hsv);
+
+  cs = new ColorSetting;
+  cs->name = n;
+  cs->automatic = true;
+  cs->color = color;
+  c->_colors.insert(n, cs);
+
+  //qDebug("new Color %s", n.ascii());
+
+  return cs;
+}
+
+/* Gives back a list of all Source Base Directories of Objects in
+ * current trace. If a special object is given in 2nd argument,
+ * put its Source Base in front.
+ */
+TQStringList Configuration::sourceDirs(TraceData* data, TraceObject* o)
+{
+  TQStringList l = config()->_generalSourceDirs, *ol, *ol2 = 0;
+  TraceObjectMap::Iterator oit;
+  for ( oit = data->objectMap().begin();
+        oit != data->objectMap().end(); ++oit ) {
+    ol = config()->_objectSourceDirs[(*oit).name()];
+    if (&(*oit) == o) {
+      ol2 = ol;
+      continue;
+    }
+    if (!ol) continue;
+
+    for(unsigned int i=0;i<ol->count();i++)
+      l.prepend( (*ol)[i] );
+  }
+  if (ol2) {
+    for(unsigned int i=0;i<ol2->count();i++)
+      l.prepend( (*ol2)[i] );
+  }
+  if (0) kdDebug() << "Configuration::sourceDirs: " << l.join(":") << endl;
+
+  return l;
+}
+
+bool Configuration::showPercentage()
+{
+  return config()->_showPercentage;
+}
+
+bool Configuration::showExpanded()
+{
+  return config()->_showExpanded;
+}
+
+bool Configuration::showCycles()
+{
+  return config()->_showCycles;
+}
+
+void Configuration::setShowPercentage(bool s)
+{
+  Configuration* c = config();
+  if (c->_showPercentage == s) return;
+
+  c->_showPercentage = s;
+}
+
+void Configuration::setShowExpanded(bool s)
+{
+  Configuration* c = config();
+  if (c->_showExpanded == s) return;
+
+  c->_showExpanded = s;
+}
+
+void Configuration::setShowCycles(bool s)
+{
+  Configuration* c = config();
+  if (c->_showCycles == s) return;
+
+  c->_showCycles = s;
+}
+
+double Configuration::cycleCut()
+{
+  return config()->_cycleCut;
+}
+
+int Configuration::percentPrecision()
+{
+  return config()->_percentPrecision;
+}
+
+int Configuration::maxSymbolLength()
+{
+  return config()->_maxSymbolLength;
+}
+
+TQString Configuration::shortenSymbol(TQString s)
+{
+    if ((int)s.length() > maxSymbolLength())
+	s = s.left(maxSymbolLength()) + "...";
+    return s;
+}
+
+int Configuration::maxListCount()
+{
+  return config()->_maxListCount;
+}
+
+int Configuration::maxSymbolCount()
+{
+  return config()->_maxSymbolCount;
+}
+
+int Configuration::context()
+{
+  return config()->_context;
+}
+
+int Configuration::noCostInside()
+{
+  return config()->_noCostInside;
+}
diff --git a/kdecachegrind/kdecachegrind/configuration.h b/kdecachegrind/kdecachegrind/configuration.h
new file mode 100644
index 0000000..478f617
--- /dev/null
+++ b/kdecachegrind/kdecachegrind/configuration.h
@@ -0,0 +1,101 @@
+/* This file is part of KCachegrind.
+   Copyright (C) 2002, 2003 Josef Weidendorfer <Josef.Weidendorfer@gmx.de>
+
+   KCachegrind 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, version 2.
+
+   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; see the file COPYING.  If not, write to
+   the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+   Boston, MA 02110-1301, USA.
+*/
+
+/*
+ * Configuration for KCachegrind
+ */
+
+#ifndef CONFIGURATION_H
+#define CONFIGURATION_H
+
+#include <tqcolor.h>
+#include <tqstringlist.h>
+#include <tqdict.h>
+
+#include "tracedata.h"
+
+class KConfig;
+
+class Configuration
+{
+  friend class ConfigDlg;
+
+public:
+  Configuration();
+
+  static Configuration* config();
+
+  static void saveOptions(KConfig*);
+  static void readOptions(KConfig*);
+
+  // color for visualisation of an object
+  static TQColor functionColor(TraceItem::CostType gt, TraceFunction*);
+  static TQColor groupColor(TraceItem*);
+  static TQColor costTypeColor(TraceCostType*);
+  static TQStringList sourceDirs(TraceData*, TraceObject* o = 0);
+  static bool showPercentage();
+  static bool showExpanded();
+  static bool showCycles();
+
+  // lower percentage limit of cost items filled into lists
+  static int percentPrecision();
+  // max symbol lengths/count in tooltip/popup
+  static int maxSymbolLength();
+  // strip a symbol name according to <maxSymbolLength>
+  static TQString shortenSymbol(TQString);
+  static int maxSymbolCount();
+  // max. number of items in lists
+  static int maxListCount();
+  
+  // how many lines of context to show before/after annotated source/assembler
+  static int context();
+  // how many lines without cost are still regarded as inside a function
+  static int noCostInside();
+
+  static void setShowPercentage(bool);
+  static void setShowExpanded(bool);
+
+  static void setShowCycles(bool);
+  // upper limit for cutting of a call in cycle detection
+  static double cycleCut();
+
+private:
+  struct ColorSetting {
+    TQString name;
+    TQColor color;
+    bool automatic;
+  };
+
+  static ColorSetting* color(TQString, bool createNew = true);
+
+  TQDict<ColorSetting> _colors;
+
+  TQStringList _generalSourceDirs;
+  TQDict<TQStringList> _objectSourceDirs;
+
+  bool _showPercentage, _showExpanded, _showCycles;
+  double _cycleCut;
+  int _percentPrecision;
+  int _maxSymbolLength, _maxSymbolCount, _maxListCount;
+  int _context, _noCostInside;
+
+  static Configuration* _config;
+};
+
+
+#endif
diff --git a/kdecachegrind/kdecachegrind/costlistitem.cpp b/kdecachegrind/kdecachegrind/costlistitem.cpp
new file mode 100644
index 0000000..1e777b0
--- /dev/null
+++ b/kdecachegrind/kdecachegrind/costlistitem.cpp
@@ -0,0 +1,136 @@
+/* This file is part of KCachegrind.
+   Copyright (C) 2002, 2003 Josef Weidendorfer <Josef.Weidendorfer@gmx.de>
+
+   KCachegrind 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, version 2.
+
+   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; see the file COPYING.  If not, write to
+   the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+   Boston, MA 02110-1301, USA.
+*/
+
+#include <math.h>
+
+#include <tqpainter.h>
+#include <tqregexp.h>
+
+#include <klocale.h>
+#include <kiconloader.h>
+#include <kapplication.h>
+
+#include "listutils.h"
+#include "costlistitem.h"
+#include "coverage.h"
+#include "configuration.h"
+
+// CostListItem
+
+
+CostListItem::CostListItem(TQListView* parent, TraceCostItem* costItem,
+                           TraceCostType* ct, int size)
+  :TQListViewItem(parent)
+{
+  _groupSize = size;
+  _skipped = 0;
+  _costItem = costItem;
+  setCostType(ct);
+
+  if (costItem) {
+    updateName();
+    setPixmap(1, colorPixmap(10, 10,
+			     Configuration::groupColor(_costItem)));
+  }
+}
+
+CostListItem::CostListItem(TQListView* parent, int skipped,
+			   TraceCostItem* costItem, TraceCostType* ct)
+  :TQListViewItem(parent)
+{
+  _skipped = skipped;
+  _costItem = costItem;
+  setCostType(ct);
+
+  setText(1, i18n("(%n item skipped)", "(%n items skipped)", _skipped));
+}
+
+void CostListItem::setCostType(TraceCostType* ct)
+{
+  _costType = ct;
+  update();
+}
+
+void CostListItem::updateName()
+{
+  if (!_costItem) return;
+
+  TQString n = _costItem->prettyName();
+  if (_groupSize>=0) n += TQString(" (%1)").arg(_groupSize);
+
+  setText(1, n);
+}
+
+void CostListItem::setSize(int s)
+{
+  _groupSize = s;
+  updateName();
+}
+
+void CostListItem::update()
+{
+  if (!_costItem) return;
+  TraceData* d = _costItem->data();
+
+  double total = d->subCost(_costType);
+  if (total == 0.0) {
+    setText(0, TQString("---"));
+    setPixmap(0, TQPixmap());
+    return;
+  }
+
+  _pure = _costItem->subCost(_costType);
+  double pure  = 100.0 * _pure / total;
+  TQString str;
+  if (Configuration::showPercentage())
+    str = TQString("%1").arg(pure, 0, 'f', Configuration::percentPrecision());
+  else
+    str = _costItem->prettySubCost(_costType);
+
+  if (_skipped) {
+    // special handling for skip entries...
+    setText(0, TQString("< %1").arg(str));
+    return;
+  }
+
+  setText(0, str);
+  setPixmap(0, costPixmap(_costType, _costItem, total, false));
+}
+
+int CostListItem::compare(TQListViewItem * i, int col, bool ascending ) const
+{
+  const CostListItem* fi1 = this;
+  const CostListItem* fi2 = (CostListItem*) i;
+
+  // we always want descending order
+  if (ascending) {
+    fi1 = fi2;
+    fi2 = this;
+  }
+
+  // a skip entry is always sorted last
+  if (fi1->_skipped) return -1;
+  if (fi2->_skipped) return 1;
+
+  if (col==0) {
+    if (fi1->_pure < fi2->_pure) return -1;
+    if (fi1->_pure > fi2->_pure) return 1;
+    return 0;
+  }
+  return TQListViewItem::compare(i, col, ascending);
+}
diff --git a/kdecachegrind/kdecachegrind/costlistitem.h b/kdecachegrind/kdecachegrind/costlistitem.h
new file mode 100644
index 0000000..99f654e
--- /dev/null
+++ b/kdecachegrind/kdecachegrind/costlistitem.h
@@ -0,0 +1,52 @@
+/* This file is part of KCachegrind.
+   Copyright (C) 2003 Josef Weidendorfer <Josef.Weidendorfer@gmx.de>
+
+   KCachegrind 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, version 2.
+
+   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; see the file COPYING.  If not, write to
+   the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+   Boston, MA 02110-1301, USA.
+*/
+
+#ifndef COSTLISTITEM_H
+#define COSTLISTITEM_H
+
+#include <tqlistview.h>
+#include "tracedata.h"
+
+class CostListItem: public TQListViewItem
+{
+public:
+  CostListItem(TQListView* parent, TraceCostItem* cost,
+               TraceCostType* ct, int size = -1);
+  // entry with multiple skipped items
+  CostListItem(TQListView* parent, int skipped, TraceCostItem* cost,
+               TraceCostType* ct);
+
+  int compare(TQListViewItem * i, int col, bool ascending ) const;
+  TraceCostItem* costItem() { return (_skipped) ? 0 : _costItem; }
+  void setCostType(TraceCostType* ct);
+  void update();
+  void setSize(int s);
+
+private:
+  void updateName();
+
+  SubCost _pure;
+  TraceCostType* _costType;
+  TraceCostItem* _costItem;
+  // >0 only for last item in list, if items are skipped 
+  int _skipped;
+  // number of items in group, is put in parenthesis after name
+  int _groupSize;
+};
+
+#endif
diff --git a/kdecachegrind/kdecachegrind/costtypeitem.cpp b/kdecachegrind/kdecachegrind/costtypeitem.cpp
new file mode 100644
index 0000000..dc35cb2
--- /dev/null
+++ b/kdecachegrind/kdecachegrind/costtypeitem.cpp
@@ -0,0 +1,149 @@
+/* This file is part of KCachegrind.
+   Copyright (C) 2003 Josef Weidendorfer <Josef.Weidendorfer@gmx.de>
+
+   KCachegrind 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, version 2.
+
+   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; see the file COPYING.  If not, write to
+   the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+   Boston, MA 02110-1301, USA.
+*/
+
+/*
+ * Items of cost type view.
+ */
+
+#include <tqpixmap.h>
+#include <klocale.h>
+
+#include "configuration.h"
+#include "listutils.h"
+#include "costtypeitem.h"
+
+
+// CostTypeItem
+
+
+CostTypeItem::CostTypeItem(TQListView* parent, TraceCostItem* costItem,
+                           TraceCostType* ct, TraceCost::CostType gt)
+  :TQListViewItem(parent)
+{
+  _costItem = costItem;
+  _costType = ct;
+  _groupType = gt;
+
+  if (ct) {
+      setText(0, ct->longName());
+      setText(3, ct->name());
+      TQString formula = ct->formula();
+      setText(5, formula);
+      if (!formula.isEmpty()) {
+	  setText(4, "=");
+	  // we have a virtual type: allow editing
+	  setRenameEnabled(0, true);
+	  setRenameEnabled(3, true);
+	  setRenameEnabled(5, true);
+      } 
+  }
+  else {
+      setText(0, i18n("Unknown Type"));
+  }
+  update();
+}
+
+void CostTypeItem::setGroupType(TraceCost::CostType gt)
+{
+    if (_groupType == gt) return;
+
+    _groupType = gt;
+    update();
+}
+
+void CostTypeItem::update()
+{
+  TraceData* d = _costItem ? _costItem->data() : 0;
+  double total = d ? ((double)d->subCost(_costType)) : 0.0;
+
+  if (total == 0.0) {
+    setText(1, "-");
+    setPixmap(1, TQPixmap());
+    setText(2, "-");
+    setPixmap(2, TQPixmap());
+    return;
+  }
+
+  TraceFunction* f = (_costItem->type()==TraceCost::Function) ?
+                     (TraceFunction*)_costItem : 0;
+
+  TraceCost* selfTotalCost = f ? f->data() : d;
+  if (f && Configuration::showExpanded()) {
+      switch(_groupType) {
+      case TraceCost::Object: selfTotalCost = f->object(); break;
+      case TraceCost::Class:  selfTotalCost = f->cls(); break;
+      case TraceCost::File:   selfTotalCost = f->file(); break;
+      case TraceCost::FunctionCycle: selfTotalCost = f->cycle(); break;
+      default: break;
+      }
+  }
+  if (_costItem->type()==TraceCost::FunctionCycle) {
+      f = (TraceFunction*)_costItem;
+      selfTotalCost = f->data();
+  }
+
+  double selfTotal = selfTotalCost->subCost(_costType);
+
+  // for all cost items there's a self cost
+  _pure = _costItem ? _costItem->subCost(_costType) : SubCost(0);
+  double pure  = 100.0 * _pure / selfTotal;
+  if (Configuration::showPercentage()) {
+    setText(2, TQString("%1")
+            .arg(pure, 0, 'f', Configuration::percentPrecision()));
+  }
+  else
+    setText(2, _costItem->prettySubCost(_costType));
+
+  setPixmap(2, costPixmap(_costType, _costItem, selfTotal, false));
+
+  if (!f) {
+    setText(1, "-");
+    setPixmap(1, TQPixmap());
+    return;
+  }
+
+  _sum = f->inclusive()->subCost(_costType);
+  double sum  = 100.0 * _sum / total;
+  if (Configuration::showPercentage()) {
+    setText(1, TQString("%1")
+            .arg(sum, 0, 'f', Configuration::percentPrecision()));
+  }
+  else
+    setText(1, _sum.pretty());
+
+  setPixmap(1, costPixmap(_costType, f->inclusive(), total, false));
+}
+
+
+int CostTypeItem::compare(TQListViewItem * i, int col, bool ascending ) const
+{
+  CostTypeItem* fi = (CostTypeItem*) i;
+  if (col==0) {
+    if (_sum < fi->_sum) return -1;
+    if (_sum > fi->_sum) return 1;
+    return 0;
+  }
+  if (col==1) {
+    if (_pure < fi->_pure) return -1;
+    if (_pure > fi->_pure) return 1;
+    return 0;
+  }
+  return TQListViewItem::compare(i, col, ascending);
+}
+
+
diff --git a/kdecachegrind/kdecachegrind/costtypeitem.h b/kdecachegrind/kdecachegrind/costtypeitem.h
new file mode 100644
index 0000000..d34973d
--- /dev/null
+++ b/kdecachegrind/kdecachegrind/costtypeitem.h
@@ -0,0 +1,50 @@
+/* This file is part of KCachegrind.
+   Copyright (C) 2003 Josef Weidendorfer <Josef.Weidendorfer@gmx.de>
+
+   KCachegrind 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, version 2.
+
+   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; see the file COPYING.  If not, write to
+   the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+   Boston, MA 02110-1301, USA.
+*/
+
+/*
+ * Items of cost type view.
+ */
+
+#ifndef COSTTYEPITEM_H
+#define COSTTYEPITEM_H
+
+#include <tqlistview.h>
+#include "tracedata.h"
+
+
+class CostTypeItem: public TQListViewItem
+{
+public:
+  CostTypeItem(TQListView* parent, TraceCostItem* costItem,
+               TraceCostType* ct, TraceCost::CostType gt);
+
+  int compare(TQListViewItem * i, int col, bool ascending ) const;
+  void setGroupType(TraceCost::CostType);
+  TraceCostItem* costItem() { return _costItem; }
+  TraceCostType* costType() { return _costType; }
+  void update();
+
+private:
+  SubCost _sum, _pure;
+  TraceCostType* _costType;
+  TraceCostItem* _costItem;
+  TraceCost::CostType _groupType;
+};
+
+
+#endif
diff --git a/kdecachegrind/kdecachegrind/costtypeview.cpp b/kdecachegrind/kdecachegrind/costtypeview.cpp
new file mode 100644
index 0000000..3f5417e
--- /dev/null
+++ b/kdecachegrind/kdecachegrind/costtypeview.cpp
@@ -0,0 +1,310 @@
+/* This file is part of KCachegrind.
+   Copyright (C) 2003 Josef Weidendorfer <Josef.Weidendorfer@gmx.de>
+
+   KCachegrind 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, version 2.
+
+   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; see the file COPYING.  If not, write to
+   the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+   Boston, MA 02110-1301, USA.
+*/
+
+/*
+ * Cost Type View
+ */
+
+#include <tqwhatsthis.h>
+#include <tqpopupmenu.h>
+#include <klocale.h>
+
+#include "configuration.h"
+#include "costtypeitem.h"
+#include "costtypeview.h"
+#include "toplevel.h"
+
+
+//
+// CostTypeView
+//
+
+
+CostTypeView::CostTypeView(TraceItemView* parentView,
+			   TQWidget* parent, const char* name)
+  : TQListView(parent, name), TraceItemView(parentView)
+{
+    addColumn( i18n( "Event Type" ) );
+    addColumn( i18n( "Incl." ) );
+    addColumn( i18n( "Self" ) );
+    addColumn( i18n( "Short" ) );
+    addColumn( TQString() );
+    addColumn( i18n( "Formula" ) );
+
+    setSorting(-1);
+    setAllColumnsShowFocus(true);
+    setColumnAlignment(1, TQt::AlignRight);
+    setColumnAlignment(2, TQt::AlignRight);
+    setColumnAlignment(3, TQt::AlignRight);
+    setMinimumHeight(50);
+
+    connect( this,
+	     TQT_SIGNAL( selectionChanged(TQListViewItem*) ),
+	     TQT_SLOT( selectedSlot(TQListViewItem*) ) );
+
+    connect( this,
+	     TQT_SIGNAL(contextMenuRequested(TQListViewItem*, const TQPoint &, int)),
+	     TQT_SLOT(context(TQListViewItem*, const TQPoint &, int)));
+
+    connect(this,
+	    TQT_SIGNAL(doubleClicked(TQListViewItem*)),
+	    TQT_SLOT(activatedSlot(TQListViewItem*)));
+
+    connect(this,
+	    TQT_SIGNAL(returnPressed(TQListViewItem*)),
+	    TQT_SLOT(activatedSlot(TQListViewItem*)));
+
+    connect(this,
+	    TQT_SIGNAL(itemRenamed(TQListViewItem*,int,const TQString&)),
+	    TQT_SLOT(renamedSlot(TQListViewItem*,int,const TQString&)));
+
+    TQWhatsThis::add( this, whatsThis() );
+}
+
+TQString CostTypeView::whatsThis() const
+{
+    return i18n( "<b>Cost Types List</b>"
+		 "<p>This list shows all cost types available "
+		 "and what the self/inclusive cost of the "
+		 "current selected function is for that cost type.</p>"
+		 "<p>By choosing a cost type from the list, "
+		 "you change the cost type of costs shown "
+		 "all over KCachegrind to be the selected one.</p>");
+}
+
+
+void CostTypeView::context(TQListViewItem* i, const TQPoint & p, int)
+{
+  TQPopupMenu popup;
+
+  TraceCostType* ct = i ? ((CostTypeItem*) i)->costType() : 0;
+
+  if (ct)
+    popup.insertItem(i18n("Set Secondary Event Type"), 99);
+  if (_costType2)
+    popup.insertItem(i18n("Remove Secondary Event Type"), 98);
+  if (popup.count()>0)
+    popup.insertSeparator();
+
+  if (ct && !ct->isReal()) {
+      popup.insertItem(i18n("Edit Long Name"), 93);
+      popup.insertItem(i18n("Edit Short Name"), 94);
+      popup.insertItem(i18n("Edit Formula"), 95);
+      popup.insertItem(i18n("Remove"), 96);
+      popup.insertSeparator();
+  }
+
+  addGoMenu(&popup);
+
+  popup.insertSeparator();
+  popup.insertItem(i18n("New Cost Type ..."), 97);
+
+  int r = popup.exec(p);
+  if (r == 98) selectedCostType2(0);
+  else if (r == 99) selectedCostType2(ct);
+  else if (r == 93) i->startRename(0);
+  else if (r == 94) i->startRename(3);
+  else if (r == 95) i->startRename(5);
+  else if (r == 96) {
+
+    // search for a previous type 
+    TraceCostType* prev = 0, *ct = 0;
+    TraceCostMapping* m = _data->mapping();
+    for (int i=0;i<m->realCount();i++) {
+	ct = m->realType(i);
+	if (ct) prev = ct;
+    }
+    for (int i=0;i<m->virtualCount();i++) {
+	ct = m->virtualType(i);
+	if (ct == _costType) break;
+	if (ct) prev = ct;
+    }
+
+    if (_data->mapping()->remove(ct)) {
+      // select previous cost type
+      selectedCostType(prev);
+      if (_costType2 == ct)
+	selectedCostType2(prev);
+      refresh();
+    }
+  }
+  else if (r == 97) {
+    int i = 1;
+    while(1) {
+      if (!TraceCostType::knownVirtualType(i18n("New%1").arg(i)))
+	break;
+      i++;
+    }
+    // add same new cost type to this mapping and to known types
+    TQString shortName = i18n("New%1").arg(i);
+    TQString longName  = i18n("New Cost Type %1").arg(i);
+    TraceCostType::add(new TraceCostType(shortName, longName, "0"));
+    _data->mapping()->add(new TraceCostType(shortName, longName, "0"));
+    refresh();
+  }
+}
+
+void CostTypeView::selectedSlot(TQListViewItem * i)
+{
+    TraceCostType* ct = i ? ((CostTypeItem*) i)->costType() : 0;
+    if (ct)
+	selectedCostType(ct);
+}
+
+void CostTypeView::activatedSlot(TQListViewItem * i)
+{
+  TraceCostType* ct = i ? ((CostTypeItem*) i)->costType() : 0;
+  if (ct)
+      selectedCostType2(ct);
+}
+
+TraceItem* CostTypeView::canShow(TraceItem* i)
+{
+    if (!i) return 0;
+
+    switch(i->type()) {
+    case TraceCost::Object:
+    case TraceCost::Class:
+    case TraceCost::File:
+    case TraceCost::Call:
+    case TraceCost::FunctionCycle:
+    case TraceCost::Function:
+	break;
+    default:
+	return 0;
+    }
+    return i;
+}
+
+void CostTypeView::doUpdate(int changeType)
+{
+    // Special case ?
+    if (changeType == selectedItemChanged) return;
+
+    if (changeType == costType2Changed) return;
+
+    if (changeType == groupTypeChanged) {
+	TQListViewItem *item;
+	for (item = firstChild();item;item = item->nextSibling())
+	    ((CostTypeItem*)item)->setGroupType(_groupType);
+
+	return;
+    }
+
+    if (changeType == costTypeChanged) {
+	TQListViewItem *item;
+	for (item = firstChild();item;item = item->nextSibling())
+	    if ( ((CostTypeItem*)item)->costType() == _costType) {
+		setSelected(item, true);
+		ensureItemVisible(item);
+		break;
+	    }
+
+	return;
+    }
+
+    if (changeType == partsChanged) {
+	TQListViewItem *item;
+	for (item = firstChild();item;item = item->nextSibling())
+	    ((CostTypeItem*)item)->update();
+
+	return;
+    }
+
+
+    refresh();
+}
+
+void CostTypeView::refresh()
+{
+    clear();
+    setColumnWidth(1, 50);
+    setColumnWidth(2, 50);
+
+    if (!_data || !_activeItem) return;
+    switch(_activeItem->type()) {
+    case TraceCost::Object:
+    case TraceCost::Class:
+    case TraceCost::File:
+    case TraceCost::FunctionCycle:
+    case TraceCost::Function:
+	break;
+    default:
+	return;
+    }
+    TraceCostItem* c = (TraceCostItem*) _activeItem;
+
+    TraceCostType* ct =0 ;
+    TQListViewItem* item = 0;
+    TQString sumStr, pureStr;
+    TQListViewItem* costItem=0;
+
+    TraceCostMapping* m = _data->mapping();
+    for (int i=m->virtualCount()-1;i>=0;i--) {
+	ct = m->virtualType(i);
+	if (!ct) continue;
+	item = new CostTypeItem(this, c, ct, _groupType);
+	if (ct == _costType) costItem = item;
+    }
+    for (int i=m->realCount()-1;i>=0;i--) {
+	ct = m->realType(i);
+	item = new CostTypeItem(this, c, ct, _groupType);
+	if (ct == _costType) costItem = item;
+    }
+
+    if (costItem) {
+	setSelected(costItem, true);
+	ensureItemVisible(costItem);
+    }
+
+    if (item) setMinimumHeight(3*item->height());
+}
+
+
+void CostTypeView::renamedSlot(TQListViewItem* item,int c,const TQString& t)
+{
+  TraceCostType* ct = item ? ((CostTypeItem*) item)->costType() : 0;
+  if (!ct || ct->isReal()) return;
+
+  // search for matching known Type
+  int knownCount = TraceCostType::knownTypeCount();
+  TraceCostType* known = 0;
+  for (int i=0; i<knownCount; i++) {
+      known = TraceCostType::knownType(i);
+      if (known->name() == ct->name()) break;
+  }
+
+  if (c == 0) {
+      ct->setLongName(t);
+      if (known) known->setLongName(t);
+  }
+  else if (c == 3) {
+      ct->setName(t);
+      if (known) known->setName(t);
+  }
+  else if (c == 5) {
+      ct->setFormula(t);
+      if (known) known->setFormula(t);
+  }
+  else return;
+
+  if (_topLevel) _topLevel->configChanged();
+  refresh();
+}
+
+#include "costtypeview.moc"
diff --git a/kdecachegrind/kdecachegrind/costtypeview.h b/kdecachegrind/kdecachegrind/costtypeview.h
new file mode 100644
index 0000000..ee9963e
--- /dev/null
+++ b/kdecachegrind/kdecachegrind/costtypeview.h
@@ -0,0 +1,54 @@
+/* This file is part of KCachegrind.
+   Copyright (C) 2003 Josef Weidendorfer <Josef.Weidendorfer@gmx.de>
+
+   KCachegrind 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, version 2.
+
+   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; see the file COPYING.  If not, write to
+   the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+   Boston, MA 02110-1301, USA.
+*/
+
+/*
+ * Cost Type View
+ */
+
+#ifndef COSTTYPEVIEW_H
+#define COSTTYPEVIEW_H
+
+#include <tqlistview.h>
+#include "tracedata.h"
+#include "traceitemview.h"
+
+class CostTypeView: public TQListView, public TraceItemView
+{
+  Q_OBJECT
+  TQ_OBJECT
+
+public:
+  CostTypeView(TraceItemView* parentView,
+	       TQWidget* parent=0, const char* name=0);
+
+  virtual TQWidget* widget() { return this; }
+  TQString whatsThis() const;
+
+private slots:
+  void context(TQListViewItem*,const TQPoint &, int);
+  void selectedSlot(TQListViewItem*);
+  void activatedSlot(TQListViewItem*);
+  void renamedSlot(TQListViewItem*,int,const TQString&);
+
+private:
+  TraceItem* canShow(TraceItem*);
+  void doUpdate(int);
+  void refresh();
+};
+
+#endif
diff --git a/kdecachegrind/kdecachegrind/coverage.cpp b/kdecachegrind/kdecachegrind/coverage.cpp
new file mode 100644
index 0000000..86e6f7f
--- /dev/null
+++ b/kdecachegrind/kdecachegrind/coverage.cpp
@@ -0,0 +1,329 @@
+/* This file is part of KCachegrind.
+   Copyright (C) 2002 Josef Weidendorfer <Josef.Weidendorfer@gmx.de>
+
+   KCachegrind 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, version 2.
+
+   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; see the file COPYING.  If not, write to
+   the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+   Boston, MA 02110-1301, USA.
+*/
+
+/*
+ * Function Coverage Analysis
+ */
+
+#include "coverage.h"
+
+//#define DEBUG_COVERAGE 1
+
+TraceCostType* Coverage::_costType;
+
+const int Coverage::maxHistogramDepth = maxHistogramDepthValue;
+const int Coverage::Rtti = 1;
+
+Coverage::Coverage()
+{
+}
+
+void Coverage::init()
+{
+  _self = 0.0;
+  _incl  = 0.0;
+  _callCount = 0.0;
+  // should always be overwritten before usage
+  _firstPercentage = 1.0;
+  _minDistance = 9999;
+  _maxDistance = 0;
+  _active = false;
+  _inRecursion = false;
+  for (int i = 0;i<maxHistogramDepth;i++) {
+    _selfHisto[i] = 0.0;
+    _inclHisto[i] = 0.0;
+  }
+
+  _valid = true;
+}
+
+int Coverage::inclusiveMedian()
+{
+  double maxP = _inclHisto[0];
+  int medD = 0;
+  for (int i = 1;i<maxHistogramDepth;i++)
+    if (_inclHisto[i]>maxP) {
+      maxP = _inclHisto[i];
+      medD = i;
+    }
+
+  return medD;
+}
+
+int Coverage::selfMedian()
+{
+  double maxP = _selfHisto[0];
+  int medD = 0;
+  for (int i = 1;i<maxHistogramDepth;i++)
+    if (_selfHisto[i]>maxP) {
+      maxP = _selfHisto[i];
+      medD = i;
+    }
+
+  return medD;
+}
+
+TraceFunctionList Coverage::coverage(TraceFunction* f, CoverageMode m,
+                                      TraceCostType* ct)
+{
+  invalidate(f->data(), Coverage::Rtti);
+
+  _costType = ct;
+
+  // function f takes ownership over c!
+  Coverage* c = new Coverage();
+  c->setFunction(f);
+  c->init();
+
+  TraceFunctionList l;
+
+  if (m == Caller)
+    c->addCallerCoverage(l, 1.0, 0);
+  else
+    c->addCallingCoverage(l, 1.0, 1.0, 0);
+
+  return l;
+}
+
+void Coverage::addCallerCoverage(TraceFunctionList& fList,
+                                 double pBack, int d)
+{
+  TraceCallList cList;
+  TraceCall* call;
+  Coverage* c;
+
+  if (_inRecursion) return;
+
+  double incl;
+  incl  = (double) (_function->inclusive()->subCost(_costType));
+
+  if (_active) {
+#ifdef DEBUG_COVERAGE
+    qDebug("CallerCov: D %d, %s (was active, incl %f, self %f): newP %f", d,
+           _function->prettyName().ascii(), _incl, _self, pBack);
+#endif
+    _inRecursion = true;
+  }
+  else {
+    _active = true;
+
+    // only add cost if this is no recursion
+
+    _incl += pBack;
+    _firstPercentage = pBack;
+
+    if (_minDistance > d) _minDistance = d;
+    if (_maxDistance < d) _maxDistance = d;
+    if (d<maxHistogramDepth) {
+      _inclHisto[d] += pBack;
+    }
+    else {
+      _inclHisto[maxHistogramDepth-1] += pBack;
+    }
+
+#ifdef DEBUG_COVERAGE
+    qDebug("CallerCov: D %d, %s (now active, new incl %f): newP %f",
+           d, _function->prettyName().ascii(), _incl, pBack);
+#endif
+  }
+
+  double callVal, pBackNew;
+
+  cList = _function->callers();
+  for (call=cList.first();call;call=cList.next()) {
+    if (call->inCycle()>0) continue;
+    if (call->isRecursion()) continue;
+
+    if (call->subCost(_costType)>0) {
+      TraceFunction* caller = call->caller();
+
+      c = (Coverage*) caller->assoziation(rtti());
+      if (!c) {
+        c = new Coverage();
+        c->setFunction(caller);
+      }
+      if (!c->isValid()) {
+        c->init();
+        fList.append(caller);
+      }
+
+      if (c->isActive()) continue;
+      if (c->inRecursion()) continue;
+
+      callVal = (double) call->subCost(_costType);
+      pBackNew = pBack * (callVal / incl);
+
+      // FIXME ?!?
+
+      if (!c->isActive()) {
+	  if (d>=0)
+	      c->callCount() += (double)call->callCount();
+	  else
+	      c->callCount() += _callCount;
+      }
+      else {
+        // adjust pNew by sum of geometric series of recursion factor.
+        // Thus we can avoid endless recursion here
+        pBackNew *= 1.0 / (1.0 - pBackNew / c->firstPercentage());
+      }
+
+      // Limit depth
+      if (pBackNew > 0.0001)
+        c->addCallerCoverage(fList, pBackNew, d+1);
+    }
+  }
+
+  if (_inRecursion)
+    _inRecursion = false;
+  else if (_active)
+    _active = false;
+}
+
+/**
+ * pForward is time on percent used,
+ * pBack is given to allow for calculation of call counts
+ */
+void Coverage::addCallingCoverage(TraceFunctionList& fList,
+                                  double pForward, double pBack, int d)
+{
+  TraceCallList cList;
+  TraceCall* call;
+  Coverage* c;
+
+  if (_inRecursion) return;
+
+#ifdef DEBUG_COVERAGE
+  static const char* spaces = "                                            ";
+#endif
+
+  double self, incl;
+  incl  = (double) (_function->inclusive()->subCost(_costType));
+
+#ifdef DEBUG_COVERAGE
+    qDebug("CngCov:%s - %s (incl %f, self %f): forward %f, back %f",
+	   spaces+strlen(spaces)-d,
+           _function->prettyName().ascii(), _incl, _self, pForward, pBack);
+#endif
+
+
+  if (_active) {
+    _inRecursion = true;
+
+#ifdef DEBUG_COVERAGE
+    qDebug("CngCov:%s < %s: STOP (is active)",
+	   spaces+strlen(spaces)-d,
+           _function->prettyName().ascii());
+#endif
+
+  }
+  else {
+    _active = true;
+
+    // only add cost if this is no recursion
+    self = pForward * (_function->subCost(_costType)) / incl;
+    _incl += pForward;
+    _self += self;
+    _firstPercentage = pForward;
+
+    if (_minDistance > d) _minDistance = d;
+    if (_maxDistance < d) _maxDistance = d;
+     if (d<maxHistogramDepth) {
+      _inclHisto[d] += pForward;
+      _selfHisto[d] += self;
+    }
+    else {
+      _inclHisto[maxHistogramDepth-1] += pForward;
+      _selfHisto[maxHistogramDepth-1] += self;
+    }
+
+#ifdef DEBUG_COVERAGE
+    qDebug("CngCov:%s < %s (incl %f, self %f)",
+	   spaces+strlen(spaces)-d,
+           _function->prettyName().ascii(), _incl, _self);
+#endif
+  }
+
+  double callVal, pForwardNew, pBackNew;
+
+  cList = _function->callings();
+  for (call=cList.first();call;call=cList.next()) {
+    if (call->inCycle()>0) continue;
+    if (call->isRecursion()) continue;
+
+    if (call->subCost(_costType)>0) {
+      TraceFunction* calling = call->called();
+
+      c = (Coverage*) calling->assoziation(rtti());
+      if (!c) {
+        c = new Coverage();
+        c->setFunction(calling);
+      }
+      if (!c->isValid()) {
+        c->init();
+        fList.append(calling);
+      }
+
+      if (c->isActive()) continue;
+      if (c->inRecursion()) continue;
+
+      callVal = (double) call->subCost(_costType);
+      pForwardNew = pForward * (callVal / incl);
+      pBackNew    = pBack * (callVal / 
+			     calling->inclusive()->subCost(_costType));
+
+      if (!c->isActive()) {
+	  c->callCount() += pBack * call->callCount();
+
+#ifdef DEBUG_COVERAGE
+        qDebug("CngCov:%s  > %s: forward %f, back %f, calls %f -> %f, now %f",
+	       spaces+strlen(spaces)-d,
+               calling->prettyName().ascii(),
+	       pForwardNew, pBackNew,
+	       (double)call->callCount(),
+	       pBack * call->callCount(),
+	       c->callCount());
+#endif
+      }
+      else {
+        // adjust pNew by sum of geometric series of recursion factor.
+        // Thus we can avoid endless recursion here
+        double fFactor = 1.0 / (1.0 - pForwardNew / c->firstPercentage());
+        double bFactor = 1.0 / (1.0 - pBackNew);
+#ifdef DEBUG_COVERAGE
+        qDebug("CngCov:%s Recursion - origP %f, actP %f => factor %f, newP %f",
+	       spaces+strlen(spaces)-d,
+               c->firstPercentage(), pForwardNew,
+	       fFactor, pForwardNew * fFactor);
+#endif
+        pForwardNew *= fFactor;
+        pBackNew *= bFactor;
+
+      }
+
+      // Limit depth
+      if (pForwardNew > 0.0001)
+        c->addCallingCoverage(fList, pForwardNew, pBackNew, d+1);
+    }
+  }
+
+  if (_inRecursion)
+    _inRecursion = false;
+  else if (_active)
+    _active = false;
+}
+
diff --git a/kdecachegrind/kdecachegrind/coverage.h b/kdecachegrind/kdecachegrind/coverage.h
new file mode 100644
index 0000000..50c5936
--- /dev/null
+++ b/kdecachegrind/kdecachegrind/coverage.h
@@ -0,0 +1,102 @@
+/* This file is part of KCachegrind.
+   Copyright (C) 2002 Josef Weidendorfer <Josef.Weidendorfer@gmx.de>
+
+   KCachegrind 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, version 2.
+
+   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; see the file COPYING.  If not, write to
+   the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+   Boston, MA 02110-1301, USA.
+*/
+
+/*
+ * Function Coverage Analysis
+ */
+
+#ifndef COVERAGE_H
+#define COVERAGE_H
+
+#include "tracedata.h"
+
+/**
+ * Coverage of a function.
+ * When analysis is done, every function involved will have a
+ * pointer to an object of this class.
+ *
+ * This function also holds the main routine for coverage analysis,
+ * Coverage::coverage(), as static method.
+ */
+class Coverage : public TraceAssoziation
+{
+public:
+  /* Direction of coverage analysis */
+  enum CoverageMode { Caller, Called };
+
+  // max depth for distance histogram
+#define maxHistogramDepthValue 40
+  static const int maxHistogramDepth;
+
+  static const int Rtti;
+
+  Coverage();
+
+  virtual int rtti() { return Rtti; }
+  void init();
+
+  TraceFunction* function() { return _function; }
+  double self() { return _self; }
+  double inclusive() { return _incl; }
+  double firstPercentage() { return _firstPercentage; }
+  double& callCount() { return _callCount; }
+  int minDistance() { return _minDistance; }
+  int maxDistance() { return _maxDistance; }
+  int inclusiveMedian();
+  int selfMedian();
+  double* selfHistogram() { return _selfHisto; }
+  double* inclusiveHistogram() { return _inclHisto; }
+  bool isActive() { return _active; }
+  bool inRecursion() { return _inRecursion; }
+
+  void setSelf(float p) { _self = p; }
+  void setInclusive(float p) { _incl = p; }
+  void setCallCount(float cc) { _callCount = cc; }
+  void setActive(bool a) { _active = a; }
+  void setInRecursion(bool r) { _inRecursion = r; }
+
+  /**
+   * Calculate coverage of all functions based on function f.
+   * If mode is Called, the coverage of functions called by
+   * f is calculated, otherwise that of functions calling f.
+   * SubCost type ct is used for the analysis.
+   * Self values are undefined for Caller mode.
+   *
+   * Returns list of functions covered.
+   * Coverage degree of returned functions can be get
+   * with function->coverage()->percentage()
+   */
+  static TraceFunctionList coverage(TraceFunction* f, CoverageMode m,
+                                    TraceCostType* ct);
+
+private:
+  void addCallerCoverage(TraceFunctionList& l, double, int d);
+  void addCallingCoverage(TraceFunctionList& l, double, double, int d);
+
+  double _self, _incl, _firstPercentage, _callCount;
+  int _minDistance, _maxDistance;
+  bool _active, _inRecursion;
+  double _selfHisto[maxHistogramDepthValue];
+  double _inclHisto[maxHistogramDepthValue];
+
+  // temporary set for one coverage analysis
+  static TraceCostType* _costType;
+};
+
+#endif
+
diff --git a/kdecachegrind/kdecachegrind/coverageitem.cpp b/kdecachegrind/kdecachegrind/coverageitem.cpp
new file mode 100644
index 0000000..26e5b36
--- /dev/null
+++ b/kdecachegrind/kdecachegrind/coverageitem.cpp
@@ -0,0 +1,343 @@
+/* This file is part of KCachegrind.
+   Copyright (C) 2003 Josef Weidendorfer <Josef.Weidendorfer@gmx.de>
+
+   KCachegrind 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, version 2.
+
+   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; see the file COPYING.  If not, write to
+   the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+   Boston, MA 02110-1301, USA.
+*/
+
+/*
+ * Items of coverage view.
+ */
+
+#include <tqpixmap.h>
+#include <klocale.h>
+
+#include "configuration.h"
+#include "listutils.h"
+#include "coverage.h"
+#include "coverageitem.h"
+
+
+// CallerCoverageItem
+
+
+CallerCoverageItem::CallerCoverageItem(TQListView* parent, Coverage* c,
+                                       TraceFunction* base,
+                                       TraceCostType* ct,
+                                       TraceCost::CostType gt)
+    : TQListViewItem(parent)
+{
+  _skipped = 0;
+  _coverage = c;
+  _function = c ? c->function() : 0;
+  _base = base;
+  _groupType = TraceCost::NoCostType;
+
+  setText(3, _function->prettyNameWithLocation());
+
+  setCostType(ct);
+  setGroupType(gt);
+}
+
+CallerCoverageItem::CallerCoverageItem(TQListView* parent, int skipped, Coverage* c,
+                                       TraceFunction* base,
+                                       TraceCostType* ct,
+                                       TraceCost::CostType gt)
+    : TQListViewItem(parent)
+{
+  _skipped = skipped;
+  _coverage = c;
+  _function = c ? c->function() : 0;
+  _base = base;
+  _groupType = TraceCost::NoCostType;
+
+  setText(3, i18n("(%n function skipped)", "(%n functions skipped)", _skipped));
+
+  setCostType(ct);
+  setGroupType(gt);
+}
+
+void CallerCoverageItem::setGroupType(TraceCost::CostType gt)
+{
+  if (_skipped) return;
+  if (_groupType == gt) return;
+  _groupType = gt;
+
+  TQColor c = Configuration::functionColor(_groupType, _function);
+  setPixmap(3, colorPixmap(10, 10, c));
+}
+
+void CallerCoverageItem::setCostType(TraceCostType* ct)
+{
+  _costType = ct;
+  update();
+}
+
+void CallerCoverageItem::update()
+{
+  if (!_coverage) {
+    setText(0, TQString());
+    setText(1, TQString());
+    return;
+  }
+
+  _pSum = 100.0 * _coverage->inclusive();
+  SubCost realSum = _base->inclusive()->subCost(_costType);
+  _sum = SubCost(realSum * _coverage->inclusive());
+  TQString str;
+  if (Configuration::showPercentage())
+    str = TQString("%1").arg(_pSum, 0, 'f', Configuration::percentPrecision());
+  else
+    str = _sum.pretty();
+
+  if (_skipped) {
+    setText(0, TQString("< %1").arg(str));
+    return;
+  }
+
+  setText(0, str);
+  setPixmap(0, partitionPixmap(25, 10, _coverage->inclusiveHistogram(), 0,
+                               Coverage::maxHistogramDepth, false));
+
+  // call count
+  _cc  = SubCost(_coverage->callCount());
+  setText(2, _cc ? _cc.pretty() : TQString("(0)"));
+
+  // distance (min/max/median)
+  _distance = _coverage->inclusiveMedian();
+  TQString distString;
+  if (_coverage->minDistance() == _coverage->maxDistance())
+    distString = TQString::number(_distance);
+  else
+    distString = TQString("%1-%2 (%3)")
+                 .arg(_coverage->minDistance())
+                 .arg(_coverage->maxDistance())
+                 .arg(_distance);
+  setText(1, distString);
+}
+
+
+int CallerCoverageItem::compare(TQListViewItem * i,
+                                int col, bool ascending ) const
+{
+  const CallerCoverageItem* ci1 = this;
+  const CallerCoverageItem* ci2 = (CallerCoverageItem*) i;
+
+  // we always want descending order
+  if (ascending) {
+    ci1 = ci2;
+    ci2 = this;
+  }
+
+  // a skip entry is always sorted last
+  if (ci1->_skipped) return -1;
+  if (ci2->_skipped) return 1;
+
+  if (col==0) {
+    if (ci1->_pSum < ci2->_pSum) return -1;
+    if (ci1->_pSum > ci2->_pSum) return 1;
+
+    // for same percentage (e.g. all 100%), use distance info
+    if (ci1->_distance < ci2->_distance) return -1;
+    if (ci1->_distance > ci2->_distance) return 1;
+    return 0;
+  }
+
+  if (col==1) {
+    if (ci1->_distance < ci2->_distance) return -1;
+    if (ci1->_distance > ci2->_distance) return 1;
+    return 0;
+  }
+
+  if (col==2) {
+    if (ci1->_cc < ci2->_cc) return -1;
+    if (ci1->_cc > ci2->_cc) return 1;
+    return 0;
+  }
+  return TQListViewItem::compare(i, col, ascending);
+}
+
+
+// CalleeCoverageItem
+
+
+CalleeCoverageItem::CalleeCoverageItem(TQListView* parent, Coverage* c,
+                                       TraceFunction* base,
+                                       TraceCostType* ct,
+                                       TraceCost::CostType gt)
+    : TQListViewItem(parent)
+{
+  _skipped = 0;
+  _coverage = c;
+  _function = c ? c->function() : 0;
+  _base = base;
+  _groupType = TraceCost::NoCostType;
+
+  setText(4, _function->prettyNameWithLocation());
+
+  setCostType(ct);
+  setGroupType(gt);
+}
+
+CalleeCoverageItem::CalleeCoverageItem(TQListView* parent, int skipped, Coverage* c,
+                                       TraceFunction* base,
+                                       TraceCostType* ct,
+                                       TraceCost::CostType gt)
+    : TQListViewItem(parent)
+{
+  _skipped = skipped;
+  _coverage = c;
+  _function = c ? c->function() : 0;
+  _base = base;
+  _groupType = TraceCost::NoCostType;
+
+  setText(4, i18n("(%n function skipped)", "(%n functions skipped)", _skipped));
+
+  setCostType(ct);
+  setGroupType(gt);
+}
+
+void CalleeCoverageItem::setGroupType(TraceCost::CostType gt)
+{
+  if (_skipped) return;
+  if (_groupType == gt) return;
+  _groupType = gt;
+
+  TQColor c = Configuration::functionColor(_groupType, _function);
+  setPixmap(4, colorPixmap(10, 10, c));
+}
+
+void CalleeCoverageItem::setCostType(TraceCostType* ct)
+{
+  _costType = ct;
+  update();
+}
+
+void CalleeCoverageItem::update()
+{
+  if (!_coverage) {
+    setText(0, TQString());
+    setText(1, TQString());
+    setText(2, TQString());
+    return;
+  }
+
+  _pSum = 100.0 * _coverage->inclusive();
+
+  // pSum/pSelf are percentages of inclusive cost of base
+  SubCost realSum = _base->inclusive()->subCost(_costType);
+  _sum = SubCost(realSum * _coverage->inclusive());
+
+
+  TQString str;
+  if (Configuration::showPercentage())
+    str = TQString("%1").arg(_pSum, 0, 'f', Configuration::percentPrecision());
+  else
+    str = _sum.pretty();
+
+  if (_skipped) {
+    str = TQString("< %1").arg(str);
+    setText(0, str);
+    setText(1, str);
+    return;
+  }
+ setText(0, str);
+
+ _pSelf = 100.0 * _coverage->self();
+ _self = SubCost(realSum * _coverage->self());
+
+ if (Configuration::showPercentage()) {
+    setText(1, TQString("%1")
+            .arg(_pSelf, 0, 'f', Configuration::percentPrecision()));
+  }
+  else {
+    setText(1, _self.pretty());
+  }
+
+  setPixmap(0, partitionPixmap(25, 10, _coverage->inclusiveHistogram(), 0,
+                               Coverage::maxHistogramDepth, false));
+  setPixmap(1, partitionPixmap(25, 10, _coverage->selfHistogram(), 0,
+                               Coverage::maxHistogramDepth, false));
+
+
+  _cc  = SubCost(_coverage->callCount());
+  setText(3, _cc ? _cc.pretty() : TQString("(0)"));
+
+  // for comparations
+  _distance = _coverage->inclusiveMedian();
+  TQString distString;
+  if (_coverage->minDistance() == _coverage->maxDistance())
+    distString = TQString::number(_distance);
+  else {
+    int sMed = _coverage->selfMedian();
+    TQString med;
+    if (_distance == sMed)
+      med = TQString::number(_distance);
+    else
+      med = TQString("%1/%2").arg(_distance).arg(sMed);
+
+    distString = TQString("%1-%2 (%3)")
+                 .arg(_coverage->minDistance())
+                 .arg(_coverage->maxDistance())
+                 .arg(med);
+  }
+  setText(2, distString);
+}
+
+
+int CalleeCoverageItem::compare(TQListViewItem * i,
+                                int col, bool ascending ) const
+{
+  CalleeCoverageItem* ci = (CalleeCoverageItem*) i;
+
+  // a skip entry is always sorted last
+  if (_skipped) return -1;
+  if (ci->_skipped) return 1;
+
+  if (col==0) {
+    if (_pSum < ci->_pSum) return -1;
+    if (_pSum > ci->_pSum) return 1;
+
+    // for same percentage (e.g. all 100%), use distance info
+    if (_distance < ci->_distance) return -1;
+    if (_distance > ci->_distance) return 1;
+    return 0;
+  }
+
+  if (col==1) {
+    if (_pSelf < ci->_pSelf) return -1;
+    if (_pSelf > ci->_pSelf) return 1;
+
+    // for same percentage (e.g. all 100%), use distance info
+    if (_distance < ci->_distance) return -1;
+    if (_distance > ci->_distance) return 1;
+    return 0;
+  }
+
+  if (col==2) {
+    // we want to sort the distance in contra direction to costs
+    if (_distance < ci->_distance) return  1;
+    if (_distance > ci->_distance) return -1;
+    return 0;
+  }
+
+  if (col==3) {
+    if (_cc < ci->_cc) return -1;
+    if (_cc > ci->_cc) return 1;
+    return 0;
+  }
+  return TQListViewItem::compare(i, col, ascending);
+}
+
+
diff --git a/kdecachegrind/kdecachegrind/coverageitem.h b/kdecachegrind/kdecachegrind/coverageitem.h
new file mode 100644
index 0000000..ba442aa
--- /dev/null
+++ b/kdecachegrind/kdecachegrind/coverageitem.h
@@ -0,0 +1,82 @@
+/* This file is part of KCachegrind.
+   Copyright (C) 2003 Josef Weidendorfer <Josef.Weidendorfer@gmx.de>
+
+   KCachegrind 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, version 2.
+
+   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; see the file COPYING.  If not, write to
+   the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+   Boston, MA 02110-1301, USA.
+*/
+
+/*
+ * Items of coverage view.
+ */
+
+#ifndef COVERAGEITEM_H
+#define COVERAGEITEM_H
+
+#include <tqlistview.h>
+#include "tracedata.h"
+
+class Coverage;
+
+class CallerCoverageItem: public TQListViewItem
+{
+public:
+  CallerCoverageItem(TQListView* parent, Coverage* c, TraceFunction* base,
+                     TraceCostType* ct, TraceCost::CostType gt);
+  CallerCoverageItem(TQListView* parent, int skipped, Coverage* c, TraceFunction* base,
+                     TraceCostType* ct, TraceCost::CostType gt);
+
+  int compare(TQListViewItem * i, int col, bool ascending ) const;
+  TraceFunction* function() { return (_skipped) ? 0 : _function; }
+  void setCostType(TraceCostType* ct);
+  void setGroupType(TraceCost::CostType);
+  void update();
+
+private:
+  float _pSum;
+  SubCost _sum;
+  TraceCostType* _costType;
+  TraceCost::CostType _groupType;
+  SubCost _cc;
+  int _distance, _skipped;
+  TraceFunction *_function, *_base;
+  Coverage* _coverage;
+};
+
+
+class CalleeCoverageItem: public TQListViewItem
+{
+public:
+  CalleeCoverageItem(TQListView* parent, Coverage* c, TraceFunction* base,
+                     TraceCostType* ct, TraceCost::CostType gt);
+  CalleeCoverageItem(TQListView* parent, int skipped, Coverage* c, TraceFunction* base,
+                     TraceCostType* ct, TraceCost::CostType gt);
+
+  int compare(TQListViewItem * i, int col, bool ascending ) const;
+  TraceFunction* function() { return (_skipped) ? 0 : _function; }
+  void setCostType(TraceCostType* ct);
+  void setGroupType(TraceCost::CostType);
+  void update();
+
+private:
+  float _pSum, _pSelf;
+  SubCost _sum, _self;
+  TraceCostType* _costType;
+  TraceCost::CostType _groupType;
+  SubCost _cc;
+  int _distance, _skipped;
+  TraceFunction *_function, *_base;
+  Coverage* _coverage;
+};
+
+#endif
diff --git a/kdecachegrind/kdecachegrind/coverageview.cpp b/kdecachegrind/kdecachegrind/coverageview.cpp
new file mode 100644
index 0000000..6657e92
--- /dev/null
+++ b/kdecachegrind/kdecachegrind/coverageview.cpp
@@ -0,0 +1,321 @@
+/* This file is part of KCachegrind.
+   Copyright (C) 2003 Josef Weidendorfer <Josef.Weidendorfer@gmx.de>
+
+   KCachegrind 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, version 2.
+
+   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; see the file COPYING.  If not, write to
+   the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+   Boston, MA 02110-1301, USA.
+*/
+
+/*
+ * Coverage Views
+ */
+
+#include <tqwhatsthis.h>
+#include <tqpopupmenu.h>
+#include <klocale.h>
+
+#include "configuration.h"
+#include "coverageitem.h"
+#include "coverage.h"
+#include "coverageview.h"
+
+
+
+//
+// CoverageView
+//
+
+
+CoverageView::CoverageView(bool showCallers, TraceItemView* parentView,
+			   TQWidget* parent, const char* name)
+  : TQListView(parent, name), TraceItemView(parentView)
+{
+    _showCallers = showCallers;
+
+
+    addColumn( i18n( "Incl." ) );
+    if (_showCallers) {
+	addColumn( i18n( "Distance" ) );
+	addColumn( i18n( "Called" ) );
+	addColumn( i18n( "Caller" ) );
+    }
+    else {
+	addColumn( i18n( "Self" ) );
+	addColumn( i18n( "Distance" ) );
+	addColumn( i18n( "Calling" ) );
+	addColumn( i18n( "Callee" ) );
+	setColumnAlignment(3, TQt::AlignRight);
+    }
+
+    setSorting(0,false);
+    setColumnAlignment(0, TQt::AlignRight);
+    setColumnAlignment(1, TQt::AlignRight);
+    setColumnAlignment(2, TQt::AlignRight);
+    setAllColumnsShowFocus(true);
+    setResizeMode(TQListView::LastColumn);
+    setMinimumHeight(50);
+
+    connect( this,
+	     TQT_SIGNAL( selectionChanged(TQListViewItem*) ),
+	     TQT_SLOT( selectedSlot(TQListViewItem*) ) );
+
+    connect( this,
+	     TQT_SIGNAL(contextMenuRequested(TQListViewItem*, const TQPoint &, int)),
+	     TQT_SLOT(context(TQListViewItem*, const TQPoint &, int)));
+
+    connect(this,
+	    TQT_SIGNAL(doubleClicked(TQListViewItem*)),
+	    TQT_SLOT(activatedSlot(TQListViewItem*)));
+
+    connect(this,
+	    TQT_SIGNAL(returnPressed(TQListViewItem*)),
+	    TQT_SLOT(activatedSlot(TQListViewItem*)));
+
+    TQWhatsThis::add( this, whatsThis() );
+}
+
+TQString CoverageView::whatsThis() const
+{
+    return _showCallers ?
+	i18n( "<b>List of all Callers</b>"
+	      "<p>This list shows all functions calling the "
+	      "current selected one, either directly or with "
+	      "several functions in-between on the stack; the "
+	      "number of functions in-between plus one "
+	      "is called the <em>Distance</em> (e.g. "
+	      "for function A,B,C there exists a call from "
+	      "A to C when A calls B and B calls C, i.e. "
+	      "A => B => C. The distance here is 2).</p>"
+
+	      "<p>Absolute cost shown is the cost spent in the "
+	      "selected function while a listed function is active; "
+	      "relative cost is the percentage of all cost spent in "
+	      "the selected function while the listed one is "
+	      "active. The cost graphic shows logarithmic "
+	      "percentage with a different color for each "
+	      "distance.</p>"
+
+	      "<p>As there can be many calls from the same function, "
+	      "the distance column sometimes shows "
+	      "the range of distances for all "
+	      "calls happening; then, in parentheses, there is the "
+	      "medium distance, i.e. the distance where most of the "
+	      "call costs happened.</p>"
+
+	      "<p>Selecting a function makes it the current selected "
+	      "one of this information panel. "
+	      "If there are two panels (Split mode), the "
+	      "function of the other panel is changed instead.</p>") :
+
+	i18n( "<b>List of all Callees</b>"
+	      "<p>This list shows all functions called by the "
+	      "current selected one, either directly or with "
+	      "several function in-between on the stack; the "
+	      "number of function in-between plus one "
+	      "is called the <em>Distance</em> (e.g. "
+	      "for function A,B,C there exists a call from "
+	      "A to C when A calls B and B calls C, i.e. "
+	      "A => B => C. The distance here is 2).</p>"
+
+	      "<p>Absolute cost shown is the cost spent in the "
+	      "listed function while the selected is active; "
+	      "relative cost is the percentage of all cost spent in "
+	      "the listed function while the selected one is active. "
+	      "The cost graphic always shows logarithmic "
+	      "percentage with a different color for each "
+	      "distance.</p>"
+
+	      "<p>As there can be many calls to the same function, "
+	      "the distance column sometimes shows "
+	      "the range of distances for all "
+	      "calls happening; then, in parentheses, there is the "
+	      "medium distance, i.e. the distance where most of the "
+	      "call costs happened.</p>"
+
+	      "<p>Selecting a function makes it the current selected "
+	      "one of this information panel. "
+	      "If there are two panels (Split mode), the "
+	      "function of the other panel is changed instead.</p>");
+}
+
+void CoverageView::context(TQListViewItem* i, const TQPoint & p, int c)
+{
+  TQPopupMenu popup;
+
+  TraceFunction* f = 0;
+  if (i) {
+      f = _showCallers ?
+	  ((CallerCoverageItem*)i)->function() :
+	  ((CalleeCoverageItem*)i)->function();
+  }
+
+  if (f) {
+    TQString name = f->name();
+    if ((int)name.length()>Configuration::maxSymbolLength())
+	name = name.left(Configuration::maxSymbolLength()) + "...";
+    popup.insertItem(i18n("Go to '%1'").arg(name), 93);
+    popup.insertSeparator();
+  }
+
+   if ((c == 0) || (!_showCallers && c == 1)) {
+    addCostMenu(&popup, false);
+    popup.insertSeparator();
+  }
+  addGoMenu(&popup); 
+
+  int r = popup.exec(p);
+  if (r == 93) activated(f);
+}
+
+void CoverageView::selectedSlot(TQListViewItem * i)
+{
+  TraceFunction* f = 0;
+  if (i) {
+      f = _showCallers ?
+	  ((CallerCoverageItem*)i)->function() :
+	  ((CalleeCoverageItem*)i)->function();
+  }
+
+  if (f) {
+      _selectedItem = f;
+      selected(f);
+  }
+}
+
+void CoverageView::activatedSlot(TQListViewItem * i)
+{
+  TraceFunction* f = 0;
+  if (i) {
+      f = _showCallers ?
+	  ((CallerCoverageItem*)i)->function() :
+	  ((CalleeCoverageItem*)i)->function();
+  }
+
+  if (f) activated(f);
+}
+
+TraceItem* CoverageView::canShow(TraceItem* i)
+{
+  TraceItem::CostType t = i ? i->type() : TraceItem::NoCostType;
+
+  switch(t) {
+  case TraceItem::Function:
+  case TraceItem::FunctionCycle:
+      return i;
+  default:
+      break;
+  }
+  return 0;
+}
+
+void CoverageView::doUpdate(int changeType)
+{
+    // Special case ?
+    if (changeType == selectedItemChanged) {
+
+	if (!_selectedItem) {
+	    clearSelection();
+	    return;
+	}
+
+	TraceFunction* f = 0;
+	TQListViewItem* i = TQListView::selectedItem();
+	if (i) {
+	    f = _showCallers ?
+		((CallerCoverageItem*)i)->function() :
+		((CalleeCoverageItem*)i)->function();
+	}
+	if (f == _selectedItem) return;
+
+	TQListViewItem *item;
+	for (item = firstChild();item;item = item->nextSibling()) {
+	    f = _showCallers ?
+		((CallerCoverageItem*)item)->function() :
+		((CalleeCoverageItem*)item)->function();
+	    if (f == _selectedItem) {
+		ensureItemVisible(item);
+		setCurrentItem(item);
+		break;
+	    }
+	}
+	return;
+    }
+
+    if (changeType == groupTypeChanged) {
+	TQListViewItem *item;
+	for (item = firstChild();item;item = item->nextSibling()) {
+	    if (_showCallers)
+		((CallerCoverageItem*)item)->setGroupType(_groupType);
+	    else
+		((CalleeCoverageItem*)item)->setGroupType(_groupType);
+	}
+	return;
+    }
+
+    refresh();
+}
+
+void CoverageView::refresh()
+{
+    clear();
+    setColumnWidth(0, 50);
+    if (!_showCallers)
+	setColumnWidth(1, 50);
+
+    if (!_data || !_activeItem) return;
+
+    TraceItem::CostType t = _activeItem->type();
+    TraceFunction* f = 0;
+    if (t == TraceItem::Function) f = (TraceFunction*) _activeItem;
+    if (t == TraceItem::FunctionCycle) f = (TraceFunction*) _activeItem;
+    if (!f) return;
+
+    TraceFunction* ff;
+    TraceFunctionList l;
+
+    _hc.clear(Configuration::maxListCount());
+    SubCost realSum = f->inclusive()->subCost(_costType);
+
+    if (_showCallers)
+      l = Coverage::coverage(f, Coverage::Caller, _costType);
+    else
+      l = Coverage::coverage(f, Coverage::Called, _costType);
+
+    for (ff=l.first();ff;ff=l.next()) {
+      Coverage* c = (Coverage*) ff->assoziation(Coverage::Rtti);
+      if (c && (c->inclusive()>0.0))
+	_hc.addCost(ff, SubCost(realSum * c->inclusive()));
+    }
+
+    for(int i=0;i<_hc.realCount();i++) {
+      ff = (TraceFunction*) _hc[i];
+      Coverage* c = (Coverage*) ff->assoziation(Coverage::Rtti);
+      if (_showCallers)
+	new CallerCoverageItem(this, c, f, _costType, _groupType);
+      else
+	new CalleeCoverageItem(this, c, f, _costType, _groupType);
+    }
+    if (_hc.hasMore()) {
+      // a placeholder for all the functions skipped ...
+      ff = (TraceFunction*) _hc[_hc.maxSize()-1];
+      Coverage* c = (Coverage*) ff->assoziation(Coverage::Rtti);
+      if (_showCallers)
+	new CallerCoverageItem(this, _hc.count() - _hc.maxSize(),
+			       c, f, _costType, _groupType);
+      else
+	new CalleeCoverageItem(this, _hc.count() - _hc.maxSize(),
+			       c, f, _costType, _groupType);
+    }
+}
+
+#include "coverageview.moc"
diff --git a/kdecachegrind/kdecachegrind/coverageview.h b/kdecachegrind/kdecachegrind/coverageview.h
new file mode 100644
index 0000000..09c5de0
--- /dev/null
+++ b/kdecachegrind/kdecachegrind/coverageview.h
@@ -0,0 +1,57 @@
+/* This file is part of KCachegrind.
+   Copyright (C) 2003 Josef Weidendorfer <Josef.Weidendorfer@gmx.de>
+
+   KCachegrind 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, version 2.
+
+   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; see the file COPYING.  If not, write to
+   the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+   Boston, MA 02110-1301, USA.
+*/
+
+/*
+ * Coverage Views
+ */
+
+#ifndef COVERAGEVIEW_H
+#define COVERAGEVIEW_H
+
+#include <tqlistview.h>
+#include "tracedata.h"
+#include "traceitemview.h"
+#include "listutils.h"
+
+class CoverageView: public TQListView, public TraceItemView
+{
+  Q_OBJECT
+  TQ_OBJECT
+
+public:
+  CoverageView(bool showCallers, TraceItemView* parentView,
+	       TQWidget* parent=0, const char* name=0);
+
+  virtual TQWidget* widget() { return this; }
+  TQString whatsThis() const;
+
+private slots:
+  void context(TQListViewItem*,const TQPoint &, int);
+  void selectedSlot(TQListViewItem*);
+  void activatedSlot(TQListViewItem*);
+
+private:
+  TraceItem* canShow(TraceItem*);
+  void doUpdate(int);
+  void refresh();
+
+  HighestCostList _hc;
+  bool _showCallers;
+};
+
+#endif
diff --git a/kdecachegrind/kdecachegrind/dumpmanager.cpp b/kdecachegrind/kdecachegrind/dumpmanager.cpp
new file mode 100644
index 0000000..2f0891a
--- /dev/null
+++ b/kdecachegrind/kdecachegrind/dumpmanager.cpp
@@ -0,0 +1,50 @@
+/**
+ * DumpManager
+ * Part of KCachegrind
+ * 2003, Josef Weidendorfer (GPL V2)
+ */
+
+#include "dumpmanager.h"
+
+
+//
+// Dump
+//
+
+Dump::Dump(TQString file)
+{
+  _filename = file;
+}
+
+
+//
+// DumpManager
+//
+
+DumpManager* DumpManager::_self = 0;
+
+
+DumpManager::DumpManager()
+{
+}
+
+DumpManager* DumpManager::self()
+{
+  if (!_self)
+    _self = new DumpManager();
+
+  return _self;
+}
+
+
+DumpList DumpManager::loadableDumps()
+{
+  DumpList res;
+
+  return res;
+}
+
+TraceData* DumpManager::load(Dump*)
+{
+  return 0;
+}
diff --git a/kdecachegrind/kdecachegrind/dumpmanager.h b/kdecachegrind/kdecachegrind/dumpmanager.h
new file mode 100644
index 0000000..4925819
--- /dev/null
+++ b/kdecachegrind/kdecachegrind/dumpmanager.h
@@ -0,0 +1,59 @@
+/**
+ * DumpManager
+ * Part of KCachegrind
+ * 2003, Josef Weidendorfer (GPL V2)
+ *
+ * DumpManager is a Singleton.
+ * - Has List of current loaded dumps / loadable dumps
+ * - Does "communication" with current running profiles
+ *   for dump selection dockable
+ */
+
+#ifndef DUMPMANAGER_H
+#define DUMPMANAGER_H
+
+#include <tqstring.h>
+#include <tqptrlist.h>
+
+class Dump;
+class TraceData;
+
+typedef TQPtrList<Dump> DumpList;
+
+
+/**
+ * A loadable profile Dump
+ */
+class Dump
+{
+public:
+  Dump(TQString);
+
+  TQString filename() { return _filename; }
+
+private:
+  TQString _filename;
+};
+
+
+/*
+ * TODO:
+ * - Everything
+ *
+ */
+
+class DumpManager
+{
+public:
+  DumpManager();
+
+  DumpManager* self();
+
+  DumpList loadableDumps();
+  TraceData* load(Dump*);
+
+private:
+  static DumpManager* _self;
+};
+
+#endif
diff --git a/kdecachegrind/kdecachegrind/dumpselection.cpp b/kdecachegrind/kdecachegrind/dumpselection.cpp
new file mode 100644
index 0000000..4d812ef
--- /dev/null
+++ b/kdecachegrind/kdecachegrind/dumpselection.cpp
@@ -0,0 +1,33 @@
+/**
+ * DumpSelection Dockable
+ * Part of KCachegrind
+ * 2003, Josef Weidendorfer (GPL V2)
+ *
+ * - Fast Selection of dumps to load/activate/use for comparing
+ * - Start a profile run from GUI (current supported: Callgrind)
+ * - View state of running profile runs.
+ *
+ */
+
+#include "dumpselection.h"
+
+/*
+ * TODO:
+ *  - Everything !!
+ *  - Request State info on current function..
+ *
+ */
+
+
+DumpSelection::DumpSelection( TopLevel* top,
+                              TQWidget* parent, const char* name)
+    : DumpSelectionBase(parent, name), TraceItemView(0, top)
+{
+}
+
+DumpSelection::~DumpSelection()
+{}
+
+
+#include "dumpselection.moc"
+
diff --git a/kdecachegrind/kdecachegrind/dumpselection.h b/kdecachegrind/kdecachegrind/dumpselection.h
new file mode 100644
index 0000000..49ca532
--- /dev/null
+++ b/kdecachegrind/kdecachegrind/dumpselection.h
@@ -0,0 +1,30 @@
+/**
+ * DumpSelection Dockable
+ * Part of KCachegrind
+ * 2003, Josef Weidendorfer (GPL V2)
+ *
+ * - Fast Selection of dumps to load/activate/use for comparing
+ * - Start a profile run from GUI (current supported: Callgrind)
+ * - View state of running profile runs.
+ *
+ */
+
+#ifndef DUMPSELECTION_H
+#define DUMPSELECTION_H
+
+#include "dumpselectionbase.h"
+#include "traceitemview.h"
+
+class DumpSelection : public DumpSelectionBase, public TraceItemView
+{
+  Q_OBJECT
+  TQ_OBJECT
+
+public:
+  DumpSelection( TopLevel*, TQWidget* parent = 0, const char* name = 0);
+  virtual ~DumpSelection();
+
+  TQWidget* widget() { return this; }
+};
+
+#endif
diff --git a/kdecachegrind/kdecachegrind/dumpselectionbase.ui b/kdecachegrind/kdecachegrind/dumpselectionbase.ui
new file mode 100644
index 0000000..b8ad1b0
--- /dev/null
+++ b/kdecachegrind/kdecachegrind/dumpselectionbase.ui
@@ -0,0 +1,1082 @@
+<!DOCTYPE UI><UI version="3.2" stdsetdef="1">
+<class>DumpSelectionBase</class>
+<widget class="TQWidget">
+    <property name="name">
+        <cstring>DumpSelectionBase</cstring>
+    </property>
+    <property name="geometry">
+        <rect>
+            <x>0</x>
+            <y>0</y>
+            <width>349</width>
+            <height>832</height>
+        </rect>
+    </property>
+    <property name="caption">
+        <string>Profile Dumps</string>
+    </property>
+    <vbox>
+        <property name="name">
+            <cstring>unnamed</cstring>
+        </property>
+        <widget class="TQSplitter">
+            <property name="name">
+                <cstring>splitter1</cstring>
+            </property>
+            <property name="orientation">
+                <enum>Vertical</enum>
+            </property>
+            <widget class="TQListView">
+                <column>
+                    <property name="text">
+                        <string>Target</string>
+                    </property>
+                    <property name="clickable">
+                        <bool>true</bool>
+                    </property>
+                    <property name="resizable">
+                        <bool>true</bool>
+                    </property>
+                </column>
+                <column>
+                    <property name="text">
+                        <string></string>
+                    </property>
+                    <property name="clickable">
+                        <bool>true</bool>
+                    </property>
+                    <property name="resizable">
+                        <bool>true</bool>
+                    </property>
+                </column>
+                <column>
+                    <property name="text">
+                        <string>Time</string>
+                    </property>
+                    <property name="clickable">
+                        <bool>true</bool>
+                    </property>
+                    <property name="resizable">
+                        <bool>true</bool>
+                    </property>
+                </column>
+                <column>
+                    <property name="text">
+                        <string>Path</string>
+                    </property>
+                    <property name="clickable">
+                        <bool>true</bool>
+                    </property>
+                    <property name="resizable">
+                        <bool>true</bool>
+                    </property>
+                </column>
+                <property name="name">
+                    <cstring>listView1</cstring>
+                </property>
+            </widget>
+            <widget class="TQTabWidget">
+                <property name="name">
+                    <cstring>tabWidget2</cstring>
+                </property>
+                <widget class="TQWidget">
+                    <property name="name">
+                        <cstring>tab</cstring>
+                    </property>
+                    <attribute name="title">
+                        <string>Options</string>
+                    </attribute>
+                    <vbox>
+                        <property name="name">
+                            <cstring>unnamed</cstring>
+                        </property>
+                        <widget class="TQLabel">
+                            <property name="name">
+                                <cstring>textLabel1</cstring>
+                            </property>
+                            <property name="sizePolicy">
+                                <sizepolicy>
+                                    <hsizetype>5</hsizetype>
+                                    <vsizetype>5</vsizetype>
+                                    <horstretch>1</horstretch>
+                                    <verstretch>0</verstretch>
+                                </sizepolicy>
+                            </property>
+                            <property name="text">
+                                <string>Target command:</string>
+                            </property>
+                        </widget>
+                        <widget class="TQLineEdit">
+                            <property name="name">
+                                <cstring>lineEdit1</cstring>
+                            </property>
+                        </widget>
+                        <widget class="TQLabel">
+                            <property name="name">
+                                <cstring>textLabel2</cstring>
+                            </property>
+                            <property name="text">
+                                <string>Profiler options:</string>
+                            </property>
+                        </widget>
+                        <widget class="TQListView">
+                            <column>
+                                <property name="text">
+                                    <string>Option</string>
+                                </property>
+                                <property name="clickable">
+                                    <bool>true</bool>
+                                </property>
+                                <property name="resizable">
+                                    <bool>true</bool>
+                                </property>
+                            </column>
+                            <column>
+                                <property name="text">
+                                    <string>Value</string>
+                                </property>
+                                <property name="clickable">
+                                    <bool>true</bool>
+                                </property>
+                                <property name="resizable">
+                                    <bool>true</bool>
+                                </property>
+                            </column>
+                        <item>
+                            <property name="text">
+                                <string>Trace</string>
+                            </property>
+                            <property name="text">
+                                <string></string>
+                            </property>
+                            <property name="pixmap">
+                                <pixmap></pixmap>
+                            </property>
+                            <property name="pixmap">
+                                <pixmap></pixmap>
+                            </property>
+                            <item>
+                                <property name="text">
+                                    <string>Jumps</string>
+                                </property>
+                                <property name="text">
+                                    <string></string>
+                                </property>
+                                <property name="pixmap">
+                                    <pixmap></pixmap>
+                                </property>
+                                <property name="pixmap">
+                                    <pixmap></pixmap>
+                                </property>
+                            </item>
+                            <item>
+                                <property name="text">
+                                    <string>Instructions</string>
+                                </property>
+                                <property name="text">
+                                    <string></string>
+                                </property>
+                                <property name="pixmap">
+                                    <pixmap></pixmap>
+                                </property>
+                                <property name="pixmap">
+                                    <pixmap></pixmap>
+                                </property>
+                            </item>
+                        </item>
+                        <item>
+                            <property name="text">
+                                <string>Events</string>
+                            </property>
+                            <property name="text">
+                                <string></string>
+                            </property>
+                            <property name="pixmap">
+                                <pixmap></pixmap>
+                            </property>
+                            <property name="pixmap">
+                                <pixmap></pixmap>
+                            </property>
+                            <item>
+                                <property name="text">
+                                    <string>Full Cache</string>
+                                </property>
+                                <property name="text">
+                                    <string></string>
+                                </property>
+                                <property name="pixmap">
+                                    <pixmap></pixmap>
+                                </property>
+                                <property name="pixmap">
+                                    <pixmap></pixmap>
+                                </property>
+                            </item>
+                            <item>
+                                <property name="text">
+                                    <string>Custom</string>
+                                </property>
+                                <property name="text">
+                                    <string></string>
+                                </property>
+                                <property name="pixmap">
+                                    <pixmap></pixmap>
+                                </property>
+                                <property name="pixmap">
+                                    <pixmap></pixmap>
+                                </property>
+                            </item>
+                        </item>
+                        <item>
+                            <property name="text">
+                                <string>Collect</string>
+                            </property>
+                            <property name="text">
+                                <string></string>
+                            </property>
+                            <property name="pixmap">
+                                <pixmap></pixmap>
+                            </property>
+                            <property name="pixmap">
+                                <pixmap></pixmap>
+                            </property>
+                            <item>
+                                <property name="text">
+                                    <string>At Startup</string>
+                                </property>
+                                <property name="text">
+                                    <string></string>
+                                </property>
+                                <property name="pixmap">
+                                    <pixmap></pixmap>
+                                </property>
+                                <property name="pixmap">
+                                    <pixmap></pixmap>
+                                </property>
+                            </item>
+                            <item>
+                                <property name="text">
+                                    <string>While In</string>
+                                </property>
+                                <property name="text">
+                                    <string></string>
+                                </property>
+                                <property name="pixmap">
+                                    <pixmap></pixmap>
+                                </property>
+                                <property name="pixmap">
+                                    <pixmap></pixmap>
+                                </property>
+                            </item>
+                        </item>
+                        <item>
+                            <property name="text">
+                                <string>Skip</string>
+                            </property>
+                            <property name="text">
+                                <string></string>
+                            </property>
+                            <property name="pixmap">
+                                <pixmap></pixmap>
+                            </property>
+                            <property name="pixmap">
+                                <pixmap></pixmap>
+                            </property>
+                            <item>
+                                <property name="text">
+                                    <string>PLT</string>
+                                </property>
+                                <property name="text">
+                                    <string></string>
+                                </property>
+                                <property name="pixmap">
+                                    <pixmap></pixmap>
+                                </property>
+                                <property name="pixmap">
+                                    <pixmap></pixmap>
+                                </property>
+                            </item>
+                            <item>
+                                <property name="text">
+                                    <string>Function</string>
+                                </property>
+                                <property name="text">
+                                    <string></string>
+                                </property>
+                                <property name="pixmap">
+                                    <pixmap></pixmap>
+                                </property>
+                                <property name="pixmap">
+                                    <pixmap></pixmap>
+                                </property>
+                            </item>
+                        </item>
+                        <item>
+                            <property name="text">
+                                <string>Dump Profile</string>
+                            </property>
+                            <property name="text">
+                                <string></string>
+                            </property>
+                            <property name="pixmap">
+                                <pixmap></pixmap>
+                            </property>
+                            <property name="pixmap">
+                                <pixmap></pixmap>
+                            </property>
+                            <item>
+                                <property name="text">
+                                    <string>Every BBs</string>
+                                </property>
+                                <property name="text">
+                                    <string></string>
+                                </property>
+                                <property name="pixmap">
+                                    <pixmap></pixmap>
+                                </property>
+                                <property name="pixmap">
+                                    <pixmap></pixmap>
+                                </property>
+                            </item>
+                            <item>
+                                <property name="text">
+                                    <string>On Entering</string>
+                                </property>
+                                <property name="text">
+                                    <string></string>
+                                </property>
+                                <property name="pixmap">
+                                    <pixmap></pixmap>
+                                </property>
+                                <property name="pixmap">
+                                    <pixmap></pixmap>
+                                </property>
+                            </item>
+                            <item>
+                                <property name="text">
+                                    <string>On Leaving</string>
+                                </property>
+                                <property name="text">
+                                    <string></string>
+                                </property>
+                                <property name="pixmap">
+                                    <pixmap></pixmap>
+                                </property>
+                                <property name="pixmap">
+                                    <pixmap></pixmap>
+                                </property>
+                            </item>
+                        </item>
+                        <item>
+                            <property name="text">
+                                <string>Zero Events</string>
+                            </property>
+                            <property name="text">
+                                <string></string>
+                            </property>
+                            <property name="pixmap">
+                                <pixmap></pixmap>
+                            </property>
+                            <property name="pixmap">
+                                <pixmap></pixmap>
+                            </property>
+                            <item>
+                                <property name="text">
+                                    <string>On Entering</string>
+                                </property>
+                                <property name="text">
+                                    <string></string>
+                                </property>
+                                <property name="pixmap">
+                                    <pixmap></pixmap>
+                                </property>
+                                <property name="pixmap">
+                                    <pixmap></pixmap>
+                                </property>
+                            </item>
+                        </item>
+                        <item>
+                            <property name="text">
+                                <string>Separate</string>
+                            </property>
+                            <property name="text">
+                                <string></string>
+                            </property>
+                            <property name="pixmap">
+                                <pixmap></pixmap>
+                            </property>
+                            <property name="pixmap">
+                                <pixmap></pixmap>
+                            </property>
+                            <item>
+                                <property name="text">
+                                    <string>Threads</string>
+                                </property>
+                                <property name="text">
+                                    <string></string>
+                                </property>
+                                <property name="pixmap">
+                                    <pixmap></pixmap>
+                                </property>
+                                <property name="pixmap">
+                                    <pixmap></pixmap>
+                                </property>
+                            </item>
+                            <item>
+                                <property name="text">
+                                    <string>Recursions</string>
+                                </property>
+                                <property name="text">
+                                    <string></string>
+                                </property>
+                                <property name="pixmap">
+                                    <pixmap></pixmap>
+                                </property>
+                                <property name="pixmap">
+                                    <pixmap></pixmap>
+                                </property>
+                            </item>
+                            <item>
+                                <property name="text">
+                                    <string>Call Chain</string>
+                                </property>
+                                <property name="text">
+                                    <string></string>
+                                </property>
+                                <property name="pixmap">
+                                    <pixmap></pixmap>
+                                </property>
+                                <property name="pixmap">
+                                    <pixmap></pixmap>
+                                </property>
+                            </item>
+                        </item>
+                            <property name="name">
+                                <cstring>listView3</cstring>
+                            </property>
+                        </widget>
+                        <widget class="TQLabel">
+                            <property name="name">
+                                <cstring>textLabel1_2</cstring>
+                            </property>
+                            <property name="sizePolicy">
+                                <sizepolicy>
+                                    <hsizetype>5</hsizetype>
+                                    <vsizetype>5</vsizetype>
+                                    <horstretch>1</horstretch>
+                                    <verstretch>0</verstretch>
+                                </sizepolicy>
+                            </property>
+                            <property name="text">
+                                <string>Custom profiler options:</string>
+                            </property>
+                        </widget>
+                        <widget class="TQLineEdit">
+                            <property name="name">
+                                <cstring>lineEdit1_2</cstring>
+                            </property>
+                        </widget>
+                        <widget class="TQLayoutWidget">
+                            <property name="name">
+                                <cstring>layout3</cstring>
+                            </property>
+                            <hbox>
+                                <property name="name">
+                                    <cstring>unnamed</cstring>
+                                </property>
+                                <spacer>
+                                    <property name="name">
+                                        <cstring>spacer1</cstring>
+                                    </property>
+                                    <property name="orientation">
+                                        <enum>Horizontal</enum>
+                                    </property>
+                                    <property name="sizeType">
+                                        <enum>Expanding</enum>
+                                    </property>
+                                    <property name="sizeHint">
+                                        <size>
+                                            <width>21</width>
+                                            <height>20</height>
+                                        </size>
+                                    </property>
+                                </spacer>
+                                <widget class="TQPushButton">
+                                    <property name="name">
+                                        <cstring>pushButton2</cstring>
+                                    </property>
+                                    <property name="text">
+                                        <string>Run New Profile</string>
+                                    </property>
+                                </widget>
+                            </hbox>
+                        </widget>
+                    </vbox>
+                </widget>
+                <widget class="TQWidget">
+                    <property name="name">
+                        <cstring>tab</cstring>
+                    </property>
+                    <attribute name="title">
+                        <string>Info</string>
+                    </attribute>
+                    <vbox>
+                        <property name="name">
+                            <cstring>unnamed</cstring>
+                        </property>
+                        <widget class="TQLabel">
+                            <property name="name">
+                                <cstring>textLabel8</cstring>
+                            </property>
+                            <property name="text">
+                                <string>Dump reason:</string>
+                            </property>
+                        </widget>
+                        <widget class="TQLineEdit">
+                            <property name="name">
+                                <cstring>lineEdit3</cstring>
+                            </property>
+                        </widget>
+                        <widget class="TQLabel">
+                            <property name="name">
+                                <cstring>textLabel6</cstring>
+                            </property>
+                            <property name="text">
+                                <string>Event summary:</string>
+                            </property>
+                        </widget>
+                        <widget class="TQListView">
+                            <column>
+                                <property name="text">
+                                    <string>Name</string>
+                                </property>
+                                <property name="clickable">
+                                    <bool>true</bool>
+                                </property>
+                                <property name="resizable">
+                                    <bool>true</bool>
+                                </property>
+                            </column>
+                            <column>
+                                <property name="text">
+                                    <string>Sum</string>
+                                </property>
+                                <property name="clickable">
+                                    <bool>true</bool>
+                                </property>
+                                <property name="resizable">
+                                    <bool>true</bool>
+                                </property>
+                            </column>
+                            <property name="name">
+                                <cstring>listView4</cstring>
+                            </property>
+                        </widget>
+                        <widget class="TQLabel">
+                            <property name="name">
+                                <cstring>textLabel7</cstring>
+                            </property>
+                            <property name="text">
+                                <string>Miscellaneous:</string>
+                            </property>
+                        </widget>
+                        <widget class="TQTextEdit">
+                            <property name="name">
+                                <cstring>textEdit2</cstring>
+                            </property>
+                        </widget>
+                        <widget class="TQLayoutWidget">
+                            <property name="name">
+                                <cstring>layout7</cstring>
+                            </property>
+                            <hbox>
+                                <property name="name">
+                                    <cstring>unnamed</cstring>
+                                </property>
+                                <spacer>
+                                    <property name="name">
+                                        <cstring>spacer3</cstring>
+                                    </property>
+                                    <property name="orientation">
+                                        <enum>Horizontal</enum>
+                                    </property>
+                                    <property name="sizeType">
+                                        <enum>Expanding</enum>
+                                    </property>
+                                    <property name="sizeHint">
+                                        <size>
+                                            <width>50</width>
+                                            <height>20</height>
+                                        </size>
+                                    </property>
+                                </spacer>
+                                <widget class="TQPushButton">
+                                    <property name="name">
+                                        <cstring>pushButton6</cstring>
+                                    </property>
+                                    <property name="text">
+                                        <string>Show</string>
+                                    </property>
+                                </widget>
+                                <widget class="TQPushButton">
+                                    <property name="name">
+                                        <cstring>pushButton5</cstring>
+                                    </property>
+                                    <property name="text">
+                                        <string>Compare</string>
+                                    </property>
+                                </widget>
+                            </hbox>
+                        </widget>
+                    </vbox>
+                </widget>
+                <widget class="TQWidget">
+                    <property name="name">
+                        <cstring>tab</cstring>
+                    </property>
+                    <attribute name="title">
+                        <string>State</string>
+                    </attribute>
+                    <vbox>
+                        <property name="name">
+                            <cstring>unnamed</cstring>
+                        </property>
+                        <widget class="TQLayoutWidget">
+                            <property name="name">
+                                <cstring>layout2</cstring>
+                            </property>
+                            <hbox>
+                                <property name="name">
+                                    <cstring>unnamed</cstring>
+                                </property>
+                                <widget class="TQPushButton">
+                                    <property name="name">
+                                        <cstring>pushButton1</cstring>
+                                    </property>
+                                    <property name="text">
+                                        <string>Update</string>
+                                    </property>
+                                </widget>
+                                <widget class="TQCheckBox">
+                                    <property name="name">
+                                        <cstring>checkBox1</cstring>
+                                    </property>
+                                    <property name="text">
+                                        <string>Every [s]:</string>
+                                    </property>
+                                </widget>
+                                <widget class="TQLineEdit">
+                                    <property name="name">
+                                        <cstring>lineEdit3_2</cstring>
+                                    </property>
+                                </widget>
+                            </hbox>
+                        </widget>
+                        <widget class="TQListView">
+                            <column>
+                                <property name="text">
+                                    <string>Counter</string>
+                                </property>
+                                <property name="clickable">
+                                    <bool>true</bool>
+                                </property>
+                                <property name="resizable">
+                                    <bool>true</bool>
+                                </property>
+                            </column>
+                            <column>
+                                <property name="text">
+                                    <string>Value</string>
+                                </property>
+                                <property name="clickable">
+                                    <bool>true</bool>
+                                </property>
+                                <property name="resizable">
+                                    <bool>true</bool>
+                                </property>
+                            </column>
+                        <item>
+                            <property name="text">
+                                <string>Dumps Done</string>
+                            </property>
+                            <property name="text">
+                                <string></string>
+                            </property>
+                            <property name="pixmap">
+                                <pixmap></pixmap>
+                            </property>
+                            <property name="pixmap">
+                                <pixmap></pixmap>
+                            </property>
+                        </item>
+                        <item>
+                            <property name="text">
+                                <string>Is Collecting</string>
+                            </property>
+                            <property name="text">
+                                <string></string>
+                            </property>
+                            <property name="pixmap">
+                                <pixmap></pixmap>
+                            </property>
+                            <property name="pixmap">
+                                <pixmap></pixmap>
+                            </property>
+                        </item>
+                        <item>
+                            <property name="text">
+                                <string>Executed</string>
+                            </property>
+                            <property name="text">
+                                <string></string>
+                            </property>
+                            <property name="pixmap">
+                                <pixmap></pixmap>
+                            </property>
+                            <property name="pixmap">
+                                <pixmap></pixmap>
+                            </property>
+                            <item>
+                                <property name="text">
+                                    <string>Basic Blocks</string>
+                                </property>
+                                <property name="text">
+                                    <string></string>
+                                </property>
+                                <property name="pixmap">
+                                    <pixmap></pixmap>
+                                </property>
+                                <property name="pixmap">
+                                    <pixmap></pixmap>
+                                </property>
+                            </item>
+                            <item>
+                                <property name="text">
+                                    <string>Calls</string>
+                                </property>
+                                <property name="text">
+                                    <string></string>
+                                </property>
+                                <property name="pixmap">
+                                    <pixmap></pixmap>
+                                </property>
+                                <property name="pixmap">
+                                    <pixmap></pixmap>
+                                </property>
+                            </item>
+                            <item>
+                                <property name="text">
+                                    <string>Jumps</string>
+                                </property>
+                                <property name="text">
+                                    <string></string>
+                                </property>
+                                <property name="pixmap">
+                                    <pixmap></pixmap>
+                                </property>
+                                <property name="pixmap">
+                                    <pixmap></pixmap>
+                                </property>
+                            </item>
+                        </item>
+                        <item>
+                            <property name="text">
+                                <string>Events</string>
+                            </property>
+                            <property name="text">
+                                <string></string>
+                            </property>
+                            <property name="pixmap">
+                                <pixmap></pixmap>
+                            </property>
+                            <property name="pixmap">
+                                <pixmap></pixmap>
+                            </property>
+                            <item>
+                                <property name="text">
+                                    <string>Ir</string>
+                                </property>
+                                <property name="text">
+                                    <string></string>
+                                </property>
+                                <property name="pixmap">
+                                    <pixmap></pixmap>
+                                </property>
+                                <property name="pixmap">
+                                    <pixmap></pixmap>
+                                </property>
+                            </item>
+                        </item>
+                        <item>
+                            <property name="text">
+                                <string>Distinct</string>
+                            </property>
+                            <property name="text">
+                                <string></string>
+                            </property>
+                            <property name="pixmap">
+                                <pixmap></pixmap>
+                            </property>
+                            <property name="pixmap">
+                                <pixmap></pixmap>
+                            </property>
+                            <item>
+                                <property name="text">
+                                    <string>ELF Objects</string>
+                                </property>
+                                <property name="text">
+                                    <string></string>
+                                </property>
+                                <property name="pixmap">
+                                    <pixmap></pixmap>
+                                </property>
+                                <property name="pixmap">
+                                    <pixmap></pixmap>
+                                </property>
+                            </item>
+                            <item>
+                                <property name="text">
+                                    <string>Functions</string>
+                                </property>
+                                <property name="text">
+                                    <string></string>
+                                </property>
+                                <property name="pixmap">
+                                    <pixmap></pixmap>
+                                </property>
+                                <property name="pixmap">
+                                    <pixmap></pixmap>
+                                </property>
+                            </item>
+                            <item>
+                                <property name="text">
+                                    <string>Contexts</string>
+                                </property>
+                                <property name="text">
+                                    <string></string>
+                                </property>
+                                <property name="pixmap">
+                                    <pixmap></pixmap>
+                                </property>
+                                <property name="pixmap">
+                                    <pixmap></pixmap>
+                                </property>
+                            </item>
+                        </item>
+                            <property name="name">
+                                <cstring>listView4_3</cstring>
+                            </property>
+                        </widget>
+                        <widget class="TQLayoutWidget">
+                            <property name="name">
+                                <cstring>layout4</cstring>
+                            </property>
+                            <hbox>
+                                <property name="name">
+                                    <cstring>unnamed</cstring>
+                                </property>
+                                <widget class="TQLabel">
+                                    <property name="name">
+                                        <cstring>textLabel4</cstring>
+                                    </property>
+                                    <property name="sizePolicy">
+                                        <sizepolicy>
+                                            <hsizetype>5</hsizetype>
+                                            <vsizetype>5</vsizetype>
+                                            <horstretch>1</horstretch>
+                                            <verstretch>0</verstretch>
+                                        </sizepolicy>
+                                    </property>
+                                    <property name="text">
+                                        <string>Stack trace:</string>
+                                    </property>
+                                </widget>
+                                <widget class="TQCheckBox">
+                                    <property name="name">
+                                        <cstring>checkBox2</cstring>
+                                    </property>
+                                    <property name="text">
+                                        <string>Sync.</string>
+                                    </property>
+                                </widget>
+                            </hbox>
+                        </widget>
+                        <widget class="TQListView">
+                            <column>
+                                <property name="text">
+                                    <string>#</string>
+                                </property>
+                                <property name="clickable">
+                                    <bool>true</bool>
+                                </property>
+                                <property name="resizable">
+                                    <bool>true</bool>
+                                </property>
+                            </column>
+                            <column>
+                                <property name="text">
+                                    <string>Incl.</string>
+                                </property>
+                                <property name="clickable">
+                                    <bool>true</bool>
+                                </property>
+                                <property name="resizable">
+                                    <bool>true</bool>
+                                </property>
+                            </column>
+                            <column>
+                                <property name="text">
+                                    <string>Called</string>
+                                </property>
+                                <property name="clickable">
+                                    <bool>true</bool>
+                                </property>
+                                <property name="resizable">
+                                    <bool>true</bool>
+                                </property>
+                            </column>
+                            <column>
+                                <property name="text">
+                                    <string>Function</string>
+                                </property>
+                                <property name="clickable">
+                                    <bool>true</bool>
+                                </property>
+                                <property name="resizable">
+                                    <bool>true</bool>
+                                </property>
+                            </column>
+                            <column>
+                                <property name="text">
+                                    <string>Location</string>
+                                </property>
+                                <property name="clickable">
+                                    <bool>true</bool>
+                                </property>
+                                <property name="resizable">
+                                    <bool>true</bool>
+                                </property>
+                            </column>
+                            <property name="name">
+                                <cstring>listView7</cstring>
+                            </property>
+                        </widget>
+                        <widget class="TQLayoutWidget">
+                            <property name="name">
+                                <cstring>layout6</cstring>
+                            </property>
+                            <hbox>
+                                <property name="name">
+                                    <cstring>unnamed</cstring>
+                                </property>
+                                <widget class="TQPushButton">
+                                    <property name="name">
+                                        <cstring>pushButton7</cstring>
+                                    </property>
+                                    <property name="text">
+                                        <string>Start</string>
+                                    </property>
+                                </widget>
+                                <spacer>
+                                    <property name="name">
+                                        <cstring>spacer2</cstring>
+                                    </property>
+                                    <property name="orientation">
+                                        <enum>Horizontal</enum>
+                                    </property>
+                                    <property name="sizeType">
+                                        <enum>Expanding</enum>
+                                    </property>
+                                    <property name="sizeHint">
+                                        <size>
+                                            <width>20</width>
+                                            <height>20</height>
+                                        </size>
+                                    </property>
+                                </spacer>
+                                <widget class="TQPushButton">
+                                    <property name="name">
+                                        <cstring>pushButton6_2</cstring>
+                                    </property>
+                                    <property name="text">
+                                        <string>Zero</string>
+                                    </property>
+                                </widget>
+                                <widget class="TQPushButton">
+                                    <property name="name">
+                                        <cstring>pushButton4</cstring>
+                                    </property>
+                                    <property name="text">
+                                        <string>Dump</string>
+                                    </property>
+                                </widget>
+                            </hbox>
+                        </widget>
+                    </vbox>
+                </widget>
+                <widget class="TQWidget">
+                    <property name="name">
+                        <cstring>tab</cstring>
+                    </property>
+                    <attribute name="title">
+                        <string>Messages</string>
+                    </attribute>
+                    <vbox>
+                        <property name="name">
+                            <cstring>unnamed</cstring>
+                        </property>
+                        <widget class="TQTextEdit">
+                            <property name="name">
+                                <cstring>textEdit2_2</cstring>
+                            </property>
+                        </widget>
+                        <widget class="TQLayoutWidget">
+                            <property name="name">
+                                <cstring>layout6</cstring>
+                            </property>
+                            <hbox>
+                                <property name="name">
+                                    <cstring>unnamed</cstring>
+                                </property>
+                                <widget class="TQPushButton">
+                                    <property name="name">
+                                        <cstring>pushButton9</cstring>
+                                    </property>
+                                    <property name="text">
+                                        <string>Kill Run</string>
+                                    </property>
+                                </widget>
+                                <spacer>
+                                    <property name="name">
+                                        <cstring>spacer4</cstring>
+                                    </property>
+                                    <property name="orientation">
+                                        <enum>Horizontal</enum>
+                                    </property>
+                                    <property name="sizeType">
+                                        <enum>Expanding</enum>
+                                    </property>
+                                    <property name="sizeHint">
+                                        <size>
+                                            <width>21</width>
+                                            <height>20</height>
+                                        </size>
+                                    </property>
+                                </spacer>
+                                <widget class="TQPushButton">
+                                    <property name="name">
+                                        <cstring>pushButton8</cstring>
+                                    </property>
+                                    <property name="text">
+                                        <string>Clear</string>
+                                    </property>
+                                </widget>
+                            </hbox>
+                        </widget>
+                    </vbox>
+                </widget>
+            </widget>
+        </widget>
+    </vbox>
+</widget>
+<layoutdefaults spacing="6" margin="11"/>
+</UI>
diff --git a/kdecachegrind/kdecachegrind/fixcost.cpp b/kdecachegrind/kdecachegrind/fixcost.cpp
new file mode 100644
index 0000000..4102926
--- /dev/null
+++ b/kdecachegrind/kdecachegrind/fixcost.cpp
@@ -0,0 +1,174 @@
+/*
+ * Part of KCacheGrind
+ *
+ * 2003, Josef Weidendorfer
+ */
+
+#include "fixcost.h"
+#include "utils.h"
+
+
+// FixCost
+
+FixCost::FixCost(TracePart* part, FixPool* pool,
+		 TraceFunctionSource* functionSource,
+		 PositionSpec& pos,
+                 TracePartFunction* partFunction,
+		 FixString& s)
+{
+    int maxCount = part->fixSubMapping()->count();
+
+    _part = part;
+    _functionSource = functionSource;
+    _pos = pos;
+
+    _cost = (SubCost*) pool->reserve(sizeof(SubCost) * maxCount);
+    s.stripSpaces();
+    int i = 0;
+    while(i<maxCount) {
+	if (!s.stripUInt64(_cost[i])) break;
+	i++;
+    }
+    _count = i;
+
+    if (!pool->allocateReserved(sizeof(SubCost) * _count))
+	_count = 0;
+
+    _nextCostOfPartFunction = partFunction ?
+	partFunction->setFirstFixCost(this) : 0;
+}
+
+void* FixCost::operator new(size_t size, FixPool* pool)
+{
+    return pool->allocate(size);
+}
+
+void FixCost::addTo(TraceCost* c)
+{
+    TraceSubMapping* sm = _part->fixSubMapping();
+
+    int i, realIndex;
+
+    for(i=0; i<_count; i++) {
+	realIndex = sm->realIndex(i);
+	c->addCost(realIndex, _cost[i]);
+    }
+}
+
+
+
+// FixCallCost
+
+FixCallCost::FixCallCost(TracePart* part, FixPool* pool,
+			 TraceFunctionSource* functionSource,
+                         unsigned int line, Addr addr,
+                         TracePartCall* partCall,
+                         SubCost callCount, FixString& s)
+{
+  if (0) qDebug("Got FixCallCost (addr 0x%s, line %d): calls %s",
+                addr.toString().ascii(), line,
+		callCount.pretty().ascii());
+
+  int maxCount = part->fixSubMapping()->count();
+
+    _part = part;
+    _functionSource = functionSource;
+    _line = line;
+    _addr = addr;
+
+    _cost = (SubCost*) pool->reserve(sizeof(SubCost) * (maxCount+1));
+    s.stripSpaces();
+    int i = 0;
+    while(i<maxCount) {
+	if (!s.stripUInt64(_cost[i])) break;
+	i++;
+    }
+    _count = i;
+
+    if (!pool->allocateReserved(sizeof(SubCost) * (_count+1) ))
+      _count = 0;
+    else
+      _cost[_count] = callCount;
+
+    _nextCostOfPartCall = partCall ? partCall->setFirstFixCallCost(this) : 0;
+}
+
+void* FixCallCost::operator new(size_t size, FixPool* pool)
+{
+    return pool->allocate(size);
+}
+
+void FixCallCost::addTo(TraceCallCost* c)
+{
+    TraceSubMapping* sm = _part->fixSubMapping();
+
+    int i, realIndex;
+
+    for(i=0; i<_count; i++) {
+	realIndex = sm->realIndex(i);
+	c->addCost(realIndex, _cost[i]);
+    }
+    c->addCallCount(_cost[_count]);
+
+    if (0) qDebug("Adding from (addr 0x%s, ln %d): calls %s",
+                  _addr.toString().ascii(), _line,
+		  _cost[_count].pretty().ascii());
+}
+
+void FixCallCost::setMax(TraceCost* c)
+{
+    TraceSubMapping* sm = _part->fixSubMapping();
+
+    int i, realIndex;
+
+    for(i=0; i<_count; i++) {
+	realIndex = sm->realIndex(i);
+	c->maxCost(realIndex, _cost[i]);
+    }
+}
+
+
+// FixJump
+
+FixJump::FixJump(TracePart* part, FixPool* pool,
+		 unsigned int line, Addr addr,
+		 TracePartFunction* partFunction,
+		 TraceFunctionSource* source,
+		 unsigned int targetLine, Addr targetAddr,
+		 TraceFunction* targetFunction,
+		 TraceFunctionSource* targetSource,
+		 bool isCondJump,
+		 SubCost executed, SubCost followed)
+{
+    _part   = part;
+    _source = source;
+    _line   = line;
+    _addr   = addr;
+
+    _targetFunction = targetFunction;
+    _targetSource   = targetSource;
+    _targetLine     = targetLine;
+    _targetAddr     = targetAddr;
+    
+    _isCondJump = isCondJump;
+
+    int size = (isCondJump ? 2 : 1) * sizeof(SubCost);
+    _cost = (SubCost*) pool->allocate(size);
+    _cost[0] = executed;
+    if (isCondJump) _cost[1] = followed;
+
+    _nextJumpOfPartFunction = partFunction ?
+	partFunction->setFirstFixJump(this) : 0;
+}
+
+void* FixJump::operator new(size_t size, FixPool* pool)
+{
+    return pool->allocate(size);
+}
+
+void FixJump::addTo(TraceJumpCost* jc)
+{
+    jc->addExecutedCount(_cost[0]);
+    if (_isCondJump) 
+	jc->addFollowedCount(_cost[1]);
+}
diff --git a/kdecachegrind/kdecachegrind/fixcost.h b/kdecachegrind/kdecachegrind/fixcost.h
new file mode 100644
index 0000000..7e90fb4
--- /dev/null
+++ b/kdecachegrind/kdecachegrind/fixcost.h
@@ -0,0 +1,171 @@
+/*
+ * Part of KCacheGrind
+ *
+ * 2003, Josef Weidendorfer
+ */
+
+#ifndef FIXCOST_H
+#define FIXCOST_H
+
+/**
+ * Setting USE_FIXCOST to 1 enables a memory space hack:
+ * For some data, build up internal data model lazy by using
+ * the Fix*Cost classes, which are simple copies from input data.
+ */
+#define USE_FIXCOST 1
+
+#include "tracedata.h"
+#include "pool.h"
+
+class PositionSpec
+{
+ public:
+  PositionSpec()
+    { fromLine = 0, toLine = 0, fromAddr = 0, toAddr = 0; }
+  PositionSpec(uint l1, uint l2, Addr a1, Addr a2)
+    { fromLine = l1, toLine = l2, fromAddr = a1, toAddr = a2; }
+
+  bool isLineRegion() const { return (fromLine != toLine); }
+  bool isAddrRegion() const { return (fromAddr != toAddr); }
+
+  uint fromLine, toLine;
+  Addr fromAddr, toAddr;
+};
+
+/**
+ * A class holding an unchangable cost item of an input file.
+ *
+ * As there can be a lot of such cost items, we use our own
+ * allocator which uses FixPool
+ */
+class FixCost
+{
+
+ public:
+    FixCost(TracePart*, FixPool*,
+	    TraceFunctionSource*,
+	    PositionSpec&,
+            TracePartFunction*,
+	    FixString&);
+
+    void *operator new(size_t size, FixPool*);
+
+    void addTo(TraceCost*);
+
+    TracePart* part() const { return _part; }
+    bool isLineRegion() const { return _pos.isLineRegion(); }
+    bool isAddrRegion() const { return _pos.isAddrRegion(); }
+    uint fromLine() const { return _pos.fromLine; }
+    uint line() const { return _pos.fromLine; }
+    uint toLine() const { return _pos.toLine; }
+    Addr fromAddr() const { return _pos.fromAddr; }
+    Addr addr() const { return _pos.fromAddr; }
+    Addr toAddr() const { return _pos.toAddr; }
+    TraceFunctionSource* functionSource() const { return _functionSource; }
+
+    FixCost* nextCostOfPartFunction() const
+	{ return _nextCostOfPartFunction; }
+
+ private:
+    int _count;
+    SubCost*  _cost;
+    PositionSpec _pos;
+
+    TracePart* _part;
+    TraceFunctionSource* _functionSource;
+    FixCost *_nextCostOfPartFunction;
+};
+
+/**
+ * A FixCallCost will be inserted into a
+ * - TracePartCall to keep source/target function info
+ * - TraceFunctionSourceFile to keep file info of call source
+ */
+class FixCallCost
+{
+
+ public:
+    FixCallCost(TracePart*, FixPool*,
+                TraceFunctionSource*,
+                unsigned int line,
+		Addr addr,
+                TracePartCall*,
+                SubCost, FixString&);
+
+    void *operator new(size_t size, FixPool*);
+
+    void addTo(TraceCallCost*);
+    void setMax(TraceCost*);
+
+    TracePart* part() const { return _part; }
+    unsigned int line() const { return _line; }
+    Addr addr() const { return _addr; }
+    SubCost callCount() const { return _cost[_count]; }
+    TraceFunctionSource* functionSource() const	{ return _functionSource; }
+    FixCallCost* nextCostOfPartCall() const
+	{ return _nextCostOfPartCall; }
+
+ private:
+    // we use 1 SubCost more than _count: _cost[_count] is the call count
+    int _count;
+    SubCost*  _cost;
+    unsigned int _line;
+    Addr _addr;
+
+    TracePart* _part;
+    TraceFunctionSource* _functionSource;
+    FixCallCost* _nextCostOfPartCall;
+};
+
+/**
+ * A class holding a jump (mostly) inside of a function
+ */
+class FixJump
+{
+
+ public:
+    FixJump(TracePart*, FixPool*,
+	    /* source position */
+	    unsigned int line, Addr addr,
+	    TracePartFunction*, TraceFunctionSource*,
+	    /* target position */
+	    unsigned int targetLine, Addr targetAddr,
+	    TraceFunction*, TraceFunctionSource*,
+	    bool isCondJump,
+	    SubCost, SubCost);
+
+    void *operator new(size_t size, FixPool*);
+
+    void addTo(TraceJumpCost*);
+
+    TracePart* part() const { return _part; }
+    unsigned int line() const { return _line; }
+    Addr addr() const { return _addr; }
+    TraceFunctionSource* source() const { return _source; }
+    TraceFunction* targetFunction() const { return _targetFunction; }
+    unsigned int targetLine() const { return _targetLine; }
+    Addr targetAddr() const { return _targetAddr; }
+    TraceFunctionSource* targetSource() const { return _targetSource; }
+    bool isCondJump() { return _isCondJump; }
+    SubCost executedCount() const { return _cost[0]; }
+    SubCost followedCount() const
+	{ return _isCondJump ? _cost[1] : SubCost(0); }
+
+    FixJump* nextJumpOfPartFunction() const
+	{ return _nextJumpOfPartFunction; }
+
+ private:
+    bool _isCondJump;
+    SubCost*  _cost;
+    unsigned int _line, _targetLine;
+    Addr _addr, _targetAddr;
+    
+    TracePart* _part;
+    TraceFunctionSource *_source, *_targetSource;
+    TraceFunction* _targetFunction;
+    FixJump *_nextJumpOfPartFunction;
+};
+
+#endif
+
+
diff --git a/kdecachegrind/kdecachegrind/functionitem.cpp b/kdecachegrind/kdecachegrind/functionitem.cpp
new file mode 100644
index 0000000..3b694dd
--- /dev/null
+++ b/kdecachegrind/kdecachegrind/functionitem.cpp
@@ -0,0 +1,236 @@
+/* This file is part of KCachegrind.
+   Copyright (C) 2003 Josef Weidendorfer <Josef.Weidendorfer@gmx.de>
+
+   KCachegrind 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, version 2.
+
+   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; see the file COPYING.  If not, write to
+   the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+   Boston, MA 02110-1301, USA.
+*/
+
+/*
+ * List Item for the FunctionSelection list
+ */
+
+
+//#include <math.h>
+
+//#include <tqpainter.h>
+//#include <tqregexp.h>
+
+#include <klocale.h>
+#include <kiconloader.h>
+#include <kapplication.h>
+
+#include "listutils.h"
+#include "functionitem.h"
+#include "configuration.h"
+
+
+// FunctionItem
+
+FunctionItem::FunctionItem(TQListView* parent, TraceFunction* f,
+                           TraceCostType* ct, TraceCost::CostType gt)
+  :TQListViewItem(parent)
+{
+#if 0
+    _costPixValid = false;
+    _groupPixValid = false;
+#endif
+
+    _function = f;
+    _skipped = 0;
+    _groupType = TraceCost::NoCostType;
+    setGroupType(gt);
+    setCostType(ct);
+
+    setText(3, f->prettyName());
+    setText(4, f->prettyLocation());
+}
+
+FunctionItem::FunctionItem(TQListView* parent, int skipped,
+			   TraceFunction* f, TraceCostType* ct)
+  :TQListViewItem(parent)
+{
+#if 0
+    _costPixValid = false;
+    _groupPixValid = false;
+#endif
+    _skipped = skipped;
+    _function = f;
+    _groupType = TraceCost::NoCostType;
+    setCostType(ct);
+
+    setText(3, i18n("(%n function skipped)", "(%n functions skipped)", skipped));
+}
+
+#if 0
+const TQPixmap* FunctionItem::pixmap(int column) const
+{
+    if (column == 3) {
+	if (!_groupPixValid) {
+	    TQColor c = Configuration::functionColor(_groupType, _function);
+	    _groupPix = colorPixmap(10, 10, c);
+	    _groupPixValid = true;
+	}
+	return &_groupPix;
+    }
+    if (column == 1) {
+	if (!_costPixValid) {
+	    _costPix = colorPixmap(10, 10, c);
+	    _costPixValid = true;
+	}
+	return &_costPix;
+    }
+    return 0;
+}
+#endif
+
+void  FunctionItem::setGroupType(TraceCost::CostType gt)
+{
+  if (_skipped) return;
+  if (_groupType == gt) return;
+  _groupType = gt;
+
+
+#if 0
+  _groupPixValid = false;
+  viewList()->repaint();
+#else
+  TQColor c = Configuration::functionColor(_groupType, _function);
+  setPixmap(3, colorPixmap(10, 10, c));
+#endif
+}
+
+void FunctionItem::setCostType(TraceCostType* c)
+{
+  _costType = c;
+  update();
+}
+
+void FunctionItem::update()
+{
+  double inclTotal = _function->data()->subCost(_costType);
+  TQString str;
+
+  TraceCost* selfCost = _function->data();
+  if (Configuration::showExpanded()) {
+      switch(_groupType) {
+      case TraceCost::Object: selfCost = _function->object(); break;
+      case TraceCost::Class:  selfCost = _function->cls(); break;
+      case TraceCost::File:   selfCost = _function->file(); break;
+      default: break;
+      }
+  }
+  double selfTotal = selfCost->subCost(_costType);
+
+  if (_skipped) {
+    // special handling for skip entries...
+
+    // only text updates of incl./self
+
+    // for all skipped functions, cost is below the given function
+    _sum  = _function->inclusive()->subCost(_costType);
+    double incl  = 100.0 * _sum / inclTotal;
+    if (Configuration::showPercentage())
+      str = TQString("%1").arg(incl, 0, 'f', Configuration::percentPrecision());
+    else
+      str = _function->inclusive()->prettySubCost(_costType);
+    str = "< " + str;
+    setText(0, str);
+    setText(1, str);
+    return;
+  }
+
+  // Call count...
+  if (_function->calledCount() >0)
+    str = _function->prettyCalledCount();
+  else {
+    if (_function == _function->cycle())
+      str = TQString("-");
+    else
+      str = TQString("(0)");
+  }
+  setText(2, str);
+
+  // Incl. cost
+  _sum  = _function->inclusive()->subCost(_costType);
+  if (inclTotal == 0.0) {
+    setPixmap(0, TQPixmap());
+    setText(0, "-");
+  }
+  else {
+      double incl  = 100.0 * _sum / inclTotal;
+      if (Configuration::showPercentage())
+	  setText(0, TQString("%1")
+		  .arg(incl, 0, 'f', Configuration::percentPrecision()));
+      else
+	  setText(0, _function->inclusive()->prettySubCost(_costType));
+
+      setPixmap(0, costPixmap(_costType, _function->inclusive(), inclTotal, false));
+  }
+
+  // self
+  _pure = _function->subCost(_costType);
+  if (selfTotal == 0.0) {
+    setPixmap(1, TQPixmap());
+    setText(1, "-");
+  }
+  else {
+      double self  = 100.0 * _pure / selfTotal;
+
+      if (Configuration::showPercentage())
+	  setText(1, TQString("%1")
+		  .arg(self, 0, 'f', Configuration::percentPrecision()));
+      else
+	  setText(1, _function->prettySubCost(_costType));
+
+      setPixmap(1, costPixmap(_costType, _function, selfTotal, false));
+  }
+}
+
+
+int FunctionItem::compare(TQListViewItem * i, int col, bool ascending ) const
+{
+  const FunctionItem* fi1 = this;
+  const FunctionItem* fi2 = (FunctionItem*) i;
+
+  // we always want descending order
+  if (ascending) {
+    fi1 = fi2;
+    fi2 = this;
+  }
+
+  // a skip entry is always sorted last
+  if (fi1->_skipped) return -1;
+  if (fi2->_skipped) return 1;
+
+  if (col==0) {
+    if (fi1->_sum < fi2->_sum) return -1;
+    if (fi1->_sum > fi2->_sum) return 1;
+    return 0;
+  }
+  if (col==1) {
+    if (fi1->_pure < fi2->_pure) return -1;
+    if (fi1->_pure > fi2->_pure) return 1;
+    return 0;
+  }
+  if (col==2) {
+    if (fi1->_function->calledCount() <
+	fi2->_function->calledCount()) return -1;
+    if (fi1->_function->calledCount() >
+	fi2->_function->calledCount()) return 1;
+    return 0;
+  }
+
+  return TQListViewItem::compare(i, col, ascending);
+}
+
diff --git a/kdecachegrind/kdecachegrind/functionitem.h b/kdecachegrind/kdecachegrind/functionitem.h
new file mode 100644
index 0000000..d8f98f4
--- /dev/null
+++ b/kdecachegrind/kdecachegrind/functionitem.h
@@ -0,0 +1,58 @@
+/* This file is part of KCachegrind.
+   Copyright (C) 2003 Josef Weidendorfer <Josef.Weidendorfer@gmx.de>
+
+   KCachegrind 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, version 2.
+
+   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; see the file COPYING.  If not, write to
+   the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+   Boston, MA 02110-1301, USA.
+*/
+
+/*
+ * List Item for the FunctionSelection list
+ */
+
+#ifndef FUNCTIONITEM_H
+#define FUNCTIONITEM_H
+
+#include <tqlistview.h>
+#include "tracedata.h"
+
+class FunctionItem: public TQListViewItem
+{
+public:    
+  FunctionItem(TQListView* parent, TraceFunction* function,
+	       TraceCostType* ct, TraceCost::CostType gt);
+  // constructor for a "Skipped ... " entry
+  FunctionItem(TQListView* parent, int skipped,
+	       TraceFunction* function, TraceCostType* ct);
+
+  int compare(TQListViewItem * i, int col, bool ascending ) const;
+  TraceFunction* function() { return (_skipped) ? 0 : _function; }
+  void setCostType(TraceCostType* ct);
+  void setGroupType(TraceCost::CostType);
+  void update();
+
+#if 0
+  const TQPixmap* pixmap (int column) const;
+  bool _costPixValid, _groupPixValid;
+  TQPixMap _costPix, _groupPix;
+#endif
+
+private:
+  SubCost _sum, _pure;
+  TraceCostType* _costType;
+  TraceCost::CostType _groupType;
+  TraceFunction* _function;
+  int _skipped;
+};
+
+#endif
diff --git a/kdecachegrind/kdecachegrind/functionselection.cpp b/kdecachegrind/kdecachegrind/functionselection.cpp
new file mode 100644
index 0000000..c5646dd
--- /dev/null
+++ b/kdecachegrind/kdecachegrind/functionselection.cpp
@@ -0,0 +1,871 @@
+/* This file is part of KCachegrind.
+   Copyright (C) 2002, 2003 Josef Weidendorfer <Josef.Weidendorfer@gmx.de>
+
+   KCachegrind 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, version 2.
+
+   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; see the file COPYING.  If not, write to
+   the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+   Boston, MA 02110-1301, USA.
+*/
+
+/*
+ * For function selection, to be put into a TQDockWindow
+ */
+
+#include <tqtimer.h>
+#include <tqlistview.h>
+#include <tqlabel.h>
+#include <tqpushbutton.h>
+#include <tqcombobox.h>
+#include <tqlineedit.h>
+#include <tqregexp.h>
+#include <tqpopupmenu.h>
+
+#include <klocale.h>
+
+#include "traceitemview.h"
+#include "stackbrowser.h"
+#include "functionselection.h"
+#include "partgraph.h"
+#include "functionitem.h"
+#include "costlistitem.h"
+#include "configuration.h"
+#include "toplevel.h"
+
+FunctionSelection::FunctionSelection( TopLevel* top,
+				      TQWidget* parent, const char* name)
+    : FunctionSelectionBase(parent, name), TraceItemView(0, top)
+{
+  _group = 0;
+  _inSetGroup = false;
+  _inSetFunction = false;
+
+  TQStringList args;
+  args << i18n("(No Grouping)")
+       << TraceCost::i18nTypeName(TraceItem::Object)
+       << TraceCost::i18nTypeName(TraceItem::File)
+       << TraceCost::i18nTypeName(TraceItem::Class)
+       << TraceCost::i18nTypeName(TraceItem::FunctionCycle);
+  
+  groupBox->insertStringList(args);
+  // this needs same order of grouptype actionlist!
+  connect(groupBox, TQT_SIGNAL(activated(int)),
+	  top, TQT_SLOT(groupTypeSelected(int)));
+
+  // search while typing...
+  connect(searchEdit, TQT_SIGNAL(textChanged(const TQString&)),
+	  this, TQT_SLOT(searchChanged(const TQString&)));
+  connect(&_searchTimer, TQT_SIGNAL(timeout()),
+	  this, TQT_SLOT(queryDelayed()));
+  // select first matching group/function on return
+  connect(searchEdit, TQT_SIGNAL(returnPressed()),
+	  this, TQT_SLOT(searchReturnPressed()));
+  searchEdit->setMinimumWidth(50);
+
+  // we start with desending cost sorting
+  functionList->setSorting(0,false);
+  functionList->setColumnAlignment(0, TQt::AlignRight);
+  functionList->setColumnAlignment(1, TQt::AlignRight);
+  functionList->setColumnAlignment(2, TQt::AlignRight);
+  functionList->setAllColumnsShowFocus(true);
+  // functionList->setShowSortIndicator(true);
+  // we can have very long function and location names
+  functionList->setColumnWidthMode(3, TQListView::Manual);
+  functionList->setColumnWidth(3, 200);
+  functionList->setColumnWidthMode(4, TQListView::Manual);
+  functionList->setColumnWidth(4, 200);
+
+  groupList->setSorting(0,false);
+  groupList->setColumnAlignment(0, TQt::AlignRight);
+  groupList->setAllColumnsShowFocus(true);
+  // groupList->setShowSortIndicator(true);
+  groupList->setResizeMode(TQListView::LastColumn);
+
+#if 0
+  // single click press activation
+  connect(functionList, TQT_SIGNAL(selectionChanged(TQListViewItem*)),
+          this, TQT_SLOT(functionActivated(TQListViewItem*)));
+  connect(functionList,
+	  TQT_SIGNAL(contextMenuRequested(TQListViewItem*, const TQPoint &, int)),
+          this, TQT_SLOT(functionContext(TQListViewItem*, const TQPoint &, int)));
+#else
+  // single click release activation
+  connect(functionList, TQT_SIGNAL(selectionChanged(TQListViewItem*)),
+          this, TQT_SLOT(functionSelected(TQListViewItem*)));
+  connect(functionList, TQT_SIGNAL(clicked(TQListViewItem*)),
+	  this, TQT_SLOT(functionActivated(TQListViewItem*)));
+  connect(functionList, TQT_SIGNAL(returnPressed(TQListViewItem*)),
+	  this, TQT_SLOT(functionActivated(TQListViewItem*)));
+  connect(functionList,
+	  TQT_SIGNAL(contextMenuRequested(TQListViewItem*, const TQPoint &, int)),
+          this, TQT_SLOT(functionContext(TQListViewItem*, const TQPoint &, int)));
+#endif
+
+  connect(groupList, TQT_SIGNAL(selectionChanged(TQListViewItem*)),
+          this, TQT_SLOT(groupSelected(TQListViewItem*)));
+  connect(groupList, TQT_SIGNAL(doubleClicked(TQListViewItem*)),
+	  this, TQT_SLOT(groupDoubleClicked(TQListViewItem*)));
+  connect(groupList, TQT_SIGNAL(returnPressed(TQListViewItem*)),
+	  this, TQT_SLOT(groupDoubleClicked(TQListViewItem*)));
+  connect(groupList,
+	  TQT_SIGNAL(contextMenuRequested(TQListViewItem*, const TQPoint &, int)),
+          this, TQT_SLOT(groupContext(TQListViewItem*, const TQPoint &, int)));
+
+  // start hidden
+  groupList->hide();
+}
+
+FunctionSelection::~FunctionSelection()
+{
+}
+
+void FunctionSelection::searchReturnPressed()
+{
+  query(searchEdit->text());
+
+  TQListViewItem* item;
+  if (_groupType != TraceItem::Function) {
+      // if current group not matching, select first matching group
+      item  = groupList->currentItem();
+      if (!item || !item->isVisible()) {
+	  item  = groupList->firstChild();
+	  for (;item;item = item->nextSibling())
+	      if (item->isVisible()) break;
+	  if (!item) return;
+
+	  setGroup(((CostListItem*)item)->costItem());
+	  return;
+      }
+  }
+
+  functionActivated(functionList->firstChild());
+}
+
+// trigger the query after some delay, dependent on length
+void FunctionSelection::searchChanged(const TQString& q)
+{
+  _searchDelayed = q;
+  int ms = 100;
+  if (q.length()<5) ms = 200;
+  if (q.length()<2) ms = 300;
+  _searchTimer.start(ms,true);
+}
+
+void FunctionSelection::queryDelayed()
+{
+  query(_searchDelayed);
+}
+
+void FunctionSelection::functionContext(TQListViewItem* i,
+					const TQPoint & p, int c)
+{
+  TQPopupMenu popup;
+  TraceFunction* f = 0;
+
+  if (i) {
+      f = ((FunctionItem*) i)->function();
+      if (f) {
+	  popup.insertItem(i18n("Go to %1").arg(f->prettyName()), 93);
+	  popup.insertSeparator();
+      }
+  }
+
+  if ((c == 0) || (c == 1)) {
+    addCostMenu(&popup,false);
+    popup.insertSeparator();
+  }
+  addGroupMenu(&popup);  
+  popup.insertSeparator();
+  addGoMenu(&popup);
+
+  int r = popup.exec(p);
+  if (r == 93) activated(f);
+}
+
+void FunctionSelection::groupContext(TQListViewItem* /*i*/,
+				     const TQPoint & p, int c)
+{
+  TQPopupMenu popup;
+
+#if 0
+  TraceCostItem* g = 0;
+  if (i) {
+      g = ((CostListItem*) i)->costItem();
+      if (!g) {
+	popup.insertItem(i18n("Show All Items"), 93);
+	popup.insertSeparator();
+      }
+  }
+#endif
+  if (c == 0) {
+    addCostMenu(&popup,false);
+    popup.insertSeparator();
+  }
+  addGroupMenu(&popup);  
+  popup.insertSeparator();
+  addGoMenu(&popup);
+
+  popup.exec(p);
+}
+
+
+void FunctionSelection::addGroupMenu(TQPopupMenu* popup)
+{
+  TQPopupMenu *popup1 = new TQPopupMenu(popup);
+  popup1->setCheckable(true);
+
+  if (_groupType != TraceItem::Function) {
+    popup1->insertItem(i18n("No Grouping"),0);
+    popup1->insertSeparator();
+  }
+  popup1->insertItem(TraceCost::i18nTypeName(TraceItem::Object),1);
+  popup1->insertItem(TraceCost::i18nTypeName(TraceItem::File),2);
+  popup1->insertItem(TraceCost::i18nTypeName(TraceItem::Class),3);
+  popup1->insertItem(TraceCost::i18nTypeName(TraceItem::FunctionCycle),4);
+  switch(_groupType) {
+  case TraceItem::Object:        popup1->setItemChecked(1, true); break;
+  case TraceItem::File:          popup1->setItemChecked(2, true); break;
+  case TraceItem::Class:         popup1->setItemChecked(3, true); break;
+  case TraceItem::FunctionCycle: popup1->setItemChecked(4, true); break;
+  default: break;
+  }
+  connect(popup1,TQT_SIGNAL(activated(int)),
+	  _topLevel,TQT_SLOT(groupTypeSelected(int)));
+
+  popup->insertItem(i18n("Grouping"), popup1);
+}    
+
+
+TraceItem* FunctionSelection::canShow(TraceItem* i)
+{
+    TraceItem::CostType t = i ? i->type() : TraceItem::NoCostType;
+
+    switch(t) {
+    case TraceItem::Function:
+    case TraceItem::FunctionCycle:
+    case TraceItem::Object:
+    case TraceItem::File:
+    case TraceItem::Class:
+	break;
+
+    case TraceItem::Instr:
+	i = ((TraceInstr*)i)->function();
+	break;
+
+    case TraceItem::Line:
+	i = ((TraceLine*)i)->functionSource()->function();
+	break;
+
+    default:
+	i = 0;
+	break;
+  }
+  return i;
+}
+
+
+void FunctionSelection::doUpdate(int changeType)
+{
+    // Special case ?
+    if (changeType == selectedItemChanged) return;
+
+    // we don't show cost 2 at all...
+    if (changeType == costType2Changed) return;
+
+    if (changeType == activeItemChanged) {
+	if (_activeItem ==0) {
+	    functionList->clearSelection();
+	    return;
+	}
+	switch(_activeItem->type()) {
+	case TraceItem::Object:
+	case TraceItem::File:
+	case TraceItem::Class:
+	    setGroup((TraceCostItem*)_activeItem);
+	    return;
+	default: break;
+	}
+
+	// active item is a function
+	TraceFunction* f = (TraceFunction*) _activeItem;
+
+	// if already current, nothing to do
+	TQListViewItem* i = functionList->currentItem();
+	if (i && (((FunctionItem*)i)->function() == f)) {
+	    functionList->setSelected(i,true);
+	    return;	    
+	}
+
+	// reset searchEdit (as not activated from this view)
+	_searchString = TQString();
+	query(TQString());
+
+	// select cost item group of function
+	switch(_groupType) {
+	case TraceItem::Object: setGroup(f->object()); break;
+	case TraceItem::Class:  setGroup(f->cls()); break;
+	case TraceItem::File:   setGroup(f->file());  break;
+	case TraceItem::FunctionCycle: setGroup(f->cycle());  break;
+	default:
+	    break;
+	}
+
+	TQListViewItem* item  = functionList->firstChild();
+	for (;item;item = item->nextSibling())
+	    if (((FunctionItem*)item)->function() == f)
+		break;
+
+	if (!item)
+	    item = new FunctionItem(functionList, f, _costType, _groupType);
+
+	functionList->ensureItemVisible(item);
+	// prohibit signalling of a function selection
+	_inSetFunction = true;
+	functionList->setSelected(item, true);
+	_inSetFunction = false;
+
+	return;
+    }
+
+    if (changeType & groupTypeChanged) {
+	if (_activeItem && (_activeItem->type() == TraceItem::Function)) {
+	    TraceFunction* f = (TraceFunction*) _activeItem;
+
+	    // select cost item group of function
+	    switch(_groupType) {
+	    case TraceItem::Object: _group = f->object(); break;
+	    case TraceItem::Class:  _group = f->cls(); break;
+	    case TraceItem::File:   _group = f->file();  break;
+	    case TraceItem::FunctionCycle: _group = f->cycle();  break;
+	    default:
+		_group = 0;
+		break;
+	    }
+	}
+
+	int id;
+	switch(_groupType) {
+	case TraceItem::Object: id = 1; break;
+	case TraceItem::File:   id = 2; break;
+	case TraceItem::Class:  id = 3; break;
+	case TraceItem::FunctionCycle: id = 4; break;
+	default: id = 0; break;
+	}
+	groupBox->setCurrentItem(id);
+
+	if (_groupType == TraceItem::Function)
+	    groupList->hide();
+	else
+	    groupList->show();
+    }
+
+    // reset searchEdit
+    _searchString = TQString();
+    query(TQString());
+
+    refresh();
+}
+
+
+/*
+ * This set/selects a group of the set available within the
+ * current group type
+ */
+void FunctionSelection::setGroup(TraceCostItem* g)
+{
+  if (!g) return;
+  if (g->type() != _groupType) return;
+  if (g == _group) return;
+  _group = g;
+
+  TQListViewItem* item  = groupList->firstChild();
+  for (;item;item = item->nextSibling())
+    if (((CostListItem*)item)->costItem() == g)
+      break;
+
+  if (item) {
+    groupList->ensureItemVisible(item);
+    // prohibit signalling of a group selection
+    _inSetGroup = true;
+    groupList->setSelected(item, true);
+    _inSetGroup = false;
+  }
+  else
+    groupList->clearSelection();
+}
+
+
+void FunctionSelection::refresh()
+{
+    groupList->setUpdatesEnabled(false);
+    groupList->clear();
+
+    // make cost columns as small as possible:
+    // the new functions make them as wide as needed
+    groupList->setColumnWidth(0, 50);
+
+    groupList->setColumnText(1, TraceItem::i18nTypeName(_groupType));
+
+    if (!_data || _data->parts().count()==0) {
+	functionList->clear();
+	groupList->setUpdatesEnabled(true);
+	groupList->repaint();
+
+	// this clears all other lists
+	functionList->setSelected(functionList->firstChild(), true);
+	return;
+    }
+
+  /*
+  qDebug("FunctionSelection::fillLists (%s)",
+         _data->command().ascii());
+  */
+
+  TraceObjectMap::Iterator oit;
+  TraceClassMap::Iterator cit;
+  TraceFileMap::Iterator fit;
+  TQListViewItem *i = 0, *item = 0, *fitem = 0;
+
+  // Fill up group list.
+  // Always show group of current function, even if cost below low limit.
+  //
+
+  _hc.clear(Configuration::maxListCount());
+
+  TraceCostItem *group;
+
+  // update group from _activeItem if possible
+  if (_activeItem && (_activeItem->type() == _groupType))
+    _group = (TraceCostItem*) _activeItem;
+
+  switch(_groupType) {
+  case TraceItem::Object:
+
+    for ( oit = _data->objectMap().begin();
+          oit != _data->objectMap().end(); ++oit )
+      _hc.addCost(&(*oit), (*oit).subCost(_costType));
+    break;
+
+  case TraceItem::Class:
+
+    for ( cit = _data->classMap().begin();
+          cit != _data->classMap().end(); ++cit )
+      _hc.addCost(&(*cit), (*cit).subCost(_costType));
+    break;
+
+  case TraceItem::File:
+
+    for ( fit = _data->fileMap().begin();
+          fit != _data->fileMap().end(); ++fit )
+      _hc.addCost(&(*fit), (*fit).subCost(_costType));
+    break;
+
+  case TraceItem::FunctionCycle:
+    {
+      // add all cycles
+      TraceFunctionCycleList l =  _data->functionCycles();
+      for (group=l.first();group;group=l.next())
+	_hc.addCost(group, group->subCost(_costType));
+    }
+
+  break;
+
+  default:
+    {
+      TQListViewItem* oldItem = functionList->selectedItem();
+      TraceFunction* oldFunction = 0;
+      int oldPos = 0;
+      if (oldItem) {
+	oldFunction = ((FunctionItem*)oldItem)->function();
+	oldPos = oldItem->itemPos();
+	oldPos -= functionList->contentsY();
+	if (oldPos < 0 || oldPos > functionList->height())
+	  oldFunction = 0;
+      }
+
+      // switching off TQListView updates is buggy with some QT versions...
+      //functionList->setUpdatesEnabled(false);
+      functionList->clear();
+      setCostColumnWidths();
+
+      if (0) qDebug("Function %s at %d, Item %p",
+		    oldFunction ? oldFunction->name().ascii() : "-",
+		    oldPos, (void*)oldItem);
+
+      TraceFunctionMap::Iterator it;
+      TraceFunction *f;
+      i = 0;
+      fitem = 0;
+      for ( it = _data->functionMap().begin();
+	    it != _data->functionMap().end(); ++it )
+	_hc.addCost(&(*it), (*it).inclusive()->subCost(_costType));
+
+      TraceFunctionCycleList l =  _data->functionCycles();
+      for (f=l.first();f;f=l.next())
+	_hc.addCost(f, f->inclusive()->subCost(_costType));
+
+      if (_activeItem &&
+	  ((_activeItem->type() == TraceItem::Function) ||
+	   (_activeItem->type() == TraceItem::FunctionCycle)))
+	fitem = new FunctionItem(functionList, (TraceFunction*)_activeItem,
+				 _costType, _groupType);
+
+      for(int i=0;i<_hc.realCount();i++) {
+	f = (TraceFunction*)_hc[i];
+	if (f == _activeItem) continue;
+	new FunctionItem(functionList, f, _costType, _groupType);
+      }
+      if (_hc.hasMore()) {
+	// a placeholder for all the cost items skipped ...
+	new FunctionItem(functionList, _hc.count() - _hc.maxSize(),
+			 (TraceFunction*)_hc[_hc.maxSize()-1], _costType);
+      }
+      functionList->sort();
+
+      if (fitem && oldFunction) {
+        _inSetFunction = true;
+	functionList->setSelected(fitem, true);
+        _inSetFunction = false;
+	int newPos = functionList->itemPos(fitem) - functionList->contentsY();
+	functionList->scrollBy(0, newPos-oldPos);
+      }
+      else if (fitem) {
+	functionList->ensureItemVisible(fitem);
+        _inSetFunction = true;
+	functionList->setSelected(fitem, true);
+        _inSetFunction = false;
+      }
+      else
+	functionList->clearSelection();
+
+      //functionList->setUpdatesEnabled(true);
+      //functionList->repaint();
+      groupList->setUpdatesEnabled(true);
+      groupList->repaint();
+      return;
+    }
+  }
+
+  // we always put group of active item in list, even if
+  // it would be skipped because of small costs
+  if (_group)
+    item = new CostListItem(groupList, _group, _costType);
+
+  for(int i=0;i<_hc.realCount();i++) {
+    group = (TraceCostItem*)_hc[i];
+    // don't put group of active item twice into list
+    if (group == _group) continue;
+    new CostListItem(groupList, group, _costType);
+  }
+  if (_hc.hasMore()) {
+      // a placeholder for all the cost items skipped ...
+    new CostListItem(groupList, _hc.count() - _hc.maxSize(),
+		     (TraceCostItem*)_hc[_hc.maxSize()-1], _costType);
+  }
+  groupList->sort();
+  if (item) {
+    groupList->ensureItemVisible(item);
+    _inSetGroup = true;
+    groupList->setSelected(item, true);
+    _inSetGroup = false;
+  }
+  else
+    groupList->clearSelection();
+
+  groupList->setUpdatesEnabled(true);
+  groupList->repaint();
+}
+
+
+void FunctionSelection::groupSelected(TQListViewItem* i)
+{
+  if (!i) return;
+  if (!_data) return;
+
+  TraceCostItem* g = ((CostListItem*) i)->costItem();
+  if (!g) return;
+
+  _group = g;
+
+  TraceFunctionList list;
+
+  switch(g->type()) {
+  case TraceItem::Object:
+    list = ((TraceObject*)g)->functions();
+    break;
+  case TraceItem::Class:
+    list = ((TraceClass*)g)->functions();
+    break;
+  case TraceItem::File:
+    list = ((TraceFile*)g)->functions();
+    break;
+  case TraceItem::FunctionCycle:
+    list = ((TraceFunctionCycle*)g)->members();
+    break;
+  default:
+    return;
+  }
+
+  // switching off TQListView updates is buggy with some QT versions...
+  //functionList->setUpdatesEnabled(false);
+
+  functionList->clear();
+  setCostColumnWidths();
+
+  double total;
+  if (Configuration::showExpanded())
+      total = (double) g->subCost(_costType);
+  else
+      total = (double) _data->subCost(_costType);
+#if 0
+  if (total == 0.0) {
+      functionList->setUpdatesEnabled(true);
+      functionList->repaint();
+      return;
+  }
+#endif
+
+  TQRegExp re(_searchString, false, true);
+
+  FunctionItem* fitem = 0;
+  TraceFunction *f;
+  _hc.clear(Configuration::maxListCount());
+  for (f=list.first();f;f=list.next()) {
+    if (re.search(f->prettyName())<0) continue;
+
+    _hc.addCost(f, f->inclusive()->subCost(_costType));
+    if (_activeItem == f)
+      fitem = new FunctionItem(functionList, (TraceFunction*)_activeItem,
+			       _costType, _groupType);
+  }
+
+  for(int i=0;i<_hc.realCount();i++) {
+    if (_activeItem == (TraceFunction*)_hc[i]) continue;
+    new FunctionItem(functionList, (TraceFunction*)_hc[i],
+		     _costType, _groupType);
+  }
+
+  if (_hc.hasMore()) {
+    // a placeholder for all the functions skipped ...
+    new FunctionItem(functionList, _hc.count() - _hc.maxSize(),
+		     (TraceFunction*)_hc[_hc.maxSize()-1], _costType);
+  }
+  functionList->sort();
+
+  if (fitem) {
+    functionList->ensureItemVisible(fitem);
+    _inSetFunction = true;
+    functionList->setSelected(fitem, true);
+    _inSetFunction = false;
+  }
+
+  //functionList->setUpdatesEnabled(true);
+  //functionList->repaint();
+
+  // Don't emit signal if cost item was changed programatically
+  if (!_inSetGroup) {
+      _selectedItem = g;
+      selected(g);
+  }
+}
+
+void FunctionSelection::groupDoubleClicked(TQListViewItem* i)
+{
+  if (!i) return;
+  if (!_data) return;
+  TraceCostItem* g = ((CostListItem*) i)->costItem();
+
+  if (!g) return;
+  // group must be selected first
+  if (g != _group) return;
+
+  activated(g);
+}
+
+
+TraceCostItem* FunctionSelection::group(TQString s)
+{
+  TQListViewItem *item;
+  item  = groupList->firstChild();
+  for(;item;item = item->nextSibling())
+    if (((CostListItem*)item)->costItem()->name() == s)
+      return ((CostListItem*)item)->costItem();
+
+  return 0;
+}
+
+
+
+void FunctionSelection::functionSelected(TQListViewItem* i)
+{
+  if (!i) return;
+  if (!_data) return;
+
+  TraceFunction* f = ((FunctionItem*) i)->function();
+  if (!f) return;
+
+  //qDebug("FunctionSelection::functionSelected %s", f->name().ascii());
+
+  // Don't emit signal if function was changed programatically
+  if (!_inSetFunction) {
+      _selectedItem = f;
+      selected(f);
+  }
+}
+
+void FunctionSelection::functionActivated(TQListViewItem* i)
+{
+  if (!i) return;
+  if (!_data) return;
+  TraceFunction* f = ((FunctionItem*) i)->function();
+
+  if (!f) return;
+
+  if (!_inSetFunction)
+    activated(f);
+}
+
+void FunctionSelection::updateGroupSizes(bool hideEmpty)
+{
+  TQListViewItem* item  = groupList->firstChild();
+  for (;item;item = item->nextSibling()) {
+    CostListItem* i = (CostListItem*)item;
+    int size = (_groupSize.contains(i->costItem())) ?
+	_groupSize[i->costItem()] : -1;    
+    i->setSize(size);
+    i->setVisible(!hideEmpty || (size>0));
+  }
+}
+
+void FunctionSelection::query(TQString query)
+{
+  if (searchEdit->text() != query)
+    searchEdit->setText(query);
+  if (_searchString == query) {
+    // when resetting query, get rid of group sizes
+    if (query.isEmpty()) {
+      _groupSize.clear();
+      updateGroupSizes(false);
+    }
+    return;
+  }
+  _searchString = query;
+
+  TQRegExp re(query, false, true);
+  _groupSize.clear();
+
+  TraceFunction* f = 0;
+  TraceFunctionList list2;
+
+  _hc.clear(Configuration::maxListCount());
+
+  TraceFunctionMap::Iterator it;
+  for ( it = _data->functionMap().begin();
+	it != _data->functionMap().end(); ++it ) {
+    f = &(*it);
+    if (re.search(f->prettyName())>=0) {
+      if (_group) {
+	if (_groupType==TraceItem::Object) {
+	  if (_groupSize.contains(f->object()))
+	    _groupSize[f->object()]++;
+	  else
+	    _groupSize[f->object()] = 1;
+	  if (f->object() != _group) continue;
+	}
+	else if (_groupType==TraceItem::Class) {
+	  if (_groupSize.contains(f->cls()))
+	    _groupSize[f->cls()]++;
+	  else
+	    _groupSize[f->cls()] = 1;
+	  if (f->cls() != _group) continue;
+	}
+	else if (_groupType==TraceItem::File) {
+	  if (_groupSize.contains(f->file()))
+	    _groupSize[f->file()]++;
+	  else
+	    _groupSize[f->file()] = 1;
+	  if (f->file() != _group) continue;
+	}
+	else if (_groupType==TraceItem::FunctionCycle) {
+	  if (_groupSize.contains(f->cycle()))
+	    _groupSize[f->cycle()]++;
+	  else
+	    _groupSize[f->cycle()] = 1;
+	  if (f->cycle() != _group) continue;
+	}
+      }
+      _hc.addCost(f, f->inclusive()->subCost(_costType));
+    }
+  }
+
+  updateGroupSizes(true);
+
+  FunctionItem *fi, *item = 0;
+
+  functionList->clear();
+  setCostColumnWidths();
+
+  for(int i=0;i<_hc.realCount();i++) {
+      fi = new FunctionItem(functionList, (TraceFunction*)_hc[i],
+			    _costType, _groupType);
+      if (_activeItem == f) item = fi;
+  }
+  if (_hc.hasMore()) {
+      // a placeholder for all the functions skipped ...
+      new FunctionItem(functionList, _hc.count() - _hc.maxSize(),
+		       (TraceFunction*)_hc[_hc.maxSize()-1], _costType);
+  }
+
+  functionList->sort();
+
+
+  if (item) {
+    functionList->ensureItemVisible(item);
+    _inSetFunction = true;
+    functionList->setSelected(item, true);
+    _inSetFunction = false;
+  }
+  else {
+    // this emits a function selection
+    functionList->setSelected(functionList->firstChild(), true);
+  }
+}
+
+bool FunctionSelection::setTopFunction()
+{
+  TQListViewItem* i = functionList->firstChild();
+  // this emits a function selection
+  functionList->setSelected(i, true);
+  functionActivated(i);
+  return i!=0;
+}
+
+void FunctionSelection::setCostColumnWidths()
+{
+  if (_costType && (_costType->subCost(_data->callMax())>0) ) {
+    functionList->setColumnWidthMode(0, TQListView::Maximum);
+    functionList->setColumnWidth(0,50);
+    functionList->setColumnWidthMode(2, TQListView::Maximum);
+    functionList->setColumnWidth(2,50);
+  }
+  else {
+    functionList->setColumnWidthMode(0, TQListView::Manual);
+    functionList->setColumnWidth(0,0);
+    functionList->setColumnWidthMode(2, TQListView::Manual);
+    functionList->setColumnWidth(2,0);
+  }
+
+  functionList->setColumnWidth(1, 50);
+}
+
+
+
+#include "functionselection.moc"
diff --git a/kdecachegrind/kdecachegrind/functionselection.h b/kdecachegrind/kdecachegrind/functionselection.h
new file mode 100644
index 0000000..c5f7810
--- /dev/null
+++ b/kdecachegrind/kdecachegrind/functionselection.h
@@ -0,0 +1,86 @@
+/* This file is part of KCachegrind.
+   Copyright (C) 2002, 2003 Josef Weidendorfer <Josef.Weidendorfer@gmx.de>
+
+   KCachegrind 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, version 2.
+
+   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; see the file COPYING.  If not, write to
+   the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+   Boston, MA 02110-1301, USA.
+*/
+
+/*
+ * For function selection, to be put into a TQDockWindow
+ */
+
+#ifndef FUNCTIONSELECTION_H
+#define FUNCTIONSELECTION_H
+
+#include "functionselectionbase.h"
+#include "traceitemview.h"
+#include "tracedata.h"
+#include "listutils.h"
+
+class TQPopupMenu;
+
+class TraceFunction;
+class TraceData;
+class StackBrowser;
+class NestedAreaItem;
+
+class FunctionSelection : public FunctionSelectionBase, public TraceItemView
+{
+  Q_OBJECT
+  TQ_OBJECT
+
+public:
+  FunctionSelection( TopLevel*, TQWidget* parent = 0, const char* name = 0);
+  ~FunctionSelection();
+
+  TraceCostItem* group(TQString);
+  void setGroup(TraceCostItem*);
+  void query(TQString);
+  bool setTopFunction();
+
+  TQWidget* widget() { return this; }
+
+  void addGroupMenu(TQPopupMenu*);
+
+public slots:
+  void searchReturnPressed();
+  void searchChanged(const TQString&);
+  void queryDelayed();
+  void groupDoubleClicked( TQListViewItem* );
+  void functionActivated( TQListViewItem* );
+  void groupSelected( TQListViewItem* );
+  void functionSelected( TQListViewItem* );
+  void functionContext(TQListViewItem*, const TQPoint &, int);
+  void groupContext(TQListViewItem*, const TQPoint &, int);
+
+private:
+  TraceItem* canShow(TraceItem* i);
+  void doUpdate(int);
+  void selectFunction();
+  void refresh();
+  void setCostColumnWidths();
+  void updateGroupSizes(bool hideEmpty);
+
+  TraceCostItem* _group;
+
+  TQString _searchString, _searchDelayed;
+  TQTimer _searchTimer;
+  TQMap<TraceCostItem*,int> _groupSize;
+
+  HighestCostList _hc;
+  // when setting a
+  bool _inSetGroup, _inSetFunction;
+};
+
+#endif
diff --git a/kdecachegrind/kdecachegrind/functionselectionbase.ui b/kdecachegrind/kdecachegrind/functionselectionbase.ui
new file mode 100644
index 0000000..eec019d
--- /dev/null
+++ b/kdecachegrind/kdecachegrind/functionselectionbase.ui
@@ -0,0 +1,163 @@
+<!DOCTYPE UI><UI version="3.1" stdsetdef="1">
+<class>FunctionSelectionBase</class>
+<widget class="TQWidget">
+    <property name="name">
+        <cstring>FunctionSelectionBase</cstring>
+    </property>
+    <property name="geometry">
+        <rect>
+            <x>0</x>
+            <y>0</y>
+            <width>223</width>
+            <height>485</height>
+        </rect>
+    </property>
+    <property name="caption">
+        <string>Function Profile</string>
+    </property>
+    <vbox>
+        <property name="name">
+            <cstring>unnamed</cstring>
+        </property>
+        <property name="margin">
+            <number>3</number>
+        </property>
+        <property name="spacing">
+            <number>6</number>
+        </property>
+        <widget class="TQLayoutWidget">
+            <property name="name">
+                <cstring>layout1</cstring>
+            </property>
+            <hbox>
+                <property name="name">
+                    <cstring>unnamed</cstring>
+                </property>
+                <widget class="TQLabel">
+                    <property name="name">
+                        <cstring>searchLabel</cstring>
+                    </property>
+                    <property name="text">
+                        <string>&amp;Search:</string>
+                    </property>
+                    <property name="buddy" stdset="0">
+                        <cstring>searchEdit</cstring>
+                    </property>
+                </widget>
+                <widget class="TQLineEdit">
+                    <property name="name">
+                        <cstring>searchEdit</cstring>
+                    </property>
+                </widget>
+                <widget class="TQComboBox">
+                    <property name="name">
+                        <cstring>groupBox</cstring>
+                    </property>
+                </widget>
+            </hbox>
+        </widget>
+        <widget class="TQListView">
+            <column>
+                <property name="text">
+                    <string>Self</string>
+                </property>
+                <property name="clickable">
+                    <bool>true</bool>
+                </property>
+                <property name="resizable">
+                    <bool>true</bool>
+                </property>
+            </column>
+            <column>
+                <property name="text">
+                    <string>Group</string>
+                </property>
+                <property name="clickable">
+                    <bool>true</bool>
+                </property>
+                <property name="resizable">
+                    <bool>true</bool>
+                </property>
+            </column>
+            <property name="name">
+                <cstring>groupList</cstring>
+            </property>
+            <property name="sizePolicy">
+                <sizepolicy>
+                    <hsizetype>7</hsizetype>
+                    <vsizetype>5</vsizetype>
+                    <horstretch>0</horstretch>
+                    <verstretch>0</verstretch>
+                </sizepolicy>
+            </property>
+            <property name="maximumSize">
+                <size>
+                    <width>32767</width>
+                    <height>150</height>
+                </size>
+            </property>
+        </widget>
+        <widget class="TQListView">
+            <column>
+                <property name="text">
+                    <string>Incl.</string>
+                </property>
+                <property name="clickable">
+                    <bool>true</bool>
+                </property>
+                <property name="resizable">
+                    <bool>true</bool>
+                </property>
+            </column>
+            <column>
+                <property name="text">
+                    <string>Self</string>
+                </property>
+                <property name="clickable">
+                    <bool>true</bool>
+                </property>
+                <property name="resizable">
+                    <bool>true</bool>
+                </property>
+            </column>
+            <column>
+                <property name="text">
+                    <string>Called</string>
+                </property>
+                <property name="clickable">
+                    <bool>true</bool>
+                </property>
+                <property name="resizable">
+                    <bool>true</bool>
+                </property>
+            </column>
+            <column>
+                <property name="text">
+                    <string>Function</string>
+                </property>
+                <property name="clickable">
+                    <bool>true</bool>
+                </property>
+                <property name="resizable">
+                    <bool>true</bool>
+                </property>
+            </column>
+            <column>
+                <property name="text">
+                    <string>Location</string>
+                </property>
+                <property name="clickable">
+                    <bool>true</bool>
+                </property>
+                <property name="resizable">
+                    <bool>true</bool>
+                </property>
+            </column>
+            <property name="name">
+                <cstring>functionList</cstring>
+            </property>
+        </widget>
+    </vbox>
+</widget>
+<layoutdefaults spacing="6" margin="11"/>
+</UI>
diff --git a/kdecachegrind/kdecachegrind/hi32-app-kcachegrind.png b/kdecachegrind/kdecachegrind/hi32-app-kcachegrind.png
new file mode 100644
index 0000000..bd41dae
Binary files /dev/null and b/kdecachegrind/kdecachegrind/hi32-app-kcachegrind.png differ
diff --git a/kdecachegrind/kdecachegrind/hi48-app-kcachegrind.png b/kdecachegrind/kdecachegrind/hi48-app-kcachegrind.png
new file mode 100644
index 0000000..58c2efd
Binary files /dev/null and b/kdecachegrind/kdecachegrind/hi48-app-kcachegrind.png differ
diff --git a/kdecachegrind/kdecachegrind/instritem.cpp b/kdecachegrind/kdecachegrind/instritem.cpp
new file mode 100644
index 0000000..ce5e81b
--- /dev/null
+++ b/kdecachegrind/kdecachegrind/instritem.cpp
@@ -0,0 +1,469 @@
+/* This file is part of KCachegrind.
+   Copyright (C) 2003 Josef Weidendorfer <Josef.Weidendorfer@gmx.de>
+
+   KCachegrind 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, version 2.
+
+   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; see the file COPYING.  If not, write to
+   the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+   Boston, MA 02110-1301, USA.
+*/
+
+/*
+ * Items of instruction view.
+ */
+
+#include <tqpixmap.h>
+#include <tqpainter.h>
+
+#include <klocale.h>
+#include <kapplication.h>
+#include <kiconloader.h>
+#include <kdebug.h>
+
+#include "configuration.h"
+#include "listutils.h"
+#include "instritem.h"
+#include "instrview.h"
+
+
+// InstrItem
+
+// for messages
+InstrItem::InstrItem(InstrView* iv, TQListView* parent,
+		     Addr addr, const TQString& msg)
+    : TQListViewItem(parent)
+{
+  _view = iv;
+  _addr = addr;
+  _instr = 0;
+  _instrCall = 0;
+  _instrJump = 0;
+  _inside = false;
+  
+  setText(0, addr.pretty());
+  setText(6, msg);
+  
+  updateGroup();
+  updateCost();
+}
+
+// for code lines
+InstrItem::InstrItem(InstrView* iv, TQListView* parent,
+		     Addr addr, bool inside,
+		     const TQString& code, const TQString& cmd,
+		     const TQString& args, TraceInstr* instr)
+    : TQListViewItem(parent)
+{
+  _view = iv;
+  _addr = addr;
+  _instr = instr;
+  _instrCall = 0;
+  _instrJump = 0;
+  _inside = inside;
+
+  if (args == "...")
+      setText(0, args);
+  else
+      setText(0, addr.pretty());
+  setText(4, code);
+  setText(5, cmd);
+  setText(6, args);
+
+  TraceLine* l;
+  if (instr && (l = instr->line()))
+      setText(7, l->name());
+
+  updateGroup();
+  updateCost();
+}
+
+// for call lines
+InstrItem::InstrItem(InstrView* iv, TQListViewItem* parent, Addr addr,
+		     TraceInstr* instr, TraceInstrCall* instrCall)
+    : TQListViewItem(parent)
+{
+  _view = iv;
+  _addr = addr;
+  _instr = instr;
+  _instrCall = instrCall;
+  _instrJump = 0;
+  _inside = true;
+
+  //qDebug("InstrItem: (file %d, line %d) Linecall to %s",
+  //       fileno, lineno, _lineCall->call()->called()->prettyName().ascii());
+
+  SubCost cc = _instrCall->callCount();
+  TQString templ = "  ";
+  if (cc==0)
+    templ += i18n("Active call to '%1'");
+  else
+    templ += i18n("%n call to '%1'", "%n calls to '%1'", cc);
+
+  TQString callStr = templ.arg(_instrCall->call()->calledName());
+  TraceFunction* calledF = _instrCall->call()->called();
+  calledF->addPrettyLocation(callStr);
+
+  setText(6, callStr);
+
+  updateGroup();
+  updateCost();
+}
+
+// for jump lines
+InstrItem::InstrItem(InstrView* iv, TQListViewItem* parent, Addr addr,
+		     TraceInstr* instr, TraceInstrJump* instrJump)
+    : TQListViewItem(parent)
+{
+  _view = iv;
+  _addr = addr;
+  _inside = true;
+  _instr = instr;
+  _instrCall = 0;
+  _instrJump = instrJump;
+
+  //qDebug("SourceItem: (file %d, line %d) Linecall to %s",
+  //       fileno, lineno, _lineCall->call()->called()->prettyName().ascii());
+
+  TQString jStr;
+  if (_instrJump->isCondJump())
+      jStr = i18n("Jump %1 of %2 times to 0x%3")
+	  .arg(_instrJump->followedCount().pretty())
+	  .arg(_instrJump->executedCount().pretty())
+	  .arg(_instrJump->instrTo()->addr().toString());
+  else
+      jStr = i18n("Jump %1 times to 0x%2")
+	  .arg(_instrJump->executedCount().pretty())
+	  .arg(_instrJump->instrTo()->addr().toString());
+
+  setText(6, jStr);
+
+  updateGroup();
+  updateCost();
+}
+
+
+void InstrItem::updateGroup()
+{
+  if (!_instrCall) return;
+
+  TraceFunction* f = _instrCall->call()->called();
+  TQColor c = Configuration::functionColor(_view->groupType(), f);
+  setPixmap(6, colorPixmap(10, 10, c));
+}
+
+void InstrItem::updateCost()
+{
+  _pure = SubCost(0);
+  _pure2 = SubCost(0);
+
+  if (!_instr) return;
+  if (_instrJump) return;
+
+  TraceCost* instrCost = _instrCall ?
+      (TraceCost*)_instrCall : (TraceCost*)_instr;
+
+  // don't show any cost inside of cycles
+  if (_instrCall &&
+      ((_instrCall->call()->inCycle()>0) ||
+       (_instrCall->call()->isRecursion()>0))) {
+    TQString str;
+    TQPixmap p;
+
+    TQString icon = "undo";
+    KIconLoader* loader = KApplication::kApplication()->iconLoader();
+    p= loader->loadIcon(icon, KIcon::Small, 0,
+                        KIcon::DefaultState, 0, true);
+    if (p.isNull())
+      str = i18n("(cycle)");
+
+    setText(1, str);
+    setPixmap(1, p);
+    setText(2, str);
+    setPixmap(2, p);
+    return;
+  }
+
+  TraceCost* totalCost;
+  if (Configuration::showExpanded())
+      totalCost = _instr->function()->inclusive();
+  else
+      totalCost = _instr->function()->data();
+
+  TraceCostType *ct = _view->costType();
+  _pure = ct ? instrCost->subCost(ct) : SubCost(0);
+  if (_pure == 0) {
+    setText(1, TQString());
+    setPixmap(1, TQPixmap());
+  }
+  else {
+    double total = totalCost->subCost(ct);
+    double pure  = 100.0 * _pure / total;
+
+    if (Configuration::showPercentage())
+      setText(1, TQString("%1")
+	      .arg(pure, 0, 'f', Configuration::percentPrecision()));
+    else
+      setText(1, _pure.pretty());
+    
+    setPixmap(1, costPixmap(ct, instrCost, total, false));
+  }
+
+  TraceCostType *ct2 = _view->costType2();
+  _pure2 = ct2 ? instrCost->subCost(ct2) : SubCost(0);
+  if (_pure2 == 0) {
+    setText(2, TQString());
+    setPixmap(2, TQPixmap());
+  }
+  else {
+    double total = totalCost->subCost(ct2);
+    double pure  = 100.0 * _pure2 / total;
+
+    if (Configuration::showPercentage())
+      setText(2, TQString("%1")
+	      .arg(pure, 0, 'f', Configuration::percentPrecision()));
+    else
+      setText(2, _pure2.pretty());
+    
+    setPixmap(2, costPixmap(ct2, instrCost, total, false));
+  }
+}
+
+
+int InstrItem::compare(TQListViewItem * i, int col, bool ascending ) const
+{
+  const InstrItem* ii1 = this;
+  const InstrItem* ii2 = (InstrItem*) i;
+
+  // we always want descending order
+  if (((col>0) && ascending) ||
+      ((col==0) && !ascending) ) {
+    ii1 = ii2;
+    ii2 = this;
+  }
+
+  if (col==1) {
+    if (ii1->_pure < ii2->_pure) return -1;
+    if (ii1->_pure > ii2->_pure) return 1;
+    return 0;
+  }
+  if (col==2) {
+    if (ii1->_pure2 < ii2->_pure2) return -1;
+    if (ii1->_pure2 > ii2->_pure2) return 1;
+    return 0;
+  }
+  if (col==0) {
+    if (ii1->_addr < ii2->_addr) return -1;
+    if (ii1->_addr > ii2->_addr) return 1;
+
+    // Same address: code gets above calls/jumps
+    if (!ii1->_instrCall && !ii1->_instrJump) return -1;
+    if (!ii2->_instrCall && !ii2->_instrJump) return 1;
+
+    // calls above jumps
+    if (ii1->_instrCall && !ii2->_instrCall) return -1;
+    if (ii2->_instrCall && !ii1->_instrCall) return 1;
+
+    if (ii1->_instrCall && ii2->_instrCall) {
+	// Two calls: desending sort according costs
+	if (ii1->_pure < ii2->_pure) return 1;
+	if (ii1->_pure > ii2->_pure) return -1;
+
+	// Two calls: sort according function names
+	TraceFunction* f1 = ii1->_instrCall->call()->called();
+	TraceFunction* f2 = ii2->_instrCall->call()->called();
+	if (f1->prettyName() > f2->prettyName()) return 1;
+	return -1;
+    }
+
+    // Two jumps: descending sort according target address
+    if (ii1->_instrJump->instrTo()->addr() <
+	ii2->_instrJump->instrTo()->addr())
+	return -1;
+    if (ii1->_instrJump->instrTo()->addr() >
+	ii2->_instrJump->instrTo()->addr())
+	return 1;
+    return 0;
+
+  }
+  return TQListViewItem::compare(i, col, ascending);
+}
+
+void InstrItem::paintCell( TQPainter *p, const TQColorGroup &cg,
+			   int column, int width, int alignment )
+{
+  TQColorGroup _cg( cg );
+
+  if ( !_inside || ((column==1) || column==2))
+    _cg.setColor( TQColorGroup::Base, cg.button() );
+  else if ((_instrCall || _instrJump) && column>2)
+    _cg.setColor( TQColorGroup::Base, cg.midlight() );
+
+  if (column == 3)
+    paintArrows(p, _cg, width);
+  else
+    TQListViewItem::paintCell( p, _cg, column, width, alignment );
+}
+
+void InstrItem::setJumpArray(const TQMemArray<TraceInstrJump*>& a)
+{
+    _jump.duplicate(a);
+}
+
+void InstrItem::paintArrows(TQPainter *p, const TQColorGroup &cg, int width)
+{
+  TQListView *lv = listView();
+  if ( !lv ) return;
+  InstrView* iv = (InstrView*) lv;
+
+  const BackgroundMode bgmode = lv->viewport()->backgroundMode();
+  const TQColorGroup::ColorRole crole
+    = TQPalette::backgroundRoleFromMode( bgmode );
+  if ( cg.brush( crole ) != lv->colorGroup().brush( crole ) )
+    p->fillRect( 0, 0, width, height(), cg.brush( crole ) );
+  else
+    iv->paintEmptyArea( p, TQRect( 0, 0, width, height() ) );
+
+  if ( isSelected() && lv->allColumnsShowFocus() )
+    p->fillRect( 0, 0, width, height(), cg.brush( TQColorGroup::Highlight ) );
+
+  int marg = lv->itemMargin();
+  int yy = height()/2, y1, y2;
+  TQColor c;
+
+  int start = -1, end = -1;
+
+  // draw line borders, detect start/stop of a line
+  for(int i=0;i< (int)_jump.size();i++) {
+      if (_jump[i] == 0) continue;
+
+      y1 = 0;
+      y2 = height();
+      if ((_instrJump == _jump[i]) &&
+	  (_jump[i]->instrFrom()->addr() == _addr)) {
+
+	  //kdDebug() << "InstrItem " << _addr.toString() << ": start " << i << endl;
+	  if (start<0) start = i;
+	  if (_jump[i]->instrTo()->addr() <= _addr)
+	      y2 = yy;
+	  else
+	      y1 = yy;
+      }
+      else if (!_instrJump && !_instrCall &&
+	       (_jump[i]->instrTo()->addr() == _addr)) {
+
+	  //kdDebug() << "InstrItem " << _addr.toString() << ": end " << i << endl;
+	  if (end<0) end = i;
+	  if (_jump[i]->instrFrom()->addr() < _addr)
+	      y2 = yy;
+	  else
+	      y1 = yy;
+      }
+
+      c = _jump[i]->isCondJump() ? red : blue;
+#if 0
+      if (_jump[i] == ((TraceItemView*)_view)->selectedItem()) {	  
+	  p->fillRect( marg + 6*i-2, (y1==0) ? y1: y1-2,
+		       8, (y2-y1==height())? y2:y2+2,
+		       cg.brush( TQColorGroup::Highlight ) );
+	  c = lv->colorGroup().highlightedText();
+      }
+#endif
+      p->fillRect( marg + 6*i, y1, 4, y2, c);
+      p->setPen(c.light());
+      p->drawLine( marg + 6*i, y1, marg + 6*i, y2);
+      p->setPen(c.dark());
+      p->drawLine( marg + 6*i +3, y1, marg + 6*i +3, y2);
+  }
+
+  // draw start/stop horizontal line
+  int x, y = yy-2, w, h = 4;
+  if (start >= 0) {
+#if 0
+      if (_jump[start] == ((TraceItemView*)_view)->selectedItem()) {	  
+	  c = lv->colorGroup().highlightedText();
+      }
+#endif
+      c = _jump[start]->isCondJump() ? red : blue;
+      x = marg + 6*start;
+      w = 6*(iv->arrowLevels() - start) + 10;
+      p->fillRect( x, y, w, h, c);
+      p->setPen(c.light());
+      p->drawLine(x, y, x+w-1, y);
+      p->drawLine(x, y, x, y+h-1);
+      p->setPen(c.dark());
+      p->drawLine(x+w-1, y, x+w-1, y+h-1);
+      p->drawLine(x+1, y+h-1, x+w-1, y+h-1);
+  }
+  if (end >= 0) {
+      c = _jump[end]->isCondJump() ? red : blue;
+      x = marg + 6*end;
+      w = 6*(iv->arrowLevels() - end) + 10;
+
+      TQPointArray a;
+      a.putPoints(0, 7, x, y+h,
+		  x,y, x+w-8, y, x+w-8, y-2,
+		  x+w, yy,
+		  x+w-8, y+h+2, x+w-8, y+h);
+      p->setBrush(c);
+      p->drawConvexPolygon(a);
+
+      p->setPen(c.light());
+      p->drawPolyline(a, 0, 5);
+      p->setPen(c.dark());
+      p->drawPolyline(a, 4, 2);
+      p->setPen(c.light());
+      p->drawPolyline(a, 5, 2);
+      p->setPen(c.dark());
+      p->drawPolyline(a, 6, 2);
+  }
+
+  // draw inner vertical line for start/stop
+  // this overwrites borders of horizontal line
+  for(int i=0;i< (int)_jump.size();i++) {
+      if (_jump[i] == 0) continue;
+
+      c = _jump[i]->isCondJump() ? red : blue;
+
+      if (_jump[i]->instrFrom()->addr() == _addr) {
+	  bool drawUp = true;
+	  if (_jump[i]->instrTo()->addr() == _addr)
+	      if (start<0) drawUp=false;	  
+	  if (_jump[i]->instrTo()->addr() > _addr) drawUp=false;
+	  if (drawUp)
+	      p->fillRect( marg + 6*i +1, 0, 2, yy, c);
+	  else
+	      p->fillRect( marg + 6*i +1, yy, 2, height()-yy, c);
+      }
+      else if (_jump[i]->instrTo()->addr() == _addr) {
+	  if (end<0) end = i;
+	  if (_jump[i]->instrFrom()->addr() < _addr)
+	      p->fillRect( marg + 6*i +1, 0, 2, yy, c);
+	  else
+	      p->fillRect( marg + 6*i +1, yy, 2, height()-yy, c);
+      }
+  }
+
+}
+
+int InstrItem::width( const TQFontMetrics& fm,
+                      const TQListView* lv, int c ) const
+{
+  if (c != 3) return TQListViewItem::width(fm, lv, c);
+
+  InstrView* iv = (InstrView*) lv;
+  int levels = iv->arrowLevels();
+
+  if (levels == 0) return 0;
+
+  // 10 pixels for the arrow
+  return 10 + 6*levels + lv->itemMargin() * 2;
+}
+
diff --git a/kdecachegrind/kdecachegrind/instritem.h b/kdecachegrind/kdecachegrind/instritem.h
new file mode 100644
index 0000000..2bbce71
--- /dev/null
+++ b/kdecachegrind/kdecachegrind/instritem.h
@@ -0,0 +1,86 @@
+/* This file is part of KCachegrind.
+   Copyright (C) 2003 Josef Weidendorfer <Josef.Weidendorfer@gmx.de>
+
+   KCachegrind 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, version 2.
+
+   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; see the file COPYING.  If not, write to
+   the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+   Boston, MA 02110-1301, USA.
+*/
+
+/*
+ * Items of instruction view.
+ */
+
+#ifndef INSTRITEM_H
+#define INSTRITEM_H
+
+#include <tqlistview.h>
+#include "tracedata.h"
+
+class InstrView;
+
+class InstrItem: public TQListViewItem
+{
+
+public:
+  // for messages
+  InstrItem(InstrView* iv, TQListView* parent,
+	    Addr addr, const TQString&);
+
+  // for instruction lines
+  InstrItem(InstrView* iv, TQListView* parent,
+	    Addr addr, bool inside,
+	    const TQString&, const TQString&, const TQString&,
+	    TraceInstr* instr);
+
+  // for call instr
+  InstrItem(InstrView* iv, TQListViewItem* parent, Addr addr,
+	    TraceInstr* instr, TraceInstrCall* instrCall);
+
+  // for jump lines
+  InstrItem(InstrView* iv, TQListViewItem* parent, Addr addr,
+	    TraceInstr* instr, TraceInstrJump* instrJump);
+
+  Addr addr() const { return _addr; }
+  TraceInstr* instr() const { return _instr; }
+  TraceInstrCall* instrCall() const { return _instrCall; }
+  TraceInstrJump* instrJump() const { return _instrJump; }
+
+  int compare(TQListViewItem * i, int col, bool ascending ) const;
+
+  void paintCell(TQPainter *p, const TQColorGroup &cg,
+                 int column, int width, int alignment );
+  int width( const TQFontMetrics& fm,
+             const TQListView* lv, int c ) const;
+
+  void updateGroup();
+  void updateCost();
+
+  // arrow lines
+  void setJumpArray(const TQMemArray<TraceInstrJump*>& a);
+
+protected:
+  void paintArrows(TQPainter *p, const TQColorGroup &cg, int width);
+  TQMemArray<TraceInstrJump*> _jump;
+
+private:
+  InstrView* _view;
+  SubCost _pure, _pure2;
+  Addr _addr;
+  TraceInstr* _instr;
+  TraceInstrJump* _instrJump;
+  TraceInstrCall* _instrCall;
+  bool _inside;
+};
+
+
+#endif
diff --git a/kdecachegrind/kdecachegrind/instrview.cpp b/kdecachegrind/kdecachegrind/instrview.cpp
new file mode 100644
index 0000000..3df1679
--- /dev/null
+++ b/kdecachegrind/kdecachegrind/instrview.cpp
@@ -0,0 +1,949 @@
+/* This file is part of KCachegrind.
+   Copyright (C) 2003 Josef Weidendorfer <Josef.Weidendorfer@gmx.de>
+
+   KCachegrind 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, version 2.
+
+   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; see the file COPYING.  If not, write to
+   the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+   Boston, MA 02110-1301, USA.
+*/
+
+/*
+ * Instruction View
+ */
+
+#include <tqfile.h>
+#include <tqregexp.h>
+#include <tqwhatsthis.h>
+#include <tqpopupmenu.h>
+#include <klocale.h>
+#include <kconfig.h>
+#include <kdebug.h>
+
+#include "configuration.h"
+#include "instritem.h"
+#include "instrview.h"
+
+// InstrView defaults
+
+#define DEFAULT_SHOWHEXCODE true
+
+
+// Helpers for parsing output of 'objdump'
+
+static Addr parseAddr(char* buf)
+{
+    Addr addr;
+    uint pos = 0;
+
+    // check for instruction line: <space>* <hex address> ":" <space>*
+    while(buf[pos]==' ' || buf[pos]=='\t') pos++;
+
+    int digits = addr.set(buf + pos);
+    if ((digits==0) || (buf[pos+digits] != ':')) return Addr(0);
+
+    return addr;
+}
+
+
+static bool parseLine(char* buf, Addr& addr,
+                      uint& pos1, uint& pos2, uint& pos3)
+{
+    // check for instruction line: <space>* <hex address> ":" <space>*
+
+    pos1 = 0;
+    while(buf[pos1]==' ' || buf[pos1]=='\t') pos1++;
+
+    int digits = addr.set(buf + pos1);
+    pos1 += digits;
+    if ((digits==0) || (buf[pos1] != ':')) return false;
+
+    // further parsing of objdump output...
+    pos1++;
+    while(buf[pos1]==' ' || buf[pos1]=='\t') pos1++;
+
+    // skip code, pattern "xx "*
+    pos2 = pos1;
+    while(1) {
+	if (! ((buf[pos2]>='0' && buf[pos2]<='9') ||
+	       (buf[pos2]>='a' && buf[pos2]<='f')) ) break;
+	if (! ((buf[pos2+1]>='0' && buf[pos2+1]<='9') ||
+	       (buf[pos2+1]>='a' && buf[pos2+1]<='f')) ) break;
+	if (buf[pos2+2] != ' ') break;
+	pos2 += 3;
+    }
+    buf[pos2-1]=0;
+    while(buf[pos2]==' '|| buf[pos2]=='\t') pos2++;
+
+    // skip mnemonic
+    pos3 = pos2;
+    while(buf[pos3] && buf[pos3]!=' ' && buf[pos3]!='\t') pos3++;
+    if (buf[pos3] != 0) {
+	buf[pos3] = 0;
+	pos3++;
+	while(buf[pos3]==' '|| buf[pos3]=='\t') pos3++;
+    }
+
+    // maximal 50 chars
+    if (strlen(buf+pos2) > 50)
+	strcpy(buf+pos2+47, "...");
+
+    if (0) qDebug("For 0x%s: Code '%s', Mnc '%s', Args '%s'",
+		  addr.toString().ascii(), buf+pos1, buf+pos2, buf+pos3);
+
+    return true;
+}
+
+
+
+
+//
+// InstrView
+//
+
+
+InstrView::InstrView(TraceItemView* parentView,
+                     TQWidget* parent, const char* name)
+  : TQListView(parent, name), TraceItemView(parentView)
+{
+  _showHexCode = DEFAULT_SHOWHEXCODE;
+  _lastHexCodeWidth = 50;
+
+  _inSelectionUpdate = false;
+  _arrowLevels = 0;
+  _lowList.setSortLow(true);
+  _highList.setSortLow(false);
+
+  addColumn( i18n( "#" ) );
+  addColumn( i18n( "Cost" ) );
+  addColumn( i18n( "Cost 2" ) );
+  addColumn( "" );
+  addColumn( i18n( "Hex" ) );
+  addColumn( "" ); // Instruction
+  addColumn( i18n( "Assembler" ) );
+  addColumn( i18n( "Source Position" ) );
+
+  setAllColumnsShowFocus(true);
+  setColumnAlignment(1, TQt::AlignRight);
+  setColumnAlignment(2, TQt::AlignRight);
+
+  connect(this,
+          TQT_SIGNAL(contextMenuRequested(TQListViewItem*, const TQPoint &, int)),
+          TQT_SLOT(context(TQListViewItem*, const TQPoint &, int)));
+
+  connect(this, TQT_SIGNAL(selectionChanged(TQListViewItem*)),
+          TQT_SLOT(selectedSlot(TQListViewItem*)));
+
+  connect(this,
+          TQT_SIGNAL(doubleClicked(TQListViewItem*)),
+          TQT_SLOT(activatedSlot(TQListViewItem*)));
+
+  connect(this,
+          TQT_SIGNAL(returnPressed(TQListViewItem*)),
+          TQT_SLOT(activatedSlot(TQListViewItem*)));
+
+  TQWhatsThis::add( this, whatsThis());
+}
+
+void InstrView::paintEmptyArea( TQPainter * p, const TQRect & r)
+{
+  TQListView::paintEmptyArea(p, r);
+}
+
+TQString InstrView::whatsThis() const
+{
+    return i18n( "<b>Annotated Assembler</b>"
+		 "<p>The annotated assembler list shows the "
+		 "machine code instructions of the current selected "
+		 "function together with (self) cost spent while "
+		 "executing an instruction. If this is a call "
+		 "instruction, lines with details on the "
+		 "call happening are inserted into the source: "
+		 "the cost spent inside of the call, the "
+		 "number of calls happening, and the call destination.</p>"
+		 "<p>The disassembler output shown is generated with "
+		 "the 'objdump' utility from the 'binutils' package.</p>"
+		 "<p>Select a line with call information to "
+		 "make the destination function of this call current.</p>");
+}
+
+void InstrView::context(TQListViewItem* i, const TQPoint & p, int c)
+{
+  TQPopupMenu popup;
+
+  TraceInstrCall* ic = i ? ((InstrItem*) i)->instrCall() : 0;
+  TraceInstrJump* ij = i ? ((InstrItem*) i)->instrJump() : 0;
+  TraceFunction* f = ic ? ic->call()->called() : 0;
+  TraceInstr* instr = ij ? ij->instrTo() : 0;
+
+  if (f) {
+    TQString name = f->name();
+    if ((int)name.length()>Configuration::maxSymbolLength())
+      name = name.left(Configuration::maxSymbolLength()) + "...";
+    popup.insertItem(i18n("Go to '%1'").arg(name), 93);
+    popup.insertSeparator();
+  }
+  else if (instr) {
+    popup.insertItem(i18n("Go to Address %1").arg(instr->name()), 93);
+    popup.insertSeparator();
+  }
+
+  if ((c == 1) || (c == 2)) {
+    addCostMenu(&popup);
+    popup.insertSeparator();
+  }
+  addGoMenu(&popup);
+
+  popup.insertSeparator();
+  popup.setCheckable(true);
+  popup.insertItem(i18n("Hex Code"), 94);
+  if (_showHexCode) popup.setItemChecked(94,true);
+
+  int r = popup.exec(p);
+  if (r == 93) {
+    if (f) activated(f);
+    if (instr) activated(instr);
+  }
+  else if (r == 94) {
+    _showHexCode = !_showHexCode;
+    // remember width when hiding
+    if (!_showHexCode)
+      _lastHexCodeWidth = columnWidth(4);
+    setColumnWidths();
+  }
+}
+
+
+void InstrView::selectedSlot(TQListViewItem * i)
+{
+  if (!i) return;
+  // programatically selected items are not signalled
+  if (_inSelectionUpdate) return;
+
+  TraceInstrCall* ic = ((InstrItem*) i)->instrCall();
+  TraceInstrJump* ij = ((InstrItem*) i)->instrJump();
+
+  if (!ic && !ij) {
+      TraceInstr* instr = ((InstrItem*) i)->instr();
+      if (instr) {
+	  _selectedItem = instr;
+	  selected(instr);
+      }
+      return;
+  }
+
+  if (ic) {
+      _selectedItem = ic;
+      selected(ic);
+  }
+  else if (ij) {
+      _selectedItem = ij;
+      selected(ij);
+  }
+}
+
+void InstrView::activatedSlot(TQListViewItem * i)
+{
+  if (!i) return;
+  TraceInstrCall* ic = ((InstrItem*) i)->instrCall();
+  TraceInstrJump* ij = ((InstrItem*) i)->instrJump();
+
+  if (!ic && !ij) {
+      TraceInstr* instr = ((InstrItem*) i)->instr();
+      if (instr) activated(instr);
+      return;
+  }
+
+  if (ic) {
+    TraceFunction* f = ic->call()->called();
+    if (f) activated(f);
+  }
+  else if (ij) {
+    TraceInstr* instr = ij->instrTo();
+    if (instr) activated(instr);
+  }
+}
+
+
+TraceItem* InstrView::canShow(TraceItem* i)
+{
+  TraceItem::CostType t = i ? i->type() : TraceItem::NoCostType;
+  TraceFunction* f = 0;
+
+  switch(t) {
+  case TraceItem::Function:
+      f = (TraceFunction*) i;
+      break;
+
+  case TraceItem::Instr:
+      f = ((TraceInstr*)i)->function();
+      select(i);
+      break;
+
+  case TraceItem::Line:
+      f = ((TraceLine*)i)->functionSource()->function();
+      select(i);
+      break;
+
+  default:
+      break;
+  }
+
+  return f;
+}
+
+
+void InstrView::doUpdate(int changeType)
+{
+  // Special case ?
+  if (changeType == selectedItemChanged) {
+
+      if (!_selectedItem) {
+	  clearSelection();
+	  return;
+      }
+
+      InstrItem *ii = (InstrItem*)TQListView::selectedItem();
+      if (ii) {
+	  if ((ii->instr() == _selectedItem) ||
+	      (ii->instr() && (ii->instr()->line() == _selectedItem))) return;
+      }
+
+      TQListViewItem *item, *item2;
+      for (item = firstChild();item;item = item->nextSibling()) {
+	  ii = (InstrItem*)item;
+	  if ((ii->instr() == _selectedItem) ||
+	      (ii->instr() && (ii->instr()->line() == _selectedItem))) {
+	      ensureItemVisible(item);
+              _inSelectionUpdate = true;
+	      setCurrentItem(item);
+              _inSelectionUpdate = false;
+	      break;
+	  }
+	  item2 = item->firstChild();
+	  for (;item2;item2 = item2->nextSibling()) {
+	      ii = (InstrItem*)item2;
+	      if (!ii->instrCall()) continue;
+	      if (ii->instrCall()->call()->called() == _selectedItem) {
+		  ensureItemVisible(item2);
+                  _inSelectionUpdate = true;
+		  setCurrentItem(item2);
+                  _inSelectionUpdate = false;
+		  break;
+	      }
+	  }
+	  if (item2) break;
+      }
+      return;
+  }
+
+  if (changeType == groupTypeChanged) {
+    TQListViewItem *item, *item2;
+    for (item = firstChild();item;item = item->nextSibling())
+      for (item2 = item->firstChild();item2;item2 = item2->nextSibling())
+        ((InstrItem*)item2)->updateGroup();
+    return;
+  }
+
+  refresh();
+}
+
+void InstrView::setColumnWidths()
+{
+  if (_showHexCode) {
+    setColumnWidthMode(4, TQListView::Maximum);
+    setColumnWidth(4, _lastHexCodeWidth);
+  }
+  else {
+    setColumnWidthMode(4, TQListView::Manual);
+    setColumnWidth(4, 0);
+  }
+}
+
+void InstrView::refresh()
+{
+    _arrowLevels = 0;
+
+    // reset to automatic sizing to get column width
+    setColumnWidthMode(4, TQListView::Maximum);
+
+    clear();
+    setColumnWidth(0, 20);
+    setColumnWidth(1, 50);
+    setColumnWidth(2, _costType2 ? 50:0);
+    setColumnWidth(3, 0);   // arrows, defaults to invisible
+    setColumnWidth(4, 0);   // hex code column
+    setColumnWidth(5, 20);  // command column
+    setColumnWidth(6, 200); // arg column
+    setSorting(0); // always reset to address number sort
+    if (_costType)
+      setColumnText(1, _costType->name());
+    if (_costType2)
+      setColumnText(2, _costType2->name());
+
+    if (!_data || !_activeItem) return;
+
+    TraceItem::CostType t = _activeItem->type();
+    TraceFunction* f = 0;
+    if (t == TraceItem::Function) f = (TraceFunction*) _activeItem;
+    if (t == TraceItem::Instr) {
+	f = ((TraceInstr*)_activeItem)->function();
+	if (!_selectedItem) _selectedItem = _activeItem;
+    }
+    if (t == TraceItem::Line) {
+	f = ((TraceLine*)_activeItem)->functionSource()->function();
+	if (!_selectedItem) _selectedItem = _activeItem;
+    }
+
+    if (!f) return;
+
+    // Allow resizing of column 2
+    setColumnWidthMode(2, TQListView::Maximum);
+
+    // check for instruction map
+    TraceInstrMap::Iterator itStart, it, tmpIt, itEnd;
+    TraceInstrMap* instrMap = f->instrMap();
+    if (instrMap) {
+	it    = instrMap->begin();
+	itEnd = instrMap->end();
+	// get first instruction with cost of selected type
+	while(it != itEnd) {
+	  if ((*it).hasCost(_costType)) break;
+	  if (_costType2 && (*it).hasCost(_costType2)) break;
+	  ++it;
+	}
+    }
+    if (!instrMap || (it == itEnd)) {
+	new InstrItem(this, this, 1,
+		      i18n("There is no instruction info in the profile data file."));
+	new InstrItem(this, this, 2,
+		      i18n("For the Valgrind Calltree Skin, rerun with option"));
+	new InstrItem(this, this, 3, i18n("      --dump-instr=yes"));
+	new InstrItem(this, this, 4, i18n("To see (conditional) jumps, additionally specify"));
+	new InstrItem(this, this, 5, i18n("      --trace-jump=yes"));
+	return;
+    }
+
+    // initialisation for arrow drawing
+    // create sorted list of jumps (for jump arrows)
+    _lowList.clear();
+    _highList.clear();
+    itStart = it;
+    while(1) {
+	TraceInstrJumpList jlist = (*it).instrJumps();
+	TraceInstrJump* ij;
+	for (ij=jlist.first();ij;ij=jlist.next()) {
+	    if (ij->executedCount()==0) continue;
+	    _lowList.append(ij);
+	    _highList.append(ij);
+	}
+	++it;
+	while(it != itEnd) {
+	  if ((*it).hasCost(_costType)) break;
+	  if (_costType2 && (*it).hasCost(_costType2)) break;
+	  ++it;
+	}
+	if (it == itEnd) break;
+    }
+    _lowList.sort();
+    _highList.sort();
+    _lowList.first(); // iterators to list start
+    _highList.first();
+    _arrowLevels = 0;
+    _jump.resize(0);
+
+
+    // do multiple calls to 'objdump' if there are large gaps in addresses
+    it = itStart;
+    while(1) {
+	itStart = it;
+	while(1) {
+	    tmpIt = it;
+	    ++it;
+	    while(it != itEnd) {
+	      if ((*it).hasCost(_costType)) break;
+	      if (_costType2 && (*it).hasCost(_costType2)) break;
+	      ++it;
+	    }
+	    if (it == itEnd) break;
+	    if (!(*it).addr().isInRange( (*tmpIt).addr(),10000) ) break;
+	}
+
+	// tmpIt is always last instruction with cost
+	if (!fillInstrRange(f, itStart, ++tmpIt)) break;
+	if (it == itEnd) break;
+    }
+
+    _lastHexCodeWidth = columnWidth(4);
+    setColumnWidths();
+
+    if (!_costType2) {
+      setColumnWidthMode(2, TQListView::Manual);
+      setColumnWidth(2, 0);
+    }
+}
+
+/* This is called after adding instrItems, for each of them in
+ * address order. _jump is the global array of valid jumps
+ * for a line while we iterate downwards.
+ * The existing jumps, sorted in lowList according lower address,
+ * is iterated in the same way.
+ */
+void InstrView::updateJumpArray(Addr addr, InstrItem* ii,
+				bool ignoreFrom, bool ignoreTo)
+{
+    TraceInstrJump* ij;
+    Addr lowAddr, highAddr;
+    int iEnd = -1, iStart = -1;
+
+    if (0) qDebug("updateJumpArray(addr 0x%s, jump to %s)",
+		  addr.toString().ascii(),
+		  ii->instrJump()
+		  ? ii->instrJump()->instrTo()->name().ascii() : "?" );
+
+    // check for new arrows starting from here downwards
+    ij=_lowList.current();
+    while(ij) {
+	lowAddr = ij->instrFrom()->addr();
+	if (ij->instrTo()->addr() < lowAddr)
+	    lowAddr = ij->instrTo()->addr();
+
+	if (lowAddr > addr) break;
+
+	// if target is downwards but we draw no source, break
+	if (ignoreFrom && (lowAddr < ij->instrTo()->addr())) break;
+	// if source is downward but we draw no target, break
+	if (ignoreTo && (lowAddr < ij->instrFrom()->addr())) break;
+	// if this is another jump start, break
+	if (ii->instrJump() && (ij != ii->instrJump())) break;
+
+#if 0
+	for(iStart=0;iStart<_arrowLevels;iStart++)
+	    if (_jump[iStart] &&
+		(_jump[iStart]->instrTo() == ij->instrTo())) break;
+#else
+	iStart = _arrowLevels;
+#endif
+
+	if (iStart==_arrowLevels) {
+	    for(iStart=0;iStart<_arrowLevels;iStart++)
+		if (_jump[iStart] == 0) break;
+	    if (iStart==_arrowLevels) {
+		_arrowLevels++;
+		_jump.resize(_arrowLevels);
+	    }
+	    if (0) qDebug("  new start at %d for %s", iStart, ij->name().ascii());
+	    _jump[iStart] = ij;
+	}
+	ij=_lowList.next();
+    }
+
+    ii->setJumpArray(_jump);
+
+    // check for active arrows ending here
+    ij=_highList.current();
+    while(ij) {
+	highAddr = ij->instrFrom()->addr();
+	if (ij->instrTo()->addr() > highAddr) {
+	    highAddr = ij->instrTo()->addr();
+	    if (ignoreTo) break;
+	}
+	else if (ignoreFrom) break;
+
+	if (highAddr > addr) break;
+
+	for(iEnd=0;iEnd<_arrowLevels;iEnd++)
+	    if (_jump[iEnd] == ij) break;
+	if (iEnd==_arrowLevels) {
+	  kdDebug() << "InstrView: no jump start for end at 0x"
+		    << highAddr.toString() << " ?" << endl;
+	  iEnd = -1;
+	}
+
+	if (0 && (iEnd>=0))
+	    qDebug(" end %d (%s to %s)",
+		   iEnd,
+		   _jump[iEnd]->instrFrom()->name().ascii(),
+		   _jump[iEnd]->instrTo()->name().ascii());
+
+	if (0 && ij) qDebug("next end: %s to %s",
+			    ij->instrFrom()->name().ascii(),
+			    ij->instrTo()->name().ascii());
+
+	ij=_highList.next();
+	if (highAddr > addr)
+	    break;
+	else {
+	    if (iEnd>=0) _jump[iEnd] = 0;
+	    iEnd = -1;
+	}
+    }
+    if (iEnd>=0) _jump[iEnd] = 0;
+}
+
+
+
+/**
+ * Fill up with instructions from cost range [it;itEnd[
+ */
+bool InstrView::fillInstrRange(TraceFunction* function,
+                               TraceInstrMap::Iterator it,
+                               TraceInstrMap::Iterator itEnd)
+{
+    Addr costAddr, nextCostAddr, objAddr, addr;
+    Addr dumpStartAddr, dumpEndAddr;
+    TraceInstrMap::Iterator costIt;
+
+    // shouldn't happen
+    if (it == itEnd) return false;
+
+    // calculate address range for call to objdump
+    TraceInstrMap::Iterator tmpIt = itEnd;
+    --tmpIt;
+    nextCostAddr = (*it).addr();
+    dumpStartAddr = (nextCostAddr<20) ? Addr(0) : nextCostAddr -20;
+    dumpEndAddr   = (*tmpIt).addr() +20;
+
+    // generate command
+    TQString popencmd, objfile;
+    objfile = function->object()->name();
+    objfile = objfile.replace(TQRegExp("[\"']"), ""); // security...
+    popencmd = TQString("objdump -C -d "
+                       "--start-address=0x%1 --stop-address=0x%2 \"%3\"")
+	.arg(dumpStartAddr.toString()).arg(dumpEndAddr.toString())
+	.arg(objfile);
+    if (1) qDebug("Running '%s'...", popencmd.ascii());
+
+    // and run...
+    FILE* iFILE = popen(TQFile::encodeName( popencmd ), "r");
+    if (iFILE == 0) {
+	new InstrItem(this, this, 1,
+		      i18n("There is an error trying to execute the command"));
+	new InstrItem(this, this, 2, "");
+	new InstrItem(this, this, 3, popencmd);
+	new InstrItem(this, this, 4, "");
+	new InstrItem(this, this, 5,
+		      i18n("Check that you have installed 'objdump'."));
+	new InstrItem(this, this, 6,
+		      i18n("This utility can be found in the 'binutils' package."));
+	return false;
+    }
+    TQFile file;
+    file.open(IO_ReadOnly, iFILE);
+
+#define BUF_SIZE  256
+
+    char buf[BUF_SIZE];
+    bool inside = false, skipLineWritten = true;
+    int readBytes = -1;
+    int objdumpLineno = 0, dumpedLines = 0, noAssLines = 0;
+    SubCost most = 0;
+    TraceInstr* currInstr;
+    InstrItem *ii, *ii2, *item = 0, *first = 0, *selected = 0;
+    TQString code, cmd, args;
+    bool needObjAddr = true, needCostAddr = true;
+
+    costAddr = 0;
+    objAddr  = 0;
+
+    while (1) {
+
+      if (needObjAddr) {
+	  needObjAddr = false;
+
+        // read next objdump line
+        while (1) {
+          readBytes=file.readLine(buf, BUF_SIZE);
+          if (readBytes<=0) { 
+	    objAddr = 0; 
+	    break;
+	  }
+
+          objdumpLineno++;
+          if (readBytes == BUF_SIZE) {
+	    qDebug("ERROR: Line %d of '%s' too long\n",
+                   objdumpLineno, popencmd.ascii());
+          }
+          else if ((readBytes>0) && (buf[readBytes-1] == '\n'))
+	    buf[readBytes-1] = 0;
+
+          objAddr = parseAddr(buf);
+          if ((objAddr<dumpStartAddr) || (objAddr>dumpEndAddr))
+            objAddr = 0;
+          if (objAddr != 0) break;
+        }
+
+        if (0) kdDebug() << "Got ObjAddr: 0x" << objAddr.toString() << endl;
+      }
+
+      // try to keep objAddr in [costAddr;nextCostAddr]
+      if (needCostAddr &&
+	  (nextCostAddr > 0) &&
+	  ((objAddr == Addr(0)) || (objAddr >= nextCostAddr)) ) {
+	  needCostAddr = false;
+
+	  costIt = it;
+	  ++it;
+	  while(it != itEnd) {
+	    if ((*it).hasCost(_costType)) break;
+	    if (_costType2 && (*it).hasCost(_costType2)) break;
+	    ++it;
+	  }
+	  costAddr = nextCostAddr;
+	  nextCostAddr = (it == itEnd) ? Addr(0) : (*it).addr();
+
+	  if (0) kdDebug() << "Got nextCostAddr: 0x" << nextCostAddr.toString()
+			   << ", costAddr 0x" << costAddr.toString() << endl;
+      }
+
+      // if we have no more address from objdump, stop
+      if (objAddr == 0) break;
+
+      if ((nextCostAddr==0) || (costAddr == 0) ||
+	  (objAddr < nextCostAddr)) {
+	  // next line is objAddr
+
+	  uint pos1, pos2, pos3;
+
+	  // this sets addr
+	  parseLine(buf, addr, pos1, pos2, pos3);
+	  code = TQString(buf + pos1);
+	  cmd  = TQString(buf + pos2);
+	  args = TQString(buf + pos3);
+
+	  if (costAddr == objAddr) {
+	      currInstr = &(*costIt);
+	      needCostAddr = true;
+	  }
+	  else
+	      currInstr = 0;
+
+	  needObjAddr = true;
+
+	  if (0) kdDebug() << "Dump Obj Addr: 0x" << addr.toString()
+			   << " [" << cmd << " " << args << "], cost (0x"
+			   << costAddr.toString() << ", next 0x"
+			   << nextCostAddr.toString() << ")" << endl;
+      }
+      else {
+	  addr = costAddr;
+	  code = cmd = TQString();
+	  args = i18n("(No Assembler)");
+
+	  currInstr = &(*costIt);
+	  needCostAddr = true;
+
+	  noAssLines++;
+	  if (0) kdDebug() << "Dump Cost Addr: 0x" << addr.toString()
+			   << " (no ass), objAddr 0x" << objAddr.toString() << endl;
+      }
+
+      // update inside
+      if (!inside) {
+	  if (currInstr) inside = true;
+      }
+      else {
+	if (0) kdDebug() << "Check if 0x" << addr.toString() << " is in ]0x"
+			 << costAddr.toString() << ",0x"
+			 << (nextCostAddr - 3*Configuration::noCostInside()).toString()
+			 << "[" << endl;
+
+	  // Suppose a average instruction len of 3 bytes
+	  if ( (addr > costAddr) &&
+	       ((nextCostAddr==0) ||
+		(addr < nextCostAddr - 3*Configuration::noCostInside()) ))
+	      inside = false;
+      }
+
+      int context = Configuration::context();
+
+      if ( ((costAddr==0)     || (addr > costAddr + 3*context)) &&
+           ((nextCostAddr==0) || (addr < nextCostAddr - 3*context)) ) {
+
+	  // the very last skipLine can be ommitted
+	  if ((it == itEnd) &&
+	      (itEnd == function->instrMap()->end())) skipLineWritten=true;
+
+	  if (!skipLineWritten) {
+	      skipLineWritten = true;
+	      // a "skipping" line: print "..." instead of a line number
+	      code = cmd = TQString();
+	      args = TQString("...");
+	  }
+	  else
+	      continue;
+      }
+      else
+	  skipLineWritten = false;
+
+
+      ii = new InstrItem(this, this, addr, inside,
+                         code, cmd, args, currInstr);
+      dumpedLines++;
+      if (0) kdDebug() << "Dumped 0x" << addr.toString() << " "
+		       << (inside ? "Inside " : "Outside")
+		       << (currInstr ? "Cost" : "") << endl;
+
+      // no calls/jumps if we have no cost for this line
+      if (!currInstr) continue;
+
+      if (!selected &&
+	  (currInstr == _selectedItem) ||
+	  (currInstr->line() == _selectedItem)) selected = ii;
+
+      if (!first) first = ii;
+
+      if (currInstr->subCost(_costType) > most) {
+        item = ii;
+        most = currInstr->subCost(_costType);
+      }
+
+      ii->setOpen(true);
+      TraceInstrCallList list = currInstr->instrCalls();
+      TraceInstrCall* ic;
+      for (ic=list.first();ic;ic=list.next()) {
+	  if ((ic->subCost(_costType)==0) &&
+	      (ic->subCost(_costType2)==0)) continue;
+
+	  if (ic->subCost(_costType) > most) {
+	      item = ii;
+	      most = ic->subCost(_costType);
+	  }
+
+	  ii2 = new InstrItem(this, ii, addr, currInstr, ic);
+
+	  if (!selected && (ic->call()->called() == _selectedItem))
+	      selected = ii2;
+      }
+
+      TraceInstrJumpList jlist = currInstr->instrJumps();
+      TraceInstrJump* ij;
+      for (ij=jlist.first();ij;ij=jlist.next()) {
+	  if (ij->executedCount()==0) continue;
+
+	  new InstrItem(this, ii, addr, currInstr, ij);
+      }
+    }
+
+    if (selected) item = selected;
+    if (item) first = item;
+    if (first) {
+	ensureItemVisible(first);
+        _inSelectionUpdate = true;
+        setCurrentItem(first);
+        _inSelectionUpdate = false;
+    }
+
+    file.close();
+    pclose(iFILE);
+
+    // for arrows: go down the list according to list sorting
+    sort();
+    TQListViewItem *item1, *item2;
+    for (item1=firstChild();item1;item1 = item1->nextSibling()) {
+	ii = (InstrItem*)item1;
+	updateJumpArray(ii->addr(), ii, true, false);
+
+	for (item2=item1->firstChild();item2;item2 = item2->nextSibling()) {
+	    ii2 = (InstrItem*)item2;
+	    if (ii2->instrJump())
+		updateJumpArray(ii->addr(), ii2, false, true);
+	    else
+		ii2->setJumpArray(_jump);
+	}
+    }
+
+    if (arrowLevels())
+	setColumnWidth(3, 10 + 6*arrowLevels() + itemMargin() * 2);
+    else
+	setColumnWidth(3, 0);
+
+
+    if (noAssLines > 1) {
+	// trace cost not machting code
+
+	new InstrItem(this, this, 1,
+		      i18n("There is %n cost line without assembler code.",
+                           "There are %n cost lines without assembler code.", noAssLines));
+	new InstrItem(this, this, 2,
+		      i18n("This happens because the code of"));
+	new InstrItem(this, this, 3, TQString("        %1").arg(objfile));
+	new InstrItem(this, this, 4,
+		      i18n("does not seem to match the profile data file."));
+	new InstrItem(this, this, 5, "");
+	new InstrItem(this, this, 6,
+		      i18n("Are you using an old profile data file or is the above mentioned"));
+	new InstrItem(this, this, 7,
+		      i18n("ELF object from an updated installation/another machine?"));
+	new InstrItem(this, this, 8, "");
+	return false;
+    }
+
+    if (dumpedLines == 0) {
+	// no matching line read from popen
+	new InstrItem(this, this, 1,
+		      i18n("There seems to be an error trying to execute the command"));
+	new InstrItem(this, this, 2, "");
+	new InstrItem(this, this, 3, popencmd);
+	new InstrItem(this, this, 4, "");
+	new InstrItem(this, this, 5,
+		      i18n("Check that the ELF object used in the command exists."));
+	new InstrItem(this, this, 6,
+		      i18n("Check that you have installed 'objdump'."));
+	new InstrItem(this, this, 7,
+		      i18n("This utility can be found in the 'binutils' package."));
+	return false;
+    }
+
+    return true;
+}
+
+
+void InstrView::updateInstrItems()
+{
+    InstrItem* ii;
+    TQListViewItem* item  = firstChild();
+    for (;item;item = item->nextSibling()) {
+	ii = (InstrItem*)item;
+	TraceInstr* instr = ii->instr();
+	if (!instr) continue;
+
+	ii->updateCost();
+
+	TQListViewItem *next, *i  = ii->firstChild();
+	for (;i;i = next) {
+	    next = i->nextSibling();
+	    ((InstrItem*)i)->updateCost();
+	}
+    }
+}
+
+void InstrView::readViewConfig(KConfig* c, 
+			       TQString prefix, TQString postfix, bool)
+{
+    KConfigGroup* g = configGroup(c, prefix, postfix);
+
+    if (0) qDebug("InstrView::readViewConfig");
+
+    _showHexCode  = g->readBoolEntry("ShowHexCode", DEFAULT_SHOWHEXCODE);
+
+    delete g;
+}
+
+void InstrView::saveViewConfig(KConfig* c,
+			       TQString prefix, TQString postfix, bool)
+{
+    KConfigGroup g(c, (prefix+postfix).ascii());
+
+    writeConfigEntry(&g, "ShowHexCode", _showHexCode, DEFAULT_SHOWHEXCODE);
+}
+
+#include "instrview.moc"
diff --git a/kdecachegrind/kdecachegrind/instrview.h b/kdecachegrind/kdecachegrind/instrview.h
new file mode 100644
index 0000000..79d3d76
--- /dev/null
+++ b/kdecachegrind/kdecachegrind/instrview.h
@@ -0,0 +1,83 @@
+/* This file is part of KCachegrind.
+   Copyright (C) 2003 Josef Weidendorfer <Josef.Weidendorfer@gmx.de>
+
+   KCachegrind 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, version 2.
+
+   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; see the file COPYING.  If not, write to
+   the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+   Boston, MA 02110-1301, USA.
+*/
+
+/*
+ * Instruction View
+ */
+
+#ifndef INSTRVIEW_H
+#define INSTRVIEW_H
+
+#include <tqlistview.h>
+#include "traceitemview.h"
+
+class InstrItem;
+
+class InstrView : public TQListView, public TraceItemView
+{
+  friend class InstrItem;
+
+  Q_OBJECT
+  TQ_OBJECT
+
+public:
+  InstrView(TraceItemView* parentView,
+            TQWidget* parent = 0, const char* name = 0);
+
+  virtual TQWidget* widget() { return this; }
+  TQString whatsThis() const;
+
+  void readViewConfig(KConfig*, TQString prefix, TQString postfix, bool);
+  void saveViewConfig(KConfig*, TQString prefix, TQString postfix, bool);
+
+protected:
+  int arrowLevels() { return _arrowLevels; }
+  void paintEmptyArea( TQPainter *, const TQRect & );
+
+private slots:
+  void context(TQListViewItem*, const TQPoint &, int);
+  void selectedSlot(TQListViewItem *);
+  void activatedSlot(TQListViewItem *);
+
+private:
+  TraceItem* canShow(TraceItem*);
+  void doUpdate(int);
+  void refresh();
+  void setColumnWidths();
+  void fillInstr();
+  void updateJumpArray(Addr,InstrItem*,bool,bool);
+  bool fillInstrRange(TraceFunction*,
+                      TraceInstrMap::Iterator,TraceInstrMap::Iterator);
+  void updateInstrItems();
+
+  bool _inSelectionUpdate;
+
+  // arrows
+  int _arrowLevels;
+  // temporary needed on creation...
+  TQMemArray<TraceInstrJump*> _jump;
+  TraceInstrJumpList _lowList, _highList;
+
+  // remember width of hex code column if hidden
+  int _lastHexCodeWidth;
+
+  // widget options
+  bool _showHexCode;
+};
+
+#endif
diff --git a/kdecachegrind/kdecachegrind/listutils.cpp b/kdecachegrind/kdecachegrind/listutils.cpp
new file mode 100644
index 0000000..0053646
--- /dev/null
+++ b/kdecachegrind/kdecachegrind/listutils.cpp
@@ -0,0 +1,266 @@
+/* This file is part of KCachegrind.
+   Copyright (C) 2003 Josef Weidendorfer <Josef.Weidendorfer@gmx.de>
+
+   KCachegrind 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, version 2.
+
+   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; see the file COPYING.  If not, write to
+   the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+   Boston, MA 02110-1301, USA.
+*/
+
+/*
+ * Some helper functions for TQListViewItem derivates
+ */
+
+#include <tqpainter.h>
+#include "listutils.h"
+
+#define COSTPIX_WIDTH 25
+
+TQPixmap colorPixmap(int w, int h, TQColor c)
+{
+  static TQPixmap* pixs[37];
+  static TQColor cols[37];
+  static bool inited = false;
+
+  if (!inited) {
+    for (int i=0;i<37;i++) pixs[i]=0;
+    inited = true;
+  }
+  int hash = (w+h+c.red()+c.green()+c.blue()) % 37;
+  if (pixs[hash]) {
+    if ((pixs[hash]->width() == w) &&
+        (pixs[hash]->height() == h) &&
+        (cols[hash] == c))
+      return *pixs[hash];
+
+    delete pixs[hash];
+  }
+
+
+  TQPixmap* pix = new TQPixmap(w, h);
+  pix->fill(c);
+  TQPainter p(pix);
+  p.setPen(c.light());
+  p.drawLine(0, 0, w-1, 0);
+  p.drawLine(0, 0, 0, h-1);
+  p.setPen(c.dark());
+  p.drawLine(w-1, 0, w-1, h-1);
+  p.drawLine(0, h-1, w-1, h-1);
+
+  pixs[hash] = pix;
+  cols[hash] = c;
+  return *pix;
+}
+
+/**
+ * Create a percentage pixmap with a filling rate of p percent (0-100).
+ * When withFrame==false, the pixmap is truncated to only the filled portion.
+ */
+TQPixmap percentagePixmap(int w, int h, int percent, TQColor c, bool framed)
+{
+  int iw, ix1, ix2, ih, iy1, iy2;
+
+  // inner rectangle to fill with bar
+  if (framed) {
+    iw = w-2, ix1 = 1, ix2 = w-2;
+    ih = h-2, iy1 = 1, iy2 = h-2;
+  }
+  else {
+    iw = w; ix1 = 0; ix2 = w-1;
+    ih = h; iy1 = 0; iy2 = h-1;
+  }
+
+  /* Limit bar to 100%  */
+  int filled = (percent>100) ? iw+1 : iw*percent/100+1;
+  if (!framed) w=filled-1;
+  if (w<3) return TQPixmap();
+
+  TQPixmap pix(w, h);
+  pix.fill(TQt::white);
+  TQPainter p(&pix);
+  p.setPen(TQt::black);
+  if (framed)
+    p.drawRect(0, 0, w, h);
+
+  // inside
+  p.setPen(TQt::NoPen);
+  p.setBrush(c);
+  p.drawRect(ix1, iy1, filled-1,ih);
+
+  // frame
+  ix2 = ix1+filled-2;
+  p.setPen(c.light());
+  p.drawLine(ix1, iy1, ix2, iy1);
+  p.drawLine(ix1, iy1, ix1, iy2);
+  p.setPen(c.dark());
+  p.drawLine(ix1+1, iy2, ix2, iy2);
+  p.drawLine(ix2, iy1, ix2, iy2);
+
+  return pix;
+}
+
+inline TQColor partitionColor(int d, int max)
+{
+  return TQColor( (720*d/max) % 360,
+                 255-(128*d/max), 192, TQColor::Hsv);
+}
+
+
+TQPixmap partitionPixmap(int w, int h,
+                        double* hist, TQColor* cArray, int maxIndex, bool framed)
+{
+  int lastPos = 0, nextPos;
+  double val=0.0, sum=0.0;
+  int d, dmin=maxIndex, dmax=0;
+  for (d = 0;d<maxIndex;d++)
+    if (hist[d]>0.0) {
+      sum += hist[d];
+      if (dmin>d) dmin = d;
+      if (dmax<d) dmax = d;
+    }
+
+  // inner rectangle to fill with bar
+  int iw, ix1, ix2, ih, iy1, iy2;
+  if (framed) {
+    iw = w-2, ix1 = 1, ix2 = w-2;
+    ih = h-2, iy1 = 1, iy2 = h-2;
+  }
+  else {
+    iw = w; ix1 = 0; ix2 = w-1;
+    ih = h; iy1 = 0; iy2 = h-1;
+  }
+
+  int filled = (int)(iw*sum+1);
+  if (!framed && (filled < w)) w=filled;
+  if (w<3) return TQPixmap();
+
+  TQPixmap pix(w, h);
+  pix.fill(TQt::white);
+  TQPainter p(&pix);
+  p.setPen(TQt::black);
+  if (framed)
+    p.drawRect(0, 0, w, h);
+
+  //qDebug("Sum %f, dw %d", sum,dw);
+
+  TQColor c, cLast;
+  bool leftDrawn = false;
+  int x1, x2=0;
+  int lastDiff=0, diff;
+  d=dmin;
+  while (d<dmax+1) {
+    val += hist[d];
+    nextPos = (int)(filled * val/sum);
+
+    //qDebug(" hist[%d] %f, val %f, nextPos %d", d, hist[d], val, nextPos);
+
+    diff = nextPos-lastPos;
+    if (diff==0) { d++; continue; }
+
+    c = cArray ? cArray[d] : partitionColor(d,maxIndex);
+
+    x1 = ix1+lastPos;
+    x2 = ix1+nextPos;
+    if (x2>=iw) x2=iw-1;
+
+    // inside
+    p.setPen(TQt::NoPen);
+    p.setBrush(c);
+    p.drawRect(x1, iy1, x2-x1+1, ih);
+
+    // lighter top border
+    p.setPen(c.light());
+    p.drawLine(x1, iy1, x2-1, iy1);
+
+    // when width for last and current distance >2, draw full 3D effect...
+    if (!leftDrawn) {
+      p.drawLine(x1, iy1+1, x1, iy2);
+      leftDrawn = true;
+    }
+
+    // darker bottom border
+    p.setPen(c.dark());
+    p.drawLine(x1, iy2, x2-1, iy2);
+
+    lastPos = nextPos;
+    lastDiff = diff;
+    cLast = c;
+    d++;
+  }
+
+  // right border (in last color)
+  if (x2>0)
+    p.drawLine(x2, iy1, x2, iy2);
+
+  return pix;
+}
+
+
+TQPixmap costPixmap(TraceCostType* ct, TraceCost* cost, double total, bool framed)
+{
+    if (ct->isReal()) {
+	TQColor color = ct->color();
+	double p = 100.0 * cost->subCost(ct) / total;
+	return percentagePixmap(COSTPIX_WIDTH, 10, (int)(p+.5), color, framed);
+    }
+
+    int maxIndex;
+    double h[MaxRealIndexValue];
+    TQColor* cs = ct->mapping()->realColors();
+    maxIndex = ct->histCost(cost, total, h);
+
+    if (maxIndex ==0) return TQPixmap();    
+    return partitionPixmap(COSTPIX_WIDTH, 10, h, cs, maxIndex, framed);
+}
+
+
+
+// HighestCostList
+
+HighestCostList::HighestCostList()
+{
+    _maxSize = 0;
+    _count = 0;
+    _costType = 0;
+}
+
+void HighestCostList::clear(int maxSize)
+{
+    _maxSize = maxSize;
+    _count = 0;
+    _item.resize(maxSize);
+    _cost.resize(maxSize);
+}
+
+void HighestCostList::addCost(TraceCost* c, SubCost cost)
+{
+    int i;
+
+    _count++;
+    if (_count > _maxSize) {
+	if (_cost[_maxSize-1] >= cost) return;
+	i = _maxSize-1;
+    }
+    else i = _count-1;
+
+    for(; i>0; i--) {
+	if (_cost[i-1] >= cost) break;
+	else {
+	    _cost[i] = _cost[i-1];
+	    _item[i] = _item[i-1];
+	}
+    }
+    _cost[i] = cost;
+    _item[i] = c;
+}
+
+	    
diff --git a/kdecachegrind/kdecachegrind/listutils.h b/kdecachegrind/kdecachegrind/listutils.h
new file mode 100644
index 0000000..e3e13fb
--- /dev/null
+++ b/kdecachegrind/kdecachegrind/listutils.h
@@ -0,0 +1,65 @@
+/* This file is part of KCachegrind.
+   Copyright (C) 2003 Josef Weidendorfer <Josef.Weidendorfer@gmx.de>
+
+   KCachegrind 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, version 2.
+
+   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; see the file COPYING.  If not, write to
+   the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+   Boston, MA 02110-1301, USA.
+*/
+
+/*
+ * Some helper functions for TQListViewItem derivates
+ */
+
+#ifndef LISTUTILS_H
+#define LISTUTILS_H
+
+#include <tqpixmap.h>
+#include <tqstring.h>
+#include <tqcolor.h>
+#include "tracedata.h"
+
+TQString bigNum(SubCost);
+TQPixmap colorPixmap(int w, int h, TQColor c);
+TQPixmap percentagePixmap(int w, int h, int percent, TQColor c, bool framed);
+TQPixmap partitionPixmap(int w, int h, double* hist, TQColor*,
+			int maxIndex, bool framed);
+TQPixmap costPixmap(TraceCostType* ct, TraceCost* cost, double total, bool framed);
+
+/**
+ * A class to calculate the <maxSize> TraceCost items
+ * with highest cost.
+ */
+
+class HighestCostList
+{
+ public:
+    HighestCostList();
+    
+    void clear(int maxSize);
+    void addCost(TraceCost*, SubCost);
+    int count() { return _count; }
+    int realCount() { return (_count > _maxSize) ? _maxSize:_count; }
+    int maxSize() { return _maxSize; }
+    bool hasMore() { return _count > _maxSize; }
+    TraceCost* operator[] (int i)
+	{ return (i>=0 && i<_count && i<_maxSize) ? _item[i] : 0; }
+    
+ private:
+    TraceCostList _list;
+    int _maxSize, _count;
+    TraceCostType* _costType;
+    TQMemArray<TraceCost*> _item;
+    TQMemArray<SubCost> _cost;
+};
+
+#endif
diff --git a/kdecachegrind/kdecachegrind/lo16-app-kcachegrind.png b/kdecachegrind/kdecachegrind/lo16-app-kcachegrind.png
new file mode 100644
index 0000000..0985586
Binary files /dev/null and b/kdecachegrind/kdecachegrind/lo16-app-kcachegrind.png differ
diff --git a/kdecachegrind/kdecachegrind/lo32-app-kcachegrind.png b/kdecachegrind/kdecachegrind/lo32-app-kcachegrind.png
new file mode 100644
index 0000000..12542c8
Binary files /dev/null and b/kdecachegrind/kdecachegrind/lo32-app-kcachegrind.png differ
diff --git a/kdecachegrind/kdecachegrind/loader.cpp b/kdecachegrind/kdecachegrind/loader.cpp
new file mode 100644
index 0000000..a4aecf5
--- /dev/null
+++ b/kdecachegrind/kdecachegrind/loader.cpp
@@ -0,0 +1,85 @@
+/* This file is part of KCachegrind.
+   Copyright (C) 2002 Josef Weidendorfer <Josef.Weidendorfer@gmx.de>
+
+   KCachegrind 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, version 2.
+
+   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; see the file COPYING.  If not, write to
+   the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+   Boston, MA 02110-1301, USA.
+*/
+
+/*
+ * Base class for loaders of profiling data.
+ */
+
+#include "loader.h"
+
+
+/// Loader
+
+LoaderList Loader::_loaderList;
+
+Loader::Loader(TQString name, TQString desc)
+{
+  _name = name;
+  _description = desc;
+}
+
+Loader::~Loader()
+{}
+
+bool Loader::canLoadTrace(TQFile*)
+{
+  return false;
+}
+
+bool Loader::loadTrace(TracePart*)
+{
+  return false;
+}
+
+Loader* Loader::matchingLoader(TQFile* file)
+{
+  Loader* l;
+  for (l=_loaderList.first(); l; l = _loaderList.next())
+    if (l->canLoadTrace(file))
+      return l;
+
+  return 0;
+}
+
+Loader* Loader::loader(TQString name)
+{
+  Loader* l;
+  for (l=_loaderList.first(); l; l = _loaderList.next())
+    if (l->name() == name)
+      return l;
+
+  return 0;
+}
+
+// factories of available loaders
+Loader* createCachegrindLoader();
+
+void Loader::initLoaders()
+{
+  _loaderList.append(createCachegrindLoader());
+  //_loaderList.append(GProfLoader::createLoader());
+}
+
+void Loader::deleteLoaders()
+{
+  _loaderList.setAutoDelete(true);
+  _loaderList.clear();
+}
+
+
+#include "loader.moc"
diff --git a/kdecachegrind/kdecachegrind/loader.h b/kdecachegrind/kdecachegrind/loader.h
new file mode 100644
index 0000000..f79f13d
--- /dev/null
+++ b/kdecachegrind/kdecachegrind/loader.h
@@ -0,0 +1,80 @@
+/* This file is part of KCachegrind.
+   Copyright (C) 2002 Josef Weidendorfer <Josef.Weidendorfer@gmx.de>
+
+   KCachegrind 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, version 2.
+
+   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; see the file COPYING.  If not, write to
+   the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+   Boston, MA 02110-1301, USA.
+*/
+
+/*
+ * Base class for loaders of profiling data.
+ */
+
+#ifndef LOADER_H
+#define LOADER_H
+
+#include <tqobject.h>
+#include <tqptrlist.h>
+#include <tqstring.h>
+
+class TQFile;
+class TraceData;
+class TracePart;
+class Loader;
+
+
+typedef TQPtrList<Loader> LoaderList;
+
+/**
+ * To implement a new loader, inherit from the Loader class
+ * and implement canLoadTrace(), loadTrace() and if a trace in
+ * this format can consist out of multiple parts, implement
+ * isPartOfTrace(), too.
+ * For registration, put into the static initLoaders() function
+ * of this base class a _loaderList.append(new MyLoader()).
+ *
+ * KCachegrind will use the first matching loader.
+ */
+
+class Loader: public TQObject
+{
+    Q_OBJECT
+  TQ_OBJECT
+
+public:
+  Loader(TQString name, TQString desc);
+  virtual ~Loader();
+
+  virtual bool canLoadTrace(TQFile* file);
+  virtual bool loadTrace(TracePart*);
+
+  static Loader* matchingLoader(TQFile* file);
+  static Loader* loader(TQString name);
+  static void initLoaders();
+  static void deleteLoaders();
+
+  TQString name() const { return _name; }
+  TQString description() const { return _description; }
+
+signals:
+  void updateStatus(TQString, int);
+
+private:
+  TQString _name, _description;
+
+  static LoaderList _loaderList;
+};
+
+
+
+#endif
diff --git a/kdecachegrind/kdecachegrind/main.cpp b/kdecachegrind/kdecachegrind/main.cpp
new file mode 100644
index 0000000..fd9df1b
--- /dev/null
+++ b/kdecachegrind/kdecachegrind/main.cpp
@@ -0,0 +1,95 @@
+/* This file is part of KCachegrind.
+   Copyright (C) 2003 Josef Weidendorfer <Josef.Weidendorfer@gmx.de>
+
+   KCachegrind 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, version 2.
+
+   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; see the file COPYING.  If not, write to
+   the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+   Boston, MA 02110-1301, USA.
+*/
+
+/*
+ * KCachegrind startup
+ */
+
+// for KCACHEGRIND_VERSION
+#include "../version.h"
+
+#include <tqfile.h>
+#include <kapplication.h>
+#include <kcmdlineargs.h>
+#include <kaboutdata.h>
+#include <klocale.h>
+
+#include "toplevel.h"
+#include "tracedata.h"
+#include "loader.h"
+
+static KCmdLineOptions options[] =
+{
+  { "r <exec>", I18N_NOOP("Run <exec> under cachegrind"), 0 },
+  { "+[trace]", I18N_NOOP("Show information of this trace"), 0 },
+  KCmdLineLastOption // End of options.
+};
+
+int main( int argc, char ** argv )
+{
+  KAboutData aboutData("kdecachegrind",
+                       I18N_NOOP("KCachegrind"),
+                       KCACHEGRIND_VERSION,
+                       I18N_NOOP("KDE Frontend for Cachegrind"),
+                       KAboutData::License_GPL,
+                       I18N_NOOP("(C) 2002, 2003, 2004"), 0,
+		       "http://kdecachegrind.sf.net");
+  aboutData.addAuthor("Josef Weidendorfer",
+                      I18N_NOOP("Author/Maintainer"),
+                      "Josef.Weidendorfer@gmx.de");
+
+  KCmdLineArgs::init(argc, argv, &aboutData);
+  KCmdLineArgs::addCmdLineOptions( options );
+
+  KApplication a;
+  TopLevel* t;
+  Loader::initLoaders();
+
+  if (a.isRestored()){
+    int n = 1;
+    while (KMainWindow::canBeRestored(n)){
+      (new TopLevel())->restore(n);
+      n++;
+    }
+  }
+  else {
+    KCmdLineArgs *args = KCmdLineArgs::parsedArgs();
+    if (args->count()>0) {
+      for(int i = 0; i < args->count(); i++) {
+        t = new TopLevel();
+        t->show();
+        t->loadDelayed(TQFile::decodeName(args->arg(i)));
+      }
+    }
+    else {
+      // load trace in current dir
+      t = new TopLevel();
+      t->show();
+      t->loadDelayed(".");
+    }
+  }
+
+  a.connect( &a, TQT_SIGNAL( lastWindowClosed() ), &a, TQT_SLOT( quit() ) );
+  int res = a.exec();
+
+  // to make leak checking in valgrind happy...
+  Loader::deleteLoaders();
+  TraceItem::cleanup();
+
+  return res;
+}
diff --git a/kdecachegrind/kdecachegrind/multiview.cpp b/kdecachegrind/kdecachegrind/multiview.cpp
new file mode 100644
index 0000000..4288e2d
--- /dev/null
+++ b/kdecachegrind/kdecachegrind/multiview.cpp
@@ -0,0 +1,224 @@
+/* This file is part of KCachegrind.
+   Copyright (C) 2003 Josef Weidendorfer <Josef.Weidendorfer@gmx.de>
+
+   KCachegrind 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, version 2.
+
+   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; see the file COPYING.  If not, write to
+   the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+   Boston, MA 02110-1301, USA.
+*/
+
+/*
+ * MultiView, enclosing multiple TabView's with a user choosable
+ * active view (i.e. focus), separated by a splitter.
+ * Selection of the active view is shown in the next to the right view
+ * (with wrap around).
+ */
+
+#include <tqobjectlist.h>
+#include <kconfig.h>
+#include <kdebug.h>
+
+#include "multiview.h"
+#include "tabview.h"
+
+//
+// MultiView
+//
+
+MultiView::MultiView(TopLevel* top, TQWidget* parent, const char* name)
+    : TQSplitter(parent, name), TraceItemView(0, top)
+{
+  // default
+  setOrientation(Qt::Horizontal);
+
+    appendView();
+    _active = _views.first();
+    _active->setActive(true);
+}
+
+void MultiView::setData(TraceData* d)
+{
+  TraceItemView::setData(d);
+
+  TabView* tv;
+  for(tv=_views.first(); tv; tv=_views.next())
+    tv->setData(d);
+}
+
+void MultiView::setChildCount(int n)
+{
+    while(n< (int)_views.count()) removeView();
+    while(n> (int)_views.count()) appendView();
+}
+
+void MultiView::appendView()
+{
+    int n = _views.count()+1;
+
+    TabView* tv = new TabView(this, this,
+			      TQString("TabView-%1").arg(n).ascii());
+    connect(tv, TQT_SIGNAL(activated(TabView*)),
+	    this, TQT_SLOT(tabActivated(TabView*)) );
+    _views.append(tv);
+    tv->show();
+
+    // set same attributes as in active view
+    tv->set(0, _data, _costType, _costType2,
+	    _groupType, _partList, _activeItem, 0);
+    tv->updateView();
+
+    if (0) kdDebug() << "MultiView::appendView, now "
+		     << _views.count() << endl;
+}
+
+void MultiView::removeView()
+{
+    if (_views.count()<=1) return;
+
+    TabView* last = _views.last();
+
+    // if last tab is active, make first active
+    if (last == _active) {
+	TabView* newActive = _views.first();
+	newActive->setActive(true);
+	tabActivated(newActive);
+    }
+
+    _views.removeRef(last);
+    delete last;
+
+    if (0) kdDebug() << "MultiView::removeView, now "
+		     << _views.count() << endl;
+}
+
+
+void MultiView::tabActivated(TabView* newActiveTab)
+{
+    if (_active == newActiveTab) return;
+
+    if (0) kdDebug() << "MultiView::tabActivated " 
+		     << newActiveTab->name() << endl;
+
+    TraceItem* oldActiveItem = 0;
+    if (_active) {
+	oldActiveItem = _active->activeItem();
+	_active->setActive(false);
+    }
+    _active = newActiveTab;
+
+    // make the active item of the new TabView active
+    if (_active && (oldActiveItem != _active->activeItem()))
+	TraceItemView::activated(_active->activeItem());
+}
+
+void MultiView::selected(TraceItemView* sender, TraceItem* i)
+{
+    if (0) kdDebug() << "MultiView::selected " << i->name()
+		     << ", sender " << sender->widget()->name() << endl;
+
+     // we react only on selection changes of the active TabView
+    if (sender != (TraceItemView*)_active) return;
+
+    _views.findRef(_active);
+    TabView* next = _views.next();
+    if (!next) next = _views.first();
+
+    // don't change item of active tab
+    if (next == _active) return;
+
+    next->activate(i);
+    next->updateView();
+}
+
+void MultiView::activated(TraceItemView* sender, TraceItem* i)
+{
+    if (0) kdDebug() << "MultiView::activated " << i->name()
+		     << ", sender " << sender->widget()->name() << endl;
+
+    // we react only on selection changes of the active TabView
+    if (sender != (TraceItemView*)_active) return;
+
+    TraceItemView::activated(sender,i);
+}
+
+void MultiView::doUpdate(int changeType)
+{
+    TabView* tv;
+    for(tv=_views.first(); tv; tv=_views.next()) {
+	tv->set(changeType, _data, _costType, _costType2,
+		_groupType, _partList,
+		(tv == _active) ? _activeItem : tv->activeItem(),
+		tv->selectedItem());
+	tv->notifyChange(changeType);
+	if (tv->isViewVisible())
+	    tv->updateView();
+    }
+}
+
+
+void MultiView::readViewConfig(KConfig* c,
+			       TQString prefix, TQString postfix,
+			       bool withOptions)
+{
+  if (0) qDebug("%s::readConfig(%s%s)", name(),
+		prefix.ascii(), postfix.ascii());
+
+  TQString active;
+  KConfigGroup* g = configGroup(c, prefix, postfix);
+  int n = g->readNumEntry("Panels", 1);
+  setChildCount(n);
+  setOrientation( (g->readEntry("Orientation") == TQString("Horizontal")) ?
+		  Qt::Horizontal : Qt::Vertical );
+  
+  setSizes(g->readIntListEntry("PanelSizes"));
+  
+  active = g->readEntry("ActivePanel", "");
+  delete g;
+
+  TabView* tv, *activeTV = 0;
+  for(tv=_views.first();tv;tv=_views.next()) {
+    if (tv->name() == active) activeTV=tv;
+    tv->readViewConfig(c, TQString("%1-%2").arg(prefix).arg(tv->name()),
+		       postfix, withOptions);
+  }
+
+  // activate panel after restoring
+  if (!activeTV) activeTV = _views.first();
+  
+  if (_active == activeTV)
+    TraceItemView::activated(_active->activeItem());
+  else
+    activeTV->setActive(true);
+}
+
+void MultiView::saveViewConfig(KConfig* c, 
+			       TQString prefix, TQString postfix,
+			       bool withOptions)
+{
+  KConfigGroup g(c, (prefix+postfix).ascii());
+  
+  g.writeEntry("Panels", childCount());
+  g.writeEntry("Orientation",
+	       (orientation() == Qt::Horizontal) ?
+	       "Horizontal" : "Vertical");
+  
+  g.writeEntry("PanelSizes", sizes());
+  g.writeEntry("ActivePanel", _active ? _active->name() : "none");
+
+  TabView* tv;
+  for(tv=_views.first();tv;tv=_views.next())
+    tv->saveViewConfig(c, TQString("%1-%2").arg(prefix).arg(tv->name()),
+		       postfix, withOptions);
+}
+
+
+#include "multiview.moc"
diff --git a/kdecachegrind/kdecachegrind/multiview.h b/kdecachegrind/kdecachegrind/multiview.h
new file mode 100644
index 0000000..9d77101
--- /dev/null
+++ b/kdecachegrind/kdecachegrind/multiview.h
@@ -0,0 +1,67 @@
+/* This file is part of KCachegrind.
+   Copyright (C) 2003 Josef Weidendorfer <Josef.Weidendorfer@gmx.de>
+
+   KCachegrind 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, version 2.
+
+   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; see the file COPYING.  If not, write to
+   the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+   Boston, MA 02110-1301, USA.
+*/
+
+/*
+ * MultiView, enclosing multiple (default: 2) TabView's with a user
+ * choosable active view (i.e. focus). This is a splitter itself.
+ * Selection of the active view is shown in the next to the right view
+ * (with wrap around).
+ */
+
+#ifndef MULTIVIEW_H
+#define MULTIVIEW_H
+
+#include <tqsplitter.h>
+#include <tqptrlist.h>
+#include "traceitemview.h"
+#include "tabview.h" // because of TQPtrList<TabView>
+
+class MultiView : public TQSplitter, public TraceItemView
+{
+  Q_OBJECT
+  TQ_OBJECT
+
+public:
+  MultiView(TopLevel* top, TQWidget* parent = 0, const char* name = 0);
+
+  TQWidget* widget() { return this; }
+  TabView* activeTabView() const { return _active; }
+  void setData(TraceData*);
+
+  void appendView();
+  void removeView();
+  void setChildCount(int);
+  int childCount() { return _views.count(); }
+
+  void selected(TraceItemView*, TraceItem*);
+  void activated(TraceItemView*, TraceItem*);
+
+  void readViewConfig(KConfig*, TQString prefix, TQString postfix, bool);
+  void saveViewConfig(KConfig*, TQString prefix, TQString postfix, bool);
+
+public slots:
+    void tabActivated(TabView*);
+
+ private:
+  void doUpdate(int);
+
+  TabView* _active;
+  TQPtrList<TabView> _views;
+};
+
+#endif
diff --git a/kdecachegrind/kdecachegrind/partgraph.cpp b/kdecachegrind/kdecachegrind/partgraph.cpp
new file mode 100644
index 0000000..a20f53d
--- /dev/null
+++ b/kdecachegrind/kdecachegrind/partgraph.cpp
@@ -0,0 +1,534 @@
+/* This file is part of KCachegrind.
+   Copyright (C) 2003 Josef Weidendorfer <Josef.Weidendorfer@gmx.de>
+
+   KCachegrind 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, version 2.
+
+   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; see the file COPYING.  If not, write to
+   the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+   Boston, MA 02110-1301, USA.
+*/
+
+/*
+ * TracePart as Nested Area
+ */
+
+#include <klocale.h>
+
+#include "partgraph.h"
+#include "configuration.h"
+#include "listutils.h"
+
+
+// PartAreaWidget
+
+PartAreaWidget::PartAreaWidget(TQWidget* parent, const char* name)
+    : TreeMapWidget(new BasePartItem(), parent, name)
+{
+  _data = 0;
+  _function = 0;
+
+  _costType = 0;
+  _groupType = TraceCost::NoCostType;
+  _visualisation = NoVisualisation;
+  _zoomFunction = false;
+  _callLevels = 1;
+}
+
+void PartAreaWidget::setData(TraceData* data)
+{
+  if (data == _data) return;
+
+  _data = data;
+  _function = 0;
+  _hiddenParts.clear();
+
+  ((BasePartItem*)base())->setData(data);
+}
+
+void PartAreaWidget::changeHidden(const TracePartList& list)
+{
+  _hiddenParts = list;
+  base()->refresh();
+}
+
+
+void PartAreaWidget::setCostType(TraceCostType* ct)
+{
+  _costType = ct;
+
+  // this resizes items
+  base()->redraw();
+}
+
+void PartAreaWidget::setVisualisation(VisualisationMode m)
+{
+  _visualisation = m;
+  refreshParts();
+}
+
+void PartAreaWidget::setZoomFunction(bool zoomFunction)
+{
+  _zoomFunction = zoomFunction;
+  refreshParts();
+}
+
+void PartAreaWidget::setCallLevels(int callLevels)
+{
+  _callLevels = callLevels;
+  refreshParts();
+}
+
+void PartAreaWidget::refreshParts()
+{
+  // rebuild only subparts to keep part selection state
+  TreeMapItem* i;
+  TreeMapItemList* l = base()->children();
+  if (l)
+    for (i=l->first();i;i=l->next())
+      i->refresh();
+
+  // but resize part areas
+  base()->redraw();
+}
+
+
+void PartAreaWidget::setFunction(TraceFunction* f)
+{
+  _function = f;
+
+  if (_visualisation == PartAreaWidget::Inclusive)
+    refreshParts();
+}
+
+void PartAreaWidget::setGroupType(TraceCost::CostType gt)
+{
+  _groupType = gt;
+
+  // rebuild hierarchy below parts.
+  // thus, selected parts stay selected
+  TreeMapItem* i;
+  TreeMapItemList* l = base()->children();
+  if (l)
+    for (i=l->first();i;i=l->next())
+      i->refresh();
+
+  base()->redraw();
+}
+
+bool PartAreaWidget::isHidden(TracePart* part) const
+{
+  return (_hiddenParts.containsRef(part)>0);
+}
+
+TQColor PartAreaWidget::groupColor(TraceFunction* f) const
+{
+  if (!f)
+    return colorGroup().button();
+
+  return Configuration::functionColor(_groupType, f);
+}
+
+TQString PartAreaWidget::tipString(TreeMapItem* i) const
+{
+  TQString tip, itemTip;
+  int count = 0;
+
+  //qDebug("PartAreaWidget::tipString for '%s'", i->name().ascii());
+
+  // first, SubPartItem's
+  while (i && count<Configuration::maxSymbolCount() && i->rtti() == 3) {
+    itemTip = i->text(0);
+    if ((int)itemTip.length()>Configuration::maxSymbolLength())
+      itemTip = itemTip.left(Configuration::maxSymbolLength()) + "...";
+
+    if (!i->text(1).isEmpty())
+      itemTip += " (" + i->text(1) + ")";
+
+    if (!tip.isEmpty())
+      itemTip += "\n";
+
+    tip = itemTip + tip;
+    i = i->parent();
+    count++;
+  }
+
+  // skip to part
+  while (i && i->rtti()==3) i = i->parent();
+
+  if (i && i->rtti()==2) {
+    itemTip = i18n("Profile Part %1").arg(i->text(0));
+    if (!i->text(1).isEmpty())
+        itemTip += " (" + i->text(1) + ")";
+
+    if (!tip.isEmpty())
+      itemTip += "\n";
+
+    tip = itemTip + tip;
+  }
+
+//  qDebug("PartAreaWidget:: tip %s, itemTip %s",
+//         tip.ascii(), itemTip.ascii());
+
+  return tip;
+}
+
+
+
+
+
+// BasePartItem
+
+BasePartItem::BasePartItem()
+  : TreeMapItem()
+{
+  _data = 0;
+  setSorting(-1);
+}
+
+void BasePartItem::setData(TraceData* data)
+{
+  if (data == _data) return;
+
+  _data = data;
+  refresh();
+}
+
+TreeMapItemList* BasePartItem::children()
+{
+  if (!_data) return _children;
+
+  if (!initialized()) {
+//    qDebug("Create Parts (%s)", name().ascii());
+
+    PartAreaWidget* w = (PartAreaWidget*) widget();
+    TracePart* part;
+    TracePartList l = _data->parts();
+    for (part=l.first();part;part=l.next())
+      if (!w->isHidden(part))
+        addItem(new PartItem(part));
+  }
+
+  return _children;
+}
+
+TQString BasePartItem::text(int textNo) const
+{
+  if (textNo == 0) {
+    if (!_data)
+      return i18n("(no trace)");
+
+    if (_data->parts().count() == 0)
+      return i18n("(no part)");
+  }
+  return TQString();
+}
+
+
+TQColor BasePartItem::backColor() const
+{
+  return widget()->colorGroup().base();
+}
+
+double BasePartItem::value() const
+{
+  if (!_data) return 0;
+
+  PartAreaWidget* w = (PartAreaWidget*) widget();
+  return (double)_data->subCost(w->costType());
+}
+
+
+
+
+
+// PartItem
+
+PartItem::PartItem(TracePart* p)
+{
+  _p = p;
+  _factor=1;
+}
+
+TQString PartItem::text(int textNo) const
+{
+  if (textNo == 0)
+    return _p->prettyName();
+
+  if (textNo != 1)
+    return TQString();
+
+  TraceCostType* ct;
+  PartAreaWidget* w = (PartAreaWidget*)widget();
+  SubCost v;
+
+  ct = w->costType();
+  v = _p->subCost(ct);
+
+  if (Configuration::showPercentage()) {
+    TraceCost* t = _p->data()->totals();
+    double p  = 100.0 * v / t->subCost(ct);
+    return TQString("%1 %")
+      .arg(p, 0, 'f', Configuration::percentPrecision());
+  }
+  return v.pretty();
+}
+
+
+TQPixmap PartItem::pixmap(int i) const
+{
+    if (i != 1) return TQPixmap();
+
+    // Cost pixmap
+
+    TraceCostType* ct = ((PartAreaWidget*)widget())->costType();
+    return costPixmap( ct, _p, (double) (_p->data()->totals()->subCost(ct)), false );
+}
+
+
+double PartItem::value() const
+{
+  PartAreaWidget* w = (PartAreaWidget*)widget();
+  TraceCostType* ct = w->costType();
+  if ((w->visualisation() == PartAreaWidget::Inclusive) &&
+      w->zoomFunction()) {
+
+    // use value of zoomed function
+    TraceFunction* f = w->function();
+    if (f) {
+      TracePartFunction* pf = (TracePartFunction*) f->findDepFromPart(_p);
+      if (pf)
+        return (double) pf->inclusive()->subCost(ct);
+      // when function is not available in part, hide part
+      return 0.0;
+    }
+  }
+  return (double) _p->subCost(ct);
+}
+
+double PartItem::sum() const
+{
+  PartAreaWidget* w = (PartAreaWidget*)widget();
+  if (w->visualisation() == PartAreaWidget::Inclusive) {
+    double s = value();
+    //qDebug("PartItem::sum [part %s]: %d", _p->name().ascii(), s);
+    return s;
+  }
+  return 0.0;
+}
+
+TreeMapItemList* PartItem::children()
+{
+  if (initialized()) return _children;
+
+  TraceCost* c;
+//    qDebug("Create Part subitems (%s)", name().ascii());
+
+  PartAreaWidget* w = (PartAreaWidget*)widget();
+  if (w->visualisation() == PartAreaWidget::Inclusive) {
+    TraceFunction* f = w->function();
+    if (f) {
+      c = f->findDepFromPart(_p);
+      if (c) addItem(new SubPartItem(c));
+    }
+
+    return _children;
+  }
+
+
+  switch( ((PartAreaWidget*)widget())->groupType() ) {
+
+  case TraceCost::Object:
+  {
+    TraceObjectMap::Iterator it;
+    for ( it = _p->data()->objectMap().begin();
+          it != _p->data()->objectMap().end(); ++it ) {
+      c = (*it).findDepFromPart(_p);
+      if (c)
+        addItem(new SubPartItem(c));
+    }
+  }
+  break;
+
+  case TraceCost::Class:
+  {
+    TraceClassMap::Iterator it;
+    for ( it = _p->data()->classMap().begin();
+          it != _p->data()->classMap().end(); ++it ) {
+      c = (*it).findDepFromPart(_p);
+      if (c)
+        addItem(new SubPartItem(c));
+    }
+  }
+  break;
+
+  case TraceCost::File:
+  {
+    TraceFileMap::Iterator it;
+    for ( it = _p->data()->fileMap().begin();
+          it != _p->data()->fileMap().end(); ++it ) {
+      c = (*it).findDepFromPart(_p);
+      if (c)
+        addItem(new SubPartItem(c));
+    }
+  }
+  break;
+
+  case TraceCost::Function:
+  {
+    TraceFunctionMap::Iterator it;
+    for ( it = _p->data()->functionMap().begin();
+          it != _p->data()->functionMap().end(); ++it ) {
+      c = (*it).findDepFromPart(_p);
+      if (c)
+        addItem(new SubPartItem(c));
+    }
+  }
+  break;
+
+  default:
+    break;
+  }
+
+  return _children;
+}
+
+
+TQColor PartItem::backColor() const
+{
+  PartAreaWidget* w = (PartAreaWidget*)widget();
+  return w->groupColor(0);
+}
+
+
+// SubPartItem
+
+SubPartItem::SubPartItem(TraceCost* c)
+{
+  _partCostItem = c;
+  _factor=1;
+}
+
+TQString SubPartItem::text(int textNo) const
+{
+  if (textNo == 0) {
+    if (!_partCostItem)
+      return i18n("(unknown)");
+
+    return _partCostItem->dependant()->prettyName();
+  }
+
+  if (textNo != 1)
+    return TQString();
+
+  TraceCostType* ct;
+  PartAreaWidget* w = (PartAreaWidget*)widget();
+  SubCost v;
+
+  ct = w->costType();
+  if (w->visualisation() == PartAreaWidget::Inclusive)
+    v = ((TracePartFunction*)_partCostItem)->inclusive()->subCost(ct);
+  else
+    v = _partCostItem->subCost(ct);
+
+  if (Configuration::showPercentage()) {
+    TraceCost* t = Configuration::showExpanded() ?
+	_partCostItem->part() : _partCostItem->part()->data()->totals();
+    double p  = 100.0 * v / t->subCost(ct);
+    return TQString("%1 %")
+      .arg(p, 0, 'f', Configuration::percentPrecision());
+  }
+  return v.pretty();
+}
+
+TQPixmap SubPartItem::pixmap(int i) const
+{
+    if (i != 1) return TQPixmap();
+
+    // Cost pixmap
+
+    PartAreaWidget* w = (PartAreaWidget*)widget();
+    TraceCostType* ct = w->costType();
+    TraceCost* t = Configuration::showExpanded() ?
+	_partCostItem->part() : _partCostItem->part()->data()->totals();
+    TraceCost* c;
+    if (w->visualisation() == PartAreaWidget::Inclusive)
+	c = ((TracePartFunction*)_partCostItem)->inclusive();
+    else
+	c = _partCostItem;
+
+    return costPixmap( ct, c, (double) (t->subCost(ct)), false );
+}
+
+double SubPartItem::value() const
+{
+  TraceCostType* ct;
+  PartAreaWidget* w = (PartAreaWidget*)widget();
+
+  ct = w->costType();
+  if (w->visualisation() == PartAreaWidget::Inclusive)
+    return (double)
+	((TracePartFunction*)_partCostItem)->inclusive()->subCost(ct);
+
+  return (double) _partCostItem->subCost(ct);
+}
+
+double SubPartItem::sum() const
+{
+  PartAreaWidget* w = (PartAreaWidget*)widget();
+  if (w->visualisation() == PartAreaWidget::Inclusive) {
+    double s = value();
+    //qDebug("SubPartItem::sum [Cost %s]: %d", _cost->name().ascii(), s);
+    return s;
+  }
+  return 0.0;
+}
+
+TreeMapItemList* SubPartItem::children()
+{
+  if (!initialized()) {
+//    qDebug("Create Part sub-subitems (%s)", name().ascii());
+
+    PartAreaWidget* w = (PartAreaWidget*)widget();
+
+    if (depth()-2 > w->callLevels())
+      return _children;
+
+    if (w->visualisation() == PartAreaWidget::Inclusive) {
+      TracePartCall* call;
+      TracePartCallList l;
+
+      setSum(value());
+
+      l = ((TracePartFunction*)_partCostItem)->partCallings();
+      for (call=l.first();call;call=l.next()) {
+        TraceFunction* called = call->call()->called();
+        TraceCost* partCalled = called->findDepFromPart(call->part());
+        if (partCalled)
+          addItem(new SubPartItem(partCalled));
+      }
+    }
+  }
+
+  return _children;
+}
+
+
+TQColor SubPartItem::backColor() const
+{
+  PartAreaWidget* w = (PartAreaWidget*)widget();
+  if (w->visualisation() == PartAreaWidget::Inclusive)
+    return w->groupColor((TraceFunction*)(_partCostItem->dependant()));
+
+  return Configuration::groupColor(_partCostItem->dependant());
+}
+
+
+#include "partgraph.moc"
diff --git a/kdecachegrind/kdecachegrind/partgraph.h b/kdecachegrind/kdecachegrind/partgraph.h
new file mode 100644
index 0000000..f28f12e
--- /dev/null
+++ b/kdecachegrind/kdecachegrind/partgraph.h
@@ -0,0 +1,132 @@
+/* This file is part of KCachegrind.
+   Copyright (C) 2003 Josef Weidendorfer <Josef.Weidendorfer@gmx.de>
+
+   KCachegrind 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, version 2.
+
+   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; see the file COPYING.  If not, write to
+   the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+   Boston, MA 02110-1301, USA.
+*/
+
+/*
+ * TracePart Graph
+ */
+
+#ifndef PARTGRAPH_H
+#define PARTGRAPH_H
+
+#include "treemap.h"
+#include "tracedata.h"
+
+class PartAreaWidget: public TreeMapWidget
+{
+  Q_OBJECT
+  TQ_OBJECT
+
+public:
+  // Visualisation inside of trace parts
+  enum VisualisationMode { NoVisualisation, Partitioning, Inclusive };
+
+  PartAreaWidget(TQWidget* parent=0, const char* name=0);
+
+  void setData(TraceData* d);
+  void setCostType(TraceCostType* ct);
+  void setGroupType(TraceCost::CostType gt);
+  void setVisualisation(VisualisationMode);
+  void setZoomFunction(bool zoomFunction);
+  void setCallLevels(int callLevels);
+  void setFunction(TraceFunction* f);
+
+  TraceCostType* costType() const { return _costType; }
+  TraceCost::CostType groupType() const { return _groupType; }
+  TraceFunction* function() const { return _function; }
+  VisualisationMode visualisation() const { return _visualisation; }
+  bool zoomFunction() const { return _zoomFunction; }
+  int callLevels() const { return _callLevels; }
+
+  TQColor groupColor(TraceFunction*) const;
+  TQString tipString(TreeMapItem*) const;
+
+  void changeHidden(const TracePartList& list);
+  bool isHidden(TracePart*) const;
+
+private:
+  void refreshParts();
+
+  TraceData* _data;
+  TraceCostType* _costType;
+  TraceCost::CostType _groupType;
+  TraceFunction* _function;
+  VisualisationMode _visualisation;
+  bool _zoomFunction;
+  int _callLevels;
+
+  TracePartList _hiddenParts;
+};
+
+class BasePartItem: public TreeMapItem
+{
+public:
+  BasePartItem();
+
+  void setData(TraceData* d);
+
+  int rtti() const { return 1; }
+  double value() const;
+  TQString text(int) const;
+  int borderWidth() const { return 0; }
+  TreeMapItemList* children();
+  TQColor backColor() const;
+
+private:
+  TraceData* _data;
+};
+
+class PartItem: public TreeMapItem
+{
+public:
+  PartItem(TracePart* p);
+  int rtti() const { return 2; }
+  TracePart* part() { return _p; }
+  double value() const;
+  double sum() const;
+  int borderWidth() const { return 0; }
+  TQString text(int) const;
+  TQPixmap pixmap(int) const;
+  TreeMapItemList* children();
+  TQColor backColor() const;
+
+private:
+  TracePart* _p;
+  unsigned int _factor;
+};
+
+class SubPartItem: public TreeMapItem
+{
+public:
+  SubPartItem(TraceCost*);
+  int rtti() const { return 3; }
+  TraceCost* partCostItem() { return _partCostItem; }
+  double value() const;
+  double sum() const;
+  SplitMode splitMode() const { return Vertical; }
+  TQString text(int) const;
+  TQPixmap pixmap(int) const;
+  TreeMapItemList* children();
+  TQColor backColor() const;
+
+private:
+  TraceCost* _partCostItem;
+  unsigned int _factor;
+};
+
+
+#endif
diff --git a/kdecachegrind/kdecachegrind/partlistitem.cpp b/kdecachegrind/kdecachegrind/partlistitem.cpp
new file mode 100644
index 0000000..40c2db3
--- /dev/null
+++ b/kdecachegrind/kdecachegrind/partlistitem.cpp
@@ -0,0 +1,189 @@
+/* This file is part of KCachegrind.
+   Copyright (C) 2003 Josef Weidendorfer <Josef.Weidendorfer@gmx.de>
+
+   KCachegrind 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, version 2.
+
+   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; see the file COPYING.  If not, write to
+   the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+   Boston, MA 02110-1301, USA.
+*/
+
+#include <math.h>
+
+#include <tqpainter.h>
+#include <tqregexp.h>
+
+#include <klocale.h>
+#include <kiconloader.h>
+#include <kapplication.h>
+
+#include "listutils.h"
+#include "partlistitem.h"
+#include "coverage.h"
+#include "configuration.h"
+
+
+// PartListItem
+
+PartListItem::PartListItem(TQListView* parent, TraceCostItem* costItem,
+                           TraceCostType* ct, TraceCost::CostType gt,
+			   TracePart* part)
+  :TQListViewItem(parent)
+{
+  _partCostItem = costItem->findDepFromPart(part);
+  _part = part;
+  _groupType = gt;
+  _costType = ct;
+
+#if 0
+  TQString partName = TQString::number(part->partNumber());
+  if (part->data()->maxThreadID() >1)
+      partName += i18n(" (Thread %1)").arg(part->threadID());
+  setText(0, partName);
+#else
+  setText(0, _part->prettyName());
+#endif
+
+  if (_part->trigger().isEmpty())
+    setText(4,i18n("(none)"));
+  else
+    setText(4, _part->trigger());
+
+  update();
+}
+
+void PartListItem::setCostType(TraceCostType* ct)
+{
+    if (_costType == ct) return;
+
+    _costType = ct;
+    update();
+}
+
+void PartListItem::setGroupType(TraceCost::CostType gt)
+{
+    if (_groupType == gt) return;
+
+    _groupType = gt;
+    update();
+}
+
+void PartListItem::update()
+{
+  TracePartFunction* pf;
+  pf = !_partCostItem ? 0 :
+       (_partCostItem->type()==TraceCost::PartFunction) ?
+       ((TracePartFunction*)_partCostItem) : 0;
+
+  double total = _part->subCost(_costType);
+
+  TraceCost* selfTotalCost = _part;
+  if (pf && Configuration::showExpanded()) {
+      switch(_groupType) {
+      case TraceCost::Object: selfTotalCost = pf->partObject(); break;
+      case TraceCost::Class:  selfTotalCost = pf->partClass(); break;
+      case TraceCost::File:   selfTotalCost = pf->partFile(); break;
+      default: break;
+      }
+  }
+  double selfTotal = selfTotalCost->subCost(_costType);
+
+  _pure = _partCostItem ? _partCostItem->subCost(_costType) : SubCost(0);
+  _sum = pf ? pf->inclusive()->subCost(_costType) : SubCost(0);
+
+  if (selfTotal == 0 || !_partCostItem) {
+    setText(2, TQString("-"));
+    setPixmap(2, TQPixmap());
+  }
+  else {
+    double pure  = 100.0 * _pure / selfTotal;
+    if (Configuration::showPercentage()) {
+      setText(2, TQString("%1")
+              .arg(pure, 0, 'f', Configuration::percentPrecision()));
+    }
+    else
+      setText(2, _partCostItem->prettySubCost(_costType));
+
+    setPixmap(2, costPixmap(_costType, _partCostItem, selfTotal, false));
+  }
+
+  if (total == 0 || !pf) {
+    setText(1, TQString("-"));
+    setPixmap(1, TQPixmap());
+  }
+  else {
+    double sum  = 100.0 * _sum / total;
+    if (Configuration::showPercentage()) {
+      setText(1, TQString("%1")
+              .arg(sum, 0, 'f', Configuration::percentPrecision()));
+    }
+    else
+      setText(1, _sum.pretty());
+
+    setPixmap(1, costPixmap(_costType, pf->inclusive(), total, false));
+  }
+
+  if (!pf) {
+    setText(3, TQString("-"));
+    _callers = 0;
+    return;
+  }
+
+  TracePartCall* pc;
+  TracePartCallList pl;
+  SubCost callers, callees;
+  TQString str;
+
+  callers = 0;
+  pl = pf->partCallers();
+  for (pc=pl.first();pc;pc=pl.next()) {
+    callers += pc->callCount();
+  }
+
+  if ((callers == 0) && (pf->calledContexts()>0))
+    str = i18n("(active)");
+  else
+    str = callers.pretty();
+
+  _callers = callers;
+  setText(3, str);
+}
+
+
+int PartListItem::compare(TQListViewItem * i, int col, bool ascending ) const
+{
+  PartListItem* fi = (PartListItem*) i;
+  if (col==0) {
+      int mTID = _part->data()->maxThreadID()+1;
+      int mNum = _part->data()->maxPartNumber()+1;
+
+      return
+	  (_part->processID()  - fi->_part->processID()) * mTID * mNum +
+	  (_part->partNumber() - fi->_part->partNumber()) * mTID +
+	  (_part->threadID()   - fi->_part->threadID());
+  }
+  if (col==1) {
+    if (_sum < fi->_sum) return -1;
+    if (_sum > fi->_sum) return 1;
+    return 0;
+  }
+  if (col==2) {
+    if (_pure < fi->_pure) return -1;
+    if (_pure > fi->_pure) return 1;
+    return 0;
+  }
+  if (col==3) {
+    if (_callers < fi->_callers) return -1;
+    if (_callers > fi->_callers) return 1;
+    return 0;
+  }
+  return TQListViewItem::compare(i, col, ascending);
+}
diff --git a/kdecachegrind/kdecachegrind/partlistitem.h b/kdecachegrind/kdecachegrind/partlistitem.h
new file mode 100644
index 0000000..0ab99a9
--- /dev/null
+++ b/kdecachegrind/kdecachegrind/partlistitem.h
@@ -0,0 +1,54 @@
+/* This file is part of KCachegrind.
+   Copyright (C) 2003 Josef Weidendorfer <Josef.Weidendorfer@gmx.de>
+
+   KCachegrind 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, version 2.
+
+   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; see the file COPYING.  If not, write to
+   the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+   Boston, MA 02110-1301, USA.
+*/
+
+#ifndef PARTLISTITEM_H
+#define PARTLISTITEM_H
+
+#include <tqlistview.h>
+#include "tracedata.h"
+
+/**
+ * For info tab, trace part list.
+ * Needs update on
+ * - cost type change
+ *
+ * Note: on a cost item / percentage change, the list is rebuild
+ */
+class PartListItem: public TQListViewItem
+{
+public:
+  PartListItem(TQListView* parent, TraceCostItem* costItem,
+               TraceCostType* ct, TraceCost::CostType gt, TracePart* part);
+
+  int compare(TQListViewItem * i, int col, bool ascending ) const;
+  TraceCost* partCostItem() { return _partCostItem; }
+  void setCostType(TraceCostType* ct);
+  void setGroupType(TraceCost::CostType);
+  TracePart* part() { return _part; }
+  void update();
+
+private:
+  SubCost _sum, _pure;
+  SubCost _callers;
+  TraceCostType* _costType;
+  TraceCost* _partCostItem;
+  TracePart* _part;
+  TraceCost::CostType _groupType;
+};
+
+#endif
diff --git a/kdecachegrind/kdecachegrind/partselection.cpp b/kdecachegrind/kdecachegrind/partselection.cpp
new file mode 100644
index 0000000..703dd75
--- /dev/null
+++ b/kdecachegrind/kdecachegrind/partselection.cpp
@@ -0,0 +1,567 @@
+/* This file is part of KCachegrind.
+   Copyright (C) 2003 Josef Weidendorfer <Josef.Weidendorfer@gmx.de>
+
+   KCachegrind 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, version 2.
+
+   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; see the file COPYING.  If not, write to
+   the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+   Boston, MA 02110-1301, USA.
+*/
+
+/*
+ * For part file selection, to be put into a TQDockWindow
+ */
+
+#include <tqtimer.h>
+#include <tqlistview.h>
+#include <tqlabel.h>
+#include <tqpushbutton.h>
+#include <tqcombobox.h>
+#include <tqlineedit.h>
+#include <tqpopupmenu.h>
+#include <tqlayout.h>
+
+#include <klocale.h>
+#include <kconfig.h>
+#include <kdebug.h>
+
+#include "partselection.h"
+#include "partgraph.h"
+
+PartSelection::PartSelection( TQWidget* parent, const char* name)
+  : PartSelectionBase(parent, name)
+{
+  _data = 0;
+  _costType = 0;
+  _costType2 = 0;
+  _groupType = TraceItem::NoCostType;
+  _group = 0;
+  _function = 0;
+  _inSelectionUpdate = false;
+
+  _diagramMode = false;
+  _drawFrames = true;
+
+  partAreaWidget->setAllowRotation(false);
+  partAreaWidget->setMaxSelectDepth(2);
+  partAreaWidget->setSelectionMode(TreeMapWidget::Extended);
+  partAreaWidget->setSplitMode(TreeMapItem::HAlternate);
+  partAreaWidget->setVisibleWidth(2, true);
+  partAreaWidget->setFieldType(0, i18n( "Name" ));
+  partAreaWidget->setFieldType(1, i18n( "Cost" ));
+
+  connect(partAreaWidget, TQT_SIGNAL(selectionChanged()),
+          this, TQT_SLOT(selectionChanged()));
+  connect(partAreaWidget, TQT_SIGNAL(currentChanged(TreeMapItem*, bool)),
+          this, TQT_SLOT(currentChangedSlot(TreeMapItem*, bool)));
+  connect(partAreaWidget, TQT_SIGNAL(doubleClicked(TreeMapItem*)),
+          this, TQT_SLOT(doubleClicked(TreeMapItem*)));
+  connect(partAreaWidget,
+          TQT_SIGNAL(contextMenuRequested(TreeMapItem*,const TQPoint &)),
+          this,
+          TQT_SLOT(contextMenuRequested(TreeMapItem*,const TQPoint &)));
+
+  _showInfo = true;
+  showInfo(false);
+}
+
+PartSelection::~PartSelection()
+{
+}
+
+void PartSelection::setData(TraceData* data)
+{
+  if (_data == data) return;
+
+  _data = data;
+  partAreaWidget->setData(data);
+  fillInfo();
+}
+
+
+void PartSelection::refresh()
+{
+  partAreaWidget->redraw();
+  fillInfo();
+}
+
+void PartSelection::setCostType(TraceCostType* ct)
+{
+  if (ct == _costType) return;
+  _costType = ct;
+
+  partAreaWidget->setCostType(ct);
+}
+
+void PartSelection::setCostType2(TraceCostType* ct)
+{  
+  if (ct == _costType2) return;
+  _costType2 = ct;
+  if (!_diagramMode) return;
+
+  //TODO: get max cost(type1)/cost(type2) of shown parts
+  //partAreaWidget->setCostType(ct);
+}
+
+void PartSelection::setGroupType(TraceItem::CostType gt)
+{
+  if (gt == _groupType) return;
+  _groupType = gt;
+
+  partAreaWidget->setGroupType(gt);
+}
+
+void PartSelection::setGroup(TraceCostItem*)
+{
+}
+
+void PartSelection::setFunction(TraceFunction* f)
+{
+  if (_function == f) return;
+  _function = f;
+
+  //kdDebug() << "PartSelection::setFunction " << f->name() << endl;
+
+  // FIXME: The TreeMap shouldn't produce spurious selectionChanged events
+  _inSelectionUpdate = true;
+  partAreaWidget->setFunction(_function);
+  _inSelectionUpdate = false;
+}
+
+void PartSelection::setPart(TracePart*)
+{}
+
+void PartSelection::currentChangedSlot(TreeMapItem* i, bool kbd)
+{
+  if (!i) return;
+  if (!kbd) return;
+  if (i->text(0).isEmpty()) return;
+
+  TQString str = i->text(0);
+  if (!i->text(1).isEmpty())
+    str += " (" + i->text(1) + ")";
+  TQString msg = i18n("Profile Part Overview: Current is '%1'").arg(str);
+  emit showMessage(msg, 5000);
+
+  if (_showInfo) fillInfo();
+}
+
+
+void PartSelection::doubleClicked(TreeMapItem* i)
+{
+  if (!i || i->rtti() != 3) return;
+
+  TraceCost* c = ((SubPartItem*) i)->partCostItem();
+  TraceCostItem* ci = 0;
+
+  switch(c->type()) {
+  case TraceItem::PartFunction:
+  {
+    TraceFunction* f = ((TracePartFunction*)c)->function();
+    if (f)
+      emit functionChanged(f);
+  }
+  return;
+
+  case TraceItem::PartObject:
+    ci = ((TracePartObject*)c)->object();
+    break;
+  case TraceItem::PartClass:
+    ci = ((TracePartClass*)c)->cls();
+    break;
+  case TraceItem::PartFile:
+    ci = ((TracePartFile*)c)->file();
+    break;
+  default:
+    break;
+  }
+
+  if (ci)
+    emit groupChanged(ci);
+}
+
+
+void PartSelection::selectionChanged()
+{
+  if (_inSelectionUpdate) return;
+  
+  kdDebug() << "PartSelection::selectionChanged" << endl;
+
+  bool something_changed = false;
+  bool nothingSelected = true;
+
+  TracePartList pList;
+  TreeMapItem* i;
+  TracePart* part;
+
+  // if nothing is selected, activate all parts
+  TreeMapItemList* list = partAreaWidget->base()->children();
+  if (!list) return;
+
+  for (i=list->first();i;i=list->next())
+    if (partAreaWidget->isSelected(i)) {
+      nothingSelected = false;
+      break;
+    }
+
+  for (i=list->first();i;i=list->next()) {
+    part = ((PartItem*)i)->part();
+    bool active = nothingSelected || partAreaWidget->isSelected(i);
+    if (active) {
+      pList.append(part);
+      something_changed = true;
+    }
+  }
+
+  if (something_changed) {
+    //qDebug("PartSelection: Something changed.");
+    emit activePartsChanged(pList);
+  }
+}
+
+/* this makes the graph selection the same to the parts in the list */
+void PartSelection::activePartsChangedSlot(const TracePartList& list)
+{
+  _inSelectionUpdate = true;
+
+  kdDebug() << "Entering PartSelection::activePartsChangedSlot" << endl;
+
+  TreeMapItem* i;
+  TreeMapItemList l = *partAreaWidget->base()->children();
+  // first deselect inactive, then select active (makes current active)
+  for (i=l.first();i;i=l.next()) {
+    TracePart* part = ((PartItem*)i)->part();
+    bool active = (list.containsRef(part)>0);
+    if (!active && partAreaWidget->isSelected(i)) {
+#if 0
+      qDebug("PartSelection::partsChangedSlot: Part %s changed to unselected.",
+             ((PartItem*)i)->part()->shortName().ascii());
+#endif
+
+      partAreaWidget->setSelected(i, false);
+    }
+  }
+  for (i=l.first();i;i=l.next()) {
+    TracePart* part = ((PartItem*)i)->part();
+    bool active = (list.containsRef(part)>0);
+    if (active && !partAreaWidget->isSelected(i)) {
+#if 0
+      qDebug("PartSelection::partsChangedSlot: Part %s changed to selected.",
+             ((PartItem*)i)->part()->shortName().ascii());
+#endif
+      partAreaWidget->setSelected(i, true);
+    }
+  }
+
+  _inSelectionUpdate = false;
+
+  kdDebug() << "Leaving PartSelection::activePartsChangedSlot" << endl;
+
+  fillInfo();
+}
+
+void PartSelection::contextMenuRequested(TreeMapItem* i,
+                                         const TQPoint & p)
+{
+  if (!i) return;
+
+  TQPopupMenu popup;
+  TQPopupMenu ppopup;
+  TQPopupMenu vpopup;
+
+  TQString str;
+  TreeMapItem* s = 0;
+
+  if (_data && (_data->parts().count()>1)) {
+    s = partAreaWidget->possibleSelection(i);
+    if (!s->text(0).isEmpty()) {
+      str = (partAreaWidget->isSelected(s)) ?
+            i18n("Deselect") : i18n("Select");
+      str += " '" + s->text(0) + "'";
+      popup.insertItem(str, 1);
+    }
+
+    popup.insertItem(i18n("Select All Parts"), 2);
+
+    popup.insertItem(i18n("Visible Parts"), &ppopup, 10);
+
+    ppopup.insertItem(i18n("Hide Selected Parts"), 3);
+    ppopup.insertItem(i18n("Unhide Hidden Parts"), 4);
+
+    popup.insertSeparator();
+  }
+
+  popup.insertItem(i18n("Go Back"), 99);
+  if (i->rtti() == 3) {
+    TreeMapItem* ni = i;
+    int id = 100;
+    while (ni && ni->rtti() == 3) {
+      TraceCost* c = ((SubPartItem*)ni)->partCostItem();
+      if (c->type() == TraceItem::PartFunction)
+        if ( ((TracePartFunction*)c)->function() == _function) break;
+
+      str = i18n("Select") + " '" + ni->text(0) + "'";
+      popup.insertItem(str, id);
+      ni = ni->parent();
+      id++;
+    }
+  }
+  popup.insertSeparator();
+
+  vpopup.setCheckable(true);
+  popup.insertItem(i18n("Visualization"), &vpopup, 10);
+
+  vpopup.insertItem(i18n("Partitioning Mode"), 30);
+  vpopup.insertItem(i18n("Diagram Mode"), 34);
+  vpopup.insertItem(i18n("Zoom Function"), 31);
+  vpopup.insertItem(i18n("Show Direct Calls"), 32);
+  vpopup.insertItem(i18n("Increment Shown Call Levels"), 33);
+  if (partAreaWidget->visualisation() == PartAreaWidget::Partitioning) {
+    vpopup.setItemChecked(30, true);
+    vpopup.setItemEnabled(31, false);
+    vpopup.setItemEnabled(32, false);
+    vpopup.setItemEnabled(33, false);
+  }
+  else {
+    vpopup.setItemChecked(31, partAreaWidget->zoomFunction());
+  }
+  vpopup.setItemChecked(34, _diagramMode);
+
+  vpopup.insertSeparator();
+
+  vpopup.insertItem(i18n("Draw Names"), 20);
+  vpopup.insertItem(i18n("Draw Costs"), 21);
+  vpopup.insertItem(i18n("Ignore Proportions"), 22);
+  vpopup.insertItem(i18n("Draw Frames"), 24);
+  vpopup.insertItem(i18n("Allow Rotation"), 23);
+  if (!partAreaWidget->fieldVisible(0) &&
+      !partAreaWidget->fieldVisible(1)) {
+    vpopup.setItemEnabled(22, false);
+    vpopup.setItemEnabled(23, false);
+  }
+  else {
+    vpopup.setItemChecked(20,partAreaWidget->fieldVisible(0));
+    vpopup.setItemChecked(21,partAreaWidget->fieldVisible(1));
+    vpopup.setItemChecked(22,partAreaWidget->fieldForced(0));
+    vpopup.setItemChecked(23,partAreaWidget->allowRotation());
+    vpopup.setItemChecked(24,_drawFrames);
+  }
+
+  if (_showInfo)
+    popup.insertItem(i18n("Hide Info"), 40);
+  else
+    popup.insertItem(i18n("Show Info"), 41);
+
+  int r = popup.exec(partAreaWidget->mapToGlobal(p));
+
+  if (r>=100) {
+    TreeMapItem* ci = i;
+    while (ci && r>100) {
+      ci = ci->parent();
+      r--;
+    }
+    doubleClicked(ci);
+    return;
+  }
+
+  switch(r) {
+  case 1:
+    // select/deselect part under mouse
+    partAreaWidget->setSelected(s, !partAreaWidget->isSelected(s));
+    break;
+
+  case 2:
+    // select all parts
+  {
+    TreeMapItemList list = *partAreaWidget->base()->children();
+    partAreaWidget->setRangeSelection(list.first(), list.last(), true);
+  }
+  break;
+
+  case 3:
+    emit partsHideSelected();
+    break;
+
+  case 4:
+    emit partsUnhideAll();
+    break;
+
+  case 99:
+    // last selected function
+    emit goBack();
+    break;
+
+  case 20:
+    partAreaWidget->setFieldVisible(0, !vpopup.isItemChecked(20));
+    break;
+
+  case 21:
+    partAreaWidget->setFieldVisible(1, !vpopup.isItemChecked(21));
+    break;
+
+  case 22:
+      partAreaWidget->setFieldForced(0, !vpopup.isItemChecked(22));
+      partAreaWidget->setFieldForced(1, !vpopup.isItemChecked(22));
+      break;
+
+  case 23: partAreaWidget->setAllowRotation(!vpopup.isItemChecked(23));  break;
+
+  case 24: 
+    _drawFrames = !_drawFrames;
+    partAreaWidget->drawFrame(2,_drawFrames);
+    partAreaWidget->drawFrame(3,_drawFrames);
+    break;
+
+  case 30:
+    partAreaWidget->setVisualisation(!vpopup.isItemChecked(30) ?
+                                     PartAreaWidget::Partitioning :
+                                     PartAreaWidget::Inclusive);
+    break;
+
+  case 31:
+    // zoom/unzoom function
+    partAreaWidget->setZoomFunction(!vpopup.isItemChecked(31));
+    break;
+
+  case 32:
+  case 33:
+    // change call Levels
+  {
+    int l = (r==32) ? 1 : partAreaWidget->callLevels()+1;
+    partAreaWidget->setCallLevels(l);
+  }
+  break;
+
+  case 34: 
+    _diagramMode = !_diagramMode;
+    partAreaWidget->setTransparent(2,_diagramMode);
+    break;
+
+
+  case 40:
+  case 41:
+    showInfo(r==41);
+    break;
+
+  default:
+    break;
+  }
+}
+
+void PartSelection::hiddenPartsChangedSlot(const TracePartList& list)
+{
+  partAreaWidget->changeHidden(list);
+}
+
+void PartSelection::readVisualisationConfig(KConfigGroup* config)
+{
+  bool enable;
+
+  TQString mode = config->readEntry("PartitionMode", "Inclusive");
+  if (mode == "Inclusive")
+    partAreaWidget->setVisualisation(PartAreaWidget::Inclusive);
+  else
+    partAreaWidget->setVisualisation(PartAreaWidget::Partitioning);
+
+  _diagramMode = config->readBoolEntry("DiagramMode", false);
+  partAreaWidget->setTransparent(2,_diagramMode);
+
+  _drawFrames = config->readBoolEntry("DrawFrames", true);
+  partAreaWidget->drawFrame(2,_drawFrames);
+  partAreaWidget->drawFrame(3,_drawFrames);
+
+  enable = config->readBoolEntry("GraphZoom", false);
+  partAreaWidget->setZoomFunction(enable);
+
+  int levels = config->readNumEntry("GraphLevels", 1);
+  partAreaWidget->setCallLevels(levels);
+
+  enable = config->readBoolEntry("GraphDrawName", true);
+  partAreaWidget->setFieldVisible(0, enable);
+
+  enable = config->readBoolEntry("GraphDrawCost", true);
+  partAreaWidget->setFieldVisible(1, enable);
+
+  enable = config->readBoolEntry("GraphForceStrings", false);
+  partAreaWidget->setFieldForced(0, enable);
+  partAreaWidget->setFieldForced(1, enable);
+
+  enable = config->readBoolEntry("GraphAllowRotation", true);
+  partAreaWidget->setAllowRotation(enable);
+
+  showInfo(config->readBoolEntry("ShowInfo", false));
+}
+
+void PartSelection::saveVisualisationConfig(KConfigGroup* config)
+{
+  TQString mode;
+  if (partAreaWidget->visualisation() == PartAreaWidget::Inclusive)
+    mode = "Inclusive";
+  else
+    mode = "Partitioning";
+  config->writeEntry("PartitionMode", mode);
+
+  config->writeEntry("DiagramMode", _diagramMode);
+  config->writeEntry("DrawFrames", _drawFrames);
+
+  config->writeEntry("GraphZoom", partAreaWidget->zoomFunction());
+  config->writeEntry("GraphLevels", partAreaWidget->callLevels());
+  config->writeEntry("GraphDrawName", partAreaWidget->fieldVisible(0));
+  config->writeEntry("GraphDrawCosts", partAreaWidget->fieldVisible(1));
+  config->writeEntry("GraphForceStrings", partAreaWidget->fieldForced(0));
+  config->writeEntry("GraphAllowRotation", partAreaWidget->allowRotation());
+
+  config->writeEntry("ShowInfo", _showInfo);
+}
+
+void PartSelection::showInfo(bool enable)
+{
+  if (_showInfo == enable) return;
+
+  _showInfo = enable;
+  if (enable) {
+    rangeLabel->show();
+    fillInfo();
+  }
+  else
+    rangeLabel->hide();
+}
+
+void PartSelection::fillInfo()
+{
+  if (!_data) {
+    rangeLabel->setText(i18n("(no trace loaded)"));
+    return;
+  }
+
+  TQString info = _data->activePartRange();
+
+  TreeMapItem* i = partAreaWidget->current();
+  while (i && i->rtti()!=2) i = i->parent();
+  if (i) {
+    TracePart* part = ((PartItem*)i)->part();
+
+    //if (!part->trigger().isEmpty()) info += ", " + part->trigger();
+    if (!part->timeframe().isEmpty())
+      info += ", Time " + part->timeframe() + " BBs";
+  }
+  else {
+    TracePart* part = _data->parts().first();
+
+    if (part && !part->version().isEmpty())
+      info += ", Cachegrind " + part->version();
+  }
+
+
+  rangeLabel->setText(info);
+}
+
+#include "partselection.moc"
diff --git a/kdecachegrind/kdecachegrind/partselection.h b/kdecachegrind/kdecachegrind/partselection.h
new file mode 100644
index 0000000..b8a195f
--- /dev/null
+++ b/kdecachegrind/kdecachegrind/partselection.h
@@ -0,0 +1,96 @@
+/* This file is part of KCachegrind.
+   Copyright (C) 2003 Josef Weidendorfer <Josef.Weidendorfer@gmx.de>
+
+   KCachegrind 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, version 2.
+
+   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; see the file COPYING.  If not, write to
+   the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+   Boston, MA 02110-1301, USA.
+*/
+
+/*
+ * PartSelection for KCachegrind
+ * For part file selection, to be put into a TQDockWindow
+ */
+
+#ifndef PARTSELECTION_H
+#define PARTSELECTION_H
+
+#include <tqobject.h>
+
+#include "partselectionbase.h"
+#include "partgraph.h"
+#include "tracedata.h"
+
+class KConfigGroup;
+class TraceFunction;
+class TraceData;
+class TreeMapItem;
+
+class PartSelection: public PartSelectionBase
+{
+  Q_OBJECT
+  TQ_OBJECT
+
+public:
+  PartSelection( TQWidget* parent = 0, const char* name = 0);
+  ~PartSelection();
+
+  TraceData* data() { return _data; }
+  void setData(TraceData*);
+
+  PartAreaWidget* graph() { return partAreaWidget; }
+
+  void readVisualisationConfig(KConfigGroup*);
+  void saveVisualisationConfig(KConfigGroup*);
+
+signals:
+  void activePartsChanged(const TracePartList& list);
+  void partsHideSelected();
+  void partsUnhideAll();
+  void groupChanged(TraceCostItem*);
+  void functionChanged(TraceItem*);
+  void showMessage(const TQString&, int);
+  void goBack();
+
+public slots:
+  void selectionChanged();
+  void doubleClicked(TreeMapItem*);
+  void contextMenuRequested(TreeMapItem*, const TQPoint &);
+  void currentChangedSlot(TreeMapItem*, bool);
+
+  void setPart(TracePart*);
+  void setCostType(TraceCostType*);
+  void setCostType2(TraceCostType*);
+  void setGroupType(TraceItem::CostType);
+  void setGroup(TraceCostItem*);
+  void setFunction(TraceFunction*);
+  void activePartsChangedSlot(const TracePartList& list);
+  void hiddenPartsChangedSlot(const TracePartList& list);
+  void refresh();
+  void showInfo(bool);
+
+private:
+  void fillInfo();
+
+  TraceData* _data;
+  TraceCostType *_costType, *_costType2;
+  TraceItem::CostType _groupType;
+  TraceCostItem* _group;
+  TraceFunction* _function;
+  bool _showInfo;
+  bool _diagramMode;
+  bool _drawFrames;
+
+  bool _inSelectionUpdate;
+};
+
+#endif
diff --git a/kdecachegrind/kdecachegrind/partselectionbase.ui b/kdecachegrind/kdecachegrind/partselectionbase.ui
new file mode 100644
index 0000000..53320d5
--- /dev/null
+++ b/kdecachegrind/kdecachegrind/partselectionbase.ui
@@ -0,0 +1,89 @@
+<!DOCTYPE UI><UI version="3.0" stdsetdef="1">
+<class>PartSelectionBase</class>
+<widget class="TQWidget">
+    <property name="name">
+        <cstring>PartSelectionBase</cstring>
+    </property>
+    <property name="geometry">
+        <rect>
+            <x>0</x>
+            <y>0</y>
+            <width>460</width>
+            <height>402</height>
+        </rect>
+    </property>
+    <property name="caption">
+        <string>Parts Overview</string>
+    </property>
+    <vbox>
+        <property name="name">
+            <cstring>unnamed</cstring>
+        </property>
+        <property name="margin">
+            <number>6</number>
+        </property>
+        <property name="spacing">
+            <number>6</number>
+        </property>
+        <widget class="PartAreaWidget">
+            <property name="name">
+                <cstring>partAreaWidget</cstring>
+            </property>
+            <property name="sizePolicy">
+                <sizepolicy>
+                    <hsizetype>5</hsizetype>
+                    <vsizetype>7</vsizetype>
+                    <horstretch>0</horstretch>
+                    <verstretch>0</verstretch>
+                </sizepolicy>
+            </property>
+            <property name="minimumSize">
+                <size>
+                    <width>0</width>
+                    <height>50</height>
+                </size>
+            </property>
+        </widget>
+        <widget class="TQLabel">
+            <property name="name">
+                <cstring>rangeLabel</cstring>
+            </property>
+            <property name="sizePolicy">
+                <sizepolicy>
+                    <hsizetype>7</hsizetype>
+                    <vsizetype>5</vsizetype>
+                    <horstretch>0</horstretch>
+                    <verstretch>0</verstretch>
+                </sizepolicy>
+            </property>
+            <property name="text">
+                <string>(no trace parts)</string>
+            </property>
+        </widget>
+    </vbox>
+</widget>
+<customwidgets>
+    <customwidget>
+        <class>PartAreaWidget</class>
+        <header location="local">partgraph.h</header>
+        <sizehint>
+            <width>-1</width>
+            <height>-1</height>
+        </sizehint>
+        <container>0</container>
+        <sizepolicy>
+            <hordata>5</hordata>
+            <verdata>7</verdata>
+            <horstretch>0</horstretch>
+            <verstretch>0</verstretch>
+        </sizepolicy>
+        <pixmap>image0</pixmap>
+    </customwidget>
+</customwidgets>
+<images>
+    <image name="image0">
+        <data format="XPM.GZ" length="5230">789c9597db4e1d4b0e86eff31428be8b46b5fb54dd551acd051020211c4320c0682eecaa5e9ccf90005bf3ee53cbbfe9d9c9c548a38ea27c2977b5cbfe6dd7fae3c3c2e1cee6c2873fde3d3cf2e3595a48a77cbff0213f5d5dbdfcf35ffff8f3ddfba65998fff161a179ffb777ef771f17d2c2d6cdf53807c705a889cdac6ee72c47736eebd637b5f2b672d70ecd30e744ca7d9b9a4ad7579587363433e527e5d072abefbb03636978ceb4a31c5bc13a91716ad41f89e0aec2fe74abcc6d6ad5f9e4945357375ef75f997357751dd61d19c71afb61bdef421b951f274ebaffb6716cb3f2b2f230f18d3183dd95b1b441d7d59f2e94757ccf1b27eceff69563618d0f5dcfd9d7beeb7a5dd7f3fac6fb4ee32b87c619f1168d976f7d6ff6df26d6ef4b301e1bac7f54f63e747a5e87f5c173276aff605c22a8fefc540e5e3af5972f956359577bf2c6d978cb78d6697edc9eb2f8b143fed7945359d778b0e6c3e7be81bf7465dce23cf4ac3c16567f19fecefaae53bd081b7baccbb131b7d05f679ca03f27c6b9d1f388c6bbaffab7f80dca4d1fed7bfafdbeedb9533d490f1e2ae8d5693ccacb83d77cd027e3d4416faa97beefa3d7f8f086f168f9d9020f43a3f5c5aa877e28eb88f74fe319becfaa873e0c15de775f95639f3dec37c143d361bf2be3cef4b76bdcb7d84ff5d2cbd0227facf1ecd360fa67d54b9f078ffcd10f636e11ff53e3847853ad3c1b668837e9fe43358c2df45a81430b3db2e6676842d368fd48abdc068b87e0fd2e788bf792b21f861e7afd0e0e5ce37dcdd7d0872218e5d789f57b3218a71ae7bb501eca3af67b510e21c05fd27a1b6218ac3ef17d0ed68fe8cb1be3fc6e5159863ca0bfed824340fe687d62c4838c23f677f0370de380fcdd2be7e03dfab1d6cf300bcd80fa80bfb358dbf9547fa18abe413d68fe421d63ade7737aded094cf63fdcc38f4d0bfee17dac2d08380a3a0dff24cb90bdc23ffaa87e0636c912fed87612e38d4df1e982bc4dbdd29872001f14aca319413eb793e83cbfbe8af27606e4c0f5f8d3bcb7763ec6b8da73b57e69083d61f9d82b9b5fada31f635fcaf8d7b7b5ffb41f16e34ff34fe214dfc0c8e1ef1a22330bfcdc345e31e4c33e3c1e6e181b1609e3ac43f8759803e8cd9f2e7e0ff18ab80ef5d8239e2fc0ef129f90ff0bf0773347fee8d13ce279bc6b34af5c61abf58157bf4b765b05435f4abfec726968c2b67e536fa80fe388279067f680d2c750dff75fe9766da07e44bc02521ba4e1d584c1fb261dcc23fd97f63f8c3af136bfc687362c4e76962ed8fac7a2ecdb7853f7c63ec6bf467bd3fc421c680780c60b6f9275fc045aea84fadaf18a2e0fc04ff0237bd9e8fefc0d236e8ef3f8d83c57fdd38daf94edeb886be74fec618b3ed7f3731e66b0fe67a403e76c0454ef8de9231dbfe9f8dc5fc47be38a6887ad2f950964d2fdc1a27d3c7b6710693f6ef9864b4fdb4ffc6cc5540fea0972c339c87afc1c9f4443a5fe2c84d40bd2f82cb3ae6c7b1716dbc37b1e68bf5be118b7e3dead78125d87d0bfa99bd7d8fb78c1bdb4fcfcfd51bcb9d716bebda3fb8966cf7cf57709103f2e327c6fe5a2fdc4ab4fb01deef5283fa65d50ffb54c13fd67ec37d61e845fb070f8571df7c341eec7e7a691c6ae453fb771937d1fa999ebfa43358bf573d3327c6fdd0a9de59b87414e59f60911ef3ff07380d16bf0b63b6fbb8ce0f4e523a80ee8ff8a5f21fe83f384f2e8cf9d419db7d4bb4bff32cb1dd871ae38c79417962dd9f8f2786bfaa3fa992ddbf68d5d8d6797d62dc27b4bf4a9bdeee5be7c619efbb169c2b9bb7aa67e972857a67d59bf8943cf4a6f5237dae3b9c3f4f8cef5713637e6a3c6548e546a7eb87e0b28e7cf7c68ddd2fb15f28acf166bd2f484c19f921f8cbc57de84ff52c397b8f7e178d7bbb7f7e9f18f743d593ccd210d12f9e8c05fd8417c1e5e704e2afefa7aa5cf850ff4fc6a1473debfc4d7561c4ebd3c48897f69fd4e4d8eb7e4efb736a0b23fe9adfd465bb3f388d6ff22933fa1df6f7597ad483c62371f6e6ff8671b6f89e198fb8cfb0ea3f49619c6f6562cc27d5474a7906e6b589d1df549f29e78479450fe0b1c2fc67d5731a0ba33ffc97a167fd7d92ebb1b1f9a87acdcdd8a23ff2e3c4a81fed0fb91bbb88f8e9f772f9b9c6b8bfac187bd41febbcc8c35831f4bb6edc227eeec8b847bc58ef0f398d91a1179d6f391746bdebfd60ac4716b0180bd8a97e473f8ea2dfdb7d9c3f8e1cff8f8760057b27e57f92cb6e743377e24efff29cb97377e12edd55b190c99eddb5bb71b7eeceddbb07f7e89edc0ff7d33dbb17f7ea16dd925b761fdd8a63d8174f52b15e756bee93fbecd6dd17b7e136dd96db763b6ed77d2dd67bee9bdb77078ed49e8b27b7c5fabb3b7447eed855ae768d6bcbd339ef7a37b8e022392a2734fbd1dd119350a24c23cde8844ee98ccee9c2f9c2977445d77443b793fd8ceee89e1ee8919ee807fdb4e7995ee8b5d82fd252b15ffe8bfd097da4155aa535fa34597fa6f5f2f717da28f69bb445dbb433d99fd22e7da53dfa3659efd3017da7c3f2af233aa68aeadfec1b6aa9236fd63d0d14ca15c0719913737b965fedcbf0c83cc29a677cc2a77cc6e77cc1977cc5d7c5fee637fbdbb2db9d5adff343b17ee427fec1737ee69762fffa9bfd222ff17259fdc82bbcca6bfc893ff33a7fe10ddee42ddee69ddfec77f92beff137dee703fece877cc4c7aee58a6b6ee8b8fc10ed7eb13f635f9a4bc5e54719477152ba671977a505c84845c57222a7bfd89fcb999ccb855cca955cbfc5546ee456ee68b14cf67b799047799aec2fdc92fc28999cef567224cff222afb2c85b32e36d599265f9282bb23ad95fba6559934f2593f3e798b74acc8fd5f6b3accb17d9904dd9926db3a7520d1fdd37d9915df95a72599e1291566df7e49beccb817c974339829eb55e56dc7e51ec0d2dcbb1545297a791563af1c5eff2d3beb4faf8562f568f0744745b9e9d5f1f7992d5e412a186ffef7afff7dfdffd077c99ae99</data>
+    </image>
+</images>
+<layoutdefaults spacing="6" margin="11"/>
+</UI>
diff --git a/kdecachegrind/kdecachegrind/partview.cpp b/kdecachegrind/kdecachegrind/partview.cpp
new file mode 100644
index 0000000..3f344bb
--- /dev/null
+++ b/kdecachegrind/kdecachegrind/partview.cpp
@@ -0,0 +1,235 @@
+/* This file is part of KCachegrind.
+   Copyright (C) 2003 Josef Weidendorfer <Josef.Weidendorfer@gmx.de>
+
+   KCachegrind 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, version 2.
+
+   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; see the file COPYING.  If not, write to
+   the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+   Boston, MA 02110-1301, USA.
+*/
+
+/*
+ * Part View
+ */
+
+#include <tqwhatsthis.h>
+#include <tqpopupmenu.h>
+#include <tqheader.h>
+#include <klocale.h>
+
+#include "configuration.h"
+#include "partlistitem.h"
+#include "toplevel.h"
+#include "partview.h"
+
+
+
+//
+// PartView
+//
+
+
+PartView::PartView(TraceItemView* parentView,
+		   TQWidget* parent, const char* name)
+  : TQListView(parent, name), TraceItemView(parentView)
+{
+    _inSelectionUpdate = false;
+
+    addColumn( i18n( "Profile Part" ) );
+    addColumn( i18n( "Incl." ) );
+    addColumn( i18n( "Self" ) );
+    addColumn( i18n( "Called" ) );
+    //addColumn( i18n( "Fixed" ) );
+    addColumn( i18n( "Comment" ) );
+
+    setAllColumnsShowFocus(true);
+    setColumnAlignment(1, TQt::AlignRight);
+    setColumnAlignment(2, TQt::AlignRight);
+    setColumnAlignment(3, TQt::AlignRight);
+    setMinimumHeight(50);
+    setSelectionMode(Extended);
+
+    connect( this,
+	     TQT_SIGNAL( selectionChanged() ),
+	     TQT_SLOT( selectionChangedSlot() ) );
+
+    connect( this,
+	     TQT_SIGNAL(contextMenuRequested(TQListViewItem*, const TQPoint &, int)),
+	     TQT_SLOT(context(TQListViewItem*, const TQPoint &, int)));
+
+    TQWhatsThis::add( this, whatsThis() );
+}
+
+TQString PartView::whatsThis() const
+{
+    return i18n( "<b>Trace Part List</b>"
+		 "<p>This list shows all trace parts of the loaded "
+		 "trace. For each part, the "
+		 "self/inclusive cost of the current selected "
+		 "function, spent in the part, is shown; "
+		 "percentage costs are always relative to the "
+		 "total cost <em>of the part</em> (not to the whole "
+		 "trace as in the Trace Part Overview). "
+		 "Also shown are the calls happening to/from the "
+		 "current function inside of the trace part.</p>"
+		 "<p>By choosing one or more trace parts from the "
+		 "list, the costs shown all over KCachegrind will "
+		 "only be the ones spent in the selected part(s). "
+		 "If no list selection is shown, in fact all trace "
+		 "parts are selected implicitly.</p>"
+		 "<p>This is a multi-selection list. You can select "
+		 "ranges by dragging the mouse or use SHIFT/CTRL "
+		 "modifiers. "
+		 "Selection/Deselection of trace parts can also be "
+		 "done by using the Trace Part Overview Dockable. "
+		 "This one also supports multiple selection.</p>"
+		 "<p>Note that the list is hidden if only one trace "
+		 "part is loaded.</p>");
+}
+
+
+void PartView::context(TQListViewItem* i, const TQPoint & pos, int)
+{
+  TQPopupMenu popup;
+
+  TracePart* p = i ? ((PartListItem*) i)->part() : 0;
+
+  if (p) {
+    popup.insertItem(i18n("Select '%1'").arg(p->name()), 93);
+    popup.insertItem(i18n("Hide '%1'").arg(p->name()), 94);
+    popup.insertSeparator();
+  }
+
+  popup.insertItem(i18n("Hide Selected"), 95);
+  popup.insertItem(i18n("Show All"), 96);
+  popup.insertSeparator();
+
+  addGoMenu(&popup);
+
+  int r = popup.exec(pos);
+  if (r == 95) {
+    ;
+  }
+
+  // TODO: ...
+}
+
+void PartView::selectionChangedSlot()
+{
+    if (_inSelectionUpdate) return;
+
+    TracePartList l;
+    TQListViewItem* item  = firstChild();
+    for(;item;item = item->nextSibling())
+      if (item->isSelected())
+        l.append( ((PartListItem*)item)->part() );
+
+    selected(l);
+}
+
+
+TraceItem* PartView::canShow(TraceItem* i)
+{
+  if (!TraceItemView::data()) return 0;
+  if (TraceItemView::data()->parts().count()>1) return i;
+  return 0;
+}
+
+void PartView::doUpdate(int changeType)
+{
+    // Special case ?
+    if (changeType == costType2Changed) return;
+    if (changeType == selectedItemChanged) return;
+
+    if (changeType == groupTypeChanged) {
+	TQListViewItem *item;
+	for (item = firstChild();item;item = item->nextSibling())
+	    ((PartListItem*)item)->setGroupType(_groupType);
+
+	return;
+    }
+
+    if (changeType == costTypeChanged) {
+	TQListViewItem *item;
+	for (item = firstChild();item;item = item->nextSibling())
+	  ((PartListItem*)item)->setCostType(_costType);
+
+	return;
+    }
+
+    if (changeType == partsChanged) {
+
+      TracePart* part;
+
+      TQListViewItem* item;
+      _inSelectionUpdate = true;
+      item  = firstChild();
+      for(;item;item = item->nextSibling()) {
+        part = ((PartListItem*)item)->part();
+
+        if (_partList.containsRef(part)>0) {
+          setSelected(item, true);
+          ensureItemVisible(item);
+        }
+        else
+          setSelected(item, false);
+      }
+      _inSelectionUpdate = false;
+
+      return;
+    }
+
+    refresh();
+}
+
+void PartView::refresh()
+{
+    clear();
+    setColumnWidth(1, 50);
+    setColumnWidth(2, 50);
+
+    if (!_data || !_activeItem) return;
+
+    TraceItem::CostType t = _activeItem->type();
+    TraceFunction* f = 0;
+    if (t == TraceItem::Function) f = (TraceFunction*) _activeItem;
+    if (!f) return;
+
+    TracePart* part;
+    TracePartList hidden;
+    if (_topLevel)
+	hidden = _topLevel->hiddenParts();
+
+    TracePartList allParts = _data->parts();
+
+    _inSelectionUpdate = true;
+
+    TQListViewItem* item = 0;
+    for (part = allParts.first(); part; part = allParts.next()) {
+	if (hidden.findRef(part)>=0) continue;
+	item = new PartListItem(this, f, _costType, _groupType, part);
+
+	if (part->isActive()) {
+	    setSelected(item, true);
+	    ensureItemVisible(item);
+	}
+    }
+
+    _inSelectionUpdate = false;
+
+    if (item) {
+	int headerHeight = header()->height();
+	int itemHeight = item->height();
+	setMinimumHeight(headerHeight + 2*itemHeight + 2);
+    }
+}
+
+#include "partview.moc"
diff --git a/kdecachegrind/kdecachegrind/partview.h b/kdecachegrind/kdecachegrind/partview.h
new file mode 100644
index 0000000..92761cc
--- /dev/null
+++ b/kdecachegrind/kdecachegrind/partview.h
@@ -0,0 +1,55 @@
+/* This file is part of KCachegrind.
+   Copyright (C) 2003 Josef Weidendorfer <Josef.Weidendorfer@gmx.de>
+
+   KCachegrind 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, version 2.
+
+   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; see the file COPYING.  If not, write to
+   the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+   Boston, MA 02110-1301, USA.
+*/
+
+/*
+ * Part View
+ */
+
+#ifndef PARTVIEW_H
+#define PARTVIEW_H
+
+#include <tqlistview.h>
+#include "tracedata.h"
+#include "traceitemview.h"
+
+class PartView: public TQListView, public TraceItemView
+{
+  Q_OBJECT
+  TQ_OBJECT
+
+public:
+  PartView(TraceItemView* parentView,
+	   TQWidget* parent=0, const char* name=0);
+
+  virtual TQWidget* widget() { return this; }
+  TQString whatsThis() const;
+
+  void refresh();
+
+private slots:
+  void context(TQListViewItem*,const TQPoint &, int);
+  void selectionChangedSlot();
+
+private:
+  TraceItem* canShow(TraceItem*);
+  void doUpdate(int);
+
+  bool _inSelectionUpdate;
+};
+
+#endif
diff --git a/kdecachegrind/kdecachegrind/pool.cpp b/kdecachegrind/kdecachegrind/pool.cpp
new file mode 100644
index 0000000..d4a89a7
--- /dev/null
+++ b/kdecachegrind/kdecachegrind/pool.cpp
@@ -0,0 +1,258 @@
+/* This file is part of KCachegrind.
+   Copyright (C) 2002-2004 Josef Weidendorfer <Josef.Weidendorfer@gmx.de>
+
+   KCachegrind 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, version 2.
+
+   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; see the file COPYING.  If not, write to
+   the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+   Boston, MA 02110-1301, USA.
+*/
+
+#include <string.h>
+#include <stdlib.h>
+#include <tqglobal.h>
+#include "pool.h"
+
+// FixPool
+
+#define CHUNK_SIZE 100000
+
+struct SpaceChunk
+{
+    struct SpaceChunk* next;
+    unsigned int used;
+    char space[1];
+};
+
+FixPool::FixPool()
+{
+    _first = _last = 0;
+    _reservation = 0;
+    _count = 0;
+    _size = 0;
+}
+
+FixPool::~FixPool()
+{
+    struct SpaceChunk* chunk = _first, *next;
+
+    while(chunk) {
+	next = chunk->next;
+	free(chunk);
+	chunk = next;
+    }
+
+    if (0) qDebug("~FixPool: Had %d objects with total size %d\n",
+		  _count, _size);
+}
+
+void* FixPool::allocate(unsigned int size)
+{
+    if (!ensureSpace(size)) return 0;
+
+    _reservation = 0;
+    void* result = _last->space + _last->used;
+    _last->used += size;
+
+    _count++;
+    _size += size;
+
+    return result;
+}
+
+void* FixPool::reserve(unsigned int size)
+{
+    if (!ensureSpace(size)) return 0;
+    _reservation = size;
+
+    return _last->space + _last->used;
+}
+
+
+bool FixPool::allocateReserved(unsigned int size)
+{
+    if (_reservation < size) return false;
+
+    _reservation = 0;
+    _last->used += size;
+
+    _count++;
+    _size += size;
+
+    return true;
+}
+
+bool FixPool::ensureSpace(unsigned int size)
+{
+    if (_last && _last->used + size <= CHUNK_SIZE) return true;
+
+    struct SpaceChunk* newChunk;
+
+    // we don't allow allocation sizes > CHUNK_SIZE
+    if (size > CHUNK_SIZE) return false;
+
+    newChunk = (struct SpaceChunk*) malloc(sizeof(struct SpaceChunk) +
+					   CHUNK_SIZE);
+    newChunk->next = 0;
+    newChunk->used = 0;
+
+    if (!_last) {
+	_last = _first = newChunk;
+    }
+    else {
+	_last->next = newChunk;
+	_last = newChunk;
+    }
+    return true;
+}
+
+
+// DynPool
+
+DynPool::DynPool()
+{
+  _data = (char*) malloc(CHUNK_SIZE);
+  _used = 0;
+  _size = CHUNK_SIZE;
+
+  // end marker
+  *(int*)_data = 0;
+}
+
+DynPool::~DynPool()
+{
+  // we could check for correctness by iteration over all objects
+
+  ::free(_data);
+}
+
+bool DynPool::allocate(char** ptr, unsigned int size)
+{
+  // round up to multiple of 4
+  size = (size+3) & ~3;
+
+  /* need 12 bytes more:
+   * - 4 bytes for forward chain
+   * - 4 bytes for pointer to ptr
+   * - 4 bytes as end marker (not used for new object)
+   */
+  if (!ensureSpace(size + 12)) return false;
+
+  char** obj = (char**) (_data+_used);
+  obj[0] = (char*)(_data + _used + size + 8);
+  obj[1] = (char*)ptr;
+  *(int*)(_data+_used+size+8) = 0;
+  *ptr = _data+_used+8;
+
+  _used += size + 8;
+
+  return true;
+}
+
+void DynPool::free(char** ptr)
+{
+  if (!ptr ||
+      !*ptr ||
+      (*(char**)(*ptr - 4)) != (char*)ptr )
+    qFatal("Chaining error in DynPool::free");
+
+  (*(char**)(*ptr - 4)) = 0;
+  *ptr = 0;
+}
+
+bool DynPool::ensureSpace(unsigned int size)
+{
+  if (_used + size <= _size) return true;
+
+  unsigned int newsize = _size *3/2 + CHUNK_SIZE;
+  char* newdata = (char*) malloc(newsize);
+
+  unsigned int freed = 0, len;
+  char **p, **pnext, **pnew;
+
+  qDebug("DynPool::ensureSpace size: %d => %d, used %d. %p => %p",
+	 _size, newsize, _used, _data, newdata);
+
+  pnew = (char**) newdata;
+  p = (char**) _data;
+  while(*p) {
+    pnext = (char**) *p;
+    len = (char*)pnext - (char*)p;
+
+    if (0) qDebug(" [%8p] Len %d (ptr %p), freed %d (=> %p)",
+		  p, len, p[1], freed, pnew);
+
+    /* skip freed space ? */
+    if (p[1] == 0) {
+      freed += len;
+      p = pnext;
+      continue;
+    }
+    
+    // new and old still at same address ?
+    if (pnew == p) {
+      pnew = p = pnext;
+      continue;
+    }
+
+    // copy object
+    pnew[0] = (char*)pnew + len;
+    pnew[1] = p[1];
+    memcpy((char*)pnew + 8, (char*)p + 8, len-8);
+
+    // update pointer to object
+    char** ptr = (char**) p[1];
+    if (*ptr != ((char*)p)+8)
+      qFatal("Chaining error in DynPool::ensureSpace");
+    *ptr = ((char*)pnew)+8;
+
+    pnew = (char**) pnew[0];
+    p = pnext;
+  }
+  pnew[0] = 0;
+
+  unsigned int newused = (char*)pnew - (char*)newdata;
+  qDebug("DynPool::ensureSpace size: %d => %d, used %d => %d (%d freed)",
+	 _size, newsize, _used, newused, freed);
+  
+  ::free(_data);
+  _data = newdata;
+  _size = newsize;
+  _used = newused;
+
+  return true;
+}
+
+/* Testing the DynPool
+int main()
+{
+  char* bufs[CHUNK_SIZE];
+  int i;
+
+  DynPool p;
+
+  for(i=0;i<CHUNK_SIZE;i++) {
+    p.allocate(bufs+i, 10+i%10);
+    if (((i%3)==0) && (i>20))
+      p.free(bufs+i-20);
+  }
+
+  for(i=0;i<CHUNK_SIZE;i++) {
+    if ((bufs[i]==0) || ((i%7)==0)) continue;
+    p.free(bufs+i);
+  }
+
+  for(i=0;i<CHUNK_SIZE;i++) {
+    if (bufs[i]) continue;
+    p.allocate(bufs+i, 10+i%10);
+  }
+}
+*/
diff --git a/kdecachegrind/kdecachegrind/pool.h b/kdecachegrind/kdecachegrind/pool.h
new file mode 100644
index 0000000..c9d70c1
--- /dev/null
+++ b/kdecachegrind/kdecachegrind/pool.h
@@ -0,0 +1,107 @@
+/* This file is part of KCachegrind.
+   Copyright (C) 2002-2004 Josef Weidendorfer <Josef.Weidendorfer@gmx.de>
+
+   KCachegrind 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, version 2.
+
+   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; see the file COPYING.  If not, write to
+   the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+   Boston, MA 02110-1301, USA.
+*/
+
+#ifndef POOL_H
+#define POOL_H
+
+/**
+ * Pool objects: containers for many small objects.
+ */
+
+struct SpaceChunk;
+
+/**
+ * FixPool
+ *
+ * For objects with fixed size and life time
+ * ending with that of the pool.
+ */
+class FixPool
+{
+ public:
+    FixPool();
+    ~FixPool();
+
+    /**
+     * Take <size> bytes from the pool
+     */
+    void* allocate(unsigned int size);
+
+    /**
+     * Reserve space. If you call allocateReservedSpace(realsize)
+     * with realSize < reserved size directly after, you
+     * will get the same memory area.
+     */
+    void* reserve(unsigned int size);
+
+    /**
+     * Before calling this, you have to reserve at least <size> bytes
+     * with reserveSpace().
+     */
+    bool allocateReserved(unsigned int size);
+
+ private:
+    /* Checks that there is enough space in the last chunk.
+     * Returns false if this is not possible.
+     */
+    bool ensureSpace(unsigned int);
+
+    struct SpaceChunk *_first, *_last;
+    unsigned int _reservation;
+    int _count, _size;
+};
+
+/**
+ * DynPool
+ *
+ * For objects which probably need to be resized
+ * in the future. Objects also can be deleted to free up space.
+ * As objects can also be moved in a defragmentation step,
+ * access has to be done via the given pointer object.
+ */
+class DynPool
+{
+ public:
+    DynPool();
+    ~DynPool();
+
+    /**
+     * Take <size> bytes from the pool, changing <*ptr>
+     * to point to this allocated space.
+     * <*ptr> will be changed if the object is moved.
+     * Returns false if no space available.
+     */
+    bool allocate(char** ptr, unsigned int size);
+
+    /**
+     * To resize, first allocate new space, and free old
+     * afterwards.
+     */
+    void free(char** ptr);
+
+ private:
+    /* Checks that there is enough space. If not,
+     * it compactifies, possibly moving objects.
+     */
+    bool ensureSpace(unsigned int);
+
+    char* _data;
+    unsigned int _used, _size;
+};
+
+#endif // POOL_H
diff --git a/kdecachegrind/kdecachegrind/sourceitem.cpp b/kdecachegrind/kdecachegrind/sourceitem.cpp
new file mode 100644
index 0000000..305b824
--- /dev/null
+++ b/kdecachegrind/kdecachegrind/sourceitem.cpp
@@ -0,0 +1,444 @@
+/* This file is part of KCachegrind.
+   Copyright (C) 2003 Josef Weidendorfer <Josef.Weidendorfer@gmx.de>
+
+   KCachegrind 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, version 2.
+
+   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; see the file COPYING.  If not, write to
+   the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+   Boston, MA 02110-1301, USA.
+*/
+
+/*
+ * Items of source view.
+ */
+
+#include <tqpixmap.h>
+#include <tqregexp.h>
+#include <tqpainter.h>
+
+#include <klocale.h>
+#include <kiconloader.h>
+#include <kapplication.h>
+
+#include "configuration.h"
+#include "listutils.h"
+#include "sourceview.h"
+#include "sourceitem.h"
+
+
+// SourceItem
+
+// for source lines
+SourceItem::SourceItem(SourceView* sv, TQListView* parent,
+		       int fileno, unsigned int lineno,
+                       bool inside, const TQString& src,
+                       TraceLine* line)
+    : TQListViewItem(parent)
+{
+  _view = sv;
+  _lineno = lineno;
+  _fileno = fileno;
+  _inside = inside;
+  _line = line;
+  _lineCall = 0;
+  _lineJump = 0;
+
+  if (src == "...")
+      setText(0, src);
+  else
+      setText(0, TQString::number(lineno));
+
+  TQString s = src;
+  setText(4, s.replace( TQRegExp("\t"), "        " ));
+
+  updateGroup();
+  updateCost();
+}
+
+// for call lines
+SourceItem::SourceItem(SourceView* sv, TQListViewItem* parent,
+		       int fileno, unsigned int lineno,
+                       TraceLine* line, TraceLineCall* lineCall)
+    : TQListViewItem(parent)
+{
+  _view = sv;
+  _lineno = lineno;
+  _fileno = fileno;
+  _inside = true;
+  _line = line;
+  _lineCall = lineCall;
+  _lineJump = 0;
+
+  //qDebug("SourceItem: (file %d, line %d) Linecall to %s",
+  //       fileno, lineno, _lineCall->call()->called()->prettyName().ascii());
+
+  SubCost cc = _lineCall->callCount();
+  TQString templ = "  ";
+  if (cc==0)
+    templ += i18n("Active call to '%1'");
+  else
+    templ += i18n("%n call to '%1'", "%n calls to '%1'", cc);
+
+  TQString callStr = templ.arg(_lineCall->call()->calledName());
+  TraceFunction* calledF = _lineCall->call()->called();
+  calledF->addPrettyLocation(callStr);
+
+  setText(4, callStr);
+
+  updateGroup();
+  updateCost();
+}
+
+// for jump lines
+SourceItem::SourceItem(SourceView* sv, TQListViewItem* parent,
+		       int fileno, unsigned int lineno,
+                       TraceLine* line, TraceLineJump* lineJump)
+    : TQListViewItem(parent)
+{
+  _view = sv;
+  _lineno = lineno;
+  _fileno = fileno;
+  _inside = true;
+  _line = line;
+  _lineCall = 0;
+  _lineJump = lineJump;
+
+  //qDebug("SourceItem: (file %d, line %d) Linecall to %s",
+  //       fileno, lineno, _lineCall->call()->called()->prettyName().ascii());
+
+  TQString to;
+  if (_lineJump->lineTo()->functionSource() == _line->functionSource())
+      to = _lineJump->lineTo()->name();
+  else
+      to = _lineJump->lineTo()->prettyName();
+
+  TQString jStr;
+  if (_lineJump->isCondJump())
+      jStr = i18n("Jump %1 of %2 times to %3")
+	  .arg(_lineJump->followedCount().pretty())
+	  .arg(_lineJump->executedCount().pretty())
+	  .arg(to);
+  else
+      jStr = i18n("Jump %1 times to %2")
+	  .arg(_lineJump->executedCount().pretty())
+	  .arg(to);
+
+  setText(4, jStr);
+}
+
+
+void SourceItem::updateGroup()
+{
+  if (!_lineCall) return;
+
+  TraceFunction* f = _lineCall->call()->called();
+  TQColor c = Configuration::functionColor(_view->groupType(), f);
+  setPixmap(4, colorPixmap(10, 10, c));
+}
+
+void SourceItem::updateCost()
+{
+  _pure = SubCost(0);
+  _pure2 = SubCost(0);
+
+  if (!_line) return;
+  if (_lineJump) return;
+
+  TraceCost* lineCost = _lineCall ? (TraceCost*)_lineCall : (TraceCost*)_line;
+
+  // don't show any cost inside of cycles
+  if (_lineCall &&
+      ((_lineCall->call()->inCycle()>0) ||
+       (_lineCall->call()->isRecursion()>0))) {
+    TQString str;
+    TQPixmap p;
+
+    TQString icon = "undo";
+    KIconLoader* loader = KApplication::kApplication()->iconLoader();
+    p= loader->loadIcon(icon, KIcon::Small, 0,
+                        KIcon::DefaultState, 0, true);
+    if (p.isNull())
+      str = i18n("(cycle)");
+
+    setText(1, str);
+    setPixmap(1, p);
+    setText(2, str);
+    setPixmap(2, p);
+    return;
+  }
+
+  TraceCost* totalCost;
+  if (Configuration::showExpanded())
+    totalCost = _line->functionSource()->function()->inclusive();
+  else
+    totalCost = _line->functionSource()->function()->data();
+
+  TraceCostType* ct = _view->costType();
+  _pure = ct ? lineCost->subCost(ct) : SubCost(0);
+  if (_pure == 0) {
+    setText(1, TQString());
+    setPixmap(1, TQPixmap());
+  }
+  else {
+    double total = totalCost->subCost(ct);
+    double pure  = 100.0 * _pure / total;
+
+    if (Configuration::showPercentage())
+      setText(1, TQString("%1")
+	      .arg(pure, 0, 'f', Configuration::percentPrecision()));
+    else
+      setText(1, _pure.pretty());
+
+    setPixmap(1, costPixmap(ct, lineCost, total, false));
+  }
+
+  TraceCostType* ct2 = _view->costType2();
+  _pure2 = ct2 ? lineCost->subCost(ct2) : SubCost(0);
+  if (_pure2 == 0) {
+    setText(2, TQString());
+    setPixmap(2, TQPixmap());
+  }
+  else {
+    double total = totalCost->subCost(ct2);
+    double pure2  = 100.0 * _pure2 / total;
+
+    if (Configuration::showPercentage())
+      setText(2, TQString("%1")
+	      .arg(pure2, 0, 'f', Configuration::percentPrecision()));
+    else
+      setText(2, _pure2.pretty());
+
+    setPixmap(2, costPixmap(ct2, lineCost, total, false));
+  }
+}
+
+
+int SourceItem::compare(TQListViewItem * i, int col, bool ascending ) const
+{
+  const SourceItem* si1 = this;
+  const SourceItem* si2 = (SourceItem*) i;
+
+  // we always want descending order
+  if (((col>0) && ascending) ||
+      ((col==0) && !ascending) ) {
+    si1 = si2;
+    si2 = this;
+  }
+
+  if (col==1) {
+    if (si1->_pure < si2->_pure) return -1;
+    if (si1->_pure > si2->_pure) return 1;
+    return 0;
+  }
+  if (col==2) {
+    if (si1->_pure2 < si2->_pure2) return -1;
+    if (si1->_pure2 > si2->_pure2) return 1;
+    return 0;
+  }
+  if (col==0) {
+    // Sort file numbers
+    if (si1->_fileno < si2->_fileno) return -1;
+    if (si1->_fileno > si2->_fileno) return 1;
+
+    // Sort line numbers
+    if (si1->_lineno < si2->_lineno) return -1;
+    if (si1->_lineno > si2->_lineno) return 1;
+
+    // Same line: code gets above calls/jumps
+    if (!si1->_lineCall && !si1->_lineJump) return -1;
+    if (!si2->_lineCall && !si2->_lineJump) return 1;
+
+    // calls above jumps
+    if (si1->_lineCall && !si2->_lineCall) return -1;
+    if (si2->_lineCall && !si1->_lineCall) return 1;
+
+    if (si1->_lineCall && si2->_lineCall) {
+	// Two calls: desending sort according costs
+	if (si1->_pure < si2->_pure) return 1;
+	if (si1->_pure > si2->_pure) return -1;
+
+	// Two calls: sort according function names
+	TraceFunction* f1 = si1->_lineCall->call()->called();
+	TraceFunction* f2 = si2->_lineCall->call()->called();
+	if (f1->prettyName() > f2->prettyName()) return 1;
+	return -1;
+    }
+
+    // Two jumps: descending sort according target line
+    if (si1->_lineJump->lineTo()->lineno() <
+	si2->_lineJump->lineTo()->lineno())
+	return -1;
+    if (si1->_lineJump->lineTo()->lineno() >
+	si2->_lineJump->lineTo()->lineno())
+	return 1;
+    return 0;
+  }
+  return TQListViewItem::compare(i, col, ascending);
+}
+
+void SourceItem::paintCell( TQPainter *p, const TQColorGroup &cg,
+                            int column, int width, int alignment )
+{
+  TQColorGroup _cg( cg );
+
+  if ( !_inside || ((column==1) || (column==2)))
+    _cg.setColor( TQColorGroup::Base, cg.button() );
+  else if ((_lineCall || _lineJump) && column>2)
+   _cg.setColor( TQColorGroup::Base, cg.midlight() );
+
+  if (column == 3)
+      paintArrows(p, _cg, width);
+  else
+      TQListViewItem::paintCell( p, _cg, column, width, alignment );
+}
+
+void SourceItem::setJumpArray(const TQMemArray<TraceLineJump*>& a)
+{
+    _jump.duplicate(a);
+}
+
+void SourceItem::paintArrows(TQPainter *p, const TQColorGroup &cg, int width)
+{
+  TQListView *lv = listView();
+  if ( !lv ) return;
+  SourceView* sv = (SourceView*) lv;
+
+  const BackgroundMode bgmode = lv->viewport()->backgroundMode();
+  const TQColorGroup::ColorRole crole
+    = TQPalette::backgroundRoleFromMode( bgmode );
+  if ( cg.brush( crole ) != lv->colorGroup().brush( crole ) )
+    p->fillRect( 0, 0, width, height(), cg.brush( crole ) );
+  else
+    sv->paintEmptyArea( p, TQRect( 0, 0, width, height() ) );
+
+  if ( isSelected() && lv->allColumnsShowFocus() )
+    p->fillRect( 0, 0, width, height(), cg.brush( TQColorGroup::Highlight ) );
+
+  int marg = lv->itemMargin();
+  int yy = height()/2, y1, y2;
+  TQColor c;
+
+  int start = -1, end = -1;
+
+  // draw line borders, detect start/stop of a line
+  for(int i=0;i< (int)_jump.size();i++) {
+      if (_jump[i] == 0) continue;
+
+      y1 = 0;
+      y2 = height();
+      if (_lineJump &&
+	  (_lineJump->lineTo() == _jump[i]->lineTo()) &&
+	  (_jump[i]->lineFrom()->lineno() == _lineno)) {
+
+	  if (start<0) start = i;
+	  if (_lineJump == _jump[i]) {
+	      if (_jump[i]->lineTo()->lineno() <= _lineno)
+		  y2 = yy;
+	      else
+		  y1 = yy;
+	  }
+      }
+      else if (!_lineJump && !_lineCall &&
+	       (_jump[i]->lineTo()->lineno() == _lineno)) {
+	  if (end<0) end = i;
+	  if (_jump[i]->lineFrom()->lineno() < _lineno)
+	      y2 = yy;
+	  else
+	      y1 = yy;
+      }
+
+      c = _jump[i]->isCondJump() ? red : blue;
+      p->fillRect( marg + 6*i, y1, 4, y2, c);
+      p->setPen(c.light());
+      p->drawLine( marg + 6*i, y1, marg + 6*i, y2);
+      p->setPen(c.dark());
+      p->drawLine( marg + 6*i +3, y1, marg + 6*i +3, y2);
+  }
+
+  // draw start/stop horizontal line
+  int x, y = yy-2, w, h = 4;
+  if (start >= 0) {
+      c = _jump[start]->isCondJump() ? red : blue;
+      x = marg + 6*start;
+      w = 6*(sv->arrowLevels() - start) + 10;
+      p->fillRect( x, y, w, h, c);
+      p->setPen(c.light());
+      p->drawLine(x, y, x+w-1, y);
+      p->drawLine(x, y, x, y+h-1);
+      p->setPen(c.dark());
+      p->drawLine(x+w-1, y, x+w-1, y+h-1);
+      p->drawLine(x+1, y+h-1, x+w-1, y+h-1);
+  }
+  if (end >= 0) {
+      c = _jump[end]->isCondJump() ? red : blue;
+      x = marg + 6*end;
+      w = 6*(sv->arrowLevels() - end) + 10;
+
+      TQPointArray a;
+      a.putPoints(0, 7, x, y+h,
+		  x,y, x+w-8, y, x+w-8, y-2,
+		  x+w, yy,
+		  x+w-8, y+h+2, x+w-8, y+h);
+      p->setBrush(c);
+      p->drawConvexPolygon(a);
+
+      p->setPen(c.light());
+      p->drawPolyline(a, 0, 5);
+      p->setPen(c.dark());
+      p->drawPolyline(a, 4, 2);
+      p->setPen(c.light());
+      p->drawPolyline(a, 5, 2);
+      p->setPen(c.dark());
+      p->drawPolyline(a, 6, 2);
+  }
+
+  // draw inner vertical line for start/stop
+  // this overwrites borders of horizontal line
+  for(int i=0;i< (int)_jump.size();i++) {
+      if (_jump[i] == 0) continue;
+
+      c = _jump[i]->isCondJump() ? red : blue;
+
+      if (_jump[i]->lineFrom()->lineno() == _lineno) {
+	  bool drawUp = true;
+	  if (_jump[i]->lineTo()->lineno() == _lineno)
+	      if (start<0) drawUp = false;
+	  if (_jump[i]->lineTo()->lineno() > _lineno) drawUp = false;
+	  if (drawUp)
+	      p->fillRect( marg + 6*i +1, 0, 2, yy, c);
+	  else
+	      p->fillRect( marg + 6*i +1, yy, 2, height()-yy, c);
+      }
+      else if (_jump[i]->lineTo()->lineno() == _lineno) {
+	  if (end<0) end = i;
+	  if (_jump[i]->lineFrom()->lineno() < _lineno)
+	      p->fillRect( marg + 6*i +1, 0, 2, yy, c);
+	  else
+	      p->fillRect( marg + 6*i +1, yy, 2, height()-yy, c);
+      }
+  }
+
+}
+
+int SourceItem::width( const TQFontMetrics& fm,
+		       const TQListView* lv, int c ) const
+{
+  if (c != 3) return TQListViewItem::width(fm, lv, c);
+
+  SourceView* sv = (SourceView*) lv;
+  int levels = sv->arrowLevels();
+
+  if (levels == 0) return 0;
+
+  // 10 pixels for the arrow
+  return 10 + 6*levels + lv->itemMargin() * 2;
+}
+
diff --git a/kdecachegrind/kdecachegrind/sourceitem.h b/kdecachegrind/kdecachegrind/sourceitem.h
new file mode 100644
index 0000000..925e575
--- /dev/null
+++ b/kdecachegrind/kdecachegrind/sourceitem.h
@@ -0,0 +1,84 @@
+/* This file is part of KCachegrind.
+   Copyright (C) 2003 Josef Weidendorfer <Josef.Weidendorfer@gmx.de>
+
+   KCachegrind 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, version 2.
+
+   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; see the file COPYING.  If not, write to
+   the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+   Boston, MA 02110-1301, USA.
+*/
+
+/*
+ * Items of source view.
+ */
+
+#ifndef SOURCEITEM_H
+#define SOURCEITEM_H
+
+#include <tqlistview.h>
+#include "tracedata.h"
+
+class SourceView;
+
+class SourceItem: public TQListViewItem
+{
+public:
+  // for source lines
+  SourceItem(SourceView* sv, TQListView* parent, 
+	     int fileno, unsigned int lineno,
+	     bool inside, const TQString& src,
+             TraceLine* line = 0);
+
+  // for call lines
+  SourceItem(SourceView* sv, TQListViewItem* parent, 
+	     int fileno, unsigned int lineno,
+             TraceLine* line, TraceLineCall* lineCall);
+
+  // for jump lines
+  SourceItem(SourceView* sv, TQListViewItem* parent, 
+	     int fileno, unsigned int lineno,
+             TraceLine* line, TraceLineJump* lineJump);
+
+  uint lineno() const { return _lineno; }
+  int fileNumber() const { return _fileno; }
+  bool inside() const { return _inside; }
+  TraceLine* line() const { return _line; }
+  TraceLineCall* lineCall() const { return _lineCall; }
+  TraceLineJump* lineJump() const { return _lineJump; }
+
+  int compare(TQListViewItem * i, int col, bool ascending ) const;
+
+  void paintCell( TQPainter *p, const TQColorGroup &cg,
+                  int column, int width, int alignment );
+  int width( const TQFontMetrics& fm,
+             const TQListView* lv, int c ) const;
+  void updateGroup();
+  void updateCost();
+
+  // arrow lines
+  void setJumpArray(const TQMemArray<TraceLineJump*>& a);
+
+protected:
+  void paintArrows(TQPainter *p, const TQColorGroup &cg, int width);
+  TQMemArray<TraceLineJump*> _jump;
+
+private:
+  SourceView* _view;
+  SubCost _pure, _pure2;
+  uint _lineno;
+  int _fileno; // for line sorting (even with multiple files)
+  bool _inside;
+  TraceLine* _line;
+  TraceLineJump* _lineJump;
+  TraceLineCall* _lineCall;
+};
+
+#endif
diff --git a/kdecachegrind/kdecachegrind/sourceview.cpp b/kdecachegrind/kdecachegrind/sourceview.cpp
new file mode 100644
index 0000000..dde291e
--- /dev/null
+++ b/kdecachegrind/kdecachegrind/sourceview.cpp
@@ -0,0 +1,813 @@
+/* This file is part of KCachegrind.
+   Copyright (C) 2003 Josef Weidendorfer <Josef.Weidendorfer@gmx.de>
+
+   KCachegrind 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, version 2.
+
+   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; see the file COPYING.  If not, write to
+   the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+   Boston, MA 02110-1301, USA.
+*/
+
+/*
+ * Source View
+ */
+
+#include <tqdir.h>
+#include <tqfile.h>
+#include <tqwhatsthis.h>
+#include <tqpopupmenu.h>
+#include <klocale.h>
+#include <kdebug.h>
+
+#include "configuration.h"
+#include "sourceitem.h"
+#include "sourceview.h"
+
+
+//
+// SourceView
+//
+
+
+SourceView::SourceView(TraceItemView* parentView,
+                       TQWidget* parent, const char* name)
+  : TQListView(parent, name), TraceItemView(parentView)
+{
+  _inSelectionUpdate = false;
+
+  _arrowLevels = 0;
+  _lowList.setSortLow(true);
+  _highList.setSortLow(false);
+
+  addColumn( i18n( "#" ) );
+  addColumn( i18n( "Cost" ) );
+  addColumn( i18n( "Cost 2" ) );
+  addColumn( "" );
+  addColumn( i18n( "Source (unknown)" ) );
+
+  setAllColumnsShowFocus(true);
+  setColumnAlignment(0, TQt::AlignRight);
+  setColumnAlignment(1, TQt::AlignRight);
+  setColumnAlignment(2, TQt::AlignRight);
+  setResizeMode(TQListView::LastColumn);
+
+  connect(this,
+          TQT_SIGNAL(contextMenuRequested(TQListViewItem*, const TQPoint &, int)),
+          TQT_SLOT(context(TQListViewItem*, const TQPoint &, int)));
+
+  connect(this,
+          TQT_SIGNAL(selectionChanged(TQListViewItem*)),
+          TQT_SLOT(selectedSlot(TQListViewItem*)));
+
+  connect(this,
+          TQT_SIGNAL(doubleClicked(TQListViewItem*)),
+          TQT_SLOT(activatedSlot(TQListViewItem*)));
+
+  connect(this,
+          TQT_SIGNAL(returnPressed(TQListViewItem*)),
+          TQT_SLOT(activatedSlot(TQListViewItem*)));
+
+  TQWhatsThis::add( this, whatsThis());
+}
+
+void SourceView::paintEmptyArea( TQPainter * p, const TQRect & r)
+{
+  TQListView::paintEmptyArea(p, r);
+}
+
+
+TQString SourceView::whatsThis() const
+{
+    return i18n( "<b>Annotated Source</b>"
+		 "<p>The annotated source list shows the "
+		 "source lines of the current selected function "
+		 "together with (self) cost spent while executing the "
+		 "code of this source line. If there was a call "
+		 "in a source line, lines with details on the "
+		 "call happening are inserted into the source: "
+		 "the cost spent inside of the call, the "
+		 "number of calls happening, and the call destination.</p>"
+		 "<p>Select a inserted call information line to "
+		 "make the destination function current.</p>");
+}
+
+void SourceView::context(TQListViewItem* i, const TQPoint & p, int c)
+{
+  TQPopupMenu popup;
+
+  // Menu entry:
+  TraceLineCall* lc = i ? ((SourceItem*) i)->lineCall() : 0;
+  TraceLineJump* lj = i ? ((SourceItem*) i)->lineJump() : 0;
+  TraceFunction* f = lc ? lc->call()->called() : 0;
+  TraceLine* line = lj ? lj->lineTo() : 0;
+
+  if (f) {
+    TQString name = f->name();
+    if ((int)name.length()>Configuration::maxSymbolLength())
+      name = name.left(Configuration::maxSymbolLength()) + "...";
+    popup.insertItem(i18n("Go to '%1'").arg(name), 93);
+    popup.insertSeparator();
+  }
+  else if (line) {
+    popup.insertItem(i18n("Go to Line %1").arg(line->name()), 93);
+    popup.insertSeparator();
+  }
+
+  if ((c == 1) || (c == 2)) {
+    addCostMenu(&popup);
+    popup.insertSeparator();
+  }
+  addGoMenu(&popup);
+
+  int r = popup.exec(p);
+  if (r == 93) {
+    if (f) activated(f);
+    if (line) activated(line);
+  }
+}
+
+
+void SourceView::selectedSlot(TQListViewItem * i)
+{
+  if (!i) return;
+  // programatically selected items are not signalled
+  if (_inSelectionUpdate) return;
+
+  TraceLineCall* lc = ((SourceItem*) i)->lineCall();
+  TraceLineJump* lj = ((SourceItem*) i)->lineJump();
+
+  if (!lc && !lj) {
+      TraceLine* l = ((SourceItem*) i)->line();
+      if (l) {
+	  _selectedItem = l;
+	  selected(l);
+      }
+      return;
+  }
+
+  TraceFunction* f = lc ? lc->call()->called() : 0;
+  if (f) {
+      _selectedItem = f;
+      selected(f);
+  }
+  else {
+    TraceLine* line = lj ? lj->lineTo() : 0;
+    if (line) {
+	_selectedItem = line;
+	selected(line);
+    }
+  }
+}
+
+void SourceView::activatedSlot(TQListViewItem * i)
+{
+  if (!i) return;
+  TraceLineCall* lc = ((SourceItem*) i)->lineCall();
+  TraceLineJump* lj = ((SourceItem*) i)->lineJump();
+
+  if (!lc && !lj) {
+      TraceLine* l = ((SourceItem*) i)->line();
+      if (l) activated(l);
+      return;
+  }
+
+  TraceFunction* f = lc ? lc->call()->called() : 0;
+  if (f) activated(f);
+  else {
+    TraceLine* line = lj ? lj->lineTo() : 0;
+    if (line) activated(line);
+  }
+}
+
+TraceItem* SourceView::canShow(TraceItem* i)
+{
+  TraceItem::CostType t = i ? i->type() : TraceItem::NoCostType;
+  TraceFunction* f = 0;
+
+  switch(t) {
+  case TraceItem::Function:
+      f = (TraceFunction*) i;
+      break;
+
+  case TraceItem::Instr:
+      f = ((TraceInstr*)i)->function();
+      select(i);
+      break;
+
+  case TraceItem::Line:
+      f = ((TraceLine*)i)->functionSource()->function();
+      select(i);
+      break;
+
+  default:
+      break;
+  }
+
+  return f;
+}
+
+void SourceView::doUpdate(int changeType)
+{
+  // Special case ?
+  if (changeType == selectedItemChanged) {
+
+      if (!_selectedItem) {
+	  clearSelection();
+	  return;
+      }
+
+      TraceLine* sLine = 0;
+      if (_selectedItem->type() == TraceItem::Line)
+	  sLine = (TraceLine*) _selectedItem;
+      if (_selectedItem->type() == TraceItem::Instr)
+	  sLine = ((TraceInstr*)_selectedItem)->line();
+
+      SourceItem* si = (SourceItem*)TQListView::selectedItem();
+      if (si) {
+	  if (si->line() == sLine) return;
+	  if (si->lineCall() &&
+	      (si->lineCall()->call()->called() == _selectedItem)) return;
+      }
+
+      TQListViewItem *item, *item2;
+      for (item = firstChild();item;item = item->nextSibling()) {
+	  si = (SourceItem*)item;
+	  if (si->line() == sLine) {
+	      ensureItemVisible(item);
+              _inSelectionUpdate = true;
+	      setCurrentItem(item);
+              _inSelectionUpdate = false;
+	      break;
+	  }
+	  item2 = item->firstChild();
+	  for (;item2;item2 = item2->nextSibling()) {
+	      si = (SourceItem*)item2;
+	      if (!si->lineCall()) continue;
+	      if (si->lineCall()->call()->called() == _selectedItem) {
+		  ensureItemVisible(item2);
+                  _inSelectionUpdate = true;
+		  setCurrentItem(item2);
+                  _inSelectionUpdate = false;
+		  break;
+	      }
+	  }
+	  if (item2) break;
+      }
+      return;
+  }
+
+  if (changeType == groupTypeChanged) {
+    TQListViewItem *item, *item2;
+    for (item = firstChild();item;item = item->nextSibling())
+      for (item2 = item->firstChild();item2;item2 = item2->nextSibling())
+        ((SourceItem*)item2)->updateGroup();
+  }
+
+  refresh();
+}
+
+void SourceView::refresh()
+{
+  clear();
+  setColumnWidth(0, 20);
+  setColumnWidth(1, 50);
+  setColumnWidth(2, _costType2 ? 50:0);
+  setColumnWidth(3, 0); // arrows, defaults to invisible
+  setSorting(0); // always reset to line number sort
+  if (_costType)
+    setColumnText(1, _costType->name());
+  if (_costType2)
+    setColumnText(2, _costType2->name());
+
+  _arrowLevels = 0;
+
+  if (!_data || !_activeItem) {
+    setColumnText(4, i18n("(No Source)"));
+    return;
+  }
+
+  TraceItem::CostType t = _activeItem->type();
+  TraceFunction* f = 0;
+  if (t == TraceItem::Function) f = (TraceFunction*) _activeItem;
+  if (t == TraceItem::Instr) {
+    f = ((TraceInstr*)_activeItem)->function();
+    if (!_selectedItem) _selectedItem = _activeItem;
+  }
+  if (t == TraceItem::Line) {
+    f = ((TraceLine*)_activeItem)->functionSource()->function();
+    if (!_selectedItem) _selectedItem = _activeItem;
+  }
+
+  if (!f) return;
+
+  // Allow resizing of column 2
+  setColumnWidthMode(2, TQListView::Maximum);
+
+  TraceFunctionSource* mainSF = f->sourceFile();
+
+  // skip first source if there's no debug info and there are more sources
+  // (this is for a bug in GCC 2.95.x giving unknown source for prologs)
+  if (mainSF &&
+      (mainSF->firstLineno() == 0) &&
+      (mainSF->lastLineno() == 0) &&
+      (f->sourceFiles().count()>1) ) {
+	  // skip
+  }
+  else
+      fillSourceFile(mainSF, 0);
+
+  TraceFunctionSource* sf;
+  int fileno = 1;
+  TraceFunctionSourceList l = f->sourceFiles();
+  for (sf=l.first();sf;sf=l.next(), fileno++)
+    if (sf != mainSF)
+      fillSourceFile(sf, fileno);
+
+  if (!_costType2) {
+    setColumnWidthMode(2, TQListView::Manual);
+    setColumnWidth(2, 0);
+  }
+}
+
+
+// helper for fillSourceList:
+// search recursive for a file, starting from a base dir
+static bool checkFileExistance(TQString& dir, const TQString& name)
+{
+  // we leave this in...
+  qDebug("Checking %s/%s", dir.ascii(), name.ascii());
+
+  if (TQFile::exists(dir + "/" + name)) return true;
+
+  // check in subdirectories
+  TQDir d(dir);
+  d.setFilter( TQDir::Dirs | TQDir::NoSymLinks );
+  d.setSorting( TQDir::Unsorted );
+  TQStringList subdirs = d.entryList();
+  TQStringList::Iterator it =subdirs.begin();
+  for(; it != subdirs.end(); ++it ) {
+    if (*it == "." || *it == ".." || *it == "CVS") continue;
+
+    dir = d.filePath(*it);
+    if (checkFileExistance(dir, name)) return true;
+  }
+  return false;
+}
+
+
+void SourceView::updateJumpArray(uint lineno, SourceItem* si,
+				 bool ignoreFrom, bool ignoreTo)
+{
+    TraceLineJump* lj;
+    uint lowLineno, highLineno;
+    int iEnd = -1, iStart = -1;
+
+    if (0) qDebug("updateJumpArray(line %d, jump to %s)",
+		  lineno,
+		  si->lineJump()
+		  ? si->lineJump()->lineTo()->name().ascii() : "?" );
+
+
+    lj=_lowList.current();
+    while(lj) {
+	lowLineno = lj->lineFrom()->lineno();
+	if (lj->lineTo()->lineno() < lowLineno)
+	    lowLineno = lj->lineTo()->lineno();
+
+	if (lowLineno > lineno) break;
+
+	if (ignoreFrom && (lowLineno < lj->lineTo()->lineno())) break;
+	if (ignoreTo && (lowLineno < lj->lineFrom()->lineno())) break;
+
+	if (si->lineJump() && (lj != si->lineJump())) break;
+
+	int asize = (int)_jump.size();
+#if 0
+	for(iStart=0;iStart<asize;iStart++)
+	    if (_jump[iStart] &&
+		(_jump[iStart]->lineTo() == lj->lineTo())) break;
+#else
+	iStart = asize;
+#endif
+
+	if (iStart == asize) {
+	    for(iStart=0;iStart<asize;iStart++)
+		if (_jump[iStart] == 0) break;
+
+	    if (iStart== asize) {
+		asize++;
+		_jump.resize(asize);
+		if (asize > _arrowLevels) _arrowLevels = asize;
+	    }
+
+	    if (0) qDebug(" start %d (%s to %s)",
+			  iStart,
+			  lj->lineFrom()->name().ascii(),
+			  lj->lineTo()->name().ascii());
+
+	    _jump[iStart] = lj;
+	}
+	lj=_lowList.next();
+    }
+
+    si->setJumpArray(_jump);
+
+    lj=_highList.current();
+    while(lj) {
+	highLineno = lj->lineFrom()->lineno();
+	if (lj->lineTo()->lineno() > highLineno) {
+	    highLineno = lj->lineTo()->lineno();
+	    if (ignoreTo) break;
+	}
+	else if (ignoreFrom) break;
+
+	if (highLineno > lineno) break;
+
+	for(iEnd=0;iEnd< (int)_jump.size();iEnd++)
+	    if (_jump[iEnd] == lj) break;
+	if (iEnd == (int)_jump.size()) {
+	    qDebug("LineView: no jump start for end at %x ?", highLineno);
+	    iEnd = -1;
+	}
+	lj=_highList.next();
+
+	if (0 && (iEnd>=0))
+	    qDebug(" end %d (%s to %s)",
+		   iEnd,
+		   _jump[iEnd]->lineFrom()->name().ascii(),
+		   _jump[iEnd]->lineTo()->name().ascii());
+
+	if (0 && lj) qDebug("next end: %s to %s",
+			    lj->lineFrom()->name().ascii(),
+			    lj->lineTo()->name().ascii());
+
+	if (highLineno > lineno)
+	    break;
+	else {
+	    if (iEnd>=0) _jump[iEnd] = 0;
+	    iEnd = -1;
+	}
+    }
+    if (iEnd>=0) _jump[iEnd] = 0;
+}
+
+
+/* If sourceList is empty we set the source file name into the header,
+ * else this code is of a inlined function, and we add "inlined from..."
+ */
+void SourceView::fillSourceFile(TraceFunctionSource* sf, int fileno)
+{
+  if (!sf) return;
+
+  if (0) qDebug("Selected Item %s", 
+		_selectedItem ? _selectedItem->name().ascii() : "(none)");
+
+  TraceLineMap::Iterator lineIt, lineItEnd;
+  int nextCostLineno = 0, lastCostLineno = 0;
+
+  bool validSourceFile = (!sf->file()->name().isEmpty());
+
+  TraceLine* sLine = 0;
+  if (_selectedItem) {
+    if (_selectedItem->type() == TraceItem::Line)
+      sLine = (TraceLine*) _selectedItem;
+    if (_selectedItem->type() == TraceItem::Instr)
+      sLine = ((TraceInstr*)_selectedItem)->line();
+  }
+
+  if (validSourceFile) {
+      TraceLineMap* lineMap = sf->lineMap();
+      if (lineMap) {
+	  lineIt    = lineMap->begin();
+	  lineItEnd = lineMap->end();
+	  // get first line with cost of selected type
+	  while(lineIt != lineItEnd) {
+	    if (&(*lineIt) == sLine) break;
+	    if ((*lineIt).hasCost(_costType)) break;
+	    if (_costType2 && (*lineIt).hasCost(_costType2)) break;
+	    ++lineIt;
+	  }
+
+	  nextCostLineno     = (lineIt == lineItEnd) ? 0 : (*lineIt).lineno();
+	  if (nextCostLineno<0) {
+	    kdError() << "SourceView::fillSourceFile: Negative line number "
+		      << nextCostLineno << endl
+		      << "  Function '" << sf->function()->name() << "'" << endl
+		      << "  File '" << sf->file()->name() << "'" << endl;
+	    nextCostLineno = 0;
+	  }
+	    
+      }
+
+      if (nextCostLineno == 0) {
+	  new SourceItem(this, this, fileno, 0, false,
+			 i18n("There is no cost of current selected type associated"));
+	  new SourceItem(this, this, fileno, 1, false,
+			 i18n("with any source line of this function in file"));
+	  new SourceItem(this, this, fileno, 2, false,
+			 TQString("    '%1'").arg(sf->function()->prettyName()));
+	  new SourceItem(this, this, fileno, 3, false,
+			 i18n("Thus, no annotated source can be shown."));
+	  return;
+      }
+  }
+
+  TQString filename = sf->file()->shortName();
+  TQString dir = sf->file()->directory();
+  if (!dir.isEmpty())
+    filename = dir + "/" + filename;
+
+  if (nextCostLineno>0) {
+    // we have debug info... search for source file
+    if (!TQFile::exists(filename)) {
+      TQStringList list = Configuration::sourceDirs(_data,
+						   sf->function()->object());
+      TQStringList::Iterator it;
+
+      for ( it = list.begin(); it != list.end(); ++it ) {
+        dir = *it;
+        if (checkFileExistance(dir, sf->file()->shortName())) break;
+      }
+
+      if (it == list.end())
+	  nextCostLineno = 0;
+      else {
+        filename = dir + "/" + sf->file()->shortName();
+        // no need to search again
+        sf->file()->setDirectory(dir);
+      }
+    }
+  }
+
+  // do it here, because the source directory could have been set before
+  if (childCount()==0) {
+    setColumnText(4, validSourceFile ?
+                  i18n("Source ('%1')").arg(filename) :
+                  i18n("Source (unknown)"));
+  }
+  else {
+    new SourceItem(this, this, fileno, 0, true,
+                   validSourceFile ?
+                   i18n("--- Inlined from '%1' ---").arg(filename) :
+                   i18n("--- Inlined from unknown source ---"));
+  }
+
+  if (nextCostLineno == 0) {
+    new SourceItem(this, this, fileno, 0, false,
+                   i18n("There is no source available for the following function:"));
+    new SourceItem(this, this, fileno, 1, false,
+                   TQString("    '%1'").arg(sf->function()->prettyName()));
+    if (sf->file()->name().isEmpty()) {
+      new SourceItem(this, this, fileno, 2, false,
+                     i18n("This is because no debug information is present."));
+      new SourceItem(this, this, fileno, 3, false,
+                     i18n("Recompile source and redo the profile run."));
+      if (sf->function()->object()) {
+        new SourceItem(this, this, fileno, 4, false,
+                       i18n("The function is located in this ELF object:"));
+        new SourceItem(this, this, fileno, 5, false,
+                       TQString("    '%1'")
+                       .arg(sf->function()->object()->prettyName()));
+      }
+    }
+    else {
+      new SourceItem(this, this, fileno, 2, false,
+                     i18n("This is because its source file cannot be found:"));
+      new SourceItem(this, this, fileno, 3, false,
+                     TQString("    '%1'").arg(sf->file()->name()));
+      new SourceItem(this, this, fileno, 4, false,
+                     i18n("Add the folder of this file to the source folder list."));
+      new SourceItem(this, this, fileno, 5, false,
+                     i18n("The list can be found in the configuration dialog."));
+    }
+    return;
+  }
+
+
+  // initialisation for arrow drawing
+  // create sorted list of jumps (for jump arrows)
+  TraceLineMap::Iterator it = lineIt, nextIt;
+  _lowList.clear();
+  _highList.clear();
+  while(1) {
+
+      nextIt = it;
+      ++nextIt;
+      while(nextIt != lineItEnd) {
+	if (&(*nextIt) == sLine) break;
+	if ((*nextIt).hasCost(_costType)) break;
+	if (_costType2 && (*nextIt).hasCost(_costType2)) break;
+	++nextIt;
+      }
+
+      TraceLineJumpList jlist = (*it).lineJumps();
+      TraceLineJump* lj;
+      for (lj=jlist.first();lj;lj=jlist.next()) {
+	  if (lj->executedCount()==0) continue;
+	  // skip jumps to next source line with cost
+	  //if (lj->lineTo() == &(*nextIt)) continue;
+
+	  _lowList.append(lj);
+	  _highList.append(lj);
+      }
+      it = nextIt;
+      if (it == lineItEnd) break;
+  }
+  _lowList.sort();
+  _highList.sort();
+  _lowList.first(); // iterators to list start
+  _highList.first();
+  _jump.resize(0);
+
+
+  char buf[256];
+  bool inside = false, skipLineWritten = true;
+  int readBytes;
+  int fileLineno = 0;
+  SubCost most = 0;
+
+  TraceLine* currLine;
+  SourceItem *si, *si2, *item = 0, *first = 0, *selected = 0;
+  TQFile file(filename);
+  if (!file.open(IO_ReadOnly)) return;
+  while (1) {
+    readBytes=file.readLine(buf, sizeof( buf ));
+    if (readBytes<=0) {
+      // for nice empty 4 lines after function with EOF
+      buf[0] = 0;
+    }
+
+    if (readBytes >= (int) sizeof( buf )) {
+      qDebug("%s:%d  Line too long\n",
+	     sf->file()->name().ascii(), fileLineno);
+    }
+    else if ((readBytes>0) && (buf[readBytes-1] == '\n'))
+      buf[readBytes-1] = 0;
+
+
+    // keep fileLineno inside [lastCostLineno;nextCostLineno]
+    fileLineno++;
+    if (fileLineno == nextCostLineno) {
+	currLine = &(*lineIt);
+
+	// get next line with cost of selected type
+	++lineIt;
+	while(lineIt != lineItEnd) {
+	  if (&(*lineIt) == sLine) break;
+	  if ((*lineIt).hasCost(_costType)) break;
+	  if (_costType2 && (*lineIt).hasCost(_costType2)) break;
+	  ++lineIt;
+	}
+
+	lastCostLineno = nextCostLineno;
+	nextCostLineno = (lineIt == lineItEnd) ? 0 : (*lineIt).lineno();
+    }
+    else
+	currLine = 0;
+
+    // update inside
+    if (!inside) {
+	if (currLine) inside = true;
+    }
+    else {
+	if ( (fileLineno > lastCostLineno) &&
+	     ((nextCostLineno == 0) ||
+	      (fileLineno < nextCostLineno - Configuration::noCostInside()) ))
+	    inside = false;
+    }
+
+    int context = Configuration::context();
+
+    if ( ((lastCostLineno==0) || (fileLineno > lastCostLineno + context)) &&
+	 ((nextCostLineno==0) || (fileLineno < nextCostLineno - context))) {
+	if (lineIt == lineItEnd) break;
+
+	if (!skipLineWritten) {
+	    skipLineWritten = true;
+	    // a "skipping" line: print "..." instead of a line number
+	    strcpy(buf,"...");
+	}
+	else
+	    continue;
+    }
+    else
+	skipLineWritten = false;
+
+    si = new SourceItem(this, this, 
+			fileno, fileLineno, inside, TQString(buf),
+                        currLine);
+
+    if (!currLine) continue;
+
+    if (!selected && (currLine == sLine)) selected = si;
+    if (!first) first = si;
+
+    if (currLine->subCost(_costType) > most) {
+      item = si;
+      most = currLine->subCost(_costType);
+    }
+
+    si->setOpen(true);
+    TraceLineCallList list = currLine->lineCalls();
+    TraceLineCall* lc;
+    for (lc=list.first();lc;lc=list.next()) {
+	if ((lc->subCost(_costType)==0) &&
+	    (lc->subCost(_costType2)==0)) continue;
+
+      if (lc->subCost(_costType) > most) {
+        item = si;
+        most = lc->subCost(_costType);
+      }
+
+      si2 = new SourceItem(this, si, fileno, fileLineno, currLine, lc);
+
+      if (!selected && (lc->call()->called() == _selectedItem))
+	  selected = si2;
+    }
+
+    TraceLineJumpList jlist = currLine->lineJumps();
+    TraceLineJump* lj;
+    for (lj=jlist.first();lj;lj=jlist.next()) {
+	if (lj->executedCount()==0) continue;
+
+	new SourceItem(this, si, fileno, fileLineno, currLine, lj);
+    }
+  }
+
+  if (selected) item = selected;
+  if (item) first = item;
+  if (first) {
+      ensureItemVisible(first);
+      _inSelectionUpdate = true;
+      setCurrentItem(first);
+      _inSelectionUpdate = false;
+  }
+
+  file.close();
+
+  // for arrows: go down the list according to list sorting
+  sort();
+  TQListViewItem *item1, *item2;
+  for (item1=firstChild();item1;item1 = item1->nextSibling()) {
+      si = (SourceItem*)item1;
+      updateJumpArray(si->lineno(), si, true, false);
+
+      for (item2=item1->firstChild();item2;item2 = item2->nextSibling()) {
+	  si2 = (SourceItem*)item2;
+	  if (si2->lineJump())
+	      updateJumpArray(si->lineno(), si2, false, true);
+	  else
+	      si2->setJumpArray(_jump);
+      }
+  }
+
+  if (arrowLevels())
+      setColumnWidth(3, 10 + 6*arrowLevels() + itemMargin() * 2);
+  else
+      setColumnWidth(3, 0);
+}
+
+
+void SourceView::updateSourceItems()
+{
+    setColumnWidth(1, 50);
+    setColumnWidth(2, _costType2 ? 50:0);
+    // Allow resizing of column 2
+    setColumnWidthMode(2, TQListView::Maximum);
+    
+    if (_costType)
+      setColumnText(1, _costType->name());
+    if (_costType2)
+      setColumnText(2, _costType2->name());
+
+    SourceItem* si;
+    TQListViewItem* item  = firstChild();
+    for (;item;item = item->nextSibling()) {
+	si = (SourceItem*)item;
+	TraceLine* l = si->line();
+	if (!l) continue;
+
+	si->updateCost();
+
+	TQListViewItem *next, *i  = si->firstChild();
+	for (;i;i = next) {
+	    next = i->nextSibling();
+	    ((SourceItem*)i)->updateCost();
+	}
+    }
+
+    if (!_costType2) {
+      setColumnWidthMode(2, TQListView::Manual);
+      setColumnWidth(2, 0);
+    }
+}
+
+#include "sourceview.moc"
diff --git a/kdecachegrind/kdecachegrind/sourceview.h b/kdecachegrind/kdecachegrind/sourceview.h
new file mode 100644
index 0000000..b72fc7a
--- /dev/null
+++ b/kdecachegrind/kdecachegrind/sourceview.h
@@ -0,0 +1,71 @@
+/* This file is part of KCachegrind.
+   Copyright (C) 2003 Josef Weidendorfer <Josef.Weidendorfer@gmx.de>
+
+   KCachegrind 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, version 2.
+
+   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; see the file COPYING.  If not, write to
+   the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+   Boston, MA 02110-1301, USA.
+*/
+
+/*
+ * Source View
+ */
+
+#ifndef SOURCEVIEW_H
+#define SOURCEVIEW_H
+
+#include <tqlistview.h>
+#include "traceitemview.h"
+
+class SourceItem;
+
+class SourceView : public TQListView, public TraceItemView
+{
+  friend class SourceItem;
+
+  Q_OBJECT
+  TQ_OBJECT
+
+public:
+  SourceView(TraceItemView* parentView,
+            TQWidget* parent = 0, const char* name = 0);
+
+  TQWidget* widget() { return this; }
+  TQString whatsThis() const;
+
+protected:
+  int arrowLevels() { return _arrowLevels; }
+  void paintEmptyArea( TQPainter *, const TQRect & );
+
+private slots:
+  void context(TQListViewItem*, const TQPoint &, int);
+  void selectedSlot(TQListViewItem *);
+  void activatedSlot(TQListViewItem *);
+
+private:
+  TraceItem* canShow(TraceItem*);
+  void doUpdate(int);
+  void refresh();
+  void updateJumpArray(uint,SourceItem*,bool,bool);
+  void fillSourceFile(TraceFunctionSource*, int);
+  void updateSourceItems();
+
+  bool _inSelectionUpdate;
+
+  // arrows
+  int _arrowLevels;
+  // temporary needed on creation...
+  TQMemArray<TraceLineJump*> _jump;
+  TraceLineJumpList _lowList, _highList;
+};
+
+#endif
diff --git a/kdecachegrind/kdecachegrind/stackbrowser.cpp b/kdecachegrind/kdecachegrind/stackbrowser.cpp
new file mode 100644
index 0000000..78095eb
--- /dev/null
+++ b/kdecachegrind/kdecachegrind/stackbrowser.cpp
@@ -0,0 +1,417 @@
+/* This file is part of KCachegrind.
+   Copyright (C) 2003 Josef Weidendorfer <Josef.Weidendorfer@gmx.de>
+
+   KCachegrind 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, version 2.
+
+   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; see the file COPYING.  If not, write to
+   the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+   Boston, MA 02110-1301, USA.
+*/
+
+#include <tqlistview.h>
+
+#include "stackbrowser.h"
+
+// Stack
+
+Stack::Stack(TraceFunction* top, TraceCallList calls)
+{
+  _refCount = 0;
+  _top = top;
+  _calls = calls;
+
+  extendBottom();
+}
+
+Stack::Stack(TraceFunction* f)
+{
+  _refCount = 0;
+  _top = f;
+
+  extendBottom();
+  extendTop();
+}
+
+void Stack::extendBottom()
+{
+  TraceCallList l;
+  TraceCall *c,  *call;
+  SubCost most;
+  TraceFunction* f;
+
+  if (_calls.last())
+    f = _calls.last()->called();
+  else
+    f = _top;
+
+  if (!f) return;
+  // don't follow calls from cycles
+  if (f->cycle() == f) return;
+
+
+  int max = 30;
+
+  // try to extend to lower stack frames
+  while (f && (max-- >0)) {
+    l = f->callings();
+    call = 0;
+    most = 0;
+    for (c=l.first();c;c=l.next()) {
+	// no cycle calls in stack: could be deleted without notice
+	if (c->called()->cycle() == c->called()) continue;
+	// no simple recursions
+	if (c->called() == _top) continue;
+
+      if (c->called()->name().isEmpty()) continue;
+      SubCost sc = c->subCost(0); // FIXME
+      if (sc == 0) continue;
+
+      if (sc > most) {
+        most = sc;
+        call = c;
+      }
+    }
+    if (!call)
+      break;
+
+    _calls.append(call);
+    f = call->called();
+  }
+}
+
+
+void Stack::extendTop()
+{
+  TraceCallList l;
+  TraceCall *c,  *call;
+  SubCost most;
+
+  int max = 10;
+
+  // don't follow calls from cycles
+  if (_top->cycle() == _top) return;
+
+  // try to extend to upper stack frames
+  while (_top && (max-- >0)) {
+    l = _top->callers();
+    call = 0;
+    most = 0;
+    for (c=l.first();c;c=l.next()) {
+	// no cycle calls in stack: could be deleted without notice
+	if (c->caller()->cycle() == c->caller()) continue;
+	// no simple recursions
+	if (c->caller() == _top) continue;
+
+      if (c->caller()->name().isEmpty()) continue;
+      SubCost sc = c->subCost(0); // FIXME
+      if (sc == 0) continue;
+
+      if (sc > most) {
+        most = sc;
+        call = c;
+      }
+    }
+    if (!call)
+      break;
+
+    _calls.prepend(call);
+    _top = call->caller();
+  }
+}
+
+TraceFunction* Stack::caller(TraceFunction* fn, bool extend)
+{
+  TraceFunction* f;
+  TraceCall* c;
+
+  if (extend && (_top == fn)) {
+    // extend at top
+    extendTop();
+    f = _top;
+  }
+
+  for (c=_calls.first();c;c=_calls.next()) {
+    f = c->called();
+    if (f == fn)
+      return c->caller();
+  }
+  return 0;
+}
+
+TraceFunction* Stack::called(TraceFunction* fn, bool extend)
+{
+  TraceFunction* f;
+  TraceCall* c;
+
+  for (c=_calls.first();c;c=_calls.next()) {
+    f = c->caller();
+    if (f == fn)
+      return c->called();
+  }
+
+  if (extend && (c->called() == fn)) {
+    // extend at bottom
+    extendBottom();
+
+    // and search again
+    for (c=_calls.first();c;c=_calls.next()) {
+      f = c->caller();
+      if (f == fn)
+        return c->called();
+    }
+  }
+
+  return 0;
+}
+
+bool Stack::contains(TraceFunction* fn)
+{
+    // cycles are listed on there own
+    if (fn->cycle() == fn) return false;
+    if (_top->cycle() == _top) return false;
+
+  if (fn == _top)
+    return true;
+
+  TraceFunction* f = _top;
+  TraceCall* c;
+
+  for (c=_calls.first();c;c=_calls.next()) {
+    f = c->called();
+    if (f == fn)
+      return true;
+  }
+
+  TraceCallList l;
+
+  // try to extend at bottom (even if callCount 0)
+  l = f->callings();
+  for (c=l.first();c;c=l.next()) {
+    f = c->called();
+    if (f == fn)
+      break;
+  }
+
+  if (c) {
+    _calls.append(c);
+
+    // extend at bottom after found one
+    extendBottom();
+    return true;
+  }
+
+  // try to extend at top (even if callCount 0)
+  l = _top->callers();
+  for (c=l.first();c;c=l.next()) {
+    f = c->caller();
+    if (f == fn)
+      break;
+  }
+
+  if (c) {
+    _calls.prepend(c);
+
+    // extend at top after found one
+    extendTop();
+    return true;
+  }
+
+  return false;
+}
+
+Stack* Stack::split(TraceFunction* f)
+{
+  TraceCallList calls = _calls;
+  TraceCall *c, *c2;
+
+  // cycles are listed on there own
+  if (f->cycle() == f) return 0;
+  if (_top->cycle() == _top) return false;
+
+  for (c=calls.first();c;c=calls.next()) {
+    TraceCallList l = c->called()->callings();
+    for (c2=l.first();c2;c2=l.next()) {
+      if (c2 == c) continue;
+      if (c2->called() == f)
+        break;
+    }
+    if (c2)
+      break;
+  }
+
+  if (!c)
+    return 0;
+
+  // remove bottom part
+  calls.last();
+  while (calls.current() && calls.current()!=c)
+    calls.removeLast();
+
+  calls.append(c2);
+  return new Stack(_top, calls );
+}
+
+TQString Stack::toString()
+{
+  TQString res = _top->name();
+  TraceCall *c;
+  for (c=_calls.first();c;c=_calls.next())
+    res += "\n > " + c->called()->name();
+
+  return res;
+}
+
+
+// HistoryItem
+
+HistoryItem::HistoryItem(Stack* stack, TraceFunction* function)
+{
+  _stack = stack;
+  _function = function;
+  if (_stack)
+    _stack->ref();
+
+  _last = 0;
+  _next = 0;
+
+/*
+  qDebug("New Stack History Item (sRef %d): %s\n  %s",
+         _stack->refCount(), _function->name().ascii(),
+         _stack->toString().ascii());
+*/
+}
+
+HistoryItem::~HistoryItem()
+{
+  if (0) qDebug("Deleting Stack History Item (sRef %d): %s",
+         _stack->refCount(),
+         _function->name().ascii());
+
+  if (_last)
+    _last->_next = _next;
+  if (_stack) {
+    if (_stack->deref() == 0)
+      delete _stack;
+  }
+}
+
+
+// StackBrowser
+
+StackBrowser::StackBrowser()
+{
+  _current = 0;
+}
+
+StackBrowser::~StackBrowser()
+{
+  delete _current;
+}
+
+HistoryItem* StackBrowser::select(TraceFunction* f)
+{
+  if (!_current) {
+    Stack* s = new Stack(f);
+    _current = new HistoryItem(s, f);
+  }
+  else if (_current->function() != f) {
+    // make current item the last one
+    HistoryItem* item = _current;
+    if (item->next()) {
+      item = item->next();
+      item->last()->setNext(0);
+
+      while (item->next()) {
+        item = item->next();
+        delete item->last();
+      }
+      delete item;
+    }
+
+    Stack* s = _current->stack();
+    if (!s->contains(f)) {
+      s = s->split(f);
+      if (!s)
+        s = new Stack(f);
+    }
+
+    item = _current;
+    _current = new HistoryItem(s, f);
+    item->setNext(_current);
+    _current->setLast(item);
+  }
+
+  // qDebug("Selected %s in StackBrowser", f->name().ascii());
+
+  return _current;
+}
+
+HistoryItem* StackBrowser::goBack()
+{
+  if (_current && _current->last())
+    _current = _current->last();
+
+  return _current;
+}
+
+HistoryItem* StackBrowser::goForward()
+{
+  if (_current && _current->next())
+    _current = _current->next();
+
+  return _current;
+}
+
+HistoryItem* StackBrowser::goUp()
+{
+  if (_current) {
+    TraceFunction* f = _current->stack()->caller(_current->function(), true);
+    if (f)
+      _current = select(f);
+  }
+
+  return _current;
+}
+
+HistoryItem* StackBrowser::goDown()
+{
+  if (_current) {
+    TraceFunction* f = _current->stack()->called(_current->function(), true);
+    if (f)
+      _current = select(f);
+  }
+
+  return _current;
+}
+
+bool StackBrowser::canGoBack()
+{
+  return _current && _current->last();
+}
+
+bool StackBrowser::canGoForward()
+{
+  return _current && _current->next();
+}
+
+bool StackBrowser::canGoUp()
+{
+  if (!_current) return false;
+
+  return _current->stack()->caller(_current->function(), false);
+}
+
+bool StackBrowser::canGoDown()
+  {
+  if (!_current) return false;
+
+  return _current->stack()->called(_current->function(), false);
+}
diff --git a/kdecachegrind/kdecachegrind/stackbrowser.h b/kdecachegrind/kdecachegrind/stackbrowser.h
new file mode 100644
index 0000000..e7d6b80
--- /dev/null
+++ b/kdecachegrind/kdecachegrind/stackbrowser.h
@@ -0,0 +1,109 @@
+/* This file is part of KCachegrind.
+   Copyright (C) 2003 Josef Weidendorfer <Josef.Weidendorfer@gmx.de>
+
+   KCachegrind 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, version 2.
+
+   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; see the file COPYING.  If not, write to
+   the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+   Boston, MA 02110-1301, USA.
+*/
+
+#ifndef STACKBROWSER_H
+#define STACKBROWSER_H
+
+#include "tracedata.h"
+
+// A history of selected functions within stacks
+
+class Stack
+{
+public:
+  Stack(TraceFunction*);
+
+  // extend the stack at top/bottom if possible
+  bool contains(TraceFunction*);
+
+  void extendBottom();
+  void extendTop();
+
+  // search for a function on stack calling specified function.
+  // if found, return upper part with new function call
+  Stack* split(TraceFunction*);
+
+  // increment reference count
+  void ref() { _refCount++; }
+  // decrement reference count
+  bool deref() { return --_refCount; }
+  int refCount() { return _refCount; }
+
+  TraceFunction* top() { return _top; }
+  TraceCallList calls() { return _calls; }
+  TraceFunction* caller(TraceFunction*, bool extend);
+  TraceFunction* called(TraceFunction*, bool extend);
+
+  TQString toString();
+
+private:
+  Stack(TraceFunction* top, TraceCallList list);
+
+  // at the top of the stack we have a function...
+  TraceFunction* _top;
+  // list ordered from top to bottom
+  TraceCallList _calls;
+  int _refCount;
+};
+
+class HistoryItem
+{
+public:
+  HistoryItem(Stack*, TraceFunction*);
+  ~HistoryItem();
+
+  Stack* stack() { return _stack; }
+  TraceFunction* function() { return _function; }
+  HistoryItem* last() { return _last; }
+  HistoryItem* next() { return _next; }
+  void setLast(HistoryItem* h) { _last = h; }
+  void setNext(HistoryItem* h) { _next = h; }
+
+private:
+
+  HistoryItem *_last, *_next;
+  Stack* _stack;
+  TraceFunction* _function;
+};
+
+
+class StackBrowser
+{
+public:
+  StackBrowser();
+  ~StackBrowser();
+
+  // A function was selected. This creates a new history entry
+  HistoryItem* select(TraceFunction*);
+
+  HistoryItem* current() { return _current; }
+  bool canGoBack();
+  bool canGoForward();
+  bool canGoUp();
+  bool canGoDown();
+  HistoryItem* goBack();
+  HistoryItem* goForward();
+  HistoryItem* goUp();
+  HistoryItem* goDown();
+
+private:
+  HistoryItem* _current;
+};
+
+
+#endif
diff --git a/kdecachegrind/kdecachegrind/stackitem.cpp b/kdecachegrind/kdecachegrind/stackitem.cpp
new file mode 100644
index 0000000..e3763ab
--- /dev/null
+++ b/kdecachegrind/kdecachegrind/stackitem.cpp
@@ -0,0 +1,116 @@
+/* This file is part of KCachegrind.
+   Copyright (C) 2003 Josef Weidendorfer <Josef.Weidendorfer@gmx.de>
+
+   KCachegrind 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, version 2.
+
+   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; see the file COPYING.  If not, write to
+   the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+   Boston, MA 02110-1301, USA.
+*/
+
+/*
+ * Items of stack dockable.
+ */
+
+#include <tqpixmap.h>
+#include <klocale.h>
+
+#include "configuration.h"
+#include "listutils.h"
+#include "stackitem.h"
+#include "stackselection.h"
+
+// StackItem
+
+StackItem::StackItem(StackSelection* ss, 
+		     TQListView* parent, TraceFunction* f)
+  :TQListViewItem(parent)
+{
+  _view = ss;
+  _function = f;
+  _call = 0;
+
+  updateGroup();
+  updateCost();
+
+  setText(2, TQString("-- "));
+  setText(3, f->prettyName());
+}
+
+StackItem::StackItem(StackSelection* ss,
+		     TQListView* parent, TraceCall* call)
+  :TQListViewItem(parent)
+{
+  _view = ss;
+  _call = call;
+  _function = call->called();
+
+  updateGroup();
+  updateCost();
+
+  setText(3, _function->prettyName());
+}
+
+
+void StackItem::updateGroup()
+{
+  TQColor c = Configuration::functionColor(_view->groupType(),
+					  _function);
+  setPixmap(3, colorPixmap(10, 10, c));
+}
+
+void StackItem::updateCost()
+{
+  if (!_call) return;
+
+  setText(2, _call->prettyCallCount());
+
+  TraceCostType* ct = _view->costType();
+  _sum = _call->subCost(ct);
+  double total = _call->called()->data()->subCost(ct);
+  if (total == 0.0) {
+    setText(0, "-");
+    setPixmap(0, TQPixmap());
+  }
+  else {
+    double sum  = 100.0 * _sum / total;
+
+    if (Configuration::showPercentage())
+      setText(0, TQString("%1")
+	      .arg(sum, 0, 'f', Configuration::percentPrecision()));
+    else
+      setText(0, _call->prettySubCost(ct));
+    
+    setPixmap(0, costPixmap(ct, _call, total, false));
+  }
+
+  // if _costType2 is 0, column1 is hidden, no change needed
+  TraceCostType* ct2 = _view->costType2();
+  if (!ct2) return;
+
+  _sum = _call->subCost(ct2);
+  total = _call->called()->data()->subCost(ct2);
+  if (total == 0.0) {
+    setText(1, "-");
+    setPixmap(1, TQPixmap());
+  }
+  else {
+    double sum  = 100.0 * _sum / total;
+
+    if (Configuration::showPercentage())
+      setText(1, TQString("%1")
+	      .arg(sum, 0, 'f', Configuration::percentPrecision()));
+    else
+      setText(1, _call->prettySubCost(ct2));
+    
+    setPixmap(1, costPixmap(ct2, _call, total, false));
+  }
+}
diff --git a/kdecachegrind/kdecachegrind/stackitem.h b/kdecachegrind/kdecachegrind/stackitem.h
new file mode 100644
index 0000000..250e9f6
--- /dev/null
+++ b/kdecachegrind/kdecachegrind/stackitem.h
@@ -0,0 +1,56 @@
+/* This file is part of KCachegrind.
+   Copyright (C) 2003, 2004
+   Josef Weidendorfer <Josef.Weidendorfer@gmx.de>
+
+   KCachegrind 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, version 2.
+
+   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; see the file COPYING.  If not, write to
+   the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+   Boston, MA 02110-1301, USA.
+*/
+
+/*
+ * Items of stack dockable.
+ */
+
+#ifndef STACKITEM_H
+#define STACKITEM_H
+
+#include <tqlistview.h>
+#include "tracedata.h"
+
+class StackSelection;
+
+
+// for the stack browser
+
+class StackItem: public TQListViewItem
+{
+public:
+  // for top
+  StackItem(StackSelection* ss, TQListView* parent, TraceFunction* f);
+  StackItem(StackSelection* ss, TQListView* parent, TraceCall* c);
+
+  TraceFunction* function() { return _function; }
+  TraceCall* call() { return _call; }
+  void updateGroup();
+  void updateCost();
+
+private:
+  StackSelection* _view;
+  SubCost _sum;
+  TraceFunction* _function;
+  TraceCall* _call;
+};
+
+
+
+#endif
diff --git a/kdecachegrind/kdecachegrind/stackselection.cpp b/kdecachegrind/kdecachegrind/stackselection.cpp
new file mode 100644
index 0000000..5909475
--- /dev/null
+++ b/kdecachegrind/kdecachegrind/stackselection.cpp
@@ -0,0 +1,230 @@
+/* This file is part of KCachegrind.
+   Copyright (C) 2003 Josef Weidendorfer <Josef.Weidendorfer@gmx.de>
+
+   KCachegrind 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, version 2.
+
+   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; see the file COPYING.  If not, write to
+   the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+   Boston, MA 02110-1301, USA.
+*/
+
+/*
+ * StackSelection for KCachegrind
+ * For function selection of a most expected stack,
+ *  to be put into a TQDockWindow
+ */
+
+#include <tqtimer.h>
+#include <tqlistview.h>
+#include <tqlabel.h>
+#include <tqpushbutton.h>
+#include <tqcombobox.h>
+#include <tqlineedit.h>
+
+#include <kdebug.h>
+
+#include "stackbrowser.h"
+#include "stackselection.h"
+#include "stackitem.h"
+
+StackSelection::StackSelection( TQWidget* parent, const char* name)
+  : StackSelectionBase(parent, name)
+{
+  _data = 0;
+  _browser = new StackBrowser();
+  _item = 0;
+  _function = 0;
+  _costType = 0;
+  _costType2 = 0;
+  _groupType = TraceItem::Function;
+
+  stackList->setSorting(-1);
+  stackList->setAllColumnsShowFocus(true);
+  stackList->setResizeMode(TQListView::LastColumn);
+  stackList->setColumnAlignment(0, TQt::AlignRight);
+  stackList->setColumnAlignment(1, TQt::AlignRight);
+  stackList->setColumnAlignment(2, TQt::AlignRight);
+  stackList->setColumnWidth(0, 50);
+  // 2nd cost column hidden at first (_costType2 == 0)
+  stackList->setColumnWidth(1, 0);
+  stackList->setColumnWidth(2, 50);
+
+  connect(stackList, TQT_SIGNAL(selectionChanged(TQListViewItem*)),
+          this, TQT_SLOT(stackSelected(TQListViewItem*)));
+}
+
+StackSelection::~StackSelection()
+{
+  delete _browser;
+}
+
+void StackSelection::setData(TraceData* data)
+{
+  if (_data == data) return;
+
+  _data = data;
+
+  stackList->clear();
+   delete _browser;
+  _browser = new StackBrowser();
+  _function = 0;
+}
+
+
+void StackSelection::setFunction(TraceFunction* f)
+{
+  if (_function == f) return;
+  _function = f;
+
+  if (!_data || !_function) return;
+
+  //kdDebug() << "StackSelection::setFunction " << f->name() << endl;
+
+  HistoryItem* item = _browser->current();
+  if (!item || item->function() != f) {
+    _browser->select(f);
+    rebuildStackList();
+  }
+}
+
+
+void StackSelection::rebuildStackList()
+{
+  HistoryItem* item = _browser->current();
+  stackList->clear();
+  stackList->setColumnWidth(0, 50);
+  stackList->setColumnWidth(1, _costType2 ? 50:0);
+  stackList->setColumnWidth(2, 50);
+  if (!item || !item->stack()) return;
+
+  TraceFunction* top = item->stack()->top();
+  if (!top) return;
+
+  stackList->setColumnWidthMode(1, TQListView::Maximum);
+
+  TraceCallList l = item->stack()->calls();
+  TraceCall* call;
+  for (call=l.last();call;call=l.prev())
+    new StackItem(this, stackList, call);
+
+  new StackItem(this, stackList, top);
+
+  // select current function
+  TQListViewItem* i = stackList->firstChild();
+  for (;i;i=i->nextSibling())
+    if (((StackItem*)i)->function() == item->function())
+      break;
+
+  if (i) {
+    // this calls stackFunctionSelected()
+    stackList->setCurrentItem(i);
+    stackList->ensureItemVisible(i);
+  }
+
+  if (!_costType2) {
+    stackList->setColumnWidthMode(1, TQListView::Manual);
+    stackList->setColumnWidth(1, 0);
+  }
+}
+
+void StackSelection::stackSelected(TQListViewItem* i)
+{
+  if (!i) return;
+
+  TraceFunction* f = ((StackItem*)i)->function();
+  emit functionSelected(f);
+}
+
+
+void StackSelection::browserBack()
+{
+  if (_browser && _browser->canGoBack()) {
+    _browser->goBack();
+    rebuildStackList();
+  }
+}
+
+void StackSelection::browserForward()
+{
+  if (_browser && _browser->canGoForward()) {
+    _browser->goForward();
+    rebuildStackList();
+  }
+}
+
+void StackSelection::browserUp()
+{
+  if (_browser) {
+    _browser->goUp();
+    rebuildStackList();
+  }
+}
+
+void StackSelection::browserDown()
+{
+  if (_browser) {
+    _browser->goDown();
+    rebuildStackList();
+  }
+}
+
+void StackSelection::refresh()
+{
+  TQListViewItem* item  = stackList->firstChild();
+  for(;item;item = item->nextSibling())
+    ((StackItem*)item)->updateCost();
+}
+
+void StackSelection::setCostType(TraceCostType* ct)
+{
+  if (ct == _costType) return;
+  _costType = ct;
+
+  stackList->setColumnWidth(0, 50);
+  if (_costType)
+    stackList->setColumnText(0, _costType->name());
+
+  TQListViewItem* item  = stackList->firstChild();
+  for(;item;item = item->nextSibling())
+    ((StackItem*)item)->updateCost();
+}
+
+void StackSelection::setCostType2(TraceCostType* ct)
+{
+  if (ct == _costType2) return;
+  _costType2 = ct;
+
+  stackList->setColumnWidth(1, 50);
+  stackList->setColumnWidthMode(1, TQListView::Maximum);
+  if (_costType2)
+    stackList->setColumnText(1, _costType2->name());
+
+  TQListViewItem* item  = stackList->firstChild();
+  for(;item;item = item->nextSibling())
+    ((StackItem*)item)->updateCost();
+
+  if (!_costType2) {
+    stackList->setColumnWidthMode(1, TQListView::Manual);
+    stackList->setColumnWidth(1, 0);
+  }
+}
+
+void StackSelection::setGroupType(TraceItem::CostType gt)
+{
+  if (_groupType == gt) return;
+  _groupType = gt;
+
+  TQListViewItem* item  = stackList->firstChild();
+  for(;item;item = item->nextSibling())
+    ((StackItem*)item)->updateGroup();
+}
+
+#include "stackselection.moc"
diff --git a/kdecachegrind/kdecachegrind/stackselection.h b/kdecachegrind/kdecachegrind/stackselection.h
new file mode 100644
index 0000000..2bb3a75
--- /dev/null
+++ b/kdecachegrind/kdecachegrind/stackselection.h
@@ -0,0 +1,81 @@
+/* This file is part of KCachegrind.
+   Copyright (C) 2003 Josef Weidendorfer <Josef.Weidendorfer@gmx.de>
+
+   KCachegrind 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, version 2.
+
+   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; see the file COPYING.  If not, write to
+   the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+   Boston, MA 02110-1301, USA.
+*/
+
+/*
+ * StackSelection for KCachegrind
+ * For function selection of a most expected stack,
+ *  to be put into a TQDockWindow
+ */
+
+#ifndef STACKSELECTION_H
+#define STACKSELECTION_H
+
+#include "stackselectionbase.h"
+#include "tracedata.h"
+
+class TraceFunction;
+class TraceData;
+class StackBrowser;
+class NestedAreaItem;
+
+class StackSelection : public StackSelectionBase
+{
+  Q_OBJECT
+  TQ_OBJECT
+
+public:
+  StackSelection( TQWidget* parent = 0, const char* name = 0);
+  ~StackSelection();
+
+  TraceData* data() const { return _data; }
+  void setData(TraceData*);
+  StackBrowser* browser() const { return _browser; }
+  TraceCostType* costType() { return _costType; }
+  TraceCostType* costType2() { return _costType2; }
+  TraceItem::CostType groupType() { return _groupType; }
+
+signals:
+  void functionSelected(TraceItem*);
+
+public slots:
+  void setFunction(TraceFunction*);
+  void setCostType(TraceCostType*);
+  void setCostType2(TraceCostType*);
+  void setGroupType(TraceItem::CostType);
+
+  void stackSelected( TQListViewItem* );
+  void browserBack();
+  void browserForward();
+  void browserUp();
+  void browserDown();
+  void refresh();
+  void rebuildStackList();
+
+private:
+  void selectFunction();
+
+  TraceData* _data;
+  StackBrowser* _browser;
+  TQListViewItem* _item;
+  TraceFunction* _function;
+  TraceCostType* _costType;
+  TraceCostType* _costType2;
+  TraceItem::CostType _groupType;
+};
+
+#endif
diff --git a/kdecachegrind/kdecachegrind/stackselectionbase.ui b/kdecachegrind/kdecachegrind/stackselectionbase.ui
new file mode 100644
index 0000000..c61010f
--- /dev/null
+++ b/kdecachegrind/kdecachegrind/stackselectionbase.ui
@@ -0,0 +1,80 @@
+<!DOCTYPE UI><UI version="3.0" stdsetdef="1">
+<class>StackSelectionBase</class>
+<widget class="TQWidget">
+    <property name="name">
+        <cstring>StackSelectionBase</cstring>
+    </property>
+    <property name="geometry">
+        <rect>
+            <x>0</x>
+            <y>0</y>
+            <width>168</width>
+            <height>108</height>
+        </rect>
+    </property>
+    <property name="caption">
+        <string>Stack Selection</string>
+    </property>
+    <vbox>
+        <property name="name">
+            <cstring>unnamed</cstring>
+        </property>
+        <property name="margin">
+            <number>3</number>
+        </property>
+        <property name="spacing">
+            <number>6</number>
+        </property>
+        <widget class="TQListView">
+            <column>
+                <property name="text">
+                    <string>Cost</string>
+                </property>
+                <property name="clickable">
+                    <bool>true</bool>
+                </property>
+                <property name="resizeable">
+                    <bool>true</bool>
+                </property>
+            </column>
+            <column>
+                <property name="text">
+                    <string>Cost2</string>
+                </property>
+                <property name="clickable">
+                    <bool>true</bool>
+                </property>
+                <property name="resizeable">
+                    <bool>true</bool>
+                </property>
+            </column>
+            <column>
+                <property name="text">
+                    <string>Calls</string>
+                </property>
+                <property name="clickable">
+                    <bool>true</bool>
+                </property>
+                <property name="resizeable">
+                    <bool>true</bool>
+                </property>
+            </column>
+            <column>
+                <property name="text">
+                    <string>Function</string>
+                </property>
+                <property name="clickable">
+                    <bool>true</bool>
+                </property>
+                <property name="resizeable">
+                    <bool>true</bool>
+                </property>
+            </column>
+            <property name="name">
+                <cstring>stackList</cstring>
+            </property>
+        </widget>
+    </vbox>
+</widget>
+<layoutdefaults spacing="6" margin="11"/>
+</UI>
diff --git a/kdecachegrind/kdecachegrind/subcost.cpp b/kdecachegrind/kdecachegrind/subcost.cpp
new file mode 100644
index 0000000..7b5034e
--- /dev/null
+++ b/kdecachegrind/kdecachegrind/subcost.cpp
@@ -0,0 +1,62 @@
+/* This file is part of KCachegrind.
+   Copyright (C) 2004 Josef Weidendorfer <Josef.Weidendorfer@gmx.de>
+
+   KCachegrind 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, version 2.
+
+   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; see the file COPYING.  If not, write to
+   the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+   Boston, MA 02110-1301, USA.
+*/
+
+#include <tqstring.h>
+
+#include "subcost.h"
+
+//---------------------------------------------------
+// SubCost
+
+bool SubCost::set(const char** ps)
+{
+    const char* s = *ps;
+    if (!s || (*s < '0') || (*s > '9')) return false;
+
+    v = *s - '0';
+    s++;
+    while(*s >= '0' && *s <= '9') {
+	v = 10* v + (*s-'0');
+	s++;
+    }
+    while(*s == ' ') s++;
+    *ps = s;
+
+    return true;
+}
+
+TQString SubCost::pretty()
+{
+    unsigned long long n = v;
+
+    if (n==0) return TQString(" 0");
+
+    int i = 0;
+    TQString res = "";
+
+    while (n) {
+	if ((i>0) && !(i%3)) res = " " + res;
+	i++;
+	res = TQChar('0'+int(n%10)) + res;
+	n /= 10;
+    }
+    res = " " + res;
+    return res;
+}
+
+
diff --git a/kdecachegrind/kdecachegrind/subcost.h b/kdecachegrind/kdecachegrind/subcost.h
new file mode 100644
index 0000000..8169280
--- /dev/null
+++ b/kdecachegrind/kdecachegrind/subcost.h
@@ -0,0 +1,66 @@
+/* This file is part of KCachegrind.
+   Copyright (C) 2002-2004 Josef Weidendorfer <Josef.Weidendorfer@gmx.de>
+
+   KCachegrind 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, version 2.
+
+   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; see the file COPYING.  If not, write to
+   the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+   Boston, MA 02110-1301, USA.
+*/
+
+#ifndef SUBCOST_H
+#define SUBCOST_H
+
+#include "utils.h"
+
+typedef unsigned long long uint64;
+
+/**
+ * Cost event counter, simple wrapper around a 64bit entity
+ */
+class SubCost
+{
+ public:
+    SubCost() {}
+    SubCost(uint64 i) { v=i; }
+    SubCost(unsigned i) { v=i; }
+    SubCost(int i) { v=(unsigned)i; }
+    SubCost(double d) { v= (uint64)(d + .5); }
+
+    SubCost& operator=(uint64 i) { v = i; return *this; }
+    SubCost& operator=(unsigned i) { v = i; return *this; }
+    SubCost& operator=(int i) { v = i; return *this; }
+    SubCost& operator=(double d) { v = (uint64)(d + .5); return *this; }
+
+    bool set(const char** s);
+    bool set(FixString& s) { return s.stripUInt64(v); }
+
+    operator uint64&() { return v; }
+
+    bool operator==(unsigned i) const { return v == i; }
+    bool operator==(int i) const { return v == (unsigned)i; }
+    bool operator<(unsigned i) const { return v < i; }
+    bool operator<(int i) const { return v < (unsigned)i; }
+    bool operator<(const SubCost& s) const { return v < s.v; }
+    bool operator>(unsigned i) const { return v > i; }
+    bool operator>(int i) const { return v > (unsigned)i; }
+    bool operator>(const SubCost& s) const { return v > s.v; }
+
+    /**
+     * Convert SubCost value into a TQString,
+     * spaced every 3 digits.
+     */
+    TQString pretty();
+
+    uint64 v;
+};
+
+#endif
diff --git a/kdecachegrind/kdecachegrind/tabview.cpp b/kdecachegrind/kdecachegrind/tabview.cpp
new file mode 100644
index 0000000..0049d1e
--- /dev/null
+++ b/kdecachegrind/kdecachegrind/tabview.cpp
@@ -0,0 +1,890 @@
+/* This file is part of KCachegrind.
+   Copyright (C) 2003 Josef Weidendorfer <Josef.Weidendorfer@gmx.de>
+
+   KCachegrind 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, version 2.
+
+   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; see the file COPYING.  If not, write to
+   the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+   Boston, MA 02110-1301, USA.
+*/
+
+/*
+ * Tab View, enclosing detailed views for one trace item in
+ * two tab widgets, separated by a splitter
+ */
+
+#include <tqobjectlist.h>
+#include <tqsplitter.h>
+#include <tqtabwidget.h>
+#include <tqlayout.h>
+#include <tqwhatsthis.h>
+#include <tqpopupmenu.h>
+
+#include <klocale.h>
+#include <kconfig.h>
+
+#include "tabview.h"
+#include "costtypeview.h"
+#include "partview.h"
+#include "callview.h"
+#include "coverageview.h"
+#include "callmapview.h"
+#include "instrview.h"
+#include "sourceview.h"
+#include "callgraphview.h"
+
+// TabBar
+
+TabBar::TabBar(TabView* v, TQTabWidget* parent, const char *name)
+    : TQTabBar(parent, name)
+{
+    _tabWidget = parent;
+    _tabView = v;
+}
+
+void TabBar::mousePressEvent(TQMouseEvent *e)
+{
+  if (e->button() == Qt::RightButton) {
+      TQTab *tab = selectTab( e->pos() );
+      TQWidget* page;
+      page = tab ? _tabWidget->page( indexOf( tab->identifier() ) ) :0;
+
+      TQPopupMenu popup, popup1, popup2, popup3;
+      if (page) {
+        TraceItemView::Position p = _tabView->tabPosition(page);
+        if (p != TraceItemView::Top) {
+          popup.insertItem(i18n("Move to Top"), 81);
+          popup2.insertItem(i18n("Top"), 91);
+        }
+        if (p != TraceItemView::Right) {
+          popup.insertItem(i18n("Move to Right"), 82);
+          popup2.insertItem(i18n("Right"), 92);
+        }
+        if (p != TraceItemView::Bottom) {
+          popup.insertItem(i18n("Move to Bottom"), 83);
+          popup2.insertItem(i18n("Bottom"), 93);
+        }
+        if (p != TraceItemView::Left) {
+          popup.insertItem(i18n("Move to Bottom Left"), 84);
+          popup2.insertItem(i18n("Bottom Left"), 94);
+        }
+        popup.insertItem(i18n("Move Area To"), &popup2, 2);
+        popup.insertSeparator();
+        popup.insertItem(i18n("Hide This Tab"), 80);
+        popup.insertItem(i18n("Hide Area"), 90);
+
+        if (_tabView->visibleTabs() <2) {
+          popup.setItemEnabled(80, false);
+          popup.setItemEnabled(90, false);
+        }
+        else if (_tabView->visibleAreas() <2)
+          popup.setItemEnabled(90, false);
+      }
+      popup3.insertItem(i18n("Top"), 101);
+      popup3.insertItem(i18n("Right"), 102);
+      popup3.insertItem(i18n("Bottom"), 103);
+      popup3.insertItem(i18n("Bottom Left"), 104);
+      popup.insertItem(i18n("Show Hidden On"), &popup3, 3);
+
+      int r = popup.exec( mapToGlobal( e->pos() ) );
+
+      TraceItemView::Position p = TraceItemView::Hidden;
+      if ((r % 10) == 1) p = TraceItemView::Top;
+      if ((r % 10) == 2) p = TraceItemView::Right;
+      if ((r % 10) == 3) p = TraceItemView::Bottom;
+      if ((r % 10) == 4) p = TraceItemView::Left;
+
+      if (r>=80 && r<100) _tabView->moveTab(page, p, r>=90);
+      if (r>=100 && r<110) _tabView->moveTab(0, p, true);
+  }
+
+  TQTabBar::mousePressEvent( e );
+}
+
+
+//
+// Splitter
+//
+
+Splitter::Splitter(Qt::Orientation o, TQWidget* parent, const char* name)
+  : TQSplitter(o, parent, name)
+{}
+
+void Splitter::moveEvent(TQMoveEvent* e)
+{
+  TQSplitter::moveEvent(e);
+
+  if (0) qDebug("Splitter %s: Move", name());
+  checkVisiblity();
+}
+
+void Splitter::checkVisiblity()
+{
+  const TQObjectList l = childrenListObject();
+  TQObjectListIt it( l );
+  TQObject *obj;
+  while ( (obj = it.current()) != 0 ) {
+    ++it;
+    if (obj->isA("Splitter")) ((Splitter*)obj)->checkVisiblity();
+    else if (obj->isA("TabWidget")) ((TabWidget*)obj)->checkVisibility();
+  }
+}
+
+
+
+
+//
+// TabWidget
+//
+
+TabWidget::TabWidget(TabView* v, TQWidget* parent,
+                     const char* name, WFlags f)
+    : TQTabWidget(parent, name, f)
+{
+    _hasVisibleRect = false;
+    setTabBar(new TabBar(v, this));
+}
+
+void TabWidget::checkVisibility()
+{
+  bool hasVisibleRect = (visibleRect().width()>1) &&
+                        (visibleRect().height()>1);
+
+  if (0) qDebug("TabWidget %s: VR (%dx%d) HasVisibleRect: %s => %s",
+                name(),
+                visibleRect().width(), visibleRect().height(),
+                _hasVisibleRect ? "Yes":"No",
+                hasVisibleRect ? "Yes":"No");
+
+  if (hasVisibleRect != _hasVisibleRect) {
+    _hasVisibleRect = hasVisibleRect;
+    emit visibleRectChanged(this);
+  }
+}
+
+void TabWidget::resizeEvent(TQResizeEvent *e)
+{
+  TQTabWidget::resizeEvent(e);
+  if (0) qDebug("TabWidget %s:\n  Resize from (%d/%d) to (%d/%d)",
+                name(),
+                e->oldSize().width(), e->oldSize().height(),
+                e->size().width(), e->size().height());
+  checkVisibility();
+}
+
+void TabWidget::showEvent(TQShowEvent* e)
+{
+  TQTabWidget::showEvent(e);
+
+  if (0) qDebug("TabWidget %s: Show", name());
+  checkVisibility();
+}
+
+void TabWidget::hideEvent(TQHideEvent* e)
+{
+  TQTabWidget::hideEvent(e);
+
+  if (0) qDebug("TabWidget %s: Hide", name());
+  checkVisibility();
+}
+
+void TabWidget::moveEvent(TQMoveEvent* e)
+{
+  TQTabWidget::moveEvent(e);
+
+  if (0) qDebug("TabWidget %s: Move", name());
+  checkVisibility();
+}
+
+
+
+//
+// TabView
+//
+
+/*
+ * Areas for child views
+ *
+ * leftSplitter
+ * |
+ * |    -----                 -----
+ * |  _/     \_______________/     \____
+ * |  | Top                 | TopRight |
+ * |  |                     |          |
+ * -> |---------------------|          |
+ *    | BottomLeft | Bottom |          |
+ *    |            |        |          |
+ *    -\_____/------\____/--------------
+ *
+ *                 ^        ^
+ *      bottomSplitter    mainSplitter
+ */
+
+TabView::TabView(TraceItemView* parentView,
+                 TQWidget* parent, const char* name)
+  : TQWidget(parent, name), TraceItemView(parentView)
+{
+    setFocusPolicy(TQ_StrongFocus);
+
+  _isCollapsed = true;
+
+  TQVBoxLayout* vbox = new TQVBoxLayout( this, 6, 6);
+
+  _nameLabel = new KSqueezedTextLabel( this, "nameLabel" );
+  _nameLabel->setText(i18n("(No profile data file loaded)"));
+  vbox->addWidget( _nameLabel );
+
+  _mainSplitter   = new TQSplitter(Qt::Horizontal, this);
+  _leftSplitter   = new Splitter(Qt::Vertical, _mainSplitter, "Left");
+  vbox->addWidget( _mainSplitter );
+
+  _rightTW = new TabWidget(this, _mainSplitter, "Right");
+  connect(_rightTW, TQT_SIGNAL(currentChanged(TQWidget*)),
+          this, TQT_SLOT(tabChanged(TQWidget*)));
+  connect(_rightTW, TQT_SIGNAL(visibleRectChanged(TabWidget*)),
+          this, TQT_SLOT(visibleRectChangedSlot(TabWidget*)));
+
+  _topTW = new TabWidget(this, _leftSplitter, "Top");
+  connect(_topTW, TQT_SIGNAL(currentChanged(TQWidget*)),
+          this, TQT_SLOT(tabChanged(TQWidget*)));
+  connect(_topTW, TQT_SIGNAL(visibleRectChanged(TabWidget*)),
+          this, TQT_SLOT(visibleRectChangedSlot(TabWidget*)));
+
+  _bottomSplitter = new Splitter(Qt::Horizontal,
+                                  _leftSplitter, "Bottom");
+
+  _leftTW = new TabWidget(this, _bottomSplitter, "Left");
+  _leftTW->setTabPosition(TQTabWidget::Bottom);
+  connect(_leftTW, TQT_SIGNAL(currentChanged(TQWidget*)),
+          this, TQT_SLOT(tabChanged(TQWidget*)));
+  connect(_leftTW, TQT_SIGNAL(visibleRectChanged(TabWidget*)),
+          this, TQT_SLOT(visibleRectChangedSlot(TabWidget*)));
+
+  _bottomTW = new TabWidget(this, _bottomSplitter, "Bottom");
+  _bottomTW->setTabPosition(TQTabWidget::Bottom);
+  connect(_bottomTW, TQT_SIGNAL(currentChanged(TQWidget*)),
+          this, TQT_SLOT(tabChanged(TQWidget*)));
+  connect(_bottomTW, TQT_SIGNAL(visibleRectChanged(TabWidget*)),
+          this, TQT_SLOT(visibleRectChangedSlot(TabWidget*)));
+
+
+  // default positions...
+
+  addTop( addTab( i18n("Types"),
+		  new CostTypeView(this, _topTW,
+				   "CostTypeView")));
+  addTop( addTab( i18n("Callers"),
+		  new CallView(true, this, _topTW,
+			       "CallerView")));
+  addTop( addTab( i18n("All Callers"),
+		  new CoverageView(true, this, _topTW,
+				   "AllCallerView")));
+  addTop( addTab( i18n("Caller Map"),
+		  new CallMapView(true, this, _bottomTW,
+				  "CallerMapView")));
+  addTop( addTab( i18n("Source"),
+		  new SourceView(this, _topTW,
+				 "SourceView")));
+
+  addBottom( addTab( i18n("Parts"),
+		     new PartView(this, _bottomTW,
+				  "PartView")));
+  addBottom( addTab( i18n("Call Graph"),
+		     new CallGraphView(this, _bottomTW,
+				       "CallGraphView")));
+  addBottom( addTab( i18n("Callees"),
+		     new CallView(false, this, _bottomTW,
+				  "CalleeView")));
+  addBottom( addTab( i18n("All Callees"),
+		     new CoverageView(false, this, _bottomTW,
+				      "AllCalleeView")));
+
+  addBottom( addTab( i18n("Callee Map"),
+		     new CallMapView(false, this, _topTW,
+				     "CalleeMapView")));
+  addBottom( addTab( i18n("Assembler"),
+		     new InstrView(this, _bottomTW,
+				   "InstrView")));
+
+  // after all child widgets are created...
+  _lastFocus = 0;
+  _active = false;
+  installFocusFilters();
+
+  updateVisibility();
+
+  TQWhatsThis::add( this, whatsThis() );
+}
+
+void TabView::setData(TraceData* d)
+{
+  TraceItemView::setData(d);
+
+  TraceItemView* v;
+  for (v=_tabs.first();v;v=_tabs.next())
+    v->setData(d);  
+}
+
+TraceItemView* TabView::addTab(TQString label, TraceItemView* view)
+{
+    view->setTitle(label);
+    _tabs.append(view);
+    return view;
+}
+
+void TabView::addTop(TraceItemView* view)
+{
+  view->setPosition(TraceItemView::Top);
+  _topTW->insertTab(view->widget(), view->title());
+}
+
+void TabView::addBottom(TraceItemView* view)
+{
+  view->setPosition(TraceItemView::Bottom);
+  _bottomTW->insertTab(view->widget(), view->title());
+}
+
+TraceItemView::Position TabView::tabPosition(TQWidget* w)
+{
+  TraceItemView* v;
+  for (v=_tabs.first();v;v=_tabs.next())
+    if (v->widget() == w) return v->position();
+
+  return Hidden;
+}
+
+int TabView::visibleTabs()
+{
+  int c = 0;
+  TraceItemView* v;
+  for (v=_tabs.first();v;v=_tabs.next()) {
+    if (v->position() == Hidden) continue;
+    c++;
+  }
+  return c;
+}
+
+
+int TabView::visibleAreas()
+{
+  int c = 0, t = 0, b = 0, r = 0, l = 0;
+  TraceItemView* v;
+  for (v=_tabs.first();v;v=_tabs.next()) {
+    switch(v->position()) {
+    case TraceItemView::Top:    t++; break;
+    case TraceItemView::Bottom: b++; break;
+    case TraceItemView::Left:   l++; break;
+    case TraceItemView::Right:  r++; break;
+    default: break;
+    }
+  }
+  if (t>0) c++;
+  if (b>0) c++;
+  if (l>0) c++;
+  if (r>0) c++;
+
+  return c;
+}
+
+
+
+// This hides/shows splitters and tabwidgets according to tab childs
+void TabView::updateVisibility()
+{
+  // calculate count of tabs in areas
+  int t = 0, b = 0, r = 0, l = 0;
+  TraceItemView* v;
+  for (v=_tabs.first();v;v=_tabs.next()) {
+    switch(v->position()) {
+    case TraceItemView::Top:    t++; break;
+    case TraceItemView::Bottom: b++; break;
+    case TraceItemView::Left:   l++; break;
+    case TraceItemView::Right:  r++; break;
+    default: break;
+    }
+  }
+
+  if (0) qDebug("TabView::updateVisiblity t %d, b %d, l %d, r %d",
+		t, b, l, r);
+
+  TQValueList<int> s;
+  s.append(100);
+
+
+  // children of mainSplitter
+  if (_rightTW->isHidden() != (r == 0)) {
+    if (r == 0) {
+      _rightTW->hide();
+
+      if (!_topTW->hasVisibleRect() &&
+          !_bottomTW->hasVisibleRect() &&
+          !_leftTW->hasVisibleRect())  _mainSplitter->setSizes(s);
+    }
+    else
+      _rightTW->show();
+  }
+  if (_leftSplitter->isHidden() != (t+b+l == 0)) {
+    if (t+b+l == 0) {
+      _leftSplitter->hide();
+
+      if (!_rightTW->hasVisibleRect()) _mainSplitter->setSizes(s);
+    }
+    else
+      _leftSplitter->show();
+  }
+
+  // children of leftSplitter
+  if (_topTW->isHidden() != (t == 0)) {
+    if (t == 0) {
+      _topTW->hide();
+
+      if (!_bottomTW->hasVisibleRect() &&
+          !_leftTW->hasVisibleRect()) _leftSplitter->setSizes(s);
+    }
+    else
+      _topTW->show();
+  }
+
+  if (_bottomSplitter->isHidden() != (b+l == 0)) {
+    if (b+l == 0) {
+      _bottomSplitter->hide();
+
+      if (!_topTW->hasVisibleRect()) _leftSplitter->setSizes(s);
+    }
+    else
+      _bottomSplitter->show();
+  }
+
+  // children of bottomSplitter
+  if (_bottomTW->isHidden() != (b == 0)) {
+    if (b == 0) {
+      _bottomTW->hide();
+
+      if (!_leftTW->hasVisibleRect()) _bottomSplitter->setSizes(s);
+    }
+    else
+      _bottomTW->show();
+  }
+  if (_leftTW->isHidden() != (l == 0)) {
+    if (l == 0) {
+      _leftTW->hide();
+
+      if (!_bottomTW->hasVisibleRect()) _bottomSplitter->setSizes(s);
+    }
+    else
+      _leftTW->show();
+  }
+}
+
+TabWidget* TabView::tabWidget(Position p)
+{
+  switch(p) {
+  case TraceItemView::Top:    return _topTW;
+  case TraceItemView::Bottom: return _bottomTW;
+  case TraceItemView::Left:   return _leftTW;
+  case TraceItemView::Right:  return _rightTW;
+  default: break;
+  }
+  return 0;
+}
+
+void TabView::moveTab(TQWidget* w, Position p, bool wholeArea)
+{
+    TraceItemView *v;
+    Position origPos = Hidden;
+    if (w) {
+      for (v=_tabs.first();v;v=_tabs.next())
+        if (v->widget() == w) break;
+
+      if (!v) return;
+      origPos = v->position();
+    }
+    if (origPos == p) return;
+
+    TabWidget *from, *to;
+    from = tabWidget(origPos);
+    to = tabWidget(p);
+
+    TQPtrList<TraceItemView> tabs;
+    for (v=_tabs.first();v;v=_tabs.next())
+      if ((v->position() == origPos) &&
+          (wholeArea || (v->widget() == w))) tabs.append(v);
+
+    bool isEnabled;
+    for (v=tabs.first();v;v=tabs.next()) {
+      v->setPosition(p);
+      w = v->widget();
+
+      if (from) {
+        isEnabled = from->isTabEnabled(w);
+        from->removePage(w);
+      }
+      else isEnabled = (v->canShow(_activeItem)!=0);
+
+      if (to) {
+        TraceItemView *vv;
+        int idx = -1, i;
+        for(vv = _tabs.first(); vv && (vv!=v); vv = _tabs.next()) {
+          i = to->indexOf(vv->widget());
+          if (i>=0) idx = i;
+        }
+        to->insertTab(w, v->title(), idx+1);
+        to->setTabEnabled(w, isEnabled);
+        if (isEnabled) {
+          to->showPage(w);
+          v->updateView();
+        }
+      }
+    }
+    updateVisibility();
+}
+
+
+TQString TabView::whatsThis() const
+{
+    return i18n( "<b>Information Tabs</b>"
+		 "<p>This widget shows information for the "
+		 "current selected function in different tabs: "
+		 "<ul>"
+		 "<li>The Costs tab shows a list of available event types "
+		 "and the inclusive and self costs regarding to these types.</li>"
+		 "<li>The Parts tab shows a list of trace parts "
+		 "if the trace consists of more than one part (otherwise, "
+		 "this tab is hided). "
+		 "The cost of the selected function spent in the different "
+		 "parts together with the calls happening is shown.</li>"
+		 "<li>The Call Lists tab shows direct callers and "
+		 "callees of the function in more detail.</li>"
+		 "<li>The Coverage tab shows the same is the Call "
+		 "Lists tab, but not only direct callers and callees "
+		 "but also indirect ones.</li>"
+		 "<li>The Call Graph tab shows a graphical "
+		 "visualization of the calls done by this function.</li>"
+		 "<li>The Source tab presents annotated source code "
+		 "if debugging information and the source file "
+		 "is available.</li>"
+		 "<li>The Assembler tab presents annotated assembler code "
+		 "if trace information on instruction level "
+		 "is available.</li></ul>"
+		 "For more information, see the <em>What's This?</em> "
+		 "help of the corresponding tab widget</p>");
+}
+
+void TabView::installFocusFilters()
+{
+    TQObjectList *l = queryList(TQWIDGET_OBJECT_NAME_STRING);
+    TQObjectListIt it( *l );
+    TQObject *obj;
+
+    while ( (obj = it.current()) != 0 ) {
+        ++it;
+	if ( ((TQWidget*)obj)->isFocusEnabled() )
+	    obj->installEventFilter(this);
+    }
+    delete l;
+}
+
+
+bool TabView::eventFilter(TQObject* o, TQEvent* e)
+{
+    if (e->type() == TQEvent::FocusIn) {
+	_lastFocus = o->isWidgetType() ? (TQWidget*) o : 0;
+	setActive(_lastFocus != 0);
+    }
+    return TQWidget::eventFilter(o,e);
+}
+
+void TabView::mousePressEvent(TQMouseEvent*)
+{
+    if (_lastFocus)
+	_lastFocus->setFocus();
+    setActive(true);
+}
+
+void TabView::setActive(bool a)
+{
+    if (a == _active) return;
+    _active = a;
+
+    TQFont nameLabel_font(  _nameLabel->font() );
+    nameLabel_font.setBold(a);
+    _nameLabel->setFont( nameLabel_font );
+
+    if (0) qDebug("%s::setActive(%s)", name(), a ? "true":"false");
+
+    if (a) emit activated(this);
+}
+
+void TabView::doUpdate(int changeType)
+{
+    if (changeType & (activeItemChanged | configChanged | dataChanged))
+
+	_nameLabel->setText( !_data ? i18n("(No Data loaded)") :
+			     !_activeItem ? i18n("(No function selected)") :
+			     _activeItem->prettyName());
+
+
+    // we use our own list iterators because setTabEnabled can
+    // invoke tabChanged, which mangles with the lists, too
+    bool canShow;
+    TraceItemView *v;
+    TQPtrListIterator<TraceItemView> it( _tabs );
+    while ( (v=it.current()) != 0) {
+      ++it;
+
+      TabWidget *tw = 0;
+      switch(v->position()) {
+      case TraceItemView::Top:    tw = _topTW; break;
+      case TraceItemView::Bottom: tw = _bottomTW; break;
+      case TraceItemView::Left:   tw = _leftTW; break;
+      case TraceItemView::Right:  tw = _rightTW; break;
+      default: break;
+      }
+
+      // update even if hidden
+      if (tw) {
+        if (!tw->hasVisibleRect()) continue;
+      }
+      canShow = v->set(changeType, _data, _costType, _costType2,
+		       _groupType, _partList,
+                       _activeItem, _selectedItem);
+      v->notifyChange(changeType);
+
+      if (!tw) continue;
+      if (tw->isTabEnabled(v->widget()) != canShow)
+        tw->setTabEnabled(v->widget(), canShow);
+
+      if (v->widget() == tw->currentPage())
+        v->updateView();
+    }
+}
+
+
+void TabView::tabChanged(TQWidget* w)
+{
+  TraceItemView *v;
+  for (v=_tabs.first();v;v=_tabs.next())
+    if (v->widget() == w) v->updateView();
+}
+
+void TabView::visibleRectChangedSlot(TabWidget* tw)
+{
+  if (0) qDebug("%s: %svisible !",
+                tw->name(), tw->hasVisibleRect() ? "":"un");
+
+  if (tw->hasVisibleRect()) doUpdate(0);
+}
+
+void TabView::resizeEvent(TQResizeEvent* e)
+{
+  TQWidget::resizeEvent(e);
+
+  bool collapsed = (e->size().width()<=1) || (e->size().height()<=1);
+  if (_isCollapsed != collapsed) {
+    _isCollapsed = collapsed;
+    updateView();
+  }
+
+  if (0) qDebug("TabView::Resize from (%d/%d) to (%d/%d)",
+         e->oldSize().width(), e->oldSize().height(),
+         e->size().width(), e->size().height());
+}
+
+void TabView::selected(TraceItemView*, TraceItem* s)
+{
+    // we set selected item for our own children
+    select(s);
+    updateView();
+
+    // still forward to parent
+    if (_parentView) _parentView->selected(this, s);
+}
+
+
+void TabView::readViewConfig(KConfig* c,
+			     TQString prefix, TQString postfix,
+			     bool withOptions)
+{
+    if (0) qDebug("%s::readConfig(%s%s)", name(),
+		  prefix.ascii(), postfix.ascii());
+
+    KConfigGroup* g = configGroup(c, prefix, postfix);
+
+    _mainSplitter->setSizes(g->readIntListEntry("MainSizes"));
+    _leftSplitter->setSizes(g->readIntListEntry("LeftSizes"));
+    _bottomSplitter->setSizes(g->readIntListEntry("BottomSizes"));
+
+    TQString activeT = g->readEntry("ActiveTop", "CallerView");
+    TQString activeB = g->readEntry("ActiveBottom", "CalleeView");
+    TQString activeL = g->readEntry("ActiveLeft", "");
+    TQString activeR = g->readEntry("ActiveRight", "");
+
+    TQStringList topTabs    = g->readListEntry("TopTabs");
+    TQStringList bottomTabs = g->readListEntry("BottomTabs");
+    TQStringList leftTabs   = g->readListEntry("LeftTabs");
+    TQStringList rightTabs  = g->readListEntry("RightTabs");
+
+    if (topTabs.isEmpty() && bottomTabs.isEmpty() &&
+        rightTabs.isEmpty() && leftTabs.isEmpty()) {
+      // no tabs visible ?! Reset to default
+      topTabs << "CostTypeView" << "CallerView" << "AllCallerView"
+              << "CalleeMapView" << "SourceView";
+      bottomTabs << "PartView" << "CalleeView" << "CallGraphView"
+                 << "AllCalleeView" << "CallerMapView" << "InstrView";
+    }
+
+    TraceItemView *activeTop = 0, *activeBottom = 0;
+    TraceItemView *activeLeft = 0, *activeRight = 0;
+
+    moveTab(0, TraceItemView::Top, true);
+    TraceItemView *v;
+    TQPtrListIterator<TraceItemView> it( _tabs );
+    while ( (v=it.current()) != 0) {
+      ++it;
+
+      TQString n = TQString(v->widget()->name());
+      if (topTabs.contains(n)) {
+        moveTab(v->widget(), TraceItemView::Top);
+        if (n == activeT) activeTop = v;
+      }
+      else if (bottomTabs.contains(n)) {
+        moveTab(v->widget(), TraceItemView::Bottom);
+        if (n == activeB) activeBottom = v;
+      }
+      else if (leftTabs.contains(n)) {
+        moveTab(v->widget(), TraceItemView::Left);
+        if (n == activeL) activeLeft = v;
+      }
+      else if (rightTabs.contains(n)) {
+        moveTab(v->widget(), TraceItemView::Right);
+        if (n == activeR) activeRight = v;
+      }
+      else moveTab(v->widget(), Hidden);
+
+      if (withOptions)
+	v->readViewConfig(c, TQString("%1-%2")
+			  .arg(prefix).arg(v->widget()->name()),
+			  postfix, true);
+    }
+    if (activeTop)   _topTW->showPage(activeTop->widget());
+    if (activeBottom)_bottomTW->showPage(activeBottom->widget());
+    if (activeLeft)  _leftTW->showPage(activeLeft->widget());
+    if (activeRight) _rightTW->showPage(activeRight->widget());
+
+    TQString activeType = g->readEntry("ActiveItemType", "");
+    TQString activeName = g->readEntry("ActiveItemName", "");
+    TQString selectedType = g->readEntry("SelectedItemType", "");
+    TQString selectedName = g->readEntry("SelectedItemName", "");
+    delete g;
+    
+    if (!_data) return;
+    
+    if (withOptions) {  
+      // restore active item
+      TraceItem::CostType t = TraceItem::costType(activeType);
+      if (t==TraceItem::NoCostType) t = TraceItem::Function;
+      TraceCost* activeItem = _data->search(t, activeName, _costType);
+      if (!activeItem) return;
+      activate(activeItem);
+      
+      // restore selected item
+      t = TraceItem::costType(selectedType);
+      if (t==TraceItem::NoCostType) t = TraceItem::Function;
+      TraceCost* selectedItem = _data->search(t, selectedName,
+					      _costType, activeItem);
+      if (selectedItem) select(selectedItem);
+    }
+
+    updateView();
+}
+
+void TabView::saveViewConfig(KConfig* c,
+			     TQString prefix, TQString postfix,
+			     bool withOptions)
+{
+    KConfigGroup g(c, (prefix+postfix).ascii());
+
+    g.writeEntry("MainSizes", _mainSplitter->sizes());
+    g.writeEntry("LeftSizes", _leftSplitter->sizes());
+    g.writeEntry("BottomSizes", _bottomSplitter->sizes());
+
+    TQString a;
+    if ((_topTW->count()>0) &&
+        (_topTW->isTabEnabled(_topTW->currentPage())))
+      a = TQString(_topTW->currentPage()->name());
+    g.writeEntry("ActiveTop", a);
+
+    a.setLength(0);
+    if ((_bottomTW->count()>0) &&
+        (_bottomTW->isTabEnabled(_bottomTW->currentPage())))
+      a = TQString(_bottomTW->currentPage()->name());
+    g.writeEntry("ActiveBottom", a);
+
+    a.setLength(0);
+    if ((_leftTW->count()>0) &&
+        (_leftTW->isTabEnabled(_leftTW->currentPage())))
+      a = TQString(_leftTW->currentPage()->name());
+    g.writeEntry("ActiveLeft", a);
+
+    a.setLength(0);
+    if ((_rightTW->count()>0) &&
+        (_rightTW->isTabEnabled(_rightTW->currentPage())))
+      a = TQString(_rightTW->currentPage()->name());
+    g.writeEntry("ActiveRight", a);
+
+    if (withOptions)
+      if (_activeItem) {
+	g.writeEntry("ActiveItemType",
+                     TraceItem::typeName(_activeItem->type()));
+	g.writeEntry("ActiveItemName", _activeItem->name());
+	if (_selectedItem) {
+	  g.writeEntry("SelectedItemType",
+		       TraceItem::typeName(_selectedItem->type()));
+	  g.writeEntry("SelectedItemName", _selectedItem->name());
+	}
+      }
+
+    TQStringList topList, bottomList, leftList, rightList;
+    TraceItemView *v;
+    for (v=_tabs.first();v;v=_tabs.next()) {
+      switch(v->position()) {
+      case TraceItemView::Top:
+        topList << TQString(v->widget()->name());
+        break;
+
+      case TraceItemView::Bottom:
+        bottomList << TQString(v->widget()->name());
+        break;
+
+      case TraceItemView::Left:
+        leftList << TQString(v->widget()->name());
+        break;
+
+      case TraceItemView::Right:
+        rightList << TQString(v->widget()->name());
+        break;
+
+      default: break;
+      }
+    }
+
+    g.writeEntry("TopTabs", topList);
+    g.writeEntry("BottomTabs", bottomList);
+    g.writeEntry("LeftTabs", leftList);
+    g.writeEntry("RightTabs", rightList);
+
+    if (withOptions)
+      for (v=_tabs.first();v;v=_tabs.next())
+	v->saveViewConfig(c, TQString("%1-%2").arg(prefix)
+			  .arg(v->widget()->name()), postfix, true);
+}
+
+#include "tabview.moc"
diff --git a/kdecachegrind/kdecachegrind/tabview.h b/kdecachegrind/kdecachegrind/tabview.h
new file mode 100644
index 0000000..b9b4026
--- /dev/null
+++ b/kdecachegrind/kdecachegrind/tabview.h
@@ -0,0 +1,174 @@
+/* This file is part of KCachegrind.
+   Copyright (C) 2003 Josef Weidendorfer <Josef.Weidendorfer@gmx.de>
+
+   KCachegrind 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, version 2.
+
+   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; see the file COPYING.  If not, write to
+   the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+   Boston, MA 02110-1301, USA.
+*/
+
+/*
+ * Tab View, enclosing detailed views for one trace item in
+ * two tab widgets, separated by a splitter
+ */
+
+#ifndef TABVIEW_H
+#define TABVIEW_H
+
+#include <tqptrlist.h>
+#include <tqwidget.h>
+#include <tqtabwidget.h>
+#include <tqtabbar.h>
+#include <ksqueezedtextlabel.h>
+#include "traceitemview.h"
+
+class TQSplitter;
+class TabView;
+
+/**
+ * Subclass of TQTabBar to enable context menu on tabs
+ */
+class TabBar : public TQTabBar
+{
+  Q_OBJECT
+  TQ_OBJECT
+
+ public:
+  TabBar(TabView*, TQTabWidget* parent, const char *name = 0);
+ protected:
+  void mousePressEvent(TQMouseEvent *e);
+
+ private:
+  TQTabWidget* _tabWidget;
+  TabView* _tabView;
+};
+
+
+/**
+ * Own Splitter:
+ * Call checkVisiblity for all TabWidget children of the splitter
+ * on a MoveEvent. This typically is produced when collapsing the widget
+ * inside of another splitter.
+ */
+class Splitter: public TQSplitter
+{
+  Q_OBJECT
+  TQ_OBJECT
+
+public:
+  Splitter(Qt::Orientation o, TQWidget* parent = 0, const char* name = 0);
+  void checkVisiblity();
+
+protected:
+  void moveEvent(TQMoveEvent *);
+};
+
+
+/**
+ * Own TabView:
+ * - A TQTabWidget able to track its visible rect via resizeEvents.
+ *   This is needed to track if this widget is collapsed in a TQSplitter.
+ * - Use own TabBar for context menu
+ */
+class TabWidget: public TQTabWidget
+{
+  Q_OBJECT
+  TQ_OBJECT
+
+public:
+
+  TabWidget(TabView*, TQWidget* parent = 0,
+            const char* name = 0, WFlags f = 0);
+
+  bool hasVisibleRect() { return _hasVisibleRect; }
+  void checkVisibility();
+
+signals:
+  void visibleRectChanged(TabWidget*);
+
+protected:
+  void resizeEvent(TQResizeEvent *);
+  void showEvent(TQShowEvent *);
+  void hideEvent(TQHideEvent *);
+  void moveEvent(TQMoveEvent *);
+
+private:
+  bool _hasVisibleRect;
+};
+
+
+
+class TabView : public TQWidget, public TraceItemView
+{
+  Q_OBJECT
+  TQ_OBJECT
+
+public:
+
+  TabView(TraceItemView* parentView,
+          TQWidget* parent = 0, const char* name = 0);
+
+  virtual TQWidget* widget() { return this; }
+  TQString whatsThis() const ;
+  void setData(TraceData*);
+  bool isViewVisible() const { return !_isCollapsed; }
+  void selected(TraceItemView*, TraceItem*);
+  bool active() const { return _active; }
+  void setActive(bool);
+
+  /**
+   * Rearrange tabs
+   * if <w> == 0, move hidden tabs
+   */
+  void moveTab(TQWidget* w, Position, bool wholeArea = false);
+
+  Position tabPosition(TQWidget*);
+  int visibleTabs();
+  int visibleAreas();
+
+  void readViewConfig(KConfig*, TQString prefix, TQString postfix, bool);
+  void saveViewConfig(KConfig*, TQString prefix, TQString postfix, bool);
+
+public slots:
+  void tabChanged(TQWidget*);
+  void visibleRectChangedSlot(TabWidget*);
+
+signals:
+  void activated(TabView*);
+
+protected:
+  void resizeEvent(TQResizeEvent *);
+  bool eventFilter(TQObject*, TQEvent*);
+  void mousePressEvent(TQMouseEvent*);
+
+private:
+  TraceItemView* addTab(TQString, TraceItemView*);
+  void addTop(TraceItemView*);
+  void addBottom(TraceItemView*);
+  TabWidget* tabWidget(Position);
+  void updateVisibility();
+  void doUpdate(int);
+  void installFocusFilters();
+
+  // this is true if width or height <= 1, and no child updates are done
+  bool _isCollapsed;
+
+  KSqueezedTextLabel* _nameLabel;
+  TQSplitter *_mainSplitter, *_leftSplitter, *_bottomSplitter;
+  TabWidget *_topTW, *_leftTW, *_bottomTW, *_rightTW;
+  TQPtrList<TraceItemView> _tabs;
+
+  TQWidget* _lastFocus;
+  bool _active;
+};
+
+#endif
diff --git a/kdecachegrind/kdecachegrind/kdecachegrind.desktop b/kdecachegrind/kdecachegrind/kdecachegrind.desktop
new file mode 100644
index 0000000..7089370
--- /dev/null
+++ b/kdecachegrind/kdecachegrind/kdecachegrind.desktop
@@ -0,0 +1,103 @@
+# KDE Config File
+[Desktop Entry]
+Type=Application
+Exec=kdecachegrind -caption "%c" %i %m %u
+MimeType=application/x-kcachegrind;
+Icon=kdecachegrind
+DocPath=kdecachegrind/index.html
+Terminal=false
+Name=KCachegrind
+Name[hi]=के-केश-ग्रिंड
+Name[sv]=Kcachegrind
+Name[ta]=  இடைமாற்றகட்டம்
+GenericName=Profiler Frontend
+GenericName[bs]=Profiler frontend
+GenericName[ca]=Interfície de Profiler
+GenericName[cs]=Rozhraní pro profilaci
+GenericName[cy]=Blaen-wyneb Proffilydd
+GenericName[da]=Grænseflade til profilering
+GenericName[de]=Profiler Oberfläche
+GenericName[el]=Πρόγραμμα προφίλ
+GenericName[eo]=Fasado de Profililo
+GenericName[es]=Interfaz para Profiler
+GenericName[et]=Profileerimisrakendus
+GenericName[eu]=Profilatzailearen interfazea
+GenericName[fa]=پایانۀ گزارش‌گیر
+GenericName[fi]=Profiloijan käyttöliittymä
+GenericName[fr]=Interface de profilage
+GenericName[ga]=Comhéadan ar Phróifíleoir
+GenericName[gl]=Interface para o profiler
+GenericName[hi]=प्रोफ़ाइलर फ्रन्टएण्ड
+GenericName[hu]=Profilozó
+GenericName[is]=Myndrænt viðmót á afkastakönnuð
+GenericName[it]=Interfaccia a profiler
+GenericName[ja]=プロファイラフロントエンド
+GenericName[ka]=პროფილერის Frontend
+GenericName[kk]=Профильдеткіштің интерфейсі
+GenericName[lt]=Profiliuoklio naudotojo sąsaja
+GenericName[nb]=Grensesnitt for profilvisning
+GenericName[nds]=Profiler-Böversiet
+GenericName[ne]=प्रोफाइलर फ्रन्टइन्ड
+GenericName[nl]=Profiler-hulpprogramma
+GenericName[nn]=Grensesnitt for profilvising
+GenericName[pa]=ਪਰੋਫਾਇਲਰ ਮੁੱਖ ਭੂਮੀ
+GenericName[pl]=Interfejs do profilera
+GenericName[pt]=Interface de Profiler
+GenericName[pt_BR]=Interface para o Profiler
+GenericName[ru]=Профилировщик
+GenericName[sk]=Rozhranie pre profiler
+GenericName[sl]=Vmesnik profilnika
+GenericName[sr]=Графички интерфејс за профајлер
+GenericName[sr@Latn]=Grafički interfejs za profajler
+GenericName[sv]=Profileringsgränssnitt
+GenericName[ta]= விவரக்குறிப்பு முன்பகுதி
+GenericName[tg]=Интерфейс ба профилкунанда
+GenericName[tr]=Profil Önyüzü
+GenericName[uk]=Інтерфейс до Profiler
+GenericName[zh_CN]=个性数据前端
+GenericName[zh_TW]=分析器前端
+Comment=Visualization of Performance Profiling Data
+Comment[bg]=Визуализация на данните за производителност
+Comment[bs]=Vizualizacija podataka za profiliranje performansi
+Comment[ca]=Visualizació de dades de perfilat de rendiment
+Comment[cs]=Vizualizace profilovacích dat výkonu
+Comment[da]=Visualisering af profileringsdata
+Comment[de]=Visualisierung von Daten des Laufzeitverhaltens eines Programmes
+Comment[el]=Αναπαράσταση δεδομένων ταχύτητας προφίλ
+Comment[en_GB]=Visualisation of Performance Profiling Data
+Comment[es]=Visualización de datos de análisis de rendimiento
+Comment[et]=Jõudluse profileerimise andmete visualiseerimise vahend
+Comment[eu]=Errendimendu profil datuen bistaratzea
+Comment[fa]=تجسم کارایی گزارش داده‌ها
+Comment[fi]=Visualisointi tehokkuusprofiloinnin tiedoista
+Comment[fr]=Visualisation des données de performance de profilage
+Comment[gl]=Visualización dos datos da análise de rendimento
+Comment[hi]=परफार्मेस प्रोफाइलिंग डाटा का विजुअलाइज़ेशन
+Comment[hu]=Teljesítményprofil-adatok megjelenítése
+Comment[is]=Sjónræn framsetning gagna úr afkastakönnun
+Comment[it]=Visualizzazione dei dati di profiling delle prestazioni
+Comment[ja]=パフォーマンスプロファイルデータを視覚化
+Comment[ka]=წარმადობის მაპროფფილებელი მონაცემების ვიზუალიზაცია
+Comment[kk]=Деректерді профильдеудің визуализациясы
+Comment[lt]=Veikimo profiliavimo duomenų vizualizacija
+Comment[nb]=Vis informasjon om ytelse.
+Comment[nds]=Visualiseren vun Programmleisten-Looptietdaten
+Comment[ne]=सम्पादन प्रोफाइलिङ डाटाको दृष्टिकरण
+Comment[nl]=Visualisatie van Performance Profiling Data
+Comment[nn]=Vis informasjon om yting
+Comment[pl]=Wizualizacja danych profilowania wydajności
+Comment[pt]=Visualização dos Dados de Análise de Performance
+Comment[pt_BR]=Visualização de Dados de Perfil de Desempenho
+Comment[ru]=Утилита для визуального профилирования приложений
+Comment[sk]=Vizualizácia dát o výkone
+Comment[sl]=Vizualizacija podatkov profilnih zmogljivosti
+Comment[sr]=Визуелизација података о профилисању перформанси
+Comment[sr@Latn]=Vizuelizacija podataka o profilisanju performansi
+Comment[sv]=Åskådliggörande av profileringsdata för prestanda
+Comment[ta]= விவர தகவலை செயல்பாட்டு காட்சியாளிப்பு
+Comment[tg]=Утилита барои гузориши профили визуалӣ
+Comment[uk]=Візуалізація даних профілювання швидкодії
+Comment[zh_CN]=性能个性数据的可视化表现
+Comment[zh_TW]=效能分析資料視覺化
+X-DCOP-ServiceType=Multi
+Categories=Qt;KDE;Development;
diff --git a/kdecachegrind/kdecachegrind/kdecachegrindui.rc b/kdecachegrind/kdecachegrind/kdecachegrindui.rc
new file mode 100644
index 0000000..9531829
--- /dev/null
+++ b/kdecachegrind/kdecachegrind/kdecachegrindui.rc
@@ -0,0 +1,57 @@
+<!DOCTYPE kpartgui>
+<kpartgui name="kdecachegrind" version="4">
+ <MenuBar>
+  <Menu name="file"><text>&amp;File</text>
+   <Action name="file_add" append="open_merge"/>
+   <Action name="reload" append="revert_merge"/>
+   <Action name="dump" append="revert_merge"/>
+   <Action name="export"/>
+  </Menu>
+  <Menu name="view"><text>&amp;View</text>
+   <Action name="view_cost_type"/>
+   <Action name="view_cost_type2"/>
+   <Action name="view_group_type"/>
+   <Separator/>
+   <Menu name="layouts"><text>&amp;Layout</text>
+     <Action name="layout_next"/>
+     <Action name="layout_previous"/>
+     <Action name="layout_duplicate"/>
+     <Action name="layout_remove"/>
+     <Separator/>
+     <Action name="layout_restore"/>
+     <Action name="layout_save"/>
+   </Menu>
+   <Action name="view_split"/>
+   <Action name="view_split_dir"/>
+   <Separator/>
+   <Action name="view_percentage"/>
+   <Action name="view_expanded"/>
+   <Action name="view_cycles"/>
+  </Menu>
+  <Menu name="settings">
+   <Menu append="show_toolbar_merge"><text>Sidebars</text>
+    <Action name="settings_show_dumpdock"/>
+    <Action name="settings_show_partdock"/>
+    <Action name="settings_show_stackdock"/>
+    <Action name="settings_show_profiledock"/>
+   </Menu>
+  </Menu>
+ </MenuBar>
+
+ <ToolBar name="mainToolBar" noMerge="1"><text>Main Toolbar</text>
+  <Action name="file_open"/>
+  <Action name="reload"/>
+  <Action name="dump"/> 
+  <Separator/>
+  <Action name="go_up"/>
+  <Action name="go_back"/>
+  <Action name="go_forward"/>
+  <Separator/>
+  <Action name="view_percentage"/>
+  <Action name="view_expanded"/>
+  <Action name="view_cycles"/>
+ </ToolBar>
+ <ToolBar name="stateToolBar" noMerge="1"><text>State Toolbar</text> 
+  <Action name="view_cost_type"/>
+ </ToolBar>
+</kpartgui>
diff --git a/kdecachegrind/kdecachegrind/tips b/kdecachegrind/kdecachegrind/tips
new file mode 100644
index 0000000..1f555c0
--- /dev/null
+++ b/kdecachegrind/kdecachegrind/tips
@@ -0,0 +1,141 @@
+<tip category="KCachegrind|Help">
+<html>
+<p>...that the <em>What's This?</em> help for every GUI widget
+in KCachegrind contains detailed usage information for this widget?
+It is highly recommended to read at least these help texts on first
+use. Request <em>What's This?</em> help by pressing
+Shift+F1 and clicking on the widget.</p>
+</html>
+</tip>
+
+<tip category="KCachegrind|Explanation">
+<html>
+<p>...that you can get profile information at instruction level
+with Calltree when you provide the option <em>--dump-instr=yes</em>?
+Use the Assembler View for the instruction annotations.
+</p>
+</html>
+</tip>
+
+<tip category="KCachegrind|Keyboard">
+<html>
+<p>...that you can use Alt-Left/Right keys of your keyboard to go
+back/forward in the active object history ?</p>
+</html>
+</tip>
+
+<tip category="KCachegrind|Keyboard">
+<html>
+<p>...that you can navigate in the Callee/Caller Map View using
+arrow keys? Use Left/Right to change to siblings of the current
+item; use Up/Down to go one nesting level up/down. To select
+the current item, press Space, and to activate it, press Return.
+</p>
+</html>
+</tip>
+
+<tip category="KCachegrind|Keyboard">
+<html>
+<p>...that you can navigate in the Call Graph View using
+arrow keys? Use Up/Down to go one calling level up/down, alternating
+between calls and functions. Use Left/Right to change to siblings of a current
+selected call. To activate the current item, press Return.
+</p>
+</html>
+</tip>
+
+<tip category="KCachegrind|Filters">
+<html>
+<p>...that you can rapidly locate a function by entering part of its
+name (case-insensitive) into the edit line of the toolbar
+and hit return?</p>
+</html>
+</tip>
+
+<tip category="KCachegrind|Appearance">
+<html>
+<p>...that you can assign custom colors to 
+ELF objects/C++ Classes/Source Files for graph coloring
+in <em>Settings->Configure KCachegrind...</em>?</p>
+</html>
+</tip>
+
+<tip category="KCachegrind|Configuration">
+<html>
+<p>...that you can see if debug info is available for a selected 
+function by looking at the location label in the Info tab or
+the source listing header in the source tab?</p>
+<p>There must be the name of the source file (with extension).
+If KCachegrind still doesn't show the source, make sure that you
+have added the directory of the source file to the
+<em>Source Directories</em> list in the configuration.
+</html>
+</tip>
+
+<tip category="KCachegrind|Appearance">
+<html>
+<p>...that you can configure whether KCachgrind should
+show absolute event counts or relative ones (percentage display)?</p>
+</html>
+</tip>
+
+<tip category="KCachegrind|Appearance">
+<html>
+<p>...that you can configure the maximum number of items
+for all function lists in KCachegrind? Limiting the number
+of items is done to get a fast reacting GUI. The last item in
+the list will show you the number of skipped functions, together
+with a cost condition for these skipped functions.</p>
+<p>To activate a function with small costs, search for it and select
+it in the flat profile. Selecting functions with small cost will
+temporarily add them to the flat profile list.</p>
+</html>
+</tip>
+
+<tip category="KCachegrind|Explanation">
+<html>
+<p>...that the Coverage tab - in contrast to the Call Lists tab -
+shows <em>all</em> functions that are calling the selected function
+(upper part) / are called by the selected function (bottom part),
+no matter how many function are between them on the stack?</p>
+<p>Examples:</p>
+<p>An entry in the upper list for function foo1() with a value of 50%
+with function bar() selected means that 50% of all the cost of function
+bar() happened while called from function foo1().</p>
+<p>An entry in the bottom list for function foo2() with a value of 50%
+with function bar() selected means that 50% of all the cost of function
+bar() happened while calling foo2() from bar().</p>
+</html>
+</tip>
+
+<tip category="KCachegrind|Explanation">
+<html>
+<p>...that waiting for the tool tip inside of a tree map
+shows the list of names of the nested rectangles the mouse
+pointer is over?</p>
+<p>Items from this list can be selected by pressing the right
+mouse button.</p>
+</html>
+</tip>
+
+<tip category="KCachegrind|Explanation">
+<html>
+<p>...that you can constrain the cost counts shown to only a
+few parts of the whole trace by selecting these parts in the
+"Trace Selection" Dockable?</p>
+<p>To generate multiple parts in a profiling run with
+cachegrind, use e.g. option --cachedumps=xxx for parts
+of a length of xxx basic blocks (A basic block is a run
+of not-branching assembler statements inside of your program
+code).</p>
+</html>
+</tip>
+
+<tip category="KCachegrind|Explanation">
+<p>...that by splitting the view to show information of 
+two functions simultaniously, selecting a function in
+one panel shows the information for that function
+in the other panel?</p>
+</html>
+</tip>
+
diff --git a/kdecachegrind/kdecachegrind/toplevel.cpp b/kdecachegrind/kdecachegrind/toplevel.cpp
new file mode 100644
index 0000000..5a2e1de
--- /dev/null
+++ b/kdecachegrind/kdecachegrind/toplevel.cpp
@@ -0,0 +1,2389 @@
+/* This file is part of KCachegrind.
+   Copyright (C) 2002, 2003 Josef Weidendorfer <Josef.Weidendorfer@gmx.de>
+
+   KCachegrind 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, version 2.
+
+   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; see the file COPYING.  If not, write to
+   the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+   Boston, MA 02110-1301, USA.
+*/
+
+/*
+ * KCachegrind top level window
+ */
+
+#define TRACE_UPDATES 0
+#define ENABLE_DUMPDOCK 0
+
+#include <stdlib.h> // for system()
+
+#include <tqvbox.h>
+#include <tqtimer.h>
+#include <tqwhatsthis.h>
+#include <tqlineedit.h>
+#include <tqtextstream.h>
+#include <tqsizepolicy.h>
+#include <tqprogressbar.h>
+#include <tqfile.h>
+#include <tqeventloop.h>
+
+#include <kapplication.h>
+#include <klocale.h>
+#include <kstatusbar.h>
+#include <kstdaccel.h>
+#include <kstdaction.h>
+#include <kaction.h>
+#include <kurl.h>
+#include <kfiledialog.h>
+#include <kio/netaccess.h>
+#include <kedittoolbar.h>
+#include <kkeydialog.h>
+#include <ktip.h>
+#include <kpopupmenu.h>
+#include <kdebug.h>
+
+#if ENABLE_DUMPDOCK
+#include "dumpselection.h"
+#endif
+
+#include "toplevel.h"
+#include "partselection.h"
+#include "functionselection.h"
+#include "stackselection.h"
+#include "stackbrowser.h"
+#include "tracedata.h"
+#include "configuration.h"
+#include "configdlg.h"
+#include "multiview.h"
+#include "callgraphview.h"
+
+
+TopLevel::TopLevel(const char *name)
+  : KMainWindow(0, name), DCOPObject("KCachegrindIface")
+{
+  init();
+
+  createDocks();
+
+  _multiView = new MultiView(this, this, "MultiView");
+  setCentralWidget(_multiView);
+
+  createActions();
+
+  _partDockShown->setChecked(!_partDock->isHidden());
+  _stackDockShown->setChecked(!_stackDock->isHidden());
+  _functionDockShown->setChecked(!_functionDock->isHidden());
+
+  connect(_partDock, TQT_SIGNAL(visibilityChanged(bool)),
+          TQT_TQOBJECT(this), TQT_SLOT(partVisibilityChanged(bool)));
+  connect(_stackDock, TQT_SIGNAL(visibilityChanged(bool)),
+          TQT_TQOBJECT(this), TQT_SLOT(stackVisibilityChanged(bool)));
+  connect(_functionDock, TQT_SIGNAL(visibilityChanged(bool)),
+          TQT_TQOBJECT(this), TQT_SLOT(functionVisibilityChanged(bool)));
+
+#if ENABLE_DUMPDOCK
+  _dumpDockShown->setChecked(!_dumpDock->isHidden());
+  connect(_dumpDock, TQT_SIGNAL(visibilityChanged(bool)),
+          TQT_TQOBJECT(this), TQT_SLOT(dumpVisibilityChanged(bool)));
+#endif
+
+  _statusbar = statusBar();
+  _statusLabel = new TQLabel(_statusbar);
+#if 0
+  // how to do avoid main window resizing on large statusbar label?
+  TQSizePolicy p(TQSizePolicy::Fixed, TQSizePolicy::Expanding);
+  _statusLabel->setSizePolicy(p);
+  _statusbar->setSizePolicy(p);
+#endif
+  _statusbar->addWidget(_statusLabel, 1);
+
+  KConfig* kconfig = KGlobal::config();
+  Configuration::readOptions( kconfig );
+  _openRecent->loadEntries( kconfig );
+
+  // set toggle after reading configuration
+  _showPercentage = Configuration::showPercentage();
+  _showExpanded   = Configuration::showExpanded();
+  _showCycles     = Configuration::showCycles();
+  _taPercentage->setChecked(_showPercentage);
+  _taExpanded->setChecked(_showExpanded);
+  _taCycles->setChecked(_showCycles);
+
+  setupPartSelection(_partSelection);
+
+  // KCachegrind for KDE 3.0.x does not allow to hide toolbars...
+#if KDE_VERSION >= 308 // KDE 3.1
+  setStandardToolBarMenuEnabled(true);
+#endif
+
+  // QT dock windows are created before (using QT position restoring)
+  createGUI();
+
+  setAutoSaveSettings();
+
+  // restore current state settings (not configuration options)
+  restoreCurrentState(TQString());
+
+  // if this is the first toplevel, show tip of day
+  if (memberList->count() == 1)
+    TQTimer::singleShot( 200, TQT_TQOBJECT(this), TQT_SLOT(slotShowTipOnStart()) );
+}
+
+void TopLevel::init()
+{
+  _activeParts.clear();
+  _hiddenParts.clear();
+
+  _progressBar = 0;
+
+  _data = 0;
+  _function = 0;
+  _costType = 0;
+  _costType2 = 0;
+  _groupType = TraceCost::NoCostType;
+  _group = 0;
+
+  _layoutCurrent = 0;
+  _layoutCount = 1;
+
+  // for delayed slots
+  _traceItemDelayed = 0;
+  _costTypeDelayed = 0;
+  _costType2Delayed = 0;
+  _groupTypeDelayed = TraceCost::NoCostType;
+  _groupDelayed = 0;
+  _directionDelayed = TraceItemView::None;
+  _lastSender = 0;
+}
+
+
+/**
+ * Setup the part selection widget.
+ * Statusbar has to be created before.
+ */
+void TopLevel::setupPartSelection(PartSelection* ps)
+{
+  // setup connections from the part selection widget
+
+  connect(ps, TQT_SIGNAL(activePartsChanged(const TracePartList&)),
+          TQT_TQOBJECT(this), TQT_SLOT(activePartsChangedSlot(const TracePartList&)));
+  connect(ps, TQT_SIGNAL(groupChanged(TraceCostItem*)),
+          TQT_TQOBJECT(this), TQT_SLOT(setGroupDelayed(TraceCostItem*)));
+  connect(ps, TQT_SIGNAL(functionChanged(TraceItem*)),
+          TQT_TQOBJECT(this), TQT_SLOT(setTraceItemDelayed(TraceItem*)));
+
+  connect(ps, TQT_SIGNAL(goBack()),
+          _stackSelection, TQT_SLOT(browserBack()));
+
+  connect(ps, TQT_SIGNAL(partsHideSelected()),
+          TQT_TQOBJECT(this), TQT_SLOT(partsHideSelectedSlotDelayed()));
+  connect(ps, TQT_SIGNAL(partsUnhideAll()),
+          TQT_TQOBJECT(this), TQT_SLOT(partsUnhideAllSlotDelayed()));
+
+  connect(ps, TQT_SIGNAL(showMessage(const TQString&, int)),
+          _statusbar, TQT_SLOT(message(const TQString&, int)));
+}
+
+/**
+ * This saves the current state of the main window and
+ * sub widgets.
+ *
+ * No positions are saved. These is done automatically for
+ * KToolbar, and manually in queryExit() for QT docks.
+ */
+void TopLevel::saveCurrentState(TQString postfix)
+{
+  KConfig* kconfig = KGlobal::config();
+  TQCString pf = postfix.ascii();
+
+  KConfigGroup psConfig(kconfig, TQCString("PartOverview")+pf);
+  _partSelection->saveVisualisationConfig(&psConfig);
+
+  KConfigGroup stateConfig(kconfig, TQCString("CurrentState")+pf);
+  stateConfig.writeEntry("CostType",
+			 _costType ? _costType->name() : TQString("?"));
+  stateConfig.writeEntry("CostType2",
+			 _costType2 ? _costType2->name() : TQString("?"));
+  stateConfig.writeEntry("GroupType", TraceItem::typeName(_groupType));
+
+  _multiView->saveViewConfig(kconfig, TQString("MainView"), postfix, true);
+}
+
+/**
+ * This function is called when a trace is closed.
+ * Save browsing position for later restoring
+ */
+void TopLevel::saveTraceSettings()
+{
+  TQString key = traceKey();
+
+  KConfigGroup pConfig(KGlobal::config(), TQCString("TracePositions"));
+  pConfig.writeEntry(TQString("CostType%1").arg(key),
+                     _costType ? _costType->name() : TQString("?"));
+  pConfig.writeEntry(TQString("CostType2%1").arg(key),
+                     _costType2 ? _costType2->name() : TQString("?"));
+  pConfig.writeEntry(TQString("GroupType%1").arg(key),
+                     TraceItem::typeName(_groupType));
+
+  if (!_data) return;
+
+  KConfigGroup aConfig(KGlobal::config(), TQCString("Layouts"));
+  aConfig.writeEntry(TQString("Count%1").arg(key), _layoutCount);
+  aConfig.writeEntry(TQString("Current%1").arg(key), _layoutCurrent);
+
+  saveCurrentState(key);
+  pConfig.writeEntry(TQString("Group%1").arg(key),
+                     _group ? _group->name() : TQString());
+}
+
+/**
+ * This restores the current state of the main window and
+ * sub widgets.
+ *
+ * This does NOT restore any positions. This is done automatically for
+ * KToolbar, and manually in the createDocks() for QT docks..
+ */
+void TopLevel::restoreCurrentState(TQString postfix)
+{
+  KConfig* kconfig = KGlobal::config();
+  TQStringList gList = kconfig->groupList();
+  TQCString pf = postfix.ascii();
+
+  // dock properties (not position, this should be have done before)
+  TQCString group = TQCString("PartOverview");
+  if (gList.contains(group+pf)) group += pf;
+  KConfigGroup psConfig(kconfig, group);
+  _partSelection->readVisualisationConfig(&psConfig);
+
+  _multiView->readViewConfig(kconfig, TQString("MainView"), postfix, true);
+  _taSplit->setChecked(_multiView->childCount()>1);
+  _taSplitDir->setEnabled(_multiView->childCount()>1);
+  _taSplitDir->setChecked(_multiView->orientation() == Qt::Horizontal);
+}
+
+
+void TopLevel::createDocks()
+{
+  _partDock = new TQDockWindow(TQDockWindow::InDock, this);
+  _partDock->setCaption(i18n("Parts Overview"));
+  _partDock->setCloseMode( TQDockWindow::Always );
+  _partSelection = new PartSelection(_partDock, "partSelection");
+  _partDock->setWidget(_partSelection);
+  _partDock->setResizeEnabled(true);
+  _partDock->setFixedExtentWidth(200);
+  TQWhatsThis::add( _partSelection, i18n(
+                   "<b>The Parts Overview</b>"
+                   "<p>A trace consists of multiple trace parts when "
+                   "there are several profile data files from one profile run. "
+                   "The Trace Part Overview dockable shows these, "
+                   "horizontally ordered in execution time; "
+                   "the rectangle sizes are proportional to the total "
+                   "cost spent in the parts. You can select one or several "
+                   "parts to constrain all costs shown to these parts only."
+                   "</p>"
+                   "<p>The parts are further subdivided: there is a "
+                   "partitioning and an callee split mode: "
+                   "<ul><li>Partitioning: You see the "
+                   "partitioning into groups for a trace part, according to "
+                   "the group type selected. E.g. if ELF object groups are "
+                   "selected, you see colored rectangles for each "
+                   "used ELF object (shared library or executable), sized "
+                   "according to the cost spent therein.</li>"
+                   "<li>Callee: A rectangle showing the inclusive "
+                   "cost of the current selected function in the trace part "
+                   "is shown. "
+                   "This is split up into smaller rectangles to show the costs of its "
+                   "callees.</li></ul></p>"));
+
+  _stackDock = new TQDockWindow(TQDockWindow::InDock, this);
+  _stackDock->setResizeEnabled(true);
+  // Why is the caption only correct with a close button?
+  _stackDock->setCloseMode( TQDockWindow::Always );
+  _stackSelection = new StackSelection(_stackDock, "stackSelection");
+  _stackDock->setWidget(_stackSelection);
+  _stackDock->setFixedExtentWidth(200);
+  _stackDock->setCaption(i18n("Top Cost Call Stack"));
+  TQWhatsThis::add( _stackSelection, i18n(
+                   "<b>The Top Cost Call Stack</b>"
+                   "<p>This is a purely fictional 'most probable' call stack. "
+                   "It is built up by starting with the current selected "
+                   "function and adds the callers/callees with highest cost "
+                   "at the top and to bottom.</p>"
+                   "<p>The <b>Cost</b> and <b>Calls</b> columns show the "
+                   "cost used for all calls from the function in the line "
+                   "above.</p>"));
+
+  connect(_stackSelection, TQT_SIGNAL(functionSelected(TraceItem*)),
+          TQT_TQOBJECT(this), TQT_SLOT(setTraceItemDelayed(TraceItem*)));
+
+  _functionDock = new TQDockWindow(TQDockWindow::InDock, this);
+  _functionDock->setCaption(i18n("Flat Profile"));
+  _functionDock->setCloseMode( TQDockWindow::Always );
+  _functionSelection = new FunctionSelection(this, _functionDock,
+                                             "functionSelection");
+  _functionSelection->setTopLevel(this);
+
+  _functionDock->setWidget(_functionSelection);
+  _functionDock->setResizeEnabled(true);
+  _functionDock->setFixedExtentWidth(200);
+  TQWhatsThis::add( _functionSelection, i18n(
+                   "<b>The Flat Profile</b>"
+                   "<p>The flat profile contains a group and a function "
+                   "selection list. The group list contains all groups "
+                   "where costs "
+                   "are spent in, depending on the chosen group type. "
+                   "The group list is hidden when group type 'Function' "
+                   "is selected.<p>"
+                   "<p>The function list contains the functions of the "
+                   "selected group (or all for 'Function' group type), "
+                   "ordered by the costs spent therein. Functions with "
+                   "costs less than 1% are hidden on default.</p>"));
+
+#if ENABLE_DUMPDOCK
+  _dumpDock = new TQDockWindow(TQDockWindow::InDock, this);
+  _dumpDock->setCaption(i18n("Profile Dumps"));
+  _dumpDock->setCloseMode( TQDockWindow::Always );
+  _dumpSelection = new DumpSelection(this, _dumpDock,
+                                     "dumpSelection");
+  _dumpSelection->setTopLevel(this);
+
+  _dumpDock->setWidget(_dumpSelection);
+  _dumpDock->setResizeEnabled(true);
+  _dumpDock->setFixedExtentWidth(200);
+  TQWhatsThis::add( _dumpSelection, i18n(
+                   "<b>Profile Dumps</b>"
+                   "<p>This dockable shows in the top part the list of "
+                   "loadable profile dumps in all subdirectories of: "
+                   "<ul><li>current working directory of KCachegrind, "
+                   "i.e. where it was started from, and "
+                   "<li>the default profile dump directory given in the "
+                   "configuration.</ul> "
+                   "The list is sorted according the the target command "
+                   "profiled in the corresponding dump.</p>"
+                   "<p>On selecting a profile dump, information for it "
+                   "is shown in the bottom area of the dockable: "
+                   "<ul><li><b>Options</b> allows you to view the profiled "
+                   "command and profile options of this dump. By changing "
+                   "any item, a new (yet unexisting) profile template "
+                   "is created. Press <b>Run Profile</b> to start a"
+                   "profile run with these options in the background. "
+                   "<li><b>Info</b> gives detailed info on the selected "
+                   "dump like event cost summary and properties of the "
+                   "simulated cache. "
+                   "<li><b>State</b> is only available for current happening "
+                   "profiles runs. Press <b>Update</b> to see different "
+                   "counters of the run, and a stack trace of the current "
+                   "position in the program profiled. Check the <b>Every</b> "
+                   "option to let KCachegrind regularly poll these data. "
+                   "Check the <b>Sync</b> option to let the dockable activate "
+                   "the top function in the current loaded dump.</ul></p>"));
+#endif
+
+  // Restore QT Dock positions...
+  KConfigGroup dockConfig(KGlobal::config(), TQCString("Docks"));
+  TQString str = dockConfig.readEntry("Position", TQString());
+  if (0) qDebug("Docks/Position: '%s'", str.ascii());
+  if (str.isEmpty()) {
+    // default positions
+    addDockWindow(_partDock, DockLeft);
+    addDockWindow(_stackDock, DockLeft);
+    addDockWindow(_functionDock, DockLeft);
+    _stackDock->hide();
+#if ENABLE_DUMPDOCK
+    addDockWindow(_dumpDock, DockLeft);
+    _dumpDock->hide();
+#endif
+  }
+  else {
+    TQTextStream ts( &str, IO_ReadOnly );
+    ts >> *this;
+  }
+  _forcePartDock = dockConfig.readBoolEntry("ForcePartDockVisible", false);
+
+#if 0
+  // dock context menu
+  setAppropriate(_partDock, true);
+  setAppropriate(_stackDock, true);
+  setAppropriate(_dumpDock, true);
+  setAppropriate(_functionDock, true);
+
+  connect( _partDock, TQT_SIGNAL(contextMenuRequested(const TQPoint &)),
+           TQT_TQOBJECT(this), TQT_SLOT(showDockMenu(const TQPoint &)));
+#endif
+}
+
+
+TopLevel::~TopLevel()
+{
+  delete _data;
+}
+
+
+void TopLevel::saveProperties(KConfig* c)
+{
+  c->writeEntry("TraceName", _data->traceName());
+}
+
+void TopLevel::readProperties(KConfig* c)
+{
+  TQString traceName = c->readEntry("TraceName");
+  if (!traceName.isEmpty()) {
+      TraceData* d = new TraceData(this);
+      d->load(traceName);
+      setData(d);
+  }
+}
+
+void TopLevel::createLayoutActions()
+{
+  TQString hint;
+  KAction* action;
+
+  action = new KAction( i18n( "&Duplicate" ),
+			KShortcut(KKey("Ctrl+Plus")),
+                        TQT_TQOBJECT(this), TQT_SLOT(layoutDuplicate()),
+                        actionCollection(), "layout_duplicate" );
+  hint = i18n("<b>Duplicate Current Layout</b>"
+              "<p>Make a copy of the current layout.</p>");
+  action->setWhatsThis( hint );
+
+  action = new KAction( i18n( "&Remove" ), KShortcut(),
+                        TQT_TQOBJECT(this), TQT_SLOT(layoutRemove()),
+                        actionCollection(), "layout_remove" );
+  hint = i18n("<b>Remove Current Layout</b>"
+              "<p>Delete current layout and make the previous active.</p>");
+  action->setWhatsThis( hint );
+
+  action = new KAction( i18n( "&Go to Next" ),
+			KShortcut(KKey("Ctrl+Right")),
+                        TQT_TQOBJECT(this), TQT_SLOT(layoutNext()),
+                        actionCollection(), "layout_next" );
+  hint = i18n("Go to Next Layout");
+  action->setWhatsThis( hint );
+
+  action = new KAction( i18n( "&Go to Previous" ),
+			KShortcut(KKey("Ctrl+Left")),
+                        TQT_TQOBJECT(this), TQT_SLOT(layoutPrevious()),
+                        actionCollection(), "layout_previous" );
+  hint = i18n("Go to Previous Layout");
+  action->setWhatsThis( hint );
+
+  action = new KAction( i18n( "&Restore to Default" ), KShortcut(),
+                        TQT_TQOBJECT(this), TQT_SLOT(layoutRestore()),
+                        actionCollection(), "layout_restore" );
+  hint = i18n("Restore Layouts to Default");
+  action->setWhatsThis( hint );
+
+  action = new KAction( i18n( "&Save as Default" ), KShortcut(),
+                        TQT_TQOBJECT(this), TQT_SLOT(layoutSave()),
+                        actionCollection(), "layout_save" );
+  hint = i18n("Save Layouts as Default");
+  action->setWhatsThis( hint );
+}
+
+// TODO: split this up...
+void TopLevel::createMiscActions()
+{
+  TQString hint;
+  KAction* action;
+
+  action = KStdAction::openNew(TQT_TQOBJECT(this), TQT_SLOT(newWindow()), actionCollection());
+  hint = i18n("<b>New</b><p>Open new empty KCachegrind window.</p>");
+  action->setWhatsThis( hint );
+
+  action = new KAction( i18n( "&Add..." ), KShortcut(),
+                        TQT_TQOBJECT(this), TQT_SLOT(addTrace()),
+                        actionCollection(), "file_add" );
+  hint = i18n("<b>Add Profile Data</b>"
+              "<p>This opens an additional profile data file in the current window.</p>");
+  action->setWhatsThis( hint );
+
+  action = new KAction( i18n( "&Reload" ), "reload",
+#if KDE_VERSION > 0x030190
+  // for KDE 3.2: KStdAccel::key is deprecated
+			KStdAccel::shortcut(KStdAccel::Reload),
+#else
+                        KStdAccel::key(KStdAccel::Reload),
+#endif
+                        TQT_TQOBJECT(this), TQT_SLOT( reload() ), actionCollection(), "reload" );
+  hint = i18n("<b>Reload Profile Data</b>"
+              "<p>This loads any new created parts, too.</p>");
+  action->setWhatsThis( hint );
+
+  action = new KAction( i18n( "&Export Graph" ), KShortcut(),
+                        TQT_TQOBJECT(this), TQT_SLOT(exportGraph()),
+                        actionCollection(), "export" );
+
+  hint = i18n("<b>Export Call Graph</b>"
+              "<p>Generates a file with extension .dot for the tools "
+              "of the GraphViz package.</p>");
+  action->setWhatsThis( hint );
+
+
+  _taDump = new KToggleAction( i18n( "&Force Dump" ), "redo",
+#if KDE_VERSION > 0x030190
+  // for KDE 3.2: KStdAccel::key is deprecated
+			       KStdAccel::shortcut(KStdAccel::Redo),
+#else
+                               KStdAccel::key(KStdAccel::Redo),
+#endif
+                               TQT_TQOBJECT(this), TQT_SLOT( forceTrace() ),
+                               actionCollection(), "dump" );
+  hint = i18n("<b>Force Dump</b>"
+              "<p>This forces a dump for a Callgrind profile run "
+              "in the current directory. This action is checked while "
+              "KCachegrind looks for the dump. If the dump is "
+              "finished, it automatically reloads the current trace. "
+              "If this is the one from the running Callgrind, the new "
+              "created trace part will be loaded, too.</p>"
+              "<p>Force dump creates a file 'callgrind.cmd', and "
+              "checks every second for its existence. A running "
+              "Callgrind will detect this file, dump a trace part, "
+              "and delete 'callgrind.cmd'. "
+              "The deletion is detected by KCachegrind, "
+              "and it does a Reload. If there's <em>no</em> Callgrind "
+              "running, press 'Force Dump' again to cancel the dump "
+              "request. This deletes 'callgrind.cmd' itself and "
+              "stops polling for a new dump.</p>"
+              "<p>Note: A Callgrind run <em>only</em> detects "
+              "existence of 'callgrind.cmd' when actively running "
+              "a few milliseconds, i.e. "
+              "<em>not</em> sleeping. Tip: For a profiled GUI program, "
+              "you can awake Callgrind e.g. by resizing a window "
+              "of the program.</p>");
+  _taDump->setWhatsThis( hint );
+
+  action = KStdAction::open(TQT_TQOBJECT(this), TQT_SLOT(loadTrace()), actionCollection());
+  hint = i18n("<b>Open Profile Data</b>"
+              "<p>This opens a profile data file, with possible multiple parts</p>");
+  action->setToolTip( hint );
+  action->setWhatsThis( hint );
+
+  _openRecent = KStdAction::openRecent(TQT_TQOBJECT(this), TQT_SLOT(loadTrace(const KURL&)),
+                                       actionCollection());
+
+  KStdAction::showStatusbar(TQT_TQOBJECT(this),
+                            TQT_SLOT(toggleStatusBar()), actionCollection());
+
+  _partDockShown = new KToggleAction(i18n("Parts Overview"), KShortcut(),
+                                     TQT_TQOBJECT(this), TQT_SLOT(togglePartDock()),
+                                     actionCollection(),
+                                     "settings_show_partdock");
+
+  hint = i18n("Show/Hide the Parts Overview Dockable");
+  _partDockShown->setToolTip( hint );
+  _partDockShown->setWhatsThis( hint );
+
+  _stackDockShown = new KToggleAction(i18n("Call Stack"), KShortcut(),
+                                     TQT_TQOBJECT(this), TQT_SLOT(toggleStackDock()),
+                                     actionCollection(),
+                                     "settings_show_stackdock");
+
+  hint = i18n("Show/Hide the Call Stack Dockable");
+  _stackDockShown->setToolTip( hint );
+  _stackDockShown->setWhatsThis( hint );
+
+  _functionDockShown = new KToggleAction(i18n("Function Profile"), KShortcut(),
+                                         TQT_TQOBJECT(this), TQT_SLOT(toggleFunctionDock()),
+                                         actionCollection(),
+                                         "settings_show_profiledock");
+
+  hint = i18n("Show/Hide the Function Profile Dockable");
+  _functionDockShown->setToolTip( hint );
+  _functionDockShown->setWhatsThis( hint );
+
+#if ENABLE_DUMPDOCK
+  _dumpDockShown = new KToggleAction(i18n("Profile Dumps"), KShortcut(),
+                                     TQT_TQOBJECT(this), TQT_SLOT(toggleDumpDock()),
+                                     actionCollection(),
+                                     "settings_show_dumpdock");
+
+  hint = i18n("Show/Hide the Profile Dumps Dockable");
+  _dumpDockShown->setToolTip( hint );
+  _dumpDockShown->setWhatsThis( hint );
+#endif
+
+  _taPercentage = new KToggleAction(i18n("Show Relative Costs"), "percent",
+				    KShortcut(),
+				    TQT_TQOBJECT(this), TQT_SLOT(togglePercentage()),
+				    actionCollection(),
+				    "view_percentage");
+#if KDE_VERSION >= 0x030290
+  // for KDE 3.3: show another text instead of a checkmark
+  _taPercentage->setCheckedState(i18n("Show Absolute Costs"));
+#endif
+
+  hint = i18n("Show relative instead of absolute costs");
+  _taPercentage->setToolTip( hint );
+  _taPercentage->setWhatsThis( hint );
+
+  _taExpanded = new KToggleAction(i18n("Percentage Relative to Parent"), "move",
+				  KShortcut(),
+				  TQT_TQOBJECT(this), TQT_SLOT(toggleExpanded()),
+				  actionCollection(),
+				  "view_expanded");
+
+  hint = i18n("Show percentage costs relative to parent");
+  _taExpanded->setToolTip( hint );
+  _taExpanded->setWhatsThis( hint );
+
+  hint = i18n("<b>Show percentage costs relative to parent</b>"
+              "<p>If this is switched off, percentage costs are always shown "
+	      "relative to the total cost of the profile part(s) that are "
+	      "currently browsed. By turning on this option, percentage cost "
+	      "of shown cost items will be relative to the parent cost item."
+	      "<ul><table>"
+	      "<tr><td><b>Cost Type</td><td><b>Parent Cost</td></tr>"
+	      "<tr><td>Function Cumulative</td><td>Total</td></tr>"
+	      "<tr><td>Function Self</td><td>Function Group (*) / Total</td></tr>"
+	      "<tr><td>Call</td><td>Function Cumulative</td></tr>"
+	      "<tr><td>Source Line</td><td>Function Cumulative</td></tr>"
+	      "</table>"
+	      "<p>(*) Only if function grouping is switched on (e.g. ELF object grouping).");
+  _taExpanded->setWhatsThis( hint );
+
+  _taCycles = new KToggleAction( i18n( "Do Cycle Detection" ), "undo",
+				 KShortcut(),
+				 TQT_TQOBJECT(this), TQT_SLOT( toggleCycles() ), actionCollection(),
+				 "view_cycles" );
+#if KDE_VERSION >= 0x030290
+  // for KDE 3.3: show another text instead of a checkmark
+  _taCycles->setCheckedState(i18n("Skip Cycle Detection"));
+#endif
+
+  hint = i18n("<b>Detect recursive cycles</b>"
+              "<p>If this is switched off, the treemap drawing will show "
+	      "black areas when a recursive call is made instead of drawing the "
+	      "recursion ad infinitum. Note that "
+	      "the size of black areas often will be wrong, as inside recursive "
+              "cycles the cost of calls cannot be determined; the error is small, "
+              "however, for false cycles (see documentation)."
+	      "<p>The correct handling for cycles is to detect them and collapse all "
+              "functions of a cycle into a virtual function, which is done when this "
+              "option is selected. Unfortunately, with GUI applications, this often will "
+              "lead to huge false cycles, making the analysis impossible; therefore, there "
+              "is the option to switch this off.");
+  _taCycles->setWhatsThis( hint );
+
+  KStdAction::quit(TQT_TQOBJECT(this), TQT_SLOT(close()), actionCollection());
+  KStdAction::preferences(TQT_TQOBJECT(this), TQT_SLOT(configure()), actionCollection());
+  KStdAction::keyBindings(TQT_TQOBJECT(this), TQT_SLOT(configureKeys()), actionCollection());
+  KStdAction::configureToolbars(TQT_TQOBJECT(this),TQT_SLOT(configureToolbars()),
+                                actionCollection());
+#if 0
+  action = KStdAction::back(_stackSelection, TQT_SLOT(browserBack()),
+                            actionCollection());
+  hint = i18n("Go back in function selection history");
+  action->setToolTip( hint );
+  action->setWhatsThis( hint );
+
+  action = KStdAction::forward(_stackSelection, TQT_SLOT(browserForward()),
+                      actionCollection());
+  hint = i18n("Go forward in function selection history");
+  action->setToolTip( hint );
+  action->setWhatsThis( hint );
+
+  action = KStdAction::up(_stackSelection, TQT_SLOT(browserUp()),
+                      actionCollection());
+  hint = i18n("<b>Go Up</b>"
+              "<p>Go to last selected caller of current function. "
+              "If no caller was visited, use that with highest cost.</p>");
+  action->setToolTip( hint );
+  action->setWhatsThis( hint );
+#else
+  _paUp = new KToolBarPopupAction( i18n( "&Up" ), "up",
+                                   ALT+Key_Up,
+                                   TQT_TQOBJECT(_stackSelection), TQT_SLOT( browserUp() ),
+                                   actionCollection(), "go_up" );
+  connect( _paUp->popupMenu(), TQT_SIGNAL( aboutToShow() ),
+           TQT_TQOBJECT(this), TQT_SLOT( upAboutToShow() ) );
+  connect( _paUp->popupMenu(), TQT_SIGNAL( activated( int ) ),
+           TQT_TQOBJECT(this), TQT_SLOT( upActivated( int ) ) );
+  hint = i18n("<b>Go Up</b>"
+              "<p>Go to last selected caller of current function. "
+              "If no caller was visited, use that with highest cost.</p>");
+  _paUp->setToolTip( hint );
+  _paUp->setWhatsThis( hint );
+
+  TQPair< KGuiItem, KGuiItem > backForward = KStdGuiItem::backAndForward();
+  _paBack = new KToolBarPopupAction( backForward.first, ALT+Key_Left,
+                                     TQT_TQOBJECT(_stackSelection), TQT_SLOT(browserBack()),
+                                     actionCollection(), "go_back" );
+  connect( _paBack->popupMenu(), TQT_SIGNAL( aboutToShow() ),
+           TQT_TQOBJECT(this), TQT_SLOT( backAboutToShow() ) );
+  connect( _paBack->popupMenu(), TQT_SIGNAL( activated( int ) ),
+           TQT_TQOBJECT(this), TQT_SLOT( backActivated( int ) ) );
+  hint = i18n("Go back in function selection history");
+  _paBack->setToolTip( hint );
+  _paBack->setWhatsThis( hint );
+
+  _paForward = new KToolBarPopupAction( backForward.second, ALT+Key_Right,
+                                        TQT_TQOBJECT(_stackSelection),
+                                        TQT_SLOT(browserForward()),
+                                        actionCollection(), "go_forward" );
+  connect( _paForward->popupMenu(), TQT_SIGNAL( aboutToShow() ),
+           this, TQT_SLOT( forwardAboutToShow() ) );
+  connect( _paForward->popupMenu(), TQT_SIGNAL( activated( int ) ),
+           this, TQT_SLOT( forwardActivated( int ) ) );
+  hint = i18n("Go forward in function selection history");
+  _paForward->setToolTip( hint );
+  _paForward->setWhatsThis( hint );
+#endif
+
+  _saCost = new KSelectAction( i18n("Primary Event Type"), KShortcut(),
+			       actionCollection(), "view_cost_type");
+  hint = i18n("Select primary event type of costs");
+  _saCost->setComboWidth(300);
+  _saCost->setToolTip( hint );
+  _saCost->setWhatsThis( hint );
+
+  // cost types are dependent on loaded data, thus KSelectAction
+  // is filled in setData()
+  connect( _saCost, TQT_SIGNAL(activated(const TQString&)),
+           TQT_TQOBJECT(this), TQT_SLOT(costTypeSelected(const TQString&)));
+
+  _saCost2 = new KSelectAction( i18n("Secondary Event Type"), KShortcut(),
+				actionCollection(), "view_cost_type2");
+  hint = i18n("Select secondary event type for cost e.g. shown in annotations");
+  _saCost2->setComboWidth(300);
+  _saCost2->setToolTip( hint );
+  _saCost2->setWhatsThis( hint );
+
+  connect( _saCost2, TQT_SIGNAL(activated(const TQString&)),
+           TQT_TQOBJECT(this), TQT_SLOT(costType2Selected(const TQString&)));
+
+  saGroup = new KSelectAction( i18n("Grouping"), KShortcut(),
+                               actionCollection(), "view_group_type");
+
+  hint = i18n("Select how functions are grouped into higher level cost items");
+  saGroup->setToolTip( hint );
+  saGroup->setWhatsThis( hint );
+
+  TQStringList args;
+
+  args << i18n("(No Grouping)")
+       << TraceCost::i18nTypeName(TraceItem::Object)
+       << TraceCost::i18nTypeName(TraceItem::File)
+       << TraceCost::i18nTypeName(TraceItem::Class)
+       << TraceCost::i18nTypeName(TraceItem::FunctionCycle);
+
+  saGroup->setItems(args);
+  connect( saGroup, TQT_SIGNAL(activated(int)),
+           TQT_TQOBJECT(this), TQT_SLOT(groupTypeSelected(int)));
+
+  _taSplit = new KToggleAction(i18n("Split"), "view_left_right", KShortcut(),
+                               TQT_TQOBJECT(this), TQT_SLOT(splitSlot()),
+                               actionCollection(), "view_split");
+
+  hint = i18n("Show two information panels");
+  _taSplit->setToolTip( hint );
+  _taSplit->setWhatsThis( hint );
+
+ _taSplitDir = new KToggleAction(i18n("SplitQt::Horizontal"),
+                                  "view_left_right", KShortcut(),
+                                  TQT_TQOBJECT(this), TQT_SLOT(splitDirSlot()),
+                                  actionCollection(), "view_split_dir");
+
+  hint = i18n("Change Split Qt::Orientation when main window is split.");
+  _taSplitDir->setToolTip( hint );
+  _taSplitDir->setWhatsThis( hint );
+
+  // copied from KMail...
+#if KDE_VERSION >= 308 // KDE 3.1
+  KStdAction::tipOfDay( TQT_TQOBJECT(this), TQT_SLOT( slotShowTip() ), actionCollection() );
+#else
+  (void) new KAction( KGuiItem( i18n("Tip of the &Day..."), "idea",
+                                i18n("Show \"Tip of the Day\"") ),
+                      0, TQT_TQOBJECT(this), TQT_SLOT(slotShowTip()),
+                      actionCollection(), "help_show_tip" );
+#endif
+}
+
+void TopLevel::createActions()
+{
+  createMiscActions();
+  createLayoutActions();
+}
+
+void TopLevel::toggleStatusBar()
+{
+  if (statusBar()->isVisible())
+    statusBar()->hide();
+  else
+    statusBar()->show();
+}
+
+void TopLevel::togglePartDock()
+{
+  if (!_partDock->isVisible())
+    _partDock->show();
+  else
+    _partDock->hide();
+}
+
+void TopLevel::toggleStackDock()
+{
+  if (!_stackDock->isVisible())
+    _stackDock->show();
+  else
+    _stackDock->hide();
+}
+
+void TopLevel::toggleDumpDock()
+{
+#if ENABLE_DUMPDOCK
+  if (!_dumpDock->isVisible())
+    _dumpDock->show();
+  else
+    _dumpDock->hide();
+#endif
+}
+
+void TopLevel::toggleFunctionDock()
+{
+  if (!_functionDock->isVisible())
+    _functionDock->show();
+  else
+    _functionDock->hide();
+}
+
+void TopLevel::togglePercentage()
+{
+  setPercentage(_taPercentage->isChecked());
+}
+
+void TopLevel::setAbsoluteCost()
+{
+  setPercentage(false);
+}
+
+void TopLevel::setRelativeCost()
+{
+  setPercentage(true);
+}
+
+void TopLevel::setPercentage(bool show)
+{
+  if (_showPercentage == show) return;
+  _showPercentage = show;
+  if (_taPercentage->isChecked() != show)
+    _taPercentage->setChecked(show);
+
+  // FIXME: Delete when no view gets this config from Configuration
+  Configuration::setShowPercentage(_showPercentage);
+
+  _partSelection->refresh();
+  _stackSelection->refresh();
+
+  _functionSelection->notifyChange(TraceItemView::configChanged);
+  _functionSelection->updateView();
+
+  _multiView->notifyChange(TraceItemView::configChanged);
+  _multiView->updateView();
+}
+
+void TopLevel::toggleExpanded()
+{
+  bool show = _taExpanded->isChecked();
+  if (_showExpanded == show) return;
+  _showExpanded = show;
+
+  // FIXME: Delete when no view gets this config from Configuration
+  Configuration::setShowExpanded(_showExpanded);
+
+  _partSelection->refresh();
+  _stackSelection->refresh();
+
+  _functionSelection->notifyChange(TraceItemView::configChanged);
+  _functionSelection->updateView();
+
+  _multiView->notifyChange(TraceItemView::configChanged);
+  _multiView->updateView();
+}
+
+void TopLevel::toggleCycles()
+{
+  bool show = _taCycles->isChecked();
+  if (_showCycles == show) return;
+  _showCycles = show;
+
+  // FIXME: Delete when no view gets this config from Configuration
+  Configuration::setShowCycles(_showCycles);
+
+  if (!_data) return;
+
+  _data->invalidateDynamicCost();
+  _data->updateFunctionCycles();
+
+  _partSelection->refresh();
+  _stackSelection->rebuildStackList();
+
+  _functionSelection->notifyChange(TraceItemView::configChanged);
+  _functionSelection->updateView();
+
+  _multiView->notifyChange(TraceItemView::configChanged);
+  _multiView->updateView();
+}
+
+void TopLevel::partVisibilityChanged(bool v)
+{
+  _partDockShown->setChecked(v);
+}
+
+void TopLevel::stackVisibilityChanged(bool v)
+{
+  _stackDockShown->setChecked(v);
+}
+
+#if ENABLE_DUMPDOCK
+void TopLevel::dumpVisibilityChanged(bool v)
+#else
+void TopLevel::dumpVisibilityChanged(bool)
+#endif
+{
+#if ENABLE_DUMPDOCK
+  _dumpDockShown->setChecked(v);
+#endif
+}
+
+void TopLevel::functionVisibilityChanged(bool v)
+{
+  _functionDockShown->setChecked(v);
+  if (v)
+    _functionSelection->updateView();
+}
+
+
+void TopLevel::querySlot()
+{
+  _functionSelection->query(queryLineEdit->text());
+}
+
+void TopLevel::configureKeys()
+{
+#if KDE_VERSION > 0x030190
+  // for KDE 3.2: KKeyDialog::configureKeys is deprecated
+  KKeyDialog::configure(actionCollection(), this, true);
+#else
+  KKeyDialog::configureKeys(actionCollection(), xmlFile(), true, this);
+#endif
+}
+
+
+void TopLevel::configureToolbars()
+{
+  KEditToolbar *dlg = new KEditToolbar(guiFactory(),this);
+
+  if (dlg->exec())
+    createGUI();
+
+  delete dlg;
+}
+
+
+void TopLevel::newTrace()
+{
+  // start cachegrind on command...
+}
+
+void TopLevel::newWindow()
+{
+  TopLevel* t = new TopLevel(0);
+  t->show();
+}
+
+
+void TopLevel::loadTrace()
+{
+    KURL url = KFileDialog::getOpenURL(":",
+                                       i18n("cachegrind.out* callgrind.out*|Callgrind Profile Data\n*|All Files"),
+                                       this,
+                                       i18n("Select Callgrind Profile Data"));
+    loadTrace(url);
+}
+
+void TopLevel::loadTrace(const KURL& url)
+{
+  if (url.isEmpty()) return;
+
+  // network transparancy
+  TQString tmpFile;
+#if KDE_VERSION > 0x030190
+  // for KDE 3.2: KIO::NetAccess::download with 2 args is deprecated
+  if(KIO::NetAccess::download( url, tmpFile, this )) {
+#else
+  if(KIO::NetAccess::download( url, tmpFile )) {
+#endif
+    _openRecent->addURL(url);
+    _openRecent->saveEntries( KGlobal::config() );
+
+    loadTrace(tmpFile);
+    KIO::NetAccess::removeTempFile( tmpFile );
+  }
+}
+
+void TopLevel::loadTrace(TQString file)
+{
+  if (file.isEmpty()) return;
+
+  if (_data && _data->parts().count()>0) {
+
+    // In new window
+    TopLevel* t = new TopLevel();
+    t->show();
+    t->loadDelayed(file);
+    return;
+  }
+
+  // this constructor enables progress bar callbacks
+  TraceData* d = new TraceData(this);
+  d->load(file);
+  setData(d);
+}
+
+
+void TopLevel::addTrace()
+{
+    KURL url = KFileDialog::getOpenURL(TQString(),
+                                       i18n("cachegrind.out* callgrind.out*|Callgrind Profile Data\n*|All Files"),
+                                       this,
+                                       i18n("Add Callgrind Profile Data"));
+    addTrace(url);
+}
+
+void TopLevel::addTrace(const KURL& url)
+{
+  if (url.isEmpty()) return;
+
+  // network transparancy
+  TQString tmpFile;
+#if KDE_VERSION > 0x030190
+  // for KDE 3.2: KIO::NetAccess::download with 2 args is deprecated
+  if(KIO::NetAccess::download( url, tmpFile, this )) {
+#else
+  if(KIO::NetAccess::download( url, tmpFile )) {
+#endif
+    _openRecent->addURL(url);
+    _openRecent->saveEntries( KGlobal::config() );
+
+    addTrace(tmpFile);
+    KIO::NetAccess::removeTempFile( tmpFile );
+  }
+}
+
+void TopLevel::addTrace(TQString file)
+{
+  if (file.isEmpty()) return;
+
+  if (_data) {
+    _data->load(file);
+
+    // GUI update for added data
+    configChanged();
+    return;
+  }
+
+  // this constructor enables progress bar callbacks
+  TraceData* d = new TraceData(this);
+  d->load(file);
+  setData(d);
+}
+
+
+
+void TopLevel::loadDelayed(TQString file)
+{
+  _loadTraceDelayed = file;
+  TQTimer::singleShot(0, TQT_TQOBJECT(this), TQT_SLOT(loadTraceDelayed()));
+}
+
+void TopLevel::loadTraceDelayed()
+{
+  if (_loadTraceDelayed.isEmpty()) return;
+
+  loadTrace(_loadTraceDelayed);
+  _loadTraceDelayed = TQString();
+}
+
+
+void TopLevel::reload()
+{
+  TQString trace;
+  if (!_data || _data->parts().count()==0)
+    trace = "."; // open first trace found in dir
+  else
+    trace = _data->traceName();
+
+  // this also keeps sure we have the same browsing position...
+  TraceData* d = new TraceData(this);
+  d->load(trace);
+  setData(d);
+}
+
+void TopLevel::exportGraph()
+{
+  if (!_data || !_function) return;
+
+  TQString n = TQString("callgraph.dot");
+  GraphExporter ge(_data, _function, _costType, _groupType, n);
+  ge.writeDot();
+
+  TQString cmd = TQString("(dot %1 -Tps > %2.ps; kghostview %3.ps)&")
+                .arg(n).arg(n).arg(n);
+  system(TQFile::encodeName( cmd ));
+}
+
+
+bool TopLevel::setCostType(TQString s)
+{
+  TraceCostType* ct;
+
+  ct = (_data) ? _data->mapping()->type(s) : 0;
+
+  // if costtype with given name not found, use first available
+  if (!ct && _data) ct = _data->mapping()->type(0);
+
+  return setCostType(ct);
+}
+
+bool TopLevel::setCostType2(TQString s)
+{
+  TraceCostType* ct;
+
+  // Special type i18n("(Hidden)") gives 0
+  ct = (_data) ? _data->mapping()->type(s) : 0;
+
+  return setCostType2(ct);
+}
+
+void TopLevel::costTypeSelected(const TQString& s)
+{
+  TraceCostType* ct;
+
+  ct = (_data) ? _data->mapping()->typeForLong(s) : 0;
+  setCostType(ct);
+}
+
+void TopLevel::costType2Selected(const TQString& s)
+{
+  TraceCostType* ct;
+
+  ct = (_data) ? _data->mapping()->typeForLong(s) : 0;
+  setCostType2(ct);
+}
+
+bool TopLevel::setCostType(TraceCostType* ct)
+{
+  if (_costType == ct) return false;
+  _costType = ct;
+
+  if (ct) {
+      int idx=0;
+      TQStringList l = _saCost->items();
+      for (TQStringList::Iterator it = l.begin(); it != l.end(); ++it, ++idx ) {
+	  if (*it == ct->longName())
+	      _saCost->setCurrentItem(idx);
+      }
+  }
+
+  _partSelection->setCostType(_costType);
+  _stackSelection->setCostType(_costType);
+
+  _functionSelection->setCostType(_costType);
+  _functionSelection->updateView();
+
+  _multiView->setCostType(_costType);
+  _multiView->updateView();
+
+  updateStatusBar();
+
+  return true;
+}
+
+bool TopLevel::setCostType2(TraceCostType* ct)
+{
+  if (_costType2 == ct) return false;
+  _costType2 = ct;
+
+  TQString longName = ct ? ct->longName() : i18n("(Hidden)");
+
+  int idx=0;
+  TQStringList l = _saCost2->items();
+  for (TQStringList::Iterator it = l.begin(); it != l.end(); ++it, ++idx ) {
+    if (*it == longName)
+      _saCost2->setCurrentItem(idx);
+  }
+
+  _partSelection->setCostType2(_costType2);
+  _stackSelection->setCostType2(_costType2);
+
+  _functionSelection->setCostType2(_costType2);
+  _functionSelection->updateView();
+
+  _multiView->setCostType2(_costType2);
+  _multiView->updateView();
+
+  updateStatusBar();
+
+  return true;
+}
+
+
+void TopLevel::groupTypeSelected(int cg)
+{
+  switch(cg) {
+  case 0: setGroupType( TraceItem::Function ); break;
+  case 1: setGroupType( TraceItem::Object ); break;
+  case 2: setGroupType( TraceItem::File ); break;
+  case 3: setGroupType( TraceItem::Class ); break;
+  case 4: setGroupType( TraceItem::FunctionCycle ); break;
+  default: break;
+  }
+}
+
+bool TopLevel::setGroupType(TQString s)
+{
+  TraceItem::CostType gt;
+
+  gt = (_data) ? _data->costType(s) : TraceData::costType(s);
+  // only allow Function/Object/File/Class as grouptype
+  switch(gt) {
+  case TraceItem::Object:
+  case TraceItem::File:
+  case TraceItem::Class:
+  case TraceItem::FunctionCycle:
+    break;
+  default:
+    gt = TraceItem::Function;
+  }
+
+  return setGroupType(gt);
+}
+
+bool TopLevel::setGroupType(TraceItem::CostType gt)
+{
+  if (_groupType == gt) return false;
+  _groupType = gt;
+
+  int idx = -1;
+  switch(gt) {
+  case TraceItem::Function: idx = 0; break;
+  case TraceItem::Object: idx = 1; break;
+  case TraceItem::File: idx = 2; break;
+  case TraceItem::Class: idx = 3; break;
+  case TraceItem::FunctionCycle: idx = 4; break;
+  default:
+    break;
+  }
+
+  if (idx==-1) return false;
+
+  if (saGroup->currentItem() != idx)
+    saGroup->setCurrentItem(idx);
+
+  _stackSelection->setGroupType(_groupType);
+  _partSelection->setGroupType(_groupType);
+
+  _functionSelection->set(_groupType);
+  _functionSelection->updateView();
+
+  _multiView->set(_groupType);
+  _multiView->updateView();
+
+  updateStatusBar();
+
+  return true;
+}
+
+bool TopLevel::setGroup(TQString s)
+{
+    return true;
+  TraceCostItem* ci = _functionSelection->group(s);
+  if (!ci)
+    return false;
+
+  return setGroup(ci);
+}
+
+
+bool TopLevel::setGroup(TraceCostItem* g)
+{
+  _multiView->activate(g);
+  _multiView->updateView();
+  _functionSelection->activate(g);
+  _functionSelection->updateView();
+
+  if (_group == g) return false;
+  _group = g;
+
+
+  updateStatusBar();
+
+  return true;
+}
+
+bool TopLevel::setFunction(TQString s)
+{
+  if (!_data) return false;
+
+  TraceCost* f = _data->search(TraceItem::Function, s, _costType);
+  if (!f) return false;
+
+  return setFunction((TraceFunction*)f);
+}
+
+bool TopLevel::setFunction(TraceFunction* f)
+{
+  _multiView->activate(f);
+  _multiView->updateView();
+
+  _functionSelection->activate(f);
+  _functionSelection->updateView();
+
+  if (_function == f) return false;
+  _function = f;
+
+  _partSelection->setFunction(_function);
+  _stackSelection->setFunction(_function);
+
+  StackBrowser* b = _stackSelection->browser();
+  if (b) {
+    // don't disable up: a press forces stack-up extending...
+    _paForward->setEnabled(b->canGoForward());
+    _paBack->setEnabled(b->canGoBack());
+  }
+
+#if TRACE_UPDATES
+  qDebug("TopLevel::setFunction(%s), lastSender %s",
+         f ? f->prettyName().ascii() : "0",
+         _lastSender ? _lastSender->name() :"0" );
+#endif
+
+  return true;
+}
+
+
+/**
+ * Delayed versions.
+ * We always have a pair of slots: One receiver to start the
+ * delay with a singleShot Timer. It stores the parameter into a
+ * temporary variable. And one parameterless slot for
+ * forwarding, using this temporary.
+ */
+void TopLevel::setCostTypeDelayed(TraceCostType* ct)
+{
+  _costTypeDelayed = ct;
+  TQTimer::singleShot (0, TQT_TQOBJECT(this), TQT_SLOT(setCostTypeDelayed()));
+}
+
+void TopLevel::setCostType2Delayed(TraceCostType* ct)
+{
+  _costType2Delayed = ct;
+  TQTimer::singleShot (0, TQT_TQOBJECT(this), TQT_SLOT(setCostType2Delayed()));
+}
+
+void TopLevel::setCostTypeDelayed()
+{
+  setCostType(_costTypeDelayed);
+}
+
+void TopLevel::setCostType2Delayed()
+{
+  setCostType2(_costType2Delayed);
+}
+
+void TopLevel::setGroupTypeDelayed(TraceItem::CostType gt)
+{
+  _groupTypeDelayed = gt;
+  TQTimer::singleShot (0, TQT_TQOBJECT(this), TQT_SLOT(setGroupTypeDelayed()));
+}
+
+void TopLevel::setGroupTypeDelayed()
+{
+  setGroupType(_groupTypeDelayed);
+}
+
+void TopLevel::setGroupDelayed(TraceCostItem* g)
+{
+#if TRACE_UPDATES
+  qDebug("TopLevel::setGroupDelayed(%s), sender %s",
+         g ? g->prettyName().ascii() : "0",
+         _lastSender ? _lastSender->name() :"0" );
+#endif
+
+  _groupDelayed = g;
+  TQTimer::singleShot (0, TQT_TQOBJECT(this), TQT_SLOT(setGroupDelayed()));
+}
+
+void TopLevel::setGroupDelayed()
+{
+  setGroup(_groupDelayed);
+}
+
+void TopLevel::setDirectionDelayed(TraceItemView::Direction d)
+{
+  _directionDelayed = d;
+  TQTimer::singleShot (0, TQT_TQOBJECT(this), TQT_SLOT(setDirectionDelayed()));
+}
+
+void TopLevel::setDirectionDelayed()
+{
+    switch(_directionDelayed) {
+    case TraceItemView::Back:
+	_stackSelection->browserBack();
+	break;
+
+    case TraceItemView::Forward:
+    	_stackSelection->browserForward();
+	break;
+
+    case TraceItemView::Up:
+	{
+	    StackBrowser* b = _stackSelection ? _stackSelection->browser() : 0;
+	    HistoryItem* hi = b ? b->current() : 0;
+	    TraceFunction* f = hi ? hi->function() : 0;
+
+	    if (!f) break;
+	    f = hi->stack()->caller(f, false);
+	    if (f) setFunction(f);
+	}
+    break;
+
+    default: break;
+    }
+
+    _directionDelayed = TraceItemView::None;
+}
+
+
+void TopLevel::setTraceItemDelayed(TraceItem* i)
+{
+  // no need to select same item a 2nd time...
+  if (_traceItemDelayed == i) return;
+  _traceItemDelayed = i;
+  _lastSender = TQT_TQOBJECT(const_cast<TQT_BASE_OBJECT_NAME*>(sender()));
+
+  kdDebug() << "Selected " << (i ? i->prettyName() : "(none)") << endl;
+
+#if TRACE_UPDATES
+  qDebug("TopLevel::setTraceItemDelayed(%s), sender %s",
+         i ? i->prettyName().ascii() : "0",
+         _lastSender ? _lastSender->name() :"0" );
+#endif
+
+  TQTimer::singleShot (0, TQT_TQOBJECT(this), TQT_SLOT(setTraceItemDelayed()));
+}
+
+void TopLevel::setTraceItemDelayed()
+{
+    if (!_traceItemDelayed) return;
+
+    switch(_traceItemDelayed->type()) {
+    case TraceItem::Function:
+    case TraceItem::FunctionCycle:
+      setFunction((TraceFunction*)_traceItemDelayed);
+      break;
+
+    case TraceItem::Object:
+    case TraceItem::File:
+    case TraceItem::Class:
+	setGroup((TraceCostItem*)_traceItemDelayed);
+	break;
+
+#if 0
+	// this conflicts with the selection policy of InstrView ?!?
+    case TraceItem::Instr:
+    case TraceItem::Line:
+	// only for multiview
+	_multiView->activate(_traceItemDelayed);
+	_multiView->updateView();
+	break;
+#endif
+
+    default: break;
+    }
+
+    _traceItemDelayed = 0;
+    _lastSender = 0;
+}
+
+/**
+ * A TraceData object cannot be viewed many times in different
+ * toplevel windows. Thus, this toplevel window takes ownership
+ * of the TraceData object: on closing the window or opening
+ * another trace, the object is destroyed.
+ */
+void TopLevel::setData(TraceData* data)
+{
+  if (data == _data) return;
+
+  _lastSender = 0;
+
+  saveTraceSettings();
+
+  if (_data) {
+    _partSelection->setData(0);
+    _stackSelection->setData(0);
+
+    _functionSelection->setData(0);
+    _functionSelection->updateView();
+    _multiView->setData(0);
+    _multiView->updateView();
+
+    // we are the owner...
+    delete _data;
+  }
+
+  // reset members
+  init();
+
+  _data = data;
+
+  // fill cost type list
+  TQStringList types;
+
+  if (_data) {
+      /* add all supported virtual types */
+      TraceCostMapping* m = _data->mapping();
+      m->addKnownVirtualTypes();
+
+      /* first, fill selection list with available cost types */
+      for (int i=0;i<m->realCount();i++)
+	  types << m->realType(i)->longName();
+      for (int i=0;i<m->virtualCount();i++)
+	  types << m->virtualType(i)->longName();
+  }
+  _saCost->setItems(types);
+  _saCost->setComboWidth(300);
+
+  if (types.count()>0) {
+    // second type list gets an additional "(Hidden)"
+    types.prepend(i18n("(Hidden)"));
+  }
+  _saCost2->setItems(types);
+  _saCost2->setComboWidth(300);
+  // default is hidden
+  if (types.count()>0)
+    _saCost2->setCurrentItem(0);
+
+  _partSelection->setData(_data);
+  _stackSelection->setData(_data);
+  _functionSelection->setData(_data);
+  _functionSelection->updateView();
+  _multiView->setData(_data);
+  _multiView->updateView();
+
+  /* this is needed to let the other widgets know the types */
+  restoreTraceTypes();
+
+  restoreTraceSettings();
+
+  TQString caption;
+  if (_data) {
+    caption = _data->traceName();
+    if (!_data->command().isEmpty())
+      caption += " [" + _data->command() + "]";
+  }
+  setCaption(caption);
+
+  if (!_data || (!_forcePartDock && _data->parts().count()<2)) {
+    _partDock->hide();
+    _partDockShown->setChecked(false);
+  }
+  else {
+    _partDock->show();
+    _partDockShown->setChecked(true);
+  }
+
+  updateStatusBar();
+}
+
+void TopLevel::addCostMenu(TQPopupMenu* popup, bool withCost2)
+{
+  if (_data) {
+    TQPopupMenu *popup1 = new TQPopupMenu(popup);
+    TQPopupMenu *popup2 = 0;
+    popup1->setCheckable(true);
+
+    if (withCost2) {
+      popup2 = new TQPopupMenu(popup);
+      popup2->setCheckable(true);
+
+      if (_costType2) {
+	popup2->insertItem(i18n("Hide"),199);
+	popup2->insertSeparator();
+      }
+    }
+
+    TraceCostMapping* m = _data->mapping();
+    TraceCostType* ct;
+    for (int i=0;i<m->realCount();i++) {
+      ct = m->realType(i);
+      popup1->insertItem(ct->longName(), 100+i);
+      if (_costType == ct) popup1->setItemChecked(100+i,true);
+      if (popup2) {
+	popup2->insertItem(ct->longName(), 100+i);
+	if (_costType2 == ct) popup2->setItemChecked(100+i,true);
+      }
+    }
+    for (int i=0;i<m->virtualCount();i++) {
+      ct = m->virtualType(i);
+      popup1->insertItem(ct->longName(), 200+i);
+      if (_costType == ct) popup1->setItemChecked(200+i,true);
+      if (popup2) {
+	popup2->insertItem(ct->longName(), 200+i);
+	if (_costType2 == ct) popup2->setItemChecked(200+i,true);
+      }
+    }
+    popup->insertItem(i18n("Primary Event Type"), popup1);
+    connect(popup1,TQT_SIGNAL(activated(int)),this,TQT_SLOT(setCostType(int)));
+    if (popup2) {
+      popup->insertItem(i18n("Secondary Event Type"), popup2);
+      connect(popup2,TQT_SIGNAL(activated(int)),this,TQT_SLOT(setCostType2(int)));
+    }
+  }
+  if (_showPercentage)
+    popup->insertItem(i18n("Show Absolute Cost"),
+		      TQT_TQOBJECT(this), TQT_SLOT(setAbsoluteCost()));
+  else
+    popup->insertItem(i18n("Show Relative Cost"),
+		      TQT_TQOBJECT(this), TQT_SLOT(setRelativeCost()));
+}
+
+bool TopLevel::setCostType(int id)
+{
+  if (!_data) return false;
+
+  TraceCostMapping* m = _data->mapping();
+  TraceCostType* ct=0;
+  if (id >=100 && id<199) ct = m->realType(id-100);
+  if (id >=200 && id<299) ct = m->virtualType(id-200);
+
+  return ct ? setCostType(ct) : false;
+}
+
+bool TopLevel::setCostType2(int id)
+{
+  if (!_data) return false;
+
+  TraceCostMapping* m = _data->mapping();
+  TraceCostType* ct=0;
+  if (id >=100 && id<199) ct = m->realType(id-100);
+  if (id >=200 && id<299) ct = m->virtualType(id-200);
+
+  return setCostType2(ct);
+}
+
+void TopLevel::addGoMenu(TQPopupMenu* popup)
+{
+  popup->insertItem(i18n("Go Back"), TQT_TQOBJECT(this), TQT_SLOT(goBack()));
+  popup->insertItem(i18n("Go Forward"), TQT_TQOBJECT(this), TQT_SLOT(goForward()));
+  popup->insertItem(i18n("Go Up"), TQT_TQOBJECT(this), TQT_SLOT(goUp()));
+}
+
+void TopLevel::goBack()
+{
+  setDirectionDelayed(TraceItemView::Back);
+}
+
+void TopLevel::goForward()
+{
+  setDirectionDelayed(TraceItemView::Forward);
+}
+
+void TopLevel::goUp()
+{
+  setDirectionDelayed(TraceItemView::Up);
+}
+
+TQString TopLevel::traceKey()
+{
+  if (!_data || _data->command().isEmpty()) return TQString();
+
+  TQString name = _data->command();
+  TQString key;
+  for (unsigned int l=0;l<name.length();l++)
+    if (name[l].isLetterOrNumber()) key += name[l];
+
+  return TQString("-") + key;
+}
+
+
+void TopLevel::restoreTraceTypes()
+{
+  TQString key = traceKey();
+
+  KConfigGroup cConfig(KGlobal::config(), TQCString("CurrentState"));
+  KConfigGroup pConfig(KGlobal::config(), TQCString("TracePositions"));
+
+  TQString groupType, costType, costType2;
+  groupType =  pConfig.readEntry(TQString("GroupType%1").arg(key));
+  costType  =  pConfig.readEntry(TQString("CostType%1").arg(key));
+  costType2 =  pConfig.readEntry(TQString("CostType2%1").arg(key));
+
+  if (groupType.isEmpty()) groupType = cConfig.readEntry("GroupType");
+  if (costType.isEmpty()) costType = cConfig.readEntry("CostType");
+  if (costType2.isEmpty()) costType2 = cConfig.readEntry("CostType2");
+
+  setGroupType(groupType);
+  setCostType(costType);
+  setCostType2(costType2);
+
+  // if still no cost type set, use first available
+  if (!_costType && !_saCost->items().isEmpty())
+      costTypeSelected(_saCost->items().first());
+
+  KConfigGroup aConfig(KGlobal::config(), TQCString("Layouts"));
+  _layoutCount = aConfig.readNumEntry(TQString("Count%1").arg(key), 0);
+  _layoutCurrent = aConfig.readNumEntry(TQString("Current%1").arg(key), 0);
+  if (_layoutCount == 0) layoutRestore();
+  updateLayoutActions();
+}
+
+
+/**
+ * This must be called after setting group/cost types in the function
+ * selection widget, because the group/function choosing depends on
+ * filled lists in the function selection widget
+ */
+void TopLevel::restoreTraceSettings()
+{
+  if (!_data) return;
+
+  TQString key = traceKey();
+
+  KConfigGroup pConfig(KGlobal::config(), TQCString("TracePositions"));
+  TQString group = pConfig.readEntry(TQString("Group%1").arg(key));
+  if (!group.isEmpty()) setGroup(group);
+
+  restoreCurrentState(key);
+
+  // restoreCurrentState() usually leads to a call to setTraceItemDelayed()
+  // to restore last active item...
+  if (!_traceItemDelayed) {
+    // function not available any more.. try with "main"
+    if (!setFunction("main"))
+      _functionSelection->setTopFunction();
+  }
+}
+
+
+/* Layout */
+
+void TopLevel::layoutDuplicate()
+{
+  // save current and allocate a new slot
+  _multiView->saveViewConfig(KGlobal::config(),
+			     TQString("Layout%1-MainView").arg(_layoutCurrent),
+			     traceKey(), false);
+  _layoutCurrent = _layoutCount;
+  _layoutCount++;
+
+  updateLayoutActions();
+
+  kdDebug() << "TopLevel::layoutDuplicate: count " << _layoutCount << endl;
+}
+
+void TopLevel::layoutRemove()
+{
+  if (_layoutCount <2) return;
+
+  int from = _layoutCount-1;
+  if (_layoutCurrent == from) { _layoutCurrent--; from--; }
+  // restore from last and decrement count
+  _multiView->readViewConfig(KGlobal::config(),
+			     TQString("Layout%1-MainView").arg(from),
+			     traceKey(), false);
+  _layoutCount--;
+
+  updateLayoutActions();
+}
+
+void TopLevel::layoutNext()
+{
+  if (_layoutCount <2) return;
+
+  KConfig* config = KGlobal::config();
+  TQString key = traceKey();
+
+  _multiView->saveViewConfig(config,
+			     TQString("Layout%1-MainView").arg(_layoutCurrent),
+			     key, false);
+  _layoutCurrent++;
+  if (_layoutCurrent == _layoutCount) _layoutCurrent = 0;
+
+  _multiView->readViewConfig(config,
+			     TQString("Layout%1-MainView").arg(_layoutCurrent),
+			     key, false);
+
+  if (0) kdDebug() << "TopLevel::layoutNext: current "
+		   << _layoutCurrent << endl;
+}
+
+void TopLevel::layoutPrevious()
+{
+  if (_layoutCount <2) return;
+
+  KConfig* config = KGlobal::config();
+  TQString key = traceKey();
+
+  _multiView->saveViewConfig(config,
+			     TQString("Layout%1-MainView").arg(_layoutCurrent),
+			     key, false);
+  _layoutCurrent--;
+  if (_layoutCurrent <0) _layoutCurrent = _layoutCount-1;
+
+  _multiView->readViewConfig(config,
+			     TQString("Layout%1-MainView").arg(_layoutCurrent),
+			     key, false);
+
+  if (0) kdDebug() << "TopLevel::layoutPrevious: current "
+		   << _layoutCurrent << endl;
+}
+
+void TopLevel::layoutSave()
+{
+  KConfig* config = KGlobal::config();
+  TQString key = traceKey();
+
+  _multiView->saveViewConfig(config,
+			     TQString("Layout%1-MainView").arg(_layoutCurrent),
+			     key, false);
+
+  for(int i=0;i<_layoutCount;i++) {
+    _multiView->readViewConfig(config,
+			       TQString("Layout%1-MainView").arg(i),
+			       key, false);
+    _multiView->saveViewConfig(config,
+			       TQString("Layout%1-MainView").arg(i),
+			       TQString(), false);
+  }
+
+  _multiView->readViewConfig(config,
+			     TQString("Layout%1-MainView").arg(_layoutCurrent),
+			     key, false);
+
+  KConfigGroup aConfig(config, TQCString("Layouts"));
+  aConfig.writeEntry("DefaultCount", _layoutCount);
+  aConfig.writeEntry("DefaultCurrent", _layoutCurrent);
+}
+
+void TopLevel::layoutRestore()
+{
+  KConfig* config = KGlobal::config();
+  KConfigGroup aConfig(config, TQCString("Layouts"));
+  _layoutCount = aConfig.readNumEntry("DefaultCount", 0);
+  _layoutCurrent = aConfig.readNumEntry("DefaultCurrent", 0);
+  if (_layoutCount == 0) {
+    _layoutCount++;
+    return;
+  }
+
+  TQString key = traceKey();
+  for(int i=0;i<_layoutCount;i++) {
+    _multiView->readViewConfig(config,
+			       TQString("Layout%1-MainView").arg(i),
+			       TQString(), false);
+    _multiView->saveViewConfig(config,
+			       TQString("Layout%1-MainView").arg(i),
+			       key, false);
+  }
+
+  _multiView->readViewConfig(config,
+			     TQString("Layout%1-MainView").arg(_layoutCurrent),
+			     key, false);
+
+  updateLayoutActions();
+}
+
+
+void TopLevel::updateLayoutActions()
+{
+  KAction* ka;
+
+  ka = actionCollection()->action("layout_next");
+  if (ka) ka->setEnabled(_layoutCount>1);
+
+  ka = actionCollection()->action("layout_previous");
+  if (ka) ka->setEnabled(_layoutCount>1);
+
+  ka = actionCollection()->action("layout_remove");
+  if (ka) ka->setEnabled(_layoutCount>1);
+
+  _statusbar->message(i18n("Layout Count: %1").arg(_layoutCount), 1000);
+}
+
+
+void TopLevel::updateStatusBar()
+{
+  if (!_data || _data->parts().count()==0) {
+    _statusLabel->setText(i18n("No profile data file loaded."));
+    return;
+  }
+
+  TQString status = TQString("%1 [%2] - ")
+                   .arg(_data->shortTraceName())
+                   .arg(_data->activePartRange());
+
+  if (_costType) {
+    status += i18n("Total %1 Cost: %2")
+      .arg(_costType->longName())
+      .arg(_data->prettySubCost(_costType));
+
+    /* this gets too long...
+    if (_costType2 && (_costType2 != _costType))
+      status += i18n(", %1 Cost: %2")
+	.arg(_costType2->longName())
+	.arg(_data->prettySubCost(_costType2));
+    */
+  }
+  else
+    status += i18n("No event type selected");
+
+  /* Not working... should give group of selected function
+  
+  if (_groupType != TraceItem::Function) {
+    status += TQString(" - %1 '%2'")
+              .arg(TraceItem::i18nTypeName(_groupType))
+              .arg(_group ? _group->prettyName() : i18n("(None)"));
+  }
+  */
+
+  _statusLabel->setText(status);
+}
+
+void TopLevel::configure()
+{
+  if (ConfigDlg::configure(Configuration::config(), _data, this)) {
+    Configuration::saveOptions(KGlobal::config());
+
+    configChanged();
+  }
+  else
+    Configuration::readOptions(KGlobal::config());
+}
+
+bool TopLevel::queryClose()
+{
+  saveTraceSettings();
+
+  return true;
+}
+
+bool TopLevel::queryExit()
+{
+    // save current toplevel options as defaults...
+    Configuration::setShowPercentage(_showPercentage);
+    Configuration::setShowExpanded(_showExpanded);
+    Configuration::setShowCycles(_showCycles);
+    Configuration::saveOptions(KGlobal::config());
+
+    saveCurrentState(TQString());
+
+  // save QT dock positions...
+
+  // We don't want to save the KToolbar position here.
+  // Its already stored.
+  delete toolBar();
+
+  KConfigGroup dockConfig(KGlobal::config(), TQCString("Docks"));
+  TQString str;
+  TQTextStream ts( &str, IO_WriteOnly );
+  ts << *this;
+#if 1
+  dockConfig.writeEntry("Position", str);
+#else
+  /* We store this with a localized key because for dock positions,
+   * QT uses the localized captions of docks.
+   * This way, when changing languages, you don't loose dock position
+   * settings.
+   * For the retrieval to work, we need to store a non-localized.
+   */
+  dockConfig.writeEntry("Position", str, true, false, true);
+#endif
+
+  // if part dock was chosen visible even for only 1 part loaded,
+  // keep this choice...
+  _forcePartDock = false;
+  if (_data && (_data->parts().count()<2) && _partDock->isVisible())
+    _forcePartDock=true;
+  dockConfig.writeEntry("ForcePartDockVisible", _forcePartDock);
+
+  return true;
+}
+
+
+void TopLevel::splitSlot()
+{
+    int count = _multiView->childCount();
+    if (count<1) count = 1;
+    if (count>2) count = 2;
+    count = 3-count;
+    _multiView->setChildCount(count);
+
+    _taSplit->setChecked(count>1);
+    _taSplitDir->setEnabled(count>1);
+    _taSplitDir->setChecked(_multiView->orientation() == Qt::Horizontal);
+}
+
+void TopLevel::splitDirSlot()
+{
+  _multiView->setOrientation( _taSplitDir->isChecked() ?
+                              Qt::Horizontal : Qt::Vertical );
+}
+
+
+
+// this is called after a config change in the dialog
+void TopLevel::configChanged()
+{
+  //qDebug("TopLevel::configChanged");
+  //_showPercentage->setChecked(Configuration::showPercentage());
+
+  // invalidate found/cached dirs of source files
+  _data->resetSourceDirs();
+
+  _partSelection->refresh();
+  _stackSelection->refresh();
+
+  _functionSelection->notifyChange(TraceItemView::configChanged);
+  _functionSelection->updateView();
+
+  _multiView->notifyChange(TraceItemView::configChanged);
+  _multiView->updateView();
+}
+
+void TopLevel::slotShowTipOnStart() {
+  KTipDialog::showTip(this);
+}
+
+void TopLevel::slotShowTip() {
+  KTipDialog::showTip( this, TQString(), true );
+}
+
+void TopLevel::dummySlot()
+{
+}
+
+void TopLevel::activePartsChangedSlot(const TracePartList& list)
+{
+  if (!_data) return;
+
+  if (!_data->activateParts(list)) {
+//    qDebug("TopLevel::activePartsChangedSlot: No Change!");
+    return;
+  }
+  _activeParts = list;
+
+  _partSelection->activePartsChangedSlot(list);
+
+  _multiView->set(list);
+  _multiView->updateView();
+
+  _functionSelection->set(list);
+  _functionSelection->updateView();
+
+  _stackSelection->refresh();
+
+  updateStatusBar();
+}
+
+void TopLevel::partsHideSelectedSlotDelayed()
+{
+  TQTimer::singleShot( 0, TQT_TQOBJECT(this), TQT_SLOT(partsHideSelectedSlot()) );
+}
+
+// this puts selected parts into hidden list,
+// deselects them and makes the remaining parts selected
+void TopLevel::partsHideSelectedSlot()
+{
+  if (!_data) return;
+
+  TracePart* part;
+  TracePartList newHidden, newActive;
+  TracePartList l = _data->parts();
+  for (part=l.first();part;part=l.next()) {
+    if ((_activeParts.findRef(part)>=0) ||
+        (_hiddenParts.findRef(part)>=0))
+      newHidden.append(part);
+    else
+      newActive.append(part);
+  }
+
+  _hiddenParts = newHidden;
+  _partSelection->hiddenPartsChangedSlot(_hiddenParts);
+
+#if 0
+  _mainWidget1->hiddenPartsChangedSlot(_hiddenParts);
+  _mainWidget2->hiddenPartsChangedSlot(_hiddenParts);
+#endif
+
+  activePartsChangedSlot(newActive);
+}
+
+void TopLevel::partsUnhideAllSlotDelayed()
+{
+  TQTimer::singleShot( 0, TQT_TQOBJECT(this), TQT_SLOT(partsUnhideAllSlot()) );
+}
+
+// this unhides all hidden parts. Does NOT change selection
+void TopLevel::partsUnhideAllSlot()
+{
+  if (!_data) return;
+
+  _hiddenParts.clear();
+  _partSelection->hiddenPartsChangedSlot(_hiddenParts);
+#if 0
+  _mainWidget1->hiddenPartsChangedSlot(_hiddenParts);
+  _mainWidget2->hiddenPartsChangedSlot(_hiddenParts);
+#endif
+}
+
+void TopLevel::forceTrace()
+{
+//  qDebug("forceTrace");
+
+  // Needs Callgrind now...
+  TQFile cmd("callgrind.cmd");
+  if (!cmd.exists()) {
+    cmd.open(IO_WriteOnly);
+    cmd.writeBlock("DUMP\n", 5);
+    cmd.close();
+  }
+  if (_taDump->isChecked())
+    TQTimer::singleShot( 1000, TQT_TQOBJECT(this), TQT_SLOT(forceTraceReload()) );
+  else {
+    // cancel request
+    cmd.remove();
+  }
+
+}
+
+void TopLevel::forceTraceReload()
+{
+//  qDebug("forceTraceReload");
+
+  TQFile cmd("callgrind.cmd");
+  if (cmd.exists()) {
+    if (_taDump->isChecked())
+      TQTimer::singleShot( 1000, TQT_TQOBJECT(this), TQT_SLOT(forceTraceReload()) );
+    return;
+  }
+  _taDump->setChecked(false);
+  reload();
+}
+
+void TopLevel::forwardAboutToShow()
+{
+  TQPopupMenu *popup = _paForward->popupMenu();
+
+  popup->clear();
+  StackBrowser* b = _stackSelection ? _stackSelection->browser() : 0;
+  HistoryItem* hi = b ? b->current() : 0;
+  TraceFunction* f;
+
+  if (!hi) {
+    popup->insertItem(i18n("(No Stack)"));
+    return;
+  }
+
+  hi = hi->next();
+  if (!hi) {
+    popup->insertItem(i18n("(No next function)"));
+    return;
+  }
+
+  int count = 1;
+  while (count<Configuration::maxSymbolCount() && hi) {
+    f = hi->function();
+    if (!f) break;
+
+    TQString name = f->prettyName();
+    if ((int)name.length()>Configuration::maxSymbolLength())
+      name = name.left(Configuration::maxSymbolLength()) + "...";
+
+    //qDebug("forward: Adding %s", name.ascii());
+    popup->insertItem(name, count);
+    hi = hi->next();
+    count++;
+  }
+}
+
+void TopLevel::backAboutToShow()
+{
+  TQPopupMenu *popup = _paBack->popupMenu();
+
+  popup->clear();
+  StackBrowser* b = _stackSelection ? _stackSelection->browser() : 0;
+  HistoryItem* hi = b ? b->current() : 0;
+  TraceFunction* f;
+
+  if (!hi) {
+    popup->insertItem(i18n("(No Stack)"));
+    return;
+  }
+
+  hi = hi->last();
+  if (!hi) {
+    popup->insertItem(i18n("(No previous function)"));
+    return;
+  }
+
+  int count = 1;
+  while (count<Configuration::maxSymbolCount() && hi) {
+    f = hi->function();
+    if (!f) break;
+
+    TQString name = f->prettyName();
+    if ((int)name.length()>Configuration::maxSymbolLength())
+      name = name.left(Configuration::maxSymbolLength()) + "...";
+
+    //qDebug("back: Adding %s", name.ascii());
+    popup->insertItem(name, count);
+    hi = hi->last();
+    count++;
+  }
+}
+
+void TopLevel::upAboutToShow()
+{
+  TQPopupMenu *popup = _paUp->popupMenu();
+
+  popup->clear();
+  StackBrowser* b = _stackSelection ? _stackSelection->browser() : 0;
+  HistoryItem* hi = b ? b->current() : 0;
+  TraceFunction* f = hi ? hi->function() : 0;
+
+  if (!f) {
+    popup->insertItem(i18n("(No Stack)"));
+    return;
+  }
+  f = hi->stack()->caller(f, false);
+  if (!f) {
+    popup->insertItem(i18n("(No Function Up)"));
+    return;
+  }
+
+  int count = 1;
+  while (count<Configuration::maxSymbolCount() && f) {
+    TQString name = f->prettyName();
+    if ((int)name.length()>Configuration::maxSymbolLength())
+      name = name.left(Configuration::maxSymbolLength()) + "...";
+
+    popup->insertItem(name, count);
+    f = hi->stack()->caller(f, false);
+    count++;
+  }
+
+}
+
+void TopLevel::forwardActivated(int id)
+{
+  //qDebug("forwardActivated: %d", id);
+
+  StackBrowser* b = _stackSelection ? _stackSelection->browser() : 0;
+  if (!b) return;
+
+  while (id>1) {
+    b->goForward();
+    id--;
+  }
+  _stackSelection->browserForward();
+}
+
+void TopLevel::backActivated(int id)
+{
+  //qDebug("backActivated: %d", id);
+
+  StackBrowser* b = _stackSelection ? _stackSelection->browser() : 0;
+  if (!b) return;
+
+  while (id>1) {
+    b->goBack();
+    id--;
+  }
+  _stackSelection->browserBack();
+}
+
+void TopLevel::upActivated(int id)
+{
+  //qDebug("upActivated: %d", id);
+
+  StackBrowser* b = _stackSelection ? _stackSelection->browser() : 0;
+  HistoryItem* hi = b ? b->current() : 0;
+  if (!hi) return;
+
+  TraceFunction* f = hi->function();
+
+  while (id>0 && f) {
+    f = hi->stack()->caller(f, false);
+    id--;
+  }
+
+  //qDebug("upActivated: %s", f ? f->prettyName().ascii() : "??" );
+  if (f)
+    setFunction(f);
+
+}
+
+void TopLevel::showMessage(const TQString& msg, int ms)
+{
+  if (_statusbar)
+    _statusbar->message(msg, ms);
+}
+
+void TopLevel::showStatus(TQString msg, int progress)
+{
+    static bool msgUpdateNeeded = true;
+
+    if (msg.isEmpty()) {
+	if (_progressBar) {
+	    _statusbar->removeWidget(_progressBar);
+	    delete _progressBar;
+	    _progressBar = 0;
+	}
+	_statusbar->clear();
+	_progressMsg = msg;
+	return;
+    }
+
+    if (_progressMsg.isEmpty())	_progressStart.start();
+
+    if (msg != _progressMsg) {
+	_progressMsg = msg;
+	msgUpdateNeeded = true;
+    }
+
+    // do nothing if last change was less than 0.5 seconds ago
+    if (_progressStart.elapsed() < 500) return;
+
+    if (!_progressBar) {
+	_progressBar = new TQProgressBar(_statusbar);
+	_progressBar->setMaximumSize(200, _statusbar->height()-4);
+	_statusbar->addWidget(_progressBar, 1, true);
+	_progressBar->show();
+	msgUpdateNeeded = true;
+    }
+
+    _progressStart.restart();
+
+    if (msgUpdateNeeded) {
+	_statusbar->message(msg);
+	msgUpdateNeeded = false;
+    }
+    _progressBar->setProgress(progress);
+
+    // let the progress bar update itself
+    TQEventLoop* l = tqApp->eventLoop();
+    if (l) l->processEvents(TQEventLoop::ExcludeUserInput);
+}
+
+#include "toplevel.moc"
diff --git a/kdecachegrind/kdecachegrind/toplevel.h b/kdecachegrind/kdecachegrind/toplevel.h
new file mode 100644
index 0000000..10e7cde
--- /dev/null
+++ b/kdecachegrind/kdecachegrind/toplevel.h
@@ -0,0 +1,275 @@
+/* This file is part of KCachegrind.
+   Copyright (C) 2002, 2003 Josef Weidendorfer <Josef.Weidendorfer@gmx.de>
+
+   KCachegrind 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, version 2.
+
+   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; see the file COPYING.  If not, write to
+   the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+   Boston, MA 02110-1301, USA.
+*/
+
+/*
+ * KCachegrind top level window
+ */
+
+#ifndef TOPLEVEL_H
+#define TOPLEVEL_H
+
+#include <tqdatetime.h>
+
+#include <dcopobject.h>
+#include <kmainwindow.h>
+
+#include "traceitemview.h"
+#include "tracedata.h"
+
+class MultiView;
+class TQLineEdit;
+class TQDockWidget;
+class TQLabel;
+class TQProgressBar;
+class TQPopupMenu;
+
+class KURL;
+class KSelectAction;
+class KToggleAction;
+class KToolBarPopupAction;
+
+class TraceData;
+class KRecentFilesAction;
+class MainWidget;
+class PartSelection;
+class FunctionSelection;
+class DumpSelection;
+class StackSelection;
+class TraceFunction;
+
+class TopLevel : public KMainWindow, public DCOPObject
+{
+  Q_OBJECT
+  TQ_OBJECT
+
+public:
+  TopLevel(const char *name = 0);
+  ~TopLevel();
+
+  TraceData* data() { return _data; }
+  void setData(TraceData*);
+
+  virtual void saveProperties(KConfig*);
+  virtual void readProperties(KConfig*);
+
+  void createActions();
+  void createDocks();
+
+  TraceItem::CostType groupType() { return _groupType; }
+  TraceCostType* costType() { return _costType; }
+  TraceCostType* costType2() { return _costType2; }
+  TracePartList activeParts() { return _activeParts; }
+  TracePartList hiddenParts() { return _hiddenParts; }
+
+  // current config
+  bool showPercentage() const { return _showPercentage; }
+  bool showExpanded() const { return _showExpanded; }
+  bool showCycles() const { return _showCycles; }
+
+  /* convenience functions for often used context menu items */
+  void addCostMenu(TQPopupMenu*,bool);
+  void addGoMenu(TQPopupMenu*);
+
+public slots:
+  void newTrace();
+  void loadTrace();
+  void loadTrace(const KURL&);
+  void loadTrace(TQString);
+  void addTrace();
+  void addTrace(const KURL&);
+  void addTrace(TQString);
+
+  // for quick showing the main window...
+  void loadDelayed(TQString);
+
+  void reload();
+  void exportGraph();
+  void newWindow();
+  void configure();
+  void querySlot();
+  void dummySlot();
+
+  // layouts
+  void layoutDuplicate();
+  void layoutRemove();
+  void layoutNext();
+  void layoutPrevious();
+  void layoutSave();
+  void layoutRestore();
+  void updateLayoutActions();
+
+  void updateStatusBar();
+  void costTypeSelected(const TQString&);
+  void costType2Selected(const TQString&);
+  void groupTypeSelected(int);
+  void splitSlot();
+  void splitDirSlot();
+  void configureToolbars();
+  void configureKeys();
+  bool queryExit();
+  bool queryClose();
+  void togglePartDock();
+  void toggleStackDock();
+  void toggleFunctionDock();
+  void toggleDumpDock();
+  void toggleStatusBar();
+  void partVisibilityChanged(bool);
+  void dumpVisibilityChanged(bool);
+  void stackVisibilityChanged(bool);
+  void functionVisibilityChanged(bool);
+  void togglePercentage();
+  void setPercentage(bool);
+  void setAbsoluteCost();
+  void setRelativeCost();
+  void toggleExpanded();
+  void toggleCycles();
+  void forceTrace();
+  void forceTraceReload();
+  void forwardAboutToShow();
+  void backAboutToShow();
+  void upAboutToShow();
+  void forwardActivated(int);
+  void backActivated(int);
+  void upActivated(int);
+
+  bool setCostType(TraceCostType*);
+  bool setCostType2(TraceCostType*);
+  bool setCostType(TQString);
+  bool setCostType2(TQString);
+  bool setCostType(int);
+  bool setCostType2(int);
+  bool setGroupType(TraceItem::CostType);
+  bool setGroupType(TQString);
+  bool setGroup(TraceCostItem*);
+  bool setGroup(TQString);
+  bool setFunction(TraceFunction*);
+  bool setFunction(TQString);
+  void activePartsChangedSlot(const TracePartList& list);
+  void partsHideSelectedSlot();
+  void partsUnhideAllSlot();
+
+  /* These go back to mainloop first by using a timer.
+   * So they can be called from event handlers that
+   * aren't allowed to delete list entries.
+   */
+  void setCostTypeDelayed(TraceCostType*);
+  void setCostType2Delayed(TraceCostType*);
+  void setGroupTypeDelayed(TraceItem::CostType);
+  void setGroupDelayed(TraceCostItem*);
+  void setTraceItemDelayed(TraceItem*);
+  void partsHideSelectedSlotDelayed();
+  void partsUnhideAllSlotDelayed();
+  void goBack();
+  void goForward();
+  void goUp();
+  void setDirectionDelayed(TraceItemView::Direction);
+
+  /* SingleShot Slots (without parameters) for the delayed versions */
+  void setCostTypeDelayed();
+  void setCostType2Delayed();
+  void setGroupTypeDelayed();
+  void setGroupDelayed();
+  void setTraceItemDelayed();
+  void loadTraceDelayed();
+  void setDirectionDelayed();
+
+  // configuration has changed
+  void configChanged();
+
+  //void refresh();
+  void slotShowTipOnStart();
+  void slotShowTip();
+
+  // progress in status bar, empty message disables progress display
+  void showStatus(TQString msg, int progress);
+  void showMessage(const TQString&, int msec);
+
+private:
+  void init();
+  void createLayoutActions();
+  void createMiscActions();
+  void setupMainWidget(MainWidget*);
+  void setupPartSelection(PartSelection*);
+  void restoreCurrentState(TQString postfix);
+  void saveCurrentState(TQString postfix);
+  void saveTraceSettings();
+  TQString traceKey();
+  void restoreTraceTypes();
+  void restoreTraceSettings();
+
+  KStatusBar* _statusbar;
+  TQLabel* _statusLabel;
+  KRecentFilesAction* _openRecent;
+  bool _twoMainWidgets;
+  Qt::Orientation _spOrientation;
+
+  MultiView* _multiView;
+  FunctionSelection* _functionSelection;
+  DumpSelection* _dumpSelection;
+  PartSelection* _partSelection;
+  StackSelection* _stackSelection;
+  TQLineEdit* queryLineEdit;
+
+  TQDockWindow *_partDock, *_stackDock, *_functionDock, *_dumpDock;
+  bool _forcePartDock;
+
+  KSelectAction *_saCost, *_saCost2, *saGroup;
+  KToggleAction *_partDockShown, *_stackDockShown;
+  KToggleAction *_functionDockShown, *_dumpDockShown;
+  KToggleAction *_taPercentage, *_taExpanded, *_taCycles;
+  KToggleAction *_taDump, *_taSplit, *_taSplitDir;
+  KToolBarPopupAction *_paForward, *_paBack, *_paUp;
+
+  TraceFunction* _function;
+  const TQObject* _lastSender;
+
+  // trace data shown in this window
+  TraceData* _data;
+  // subcost types used for visualisation
+  TraceCostType* _costType;
+  TraceCostType* _costType2;
+  // grouping of function list
+  TraceItem::CostType _groupType;
+  // selected group
+  TraceCostItem* _group;
+  // selected parts
+  TracePartList _activeParts;
+  // hidden parts
+  TracePartList _hiddenParts;
+  // layouts
+  int _layoutCurrent, _layoutCount;
+
+  // for delayed slots
+  TraceCostType* _costTypeDelayed;
+  TraceCostType* _costType2Delayed;
+  TraceItem::CostType _groupTypeDelayed;
+  TraceCostItem* _groupDelayed;
+  TraceItem* _traceItemDelayed;
+  TQString _loadTraceDelayed;
+  TraceItemView::Direction _directionDelayed;
+
+  // for status progress display
+  TQString _progressMsg;
+  TQTime _progressStart;
+  TQProgressBar* _progressBar;
+
+  // toplevel configuration options
+  bool _showPercentage, _showExpanded, _showCycles;
+};
+
+#endif
diff --git a/kdecachegrind/kdecachegrind/tracedata.cpp b/kdecachegrind/kdecachegrind/tracedata.cpp
new file mode 100644
index 0000000..f129c2e
--- /dev/null
+++ b/kdecachegrind/kdecachegrind/tracedata.cpp
@@ -0,0 +1,5068 @@
+/* This file is part of KCachegrind.
+   Copyright (C) 2002, 2003 Josef Weidendorfer <Josef.Weidendorfer@gmx.de>
+
+   KCachegrind 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, version 2.
+
+   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; see the file COPYING.  If not, write to
+   the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+   Boston, MA 02110-1301, USA.
+*/
+
+
+#include <stdlib.h>
+
+#include <tqfile.h>
+#include <tqdir.h>
+#include <tqfileinfo.h>
+#include <tqregexp.h>
+
+#include <klocale.h>
+#include <kdebug.h>
+
+#include "tracedata.h"
+#include "toplevel.h"
+#include "loader.h"
+#include "configuration.h"
+#include "utils.h"
+#include "fixcost.h"
+
+
+#define TRACE_DEBUG      0
+#define TRACE_ASSERTIONS 0
+
+const int TraceCost::MaxRealIndex = MaxRealIndexValue;
+const int TraceCost::InvalidIndex = -1;
+
+//---------------------------------------------------
+// Addr
+
+bool Addr::set(FixString& s)
+{
+  return s.stripUInt64(_v); 
+}
+
+int Addr::set(const char *s)
+{
+  int n = 0;
+  _v = 0;
+
+  while((n<16) && *s) {
+    if ((*s>='0') && (*s<='9'))
+      _v = 16*_v + (*s-'0');
+    else if ((*s>='a') && (*s<='f'))
+      _v = 16*_v + 10 + (*s-'a');
+    else if ((*s>='A') && (*s<='F'))
+      _v = 16*_v + 10 + (*s-'A');    
+    else break;
+    s++;
+    n++;
+  }
+  
+  return n;
+}
+
+
+TQString Addr::toString() const
+{
+  if (_v == 0) return TQString("0");
+
+  uint64 n = _v;
+  TQString hex;
+  hex.reserve(16);
+
+  while(n>0) {
+    int d = (n & 15);
+    hex = TQChar((d<10) ? ('0'+d) : ('A'-10+d)) + hex;
+    n /= 16;
+  }
+
+  return hex;
+}
+
+TQString Addr::pretty() const
+{
+  if (_v == 0) return TQString("0");
+
+  uint64 n = _v;
+  int p = 0;
+  TQString hex;
+  hex.reserve(20);
+
+  while(n>0) {
+    int d = (n & 15);
+    if ((p>0) && ((p%4)==0)) hex = " " + hex;
+    hex = TQChar((d<10) ? ('0'+d) : ('A'-10+d)) + hex;
+    n /= 16;
+    p++;
+  }
+
+  return hex;
+}
+
+bool Addr::isInRange(Addr a, int distance)
+{
+  uint64 diff = (a._v > _v) ? (a._v - _v) : (_v - a._v);
+  uint64 dist = (distance<0) ? distance : -distance;
+  return (diff < dist);
+}
+
+//---------------------------------------------------
+// TraceItem
+
+TQString* TraceItem::_typeName = 0;
+TQString* TraceItem::_i18nTypeName = 0;
+
+TraceItem::TraceItem()
+{
+  _position = 0;
+  _dep = 0;
+  _dirty = true;
+}
+
+TraceItem::~TraceItem()
+{}
+
+void TraceItem::cleanup()
+{
+  if (_typeName) {
+    delete [] _typeName;
+    _typeName = 0;
+  }
+  if (_i18nTypeName) {
+    delete [] _i18nTypeName;
+    _i18nTypeName = 0;
+  }
+}
+
+TQString TraceItem::typeName(CostType t)
+{
+    if (!_typeName) {
+      _typeName = new TQString [MaxCostType+1];
+      TQString* strs = _typeName;
+      for(int i=0;i<=MaxCostType;i++)
+	strs[i] = TQString("?");
+
+       strs[Item] = I18N_NOOP("Abstract Item");
+       strs[Cost] = I18N_NOOP("Cost Item");
+       strs[PartLine] = I18N_NOOP("Part Source Line");
+       strs[Line] = I18N_NOOP("Source Line");
+       strs[PartLineCall] = I18N_NOOP("Part Line Call");
+       strs[LineCall] = I18N_NOOP("Line Call");
+       strs[PartLineJump] = I18N_NOOP("Part Jump");
+       strs[LineJump] = I18N_NOOP("Jump");
+       strs[PartInstr] = I18N_NOOP("Part Instruction");
+       strs[Instr] = I18N_NOOP("Instruction");
+       strs[PartInstrJump] = I18N_NOOP("Part Instruction Jump");
+       strs[InstrJump] = I18N_NOOP("Instruction Jump");
+       strs[PartInstrCall] = I18N_NOOP("Part Instruction Call");
+       strs[InstrCall] = I18N_NOOP("Instruction Call");
+       strs[PartCall] = I18N_NOOP("Part Call");
+       strs[Call] = I18N_NOOP("Call");
+       strs[PartFunction] = I18N_NOOP("Part Function");
+       strs[FunctionSource] = I18N_NOOP("Function Source File");
+       strs[Function] = I18N_NOOP("Function");
+       strs[FunctionCycle] = I18N_NOOP("Function Cycle");
+       strs[PartClass] = I18N_NOOP("Part Class");
+       strs[Class] = I18N_NOOP("Class");
+       strs[PartFile] = I18N_NOOP("Part Source File");
+       strs[File] = I18N_NOOP("Source File");
+       strs[PartObject] = I18N_NOOP("Part ELF Object");
+       strs[Object] = I18N_NOOP("ELF Object");
+       strs[Part] = I18N_NOOP("Profile Part");
+       strs[Data] = I18N_NOOP("Program Trace");
+    }
+    if (t<0 || t> MaxCostType) t = MaxCostType;
+    return _typeName[t];
+}
+
+TraceItem::CostType TraceItem::costType(TQString s)
+{
+  // This is the default cost Type
+  if (s.isEmpty()) return Function;
+
+  CostType type;
+  for (int i=0; i<MaxCostType;i++) {
+    type = (CostType) i;
+    if (typeName(type) == s)
+      return type;
+  }
+  return NoCostType;
+}
+
+// all strings of typeName() are translatable because of I18N_NOOP there
+TQString TraceItem::i18nTypeName(CostType t)
+{
+    if (!_i18nTypeName) {
+	_i18nTypeName = new TQString [MaxCostType+1];
+	for(int i=0;i<=MaxCostType;i++)
+	    _i18nTypeName[i] = i18n(typeName((CostType)i).utf8().data());
+    }
+    if (t<0 || t> MaxCostType) t = MaxCostType;
+    return _i18nTypeName[t];
+}
+
+TraceItem::CostType TraceItem::i18nCostType(TQString s)
+{
+  // This is the default cost Type
+  if (s.isEmpty()) return Function;
+
+  CostType type;
+  for (int i=0; i<MaxCostType;i++) {
+    type = (CostType) i;
+    if (i18nTypeName(type) == s)
+      return type;
+  }
+  return NoCostType;
+}
+
+
+void TraceItem::clear()
+{
+    invalidate();
+}
+
+
+TQString TraceItem::costString(TraceCostMapping*)
+{
+    return TQString("(no cost)");
+}
+
+TQString TraceItem::name() const
+{
+  if (part()) {
+    return i18n("%1 from %2")
+      .arg(_dep->name())
+      .arg(part()->name());
+  }
+
+  if (_dep)
+    return _dep->name();
+
+  return i18n("(unknown)");
+}
+
+TQString TraceItem::prettyName() const
+{
+    if (name().isEmpty()) return i18n("(unknown)");
+    return name();
+}
+
+
+TQString TraceItem::fullName() const
+{
+  return TQString("%1 %2")
+    .arg(typeName(type())).arg(prettyName());
+}
+
+TQString TraceItem::toString()
+{
+  return TQString("%1\n  [%3]").arg(fullName()).arg(costString(0));
+}
+
+void TraceItem::invalidate()
+{
+  if (_dirty) return;
+  _dirty = true;
+
+  if (_dep)
+    _dep->invalidate();
+}
+
+void TraceItem::update()
+{
+  _dirty = false;
+}
+
+TracePart* TraceItem::part()
+{
+  return _position ? _position->part() : 0; 
+}
+
+const TracePart* TraceItem::part() const
+{
+  return _position ? _position->part() : 0; 
+}
+
+TraceData* TraceItem::data()
+{
+  return _position ? _position->data() : 0;
+}
+
+const TraceData* TraceItem::data() const
+{
+  return _position ? _position->data() : 0; 
+}
+
+
+//---------------------------------------------------
+// TraceCost
+
+TraceCost::TraceCost()
+    : TraceItem()
+{
+  _cachedType = 0; // no virtual value cached
+
+  TraceCost::clear();
+}
+
+TraceCost::~TraceCost()
+{}
+
+
+void TraceCost::clear()
+{
+    // simple set usage count to 0
+    _count = 0;
+
+    TraceItem::clear();
+}
+
+
+
+void TraceCost::set(TraceSubMapping* sm, const char* s)
+{
+    if (!sm) return;
+    if (!s) {
+	if (_count>0) clear();
+	return;
+    }
+
+    while(*s == ' ') s++;
+
+    if (sm->isIdentity()) {
+	int i = 0;
+	while(i<sm->count()) {
+	    if (!_cost[i].set(&s)) break;
+	    i++;
+	}
+	_count = i;
+    }
+    else {
+	int i = 0, maxIndex = 0, index;
+	while(1) {
+	    index = sm->realIndex(i);
+	    if (maxIndex<index) maxIndex=index;
+	    if (index == TraceCost::InvalidIndex) break;
+	    if (!_cost[index].set(&s)) break;
+	    i++;
+	}
+	// we have to set all costs of unused indexes till maxIndex to zero
+	for(i=sm->firstUnused(); i<=maxIndex; i=sm->nextUnused(i))
+	    _cost[i] = 0;
+	_count = maxIndex;
+    }
+    // a cost change has to be propagated (esp. in subclasses)
+    invalidate();
+}
+
+void TraceCost::set(TraceSubMapping* sm, FixString & s)
+{
+    if (!sm) return;
+
+    s.stripSpaces();
+
+    if (sm->isIdentity()) {
+	int i = 0;
+	while(i<sm->count()) {
+	    if (!s.stripUInt64(_cost[i])) break;
+	    i++;
+	}
+	_count = i;
+    }
+    else {
+	int i = 0, maxIndex = 0, index;
+	while(1) {
+	    index = sm->realIndex(i);
+	    if (maxIndex<index) maxIndex=index;
+	    if (index == TraceCost::InvalidIndex) break;
+	    if (!s.stripUInt64(_cost[index])) break;
+	    i++;
+	}
+	// we have to set all costs of unused indexes till maxIndex to zero
+	for(i=sm->firstUnused(); i<=maxIndex; i=sm->nextUnused(i))
+	    _cost[i] = 0;
+	_count = maxIndex+1;
+    }
+    invalidate();
+}
+
+
+void TraceCost::addCost(TraceSubMapping* sm, const char* s)
+{
+    if (!sm || !s) return;
+
+    SubCost v;
+
+    if (sm->isIdentity()) {
+	int i = 0;
+	while(i<sm->count()) {
+	    if (!v.set(&s)) break;
+	    if (i<_count)
+		_cost[i] += v;
+	    else
+		_cost[i] = v;
+	    i++;
+	}
+	if (i > _count) _count = i;
+    }
+    else {
+	int i = 0, maxIndex = 0, index;
+	while(1) {
+	    if (!v.set(&s)) break;
+	    index = sm->realIndex(i);
+	    if (maxIndex<index) maxIndex=index;
+	    if (index == TraceCost::InvalidIndex) break;
+	    if (index<_count)
+		_cost[index] += v;
+	    else
+		_cost[index] = v;
+	    i++;
+	}
+	if (maxIndex >= _count) {
+	    /* we have to set all costs of unused indexes in the interval
+	     *  [_count;maxIndex] to zero */
+	    for(i=sm->nextUnused(_count-1); i<=maxIndex; i=sm->nextUnused(i))
+		_cost[i] = 0;
+	    _count = maxIndex+1;
+	}
+    }
+
+    // a cost change has to be propagated (esp. in subclasses)
+    invalidate();
+
+#if TRACE_DEBUG
+    _dirty = false; // don't recurse !
+    qDebug("%s\n now %s", fullName().ascii(),
+	   TraceCost::costString(0).ascii());
+    _dirty = true; // because of invalidate()
+#endif
+}
+
+void TraceCost::addCost(TraceSubMapping* sm, FixString & s)
+{
+    if (!sm) return;
+
+    s.stripSpaces();
+
+    SubCost v;
+
+    if (sm->isIdentity()) {
+	int i = 0;
+	while(i<sm->count()) {
+	    if (!s.stripUInt64(v)) break;
+	    if (i<_count)
+		_cost[i] += v;
+	    else
+		_cost[i] = v;
+	    i++;
+	}
+	if (i > _count) _count = i;
+    }
+    else {
+	int i = 0, maxIndex = 0, index;
+	while(1) {
+	    if (!s.stripUInt64(v)) break;
+	    index = sm->realIndex(i);
+	    if (maxIndex<index) maxIndex=index;
+	    if (index == TraceCost::InvalidIndex) break;
+	    if (index<_count)
+		_cost[index] += v;
+	    else
+		_cost[index] = v;
+	    i++;
+	}
+	if (maxIndex >= _count) {
+	    /* we have to set all costs of unused indexes in the interval
+	     *  [_count;maxIndex] to zero */
+	    for(i=sm->nextUnused(_count-1); i<=maxIndex; i=sm->nextUnused(i))
+		_cost[i] = 0;
+	    _count = maxIndex+1;
+	}
+    }
+
+    invalidate();
+
+#if TRACE_DEBUG
+    _dirty = false; // don't recurse !
+    qDebug("%s\n now %s", fullName().ascii(),
+	   TraceCost::costString(0).ascii());
+    _dirty = true; // because of invalidate()
+#endif
+}
+
+
+// update each subcost to be maximum of old and given costs
+void TraceCost::maxCost(TraceSubMapping* sm, FixString & s)
+{
+    if (!sm) return;
+
+    s.stripSpaces();
+
+    SubCost v;
+
+    if (sm->isIdentity()) {
+	int i = 0;
+	while(i<sm->count()) {
+	    if (!s.stripUInt64(v)) break;
+	    if (i<_count) {
+	      if (v>_cost[i]) _cost[i] = v;
+	    }
+	    else
+		_cost[i] = v;
+	    i++;
+	}
+	if (i > _count) _count = i;
+    }
+    else {
+	int i = 0, maxIndex = 0, index;
+	while(1) {
+	    if (!s.stripUInt64(v)) break;
+	    index = sm->realIndex(i);
+	    if (maxIndex<index) maxIndex=index;
+	    if (index == TraceCost::InvalidIndex) break;
+	    if (index<_count) {
+	      if (v>_cost[index]) _cost[index] = v;
+	    }
+	    else
+		_cost[index] = v;
+	    i++;
+	}
+	if (maxIndex >= _count) {
+	    /* we have to set all costs of unused indexes in the interval
+	     *  [_count;maxIndex] to zero */
+	    for(i=sm->nextUnused(_count-1); i<=maxIndex; i=sm->nextUnused(i))
+		_cost[i] = 0;
+	    _count = maxIndex+1;
+	}
+    }
+
+    invalidate();
+
+#if TRACE_DEBUG
+    _dirty = false; // don't recurse !
+    qDebug("%s\n now %s", fullName().ascii(),
+	   TraceCost::costString(0).ascii());
+    _dirty = true; // because of invalidate()
+#endif
+}
+
+
+void TraceCost::addCost(TraceCost* item)
+{
+    int i;
+
+    if (!item) return;
+
+    // we have to update the other item if needed
+    // because we access the item costs directly
+    if (item->_dirty) item->update();
+
+    if (item->_count < _count) {
+	for (i = 0; i<item->_count; i++)
+	    _cost[i] += item->_cost[i];
+    }
+    else {
+	for (i = 0; i<_count; i++)
+	    _cost[i] += item->_cost[i];
+	for (; i<item->_count; i++)
+	    _cost[i] = item->_cost[i];
+	_count = item->_count;
+    }
+
+    // a cost change has to be propagated (esp. in subclasses)
+    invalidate();
+
+#if TRACE_DEBUG
+    _dirty = false; // don't recurse !
+    qDebug("%s added cost item\n %s\n  now %s",
+	   fullName().ascii(), item->fullName().ascii(),
+	   TraceCost::costString(0).ascii());
+    _dirty = true; // because of invalidate()
+#endif
+}
+
+void TraceCost::maxCost(TraceCost* item)
+{
+    int i;
+
+    if (!item) return;
+
+    // we have to update the other item if needed
+    // because we access the item costs directly
+    if (item->_dirty) item->update();
+
+    if (item->_count < _count) {
+	for (i = 0; i<item->_count; i++)
+	  if (_cost[i] < item->_cost[i]) _cost[i] = item->_cost[i];
+    }
+    else {
+	for (i = 0; i<_count; i++)
+	  if (_cost[i] < item->_cost[i]) _cost[i] = item->_cost[i];
+	for (; i<item->_count; i++)
+	    _cost[i] = item->_cost[i];
+	_count = item->_count;
+    }
+
+    // a cost change has to be propagated (esp. in subclasses)
+    invalidate();
+
+#if TRACE_DEBUG
+    _dirty = false; // don't recurse !
+    qDebug("%s added cost item\n %s\n  now %s",
+	   fullName().ascii(), item->fullName().ascii(),
+	   TraceCost::costString(0).ascii());
+    _dirty = true; // because of invalidate()
+#endif
+}
+
+void TraceCost::addCost(int type, SubCost value)
+{
+    if (type<0 || type>=MaxRealIndex) return;
+    if (type<_count)
+	_cost[type] += value;
+    else {
+	for(int i=_count;i<type;i++)
+	    _cost[i] = 0;
+	_cost[type] = value;
+	_count = type+1;
+    }
+
+    // a cost change has to be propagated (esp. in subclasses)
+    invalidate();
+}
+
+void TraceCost::maxCost(int type, SubCost value)
+{
+    if (type<0 || type>=MaxRealIndex) return;
+    if (type<_count) {
+      if (value>_cost[type]) _cost[type] = value;
+    }
+    else {
+	for(int i=_count;i<type;i++)
+	    _cost[i] = 0;
+	_cost[type] = value;
+	_count = type+1;
+    }
+
+    // a cost change has to be propagated (esp. in subclasses)
+    invalidate();
+}
+
+
+TraceCost TraceCost::diff(TraceCost* item)
+{
+  TraceCost res;
+
+  // we have to update the other item if needed
+  // because we access the item costs directly
+  if (item->_dirty) item->update();
+
+  int maxCount = (item->_count > _count) ? item->_count : _count;
+
+  res._count = maxCount;
+  for (int i=0; i<maxCount;i++)
+    res._cost[i] = item->subCost(i) - subCost(i);
+
+  return res;
+}
+
+TQString TraceCost::costString(TraceCostMapping* m)
+{
+  TQString res;
+
+  if (_dirty) update();
+
+  int maxIndex = m ? m->realCount() : TraceCost::MaxRealIndex;
+  for (int i = 0; i<maxIndex; i++) {
+    if (!res.isEmpty()) res += ", ";
+    if (m) res += m->type(i)->name() + " ";
+
+    res += subCost(i).pretty();
+  }
+  return res;
+}
+
+
+void TraceCost::invalidate()
+{
+  if (_dirty) return;
+  _dirty = true;
+  _cachedType = 0; // cached value is invalid, too
+
+  if (_dep)
+    _dep->invalidate();
+}
+
+void TraceCost::update()
+{
+  _dirty = false;
+}
+
+// this is only for real types
+SubCost TraceCost::subCost(int idx)
+{
+    if (idx<0) return 0;
+
+    /* update if needed as cost could be calculated dynamically in subclasses
+     * this can change _count !! */
+    if (_dirty) update();
+    if (idx>=_count) return 0;
+
+    return _cost[idx];
+}
+
+SubCost TraceCost::subCost(TraceCostType* t)
+{
+  if (!t) return 0;
+  if (_cachedType != t) {
+      _cachedType = t;
+      _cachedCost = t->subCost(this);
+  }
+  return _cachedCost;
+}
+
+TQString TraceCost::prettySubCost(TraceCostType* t)
+{
+    return subCost(t).pretty();
+}
+
+
+
+//---------------------------------------------------
+// TraceJumpCost
+
+TraceJumpCost::TraceJumpCost()
+    :TraceItem()
+{
+    TraceJumpCost::clear();
+}
+
+TraceJumpCost::~TraceJumpCost()
+{}
+
+SubCost TraceJumpCost::executedCount()
+{
+    if (_dirty) update();
+
+    return _executedCount;
+}
+
+SubCost TraceJumpCost::followedCount()
+{
+    if (_dirty) update();
+
+    return _followedCount;
+}
+
+TQString TraceJumpCost::costString(TraceCostMapping*)
+{
+  if (_dirty) update();
+
+  return TQString("%1/%2")
+      .arg(_followedCount.pretty())
+      .arg(_executedCount.pretty());
+}
+
+void TraceJumpCost::clear()
+{
+    _followedCount = 0;
+    _executedCount = 0;
+}
+
+void TraceJumpCost::addCost(TraceJumpCost* item)
+{
+    if (item->_dirty) item->update();
+
+    _followedCount += item->followedCount();
+    _executedCount += item->executedCount();
+}
+
+
+//---------------------------------------------------
+// TraceCostType
+
+TQPtrList<TraceCostType>* TraceCostType::_knownTypes = 0;
+
+TraceCostType::TraceCostType(TQString name,  TQString longName, TQString formula)
+{
+  _name = name;
+  _longName = longName;
+  _formula = formula;
+  _mapping = 0;
+  _realIndex = TraceCost::InvalidIndex;
+  _parsed = false;
+  _inParsing = false;
+
+  for (int i=0; i<TraceCost::MaxRealIndex;i++)
+    _coefficient[i] = 0;
+}
+
+void TraceCostType::setFormula(TQString formula)
+{
+  _formula = formula;
+  _realIndex = TraceCost::InvalidIndex;
+  _parsed = false;
+}
+
+void TraceCostType::setMapping(TraceCostMapping* m)
+{
+  _parsed = false;
+  _mapping = m;
+}
+
+// setting the index to TraceCost::MaxRealIndex makes it a
+// real type with unspecified index
+void TraceCostType::setRealIndex(int i)
+{
+  if (i<0 || i>TraceCost::MaxRealIndex)
+    i=TraceCost::InvalidIndex;
+
+  _realIndex = i;
+  _formula = TQString();
+}
+
+// checks for existing types and sets coefficients
+bool TraceCostType::parseFormula()
+{
+  if (_parsed) return true;
+  if (_inParsing) {
+    qDebug("TraceCostType::parseFormula: Recursion detected.");
+    return false;
+  }
+
+  if (!_mapping) {
+    qDebug("TraceCostType::parseFormula: No mapping set!");
+    return false;
+  }
+
+  _inParsing = true;
+
+  for (int i=0; i<TraceCost::MaxRealIndex;i++)
+    _coefficient[i] = 0;
+
+  TQRegExp rx( "((?:\\+|\\-)?)\\s*(\\d*)\\s*\\*?\\s*(\\w+)" );
+
+  int factor, pos;
+  TQString costName;
+  TraceCostType* costType;
+
+  pos = 0;
+  while (1) {
+    pos = rx.search(_formula, pos);
+    if (pos<0) break;
+    pos += rx.matchedLength();
+    if (rx.cap(0).isEmpty()) break;
+
+    //qDebug("parseFormula: matched '%s','%s','%s'",
+    //       rx.cap(1).ascii(), rx.cap(2).ascii(), rx.cap(3).ascii());
+
+    costName = rx.cap(3);
+    costType = _mapping->type(costName);
+    if (!costType) {
+	// qDebug("Cost type '%s': In formula cost '%s' unknown.",
+        //     _name.ascii(), costName.ascii());
+
+	_inParsing = false;
+	return false;
+    }
+
+    factor = (rx.cap(2).isEmpty()) ? 1 : rx.cap(2).toInt();
+    if (rx.cap(1) == "-") factor = -factor;
+
+    if (costType->isReal())
+      _coefficient[costType->realIndex()] += factor;
+    else {
+      costType->parseFormula();
+      for (int i=0; i<TraceCost::MaxRealIndex;i++)
+        _coefficient[i] += factor * costType->_coefficient[i];
+    }
+  }
+
+  _inParsing = false;
+  _parsed = true;
+
+  return true;
+}
+
+TQString TraceCostType::parsedFormula()
+{
+  TQString res;
+
+  if (!parseFormula()) return res;
+
+  for (int i=0; i<TraceCost::MaxRealIndex;i++) {
+    int c = _coefficient[i];
+    if (c == 0) continue;
+
+    if (!res.isEmpty()) {
+      res += " ";
+      if (c>0) res += "+ ";
+    }
+    if (c<0) { res += "- "; c = -c; }
+    res += TQString::number(c);
+
+    TraceCostType* t = _mapping->type(i);
+    if (!t) continue;
+
+    if (!t->name().isEmpty())
+      res += TQString(" * %1").arg(t->name());
+  }
+
+  return res;
+}
+
+SubCost TraceCostType::subCost(TraceCost* c)
+{
+  if (_realIndex != TraceCost::InvalidIndex)
+    return c->subCost(_realIndex);
+
+  if (!_parsed) {
+    if (!parseFormula()) return 0;
+  }
+  SubCost res = 0;
+
+  int rc = _mapping->realCount();
+  for (int i = 0;i<rc;i++)
+    if (_coefficient[i] != 0)
+      res += _coefficient[i] * c->subCost(i);
+
+  return res;
+}
+
+int TraceCostType::histCost(TraceCost* c, double total, double* hist)
+{
+  if (total == 0.0) return 0;
+
+  if (!_parsed) {
+    if (!parseFormula()) return 0;
+  }
+
+  int rc = _mapping->realCount();
+  for (int i = 0;i<rc;i++) {
+    if (_coefficient[i] != 0)
+      hist[i] = _coefficient[i] * c->subCost(i) / total;
+    else
+      hist[i] = 0.0;
+  }
+
+  return rc;
+}
+
+
+
+
+TraceCostType* TraceCostType::knownRealType(TQString n)
+{
+  if (!_knownTypes) return 0;
+
+  TraceCostType* t;
+  for (t=_knownTypes->first();t;t=_knownTypes->next())
+    if (t->isReal() && (t->name() == n)) {
+      TraceCostType* type = new TraceCostType(*t);
+      return type;
+    }
+
+  return 0;
+}
+
+TraceCostType* TraceCostType::knownVirtualType(TQString n)
+{
+  if (!_knownTypes) return 0;
+
+  TraceCostType* t;
+  for (t=_knownTypes->first();t;t=_knownTypes->next())
+    if (!t->isReal() && (t->name() == n)) {
+      TraceCostType* type = new TraceCostType(*t);
+      return type;
+    }
+
+  return 0;
+}
+
+// we take ownership
+void TraceCostType::add(TraceCostType* t)
+{
+  if (!t) return;
+
+  t->setMapping(0);
+
+  if (!_knownTypes)
+    _knownTypes = new TQPtrList<TraceCostType>;
+
+  /* Already known? */
+  TraceCostType* kt;
+  for (kt=_knownTypes->first();kt;kt=_knownTypes->next())
+    if (kt->name() == t->name()) break;
+
+  if (kt) {
+    // Overwrite old type
+    if (!t->longName().isEmpty() &&
+	(t->longName() != t->name())) kt->setLongName(t->longName());
+    if (!t->formula().isEmpty()) kt->setFormula(t->formula());
+
+    delete t;
+  }
+  else {
+    if (t->longName().isEmpty()) t->setLongName(t->name());
+    _knownTypes->append(t);
+  }
+}
+
+
+int TraceCostType::knownTypeCount()
+{
+  if (!_knownTypes) return 0;
+
+  return _knownTypes->count();
+}
+
+bool TraceCostType::remove(TQString n)
+{
+  if (!_knownTypes) return false;
+
+  TraceCostType* t;
+  for (t=_knownTypes->first();t;t=_knownTypes->next())
+    if (!t->isReal() && (t->name() == n)) {
+      _knownTypes->removeRef(t);
+      delete t;
+      return true;
+    }
+
+  return false;
+}
+
+TraceCostType* TraceCostType::knownType(int i)
+{
+  if (!_knownTypes) return 0;
+  if (i<0 || i>=(int)_knownTypes->count()) return 0;
+
+  return _knownTypes->at(i);
+}
+
+TQColor TraceCostType::color()
+{
+  if (!_mapping) return TQColor();
+  return _mapping->realColors()[_realIndex];
+}
+
+
+//---------------------------------------------------
+// TraceCostMapping
+
+TraceCostMapping::TraceCostMapping()
+{
+  _realCount = 0;
+  _virtualCount = 0;
+  for (int i=0;i<TraceCost::MaxRealIndex;i++) _real[i] = 0;
+  for (int i=0;i<TraceCost::MaxRealIndex;i++) _virtual[i] = 0;
+}
+
+TraceCostMapping::~TraceCostMapping()
+{
+  for (int i=0;i<TraceCost::MaxRealIndex;i++)
+    if (_real[i]) delete _real[i];
+
+  for (int i=0;i<TraceCost::MaxRealIndex;i++)
+    if (_virtual[i]) delete _virtual[i];
+}
+
+TraceSubMapping* TraceCostMapping::subMapping(TQString types, bool create)
+{
+  // first check if there's enough space in the mapping
+  int newCount = 0;
+  int pos = 0, pos2, len = types.length();
+
+  while (1) {
+    // skip space
+    while((pos<len) && types[pos].isSpace()) pos++;
+
+    pos2 = pos;
+    while((pos2<len) && !types[pos2].isSpace()) pos2++;
+    if (pos2 == pos) break;
+
+    if (realIndex(types.mid(pos,pos2-pos)) == TraceCost::InvalidIndex)
+      newCount++;
+
+    pos = pos2;
+  }
+
+  if (!create && (newCount>0)) return 0;
+
+  if (newCount+_realCount > TraceCost::MaxRealIndex) {
+    kdDebug() << "TraceCostMapping::subMapping: No space for " 
+	      << newCount << " sub costs." << endl;
+    return 0;
+  }
+
+  TraceSubMapping* sm = new TraceSubMapping(this);
+
+  pos = 0;
+  while (1) {
+    // skip space
+    while((pos<len) && types[pos].isSpace()) pos++;
+
+    pos2 = pos;
+    while((pos2<len) && !types[pos2].isSpace()) pos2++;
+    if (pos2 == pos) break;
+
+    sm->append(addReal(types.mid(pos,pos2-pos)));
+
+    pos = pos2;
+  }
+
+  return sm;
+}
+
+
+int TraceCostMapping::addReal(TQString t)
+{
+  int index = realIndex(t);
+  if (index>=0) return index;
+
+  TraceCostType* ct = TraceCostType::knownRealType(t);
+  if (!ct) ct = new TraceCostType(t, t);
+
+  // make it real
+  ct->setRealIndex();
+
+  return add(ct);
+}
+
+// add a cost type to a mapping
+// this transfers ownership of the type!
+int TraceCostMapping::add(TraceCostType* ct)
+{
+  if (!ct) return TraceCost::InvalidIndex;
+
+  ct->setMapping(this);
+
+  if (ct->isReal()) {
+    if (_realCount >= TraceCost::MaxRealIndex) {
+      qDebug("WARNING: Maximum for real cost types reached (on adding '%s')",
+             ct->name().ascii());
+      return TraceCost::InvalidIndex;
+    }
+    _real[_realCount] = ct;
+    ct->setRealIndex(_realCount);
+    _realColor[_realCount] = Configuration::costTypeColor(ct);
+
+    _realCount++;
+    return _realCount-1;
+  }
+
+  if (_virtualCount >= TraceCost::MaxRealIndex) {
+    qDebug("WARNING: Maximum for virtual cost types reached (on adding '%s')",
+           ct->name().ascii());
+    return TraceCost::InvalidIndex;
+  }
+  _virtual[_virtualCount] = ct;
+  _virtualCount++;
+  return _virtualCount-1;
+}
+
+// we delete the type: t is invalid when returning true!
+bool TraceCostMapping::remove(TraceCostType* t)
+{
+  if (!t) return false;
+  if (t->mapping() != this) return false;
+
+  // don't delete real types
+  if (t->isReal()) return false;
+
+  int i;
+  for(i=0;i<_virtualCount;i++)
+    if (_virtual[i] == t) break;
+  
+  // not found?
+  if (i == _virtualCount) return false;
+
+  // delete known type with same name
+  TraceCostType::remove(t->name());
+
+  // delete this type
+  _virtual[i] = 0;
+  delete t;
+  if (i+1 == _virtualCount) {
+    // we can reuse the last index
+    _virtualCount--;
+  }
+  return true;
+}
+
+
+TraceCostType* TraceCostMapping::realType(int t)
+{
+  if (t<0 || t>=_realCount) return 0;
+  return _real[t];
+}
+
+TraceCostType* TraceCostMapping::virtualType(int t)
+{
+  if (t<0 || t>=_virtualCount) return 0;
+  return _virtual[t];
+}
+
+
+TraceCostType* TraceCostMapping::type(int t)
+{
+  if (t<0) return 0;
+  if (t<_realCount) return _real[t];
+
+  t -= TraceCost::MaxRealIndex;
+  if (t<0) return 0;
+  if (t<_virtualCount) return _virtual[t];
+
+  return 0;
+}
+
+TraceCostType* TraceCostMapping::type(TQString name)
+{
+  for (int i=0;i<_realCount;i++)
+    if (_real[i] && (_real[i]->name() == name))
+      return _real[i];
+
+  for (int i=0;i<_virtualCount;i++)
+    if (_virtual[i] && (_virtual[i]->name() == name))
+      return _virtual[i];
+
+  return 0;
+}
+
+TraceCostType* TraceCostMapping::typeForLong(TQString name)
+{
+  for (int i=0;i<_realCount;i++)
+    if (_real[i] && (_real[i]->longName() == name))
+      return _real[i];
+
+  for (int i=0;i<_virtualCount;i++)
+    if (_virtual[i] && (_virtual[i]->longName() == name))
+      return _virtual[i];
+
+  return 0;
+}
+
+
+int TraceCostMapping::realIndex(TQString name)
+{
+  for (int i=0;i<_realCount;i++)
+    if (_real[i] && (_real[i]->name() == name))
+      return i;
+
+  return TraceCost::InvalidIndex;
+}
+
+int TraceCostMapping::index(TQString name)
+{
+  for (int i=0;i<_realCount;i++)
+    if (_real[i] && (_real[i]->name() == name))
+      return i;
+
+  for (int i=0;i<_virtualCount;i++)
+    if (_virtual[i] && (_virtual[i]->name() == name))
+      return TraceCost::MaxRealIndex + 1 + i;
+
+  return TraceCost::InvalidIndex;
+}
+
+int TraceCostMapping::addKnownVirtualTypes()
+{
+  int addCount = 0;
+  int addDiff, i;
+  int knownCount = TraceCostType::knownTypeCount();
+
+  while (1) {
+    addDiff = 0;
+    for (i=0; i<knownCount; i++) {
+      TraceCostType* t = TraceCostType::knownType(i);
+      if (t->isReal()) continue;
+      if (index(t->name()) != TraceCost::InvalidIndex) continue;
+      t->setMapping(this);
+      if (t->parseFormula()) {
+        addDiff++;
+        add(new TraceCostType(t->name(), t->longName(), t->formula()));
+      }
+      t->setMapping(0);
+    }
+    if (addDiff == 0) break;
+    addCount += addDiff;
+  }
+  return addCount;
+}
+
+
+//---------------------------------------------------
+// TraceSubMapping
+
+TraceSubMapping::TraceSubMapping(TraceCostMapping* mapping)
+{
+  _mapping = mapping;
+  clear();
+}
+
+void TraceSubMapping::clear()
+{
+  _count = 0;
+  _isIdentity = true;
+  _firstUnused = 0;
+  for(int i=0;i<TraceCost::MaxRealIndex;i++) {
+    _realIndex[i] = TraceCost::InvalidIndex;
+    _nextUnused[i] = i+1;
+  }
+}
+
+bool TraceSubMapping::append(TQString type, bool create)
+{
+  if (!_mapping) return false;
+  int index = create ? _mapping->addReal(type) : _mapping->realIndex(type);
+
+  return append(index);
+}
+
+bool TraceSubMapping::append(int type)
+{
+  if (!_mapping) return false;
+  if ((type<0) || (type >= _mapping->realCount())) return false;
+
+  if ( _count >=  TraceCost::MaxRealIndex) return false;
+
+  _realIndex[_count] = type;
+
+  if (_isIdentity && (_count != type)) _isIdentity = false;
+  if (type == _firstUnused)
+      _firstUnused = _nextUnused[type];
+  for(int i=0;i<type;i++)
+      if (_nextUnused[i] == type)
+	  _nextUnused[i]=_nextUnused[type];
+
+  _count++;
+  return true;
+}
+
+
+//---------------------------------------------------
+// TraceCallCost
+
+TraceCallCost::TraceCallCost()
+{
+  _callCount = 0;
+}
+
+TraceCallCost::~TraceCallCost()
+{}
+
+
+TQString TraceCallCost::costString(TraceCostMapping* m)
+{
+  return TQString("%1, Calls %2")
+      .arg(TraceCost::costString(m))
+      .arg(_callCount.pretty());
+}
+
+TQString TraceCallCost::prettyCallCount()
+{
+  return _callCount.pretty();
+}
+
+void TraceCallCost::clear()
+{
+  _callCount = 0;
+  TraceCost::clear();
+}
+
+SubCost TraceCallCost::callCount()
+{
+  if (_dirty) update();
+
+  return _callCount;
+}
+
+void TraceCallCost::addCallCount(SubCost c)
+{
+  _callCount += c;
+
+  invalidate();
+}
+
+
+//---------------------------------------------------
+// TraceInclusiveCost
+
+TraceInclusiveCost::TraceInclusiveCost()
+{}
+
+TraceInclusiveCost::~TraceInclusiveCost()
+{}
+
+TQString TraceInclusiveCost::costString(TraceCostMapping* m)
+{
+  return TQString("%1, Inclusive %2")
+    .arg(TraceCost::costString(m))
+    .arg(_inclusive.costString(m));
+}
+
+void TraceInclusiveCost::clear()
+{
+  _inclusive.clear();
+  TraceCost::clear();
+}
+
+TraceCost* TraceInclusiveCost::inclusive()
+{
+  if (_dirty) update();
+
+  return &_inclusive;
+}
+
+void TraceInclusiveCost::addInclusive(TraceCost* c)
+{
+  _inclusive.addCost(c);
+
+  invalidate();
+}
+
+
+//---------------------------------------------------
+// TraceListCost
+
+TraceListCost::TraceListCost()
+{
+  _lastDep = 0;
+}
+
+TraceListCost::~TraceListCost()
+{}
+
+void TraceListCost::addDep(TraceCost* dep)
+{
+#if TRACE_ASSERTIONS
+  if (_deps.findRef(dep)>=0) {
+    qDebug("addDep: %s already in list!",
+           dep->fullName().ascii());
+    return;
+  }
+#endif
+
+  _deps.append(dep);
+  _lastDep = dep;
+  invalidate();
+
+#if TRACE_DEBUG
+  qDebug("%s added\n %s (now %d)",
+         fullName().ascii(), dep->fullName().ascii(),
+         _deps.count());
+#endif
+}
+
+TraceCost* TraceListCost::findDepFromPart(TracePart* part)
+{
+  if (_lastDep && _lastDep->part() == part)
+    return _lastDep;
+
+  TraceCost* dep;
+  for (dep = _deps.first(); dep; dep = _deps.next())
+    if (dep->part() == part) {
+      _lastDep = dep;
+      return dep;
+    }
+  return 0;
+}
+
+
+void TraceListCost::update()
+{
+  if (!_dirty) return;
+
+#if TRACE_DEBUG
+  qDebug("update %s (count %d)",
+         fullName().ascii(), _deps.count());
+#endif
+
+  clear();
+  TraceCost* item;
+  for (item = _deps.first(); item; item = _deps.next()) {
+    if (onlyActiveParts())
+      if (!item->part() || !item->part()->isActive()) continue;
+
+    addCost(item);
+  }
+
+  _dirty = false;
+
+#if TRACE_DEBUG
+  qDebug("   > %s", costString(0).ascii());
+#endif
+}
+
+
+
+//---------------------------------------------------
+// TraceJumpListCost
+
+TraceJumpListCost::TraceJumpListCost()
+{
+  _lastDep = 0;
+}
+
+TraceJumpListCost::~TraceJumpListCost()
+{}
+
+void TraceJumpListCost::addDep(TraceJumpCost* dep)
+{
+#if TRACE_ASSERTIONS
+  if (_deps.findRef(dep)>=0) {
+    qDebug("addDep: %s already in list!",
+           dep->fullName().ascii());
+    return;
+  }
+#endif
+
+  _deps.append(dep);
+  _lastDep = dep;
+  invalidate();
+
+#if TRACE_DEBUG
+  qDebug("%s added\n %s (now %d)",
+         fullName().ascii(), dep->fullName().ascii(),
+         _deps.count());
+#endif
+}
+
+TraceJumpCost* TraceJumpListCost::findDepFromPart(TracePart* part)
+{
+  if (_lastDep && _lastDep->part() == part)
+    return _lastDep;
+
+  TraceJumpCost* dep;
+  for (dep = _deps.first(); dep; dep = _deps.next())
+    if (dep->part() == part) {
+      _lastDep = dep;
+      return dep;
+    }
+  return 0;
+}
+
+
+void TraceJumpListCost::update()
+{
+  if (!_dirty) return;
+
+#if TRACE_DEBUG
+  qDebug("update %s (count %d)",
+         fullName().ascii(), _deps.count());
+#endif
+
+  clear();
+  TraceJumpCost* item;
+  for (item = _deps.first(); item; item = _deps.next()) {
+    if (onlyActiveParts())
+      if (!item->part() || !item->part()->isActive()) continue;
+
+    addCost(item);
+  }
+
+  _dirty = false;
+
+#if TRACE_DEBUG
+  qDebug("   > %s", costString(0).ascii());
+#endif
+}
+
+
+
+//---------------------------------------------------
+// TraceCallListCost
+
+TraceCallListCost::TraceCallListCost()
+{
+  _lastDep = 0;
+}
+
+TraceCallListCost::~TraceCallListCost()
+{}
+
+void TraceCallListCost::addDep(TraceCallCost* dep)
+{
+#if TRACE_ASSERTIONS
+  if (_deps.findRef(dep)>=0) {
+    qDebug("addDep: %s already in list!",
+           dep->fullName().ascii());
+    return;
+  }
+#endif
+
+  _deps.append(dep);
+  _lastDep = dep;
+  invalidate();
+
+#if TRACE_DEBUG
+  qDebug("%s added\n %s (now %d)",
+         fullName().ascii(), dep->fullName().ascii(),
+         _deps.count());
+#endif
+}
+
+TraceCallCost* TraceCallListCost::findDepFromPart(TracePart* part)
+{
+  if (_lastDep && _lastDep->part() == part)
+    return _lastDep;
+
+  TraceCallCost* dep;
+  for (dep = _deps.first(); dep; dep = _deps.next())
+    if (dep->part() == part) {
+      _lastDep = dep;
+      return dep;
+    }
+  return 0;
+}
+
+
+void TraceCallListCost::update()
+{
+  if (!_dirty) return;
+
+#if TRACE_DEBUG
+  qDebug("update %s (count %d)",
+         fullName().ascii(), _deps.count());
+#endif
+
+  /* Without dependent cost items, assume fixed costs,
+   * i.e. don't change cost */
+  if (_deps.count()>0) {
+    clear();
+    TraceCallCost* item;
+    for (item = _deps.first(); item; item = _deps.next()) {
+      if (onlyActiveParts())
+	if (!item->part() || !item->part()->isActive()) continue;
+      
+      addCost(item);
+      addCallCount(item->callCount());
+    }
+  }
+
+  _dirty = false;
+
+#if TRACE_DEBUG
+  qDebug("   > %s", costString(0).ascii());
+#endif
+}
+
+
+//---------------------------------------------------
+// TraceInclusiveListCost
+
+TraceInclusiveListCost::TraceInclusiveListCost()
+{
+  _lastDep = 0;
+}
+
+TraceInclusiveListCost::~TraceInclusiveListCost()
+{}
+
+
+void TraceInclusiveListCost::addDep(TraceInclusiveCost* dep)
+{
+#if TRACE_ASSERTIONS
+  if (_deps.findRef(dep)>=0) {
+    qDebug("addDep: %s already in list!",
+           dep->fullName().ascii());
+    return;
+  }
+#endif
+
+  _deps.append(dep);
+  _lastDep = dep;
+  invalidate();
+
+#if TRACE_DEBUG
+  qDebug("%s added\n %s (now %d)",
+         fullName().ascii(), dep->fullName().ascii(),
+         _deps.count());
+#endif
+}
+
+TraceInclusiveCost* TraceInclusiveListCost::findDepFromPart(TracePart* part)
+{
+  if (_lastDep && _lastDep->part() == part)
+    return _lastDep;
+
+  TraceInclusiveCost* dep;
+  for (dep = _deps.first(); dep; dep = _deps.next())
+    if (dep->part() == part) {
+      _lastDep = dep;
+      return dep;
+    }
+  return 0;
+}
+
+void TraceInclusiveListCost::update()
+{
+  if (!_dirty) return;
+
+#if TRACE_DEBUG
+  qDebug("update %s (count %d)",
+         fullName().ascii(), _deps.count());
+#endif
+
+  clear();
+  TraceInclusiveCost* item;
+  for (item = _deps.first(); item; item = _deps.next()) {
+    if (onlyActiveParts())
+      if (!item->part() || !item->part()->isActive()) continue;
+
+    addCost(item);
+    addInclusive(item->inclusive());
+  }
+
+  _dirty = false;
+
+#if TRACE_DEBUG
+  qDebug("   > %s", costString(0).ascii());
+#endif
+}
+
+
+
+//---------------------------------------------------
+// TracePartInstrJump
+
+TracePartInstrJump::TracePartInstrJump(TraceInstrJump* instrJump,
+				       TracePartInstrJump* next)
+{
+  _dep = instrJump;
+  _next = next;
+}
+
+TracePartInstrJump::~TracePartInstrJump()
+{}
+
+
+//---------------------------------------------------
+// TracePartInstrCall
+
+TracePartInstrCall::TracePartInstrCall(TraceInstrCall* instrCall)
+{
+  _dep = instrCall;
+}
+
+TracePartInstrCall::~TracePartInstrCall()
+{}
+
+
+
+//---------------------------------------------------
+// TracePartInstr
+
+TracePartInstr::TracePartInstr(TraceInstr* instr)
+{
+  _dep = instr;
+}
+
+TracePartInstr::~TracePartInstr()
+{}
+
+
+
+//---------------------------------------------------
+// TracePartLineJump
+
+TracePartLineJump::TracePartLineJump(TraceLineJump* lineJump)
+{
+  _dep = lineJump;
+}
+
+TracePartLineJump::~TracePartLineJump()
+{}
+
+
+//---------------------------------------------------
+// TracePartLineCall
+
+TracePartLineCall::TracePartLineCall(TraceLineCall* lineCall)
+{
+  _dep = lineCall;
+}
+
+TracePartLineCall::~TracePartLineCall()
+{}
+
+
+//---------------------------------------------------
+// TracePartLine
+
+TracePartLine::TracePartLine(TraceLine* line)
+{
+  _dep = line;
+}
+
+TracePartLine::~TracePartLine()
+{}
+
+
+
+
+//---------------------------------------------------
+// TracePartCall
+
+TracePartCall::TracePartCall(TraceCall* call)
+{
+  _dep = call;
+
+  _firstFixCallCost = 0;
+}
+
+TracePartCall::~TracePartCall()
+{}
+
+bool TracePartCall::isRecursion()
+{
+  return call()->isRecursion();
+}
+
+void TracePartCall::update()
+{
+#if !USE_FIXCOST
+  TraceCallListCost::update();
+#else
+
+  if (!_dirty) return;
+
+#if TRACE_DEBUG
+  qDebug("update %s", fullName().ascii());
+#endif
+
+  /* Without dependent cost items, assume fixed costs,
+   * i.e. don't change cost */
+  if (_firstFixCallCost) {
+    clear();
+    FixCallCost* item;
+    for (item = _firstFixCallCost; item; item = item->nextCostOfPartCall())
+      item->addTo(this);
+  }
+
+  _dirty = false;
+
+#if TRACE_DEBUG
+  qDebug("   > %s", costString(0).ascii());
+#endif
+
+#endif // USE_FIXCOST
+}
+
+
+//---------------------------------------------------
+// TracePartFunction
+
+TracePartFunction::TracePartFunction(TraceFunction* function,
+                                     TracePartObject* partObject,
+				     TracePartFile *partFile)
+{
+  _dep = function;
+  _partObject = partObject;
+  _partFile = partFile;
+  _partClass = 0;
+
+  _calledCount     = 0;
+  _callingCount    = 0;
+  _calledContexts  = 0;
+  _callingContexts = 0;
+
+  _firstFixCost = 0;
+  _firstFixJump = 0;
+}
+
+TracePartFunction::~TracePartFunction()
+{}
+
+TQString TracePartFunction::prettyCalledCount()
+{
+  return _calledCount.pretty();
+}
+
+TQString TracePartFunction::prettyCallingCount()
+{
+  return _callingCount.pretty();
+}
+
+TQString TracePartFunction::costString(TraceCostMapping* m)
+{
+  update();
+
+  TQString res = TraceInclusiveCost::costString(m);
+  res += TQString(", called from %1: %2")
+         .arg(_calledContexts).arg(prettyCalledCount());
+  res += TQString(", calling from %1: %2")
+         .arg(_callingContexts).arg(prettyCallingCount());
+
+  return res;
+}
+
+
+void TracePartFunction::addPartInstr(TracePartInstr* ref)
+{
+#if TRACE_ASSERTIONS
+  if (_partInstr.findRef(ref)>=0) {
+    qDebug("TracePartFunction::addPartInstr: %s already in list!",
+           ref->name().ascii());
+    return;
+  }
+#endif
+
+  _partInstr.append(ref);
+  invalidate();
+
+#if TRACE_DEBUG
+  qDebug("%s added\n %s (now %d)",
+         fullName().ascii(), ref->fullName().ascii(),
+         _partInstr.count());
+#endif
+}
+
+
+void TracePartFunction::addPartLine(TracePartLine* ref)
+{
+#if TRACE_ASSERTIONS
+  if (_partLines.findRef(ref)>=0) {
+    qDebug("TracePartFunction::addPartLine: %s already in list!",
+           ref->name().ascii());
+    return;
+  }
+#endif
+
+  _partLines.append(ref);
+  invalidate();
+
+#if TRACE_DEBUG
+  qDebug("%s added\n %s (now %d)",
+         fullName().ascii(), ref->fullName().ascii(),
+         _partLines.count());
+#endif
+}
+
+
+void TracePartFunction::addPartCaller(TracePartCall* ref)
+{
+#if TRACE_ASSERTIONS
+  if (_partCallers.findRef(ref)>=0) {
+    qDebug("TracePartFunction::addPartCaller: %s already in list!",
+           ref->name().ascii());
+    return;
+  }
+#endif
+
+  _partCallers.append(ref);
+  invalidate();
+
+#if TRACE_DEBUG
+  qDebug("%s added Caller\n %s (now %d)",
+         fullName().ascii(), ref->fullName().ascii(),
+         _partCallers.count());
+#endif
+}
+
+
+void TracePartFunction::addPartCalling(TracePartCall* ref)
+{
+#if TRACE_ASSERTIONS
+  if (_partCallings.findRef(ref)>=0) {
+    qDebug("TracePartFunction::addPartCalling: %s already in list!",
+           ref->name().ascii());
+    return;
+  }
+#endif
+
+  _partCallings.append(ref);
+  invalidate();
+
+#if TRACE_DEBUG
+  qDebug("%s added Calling\n %s (now %d)",
+         fullName().ascii(), ref->fullName().ascii(),
+         _partCallings.count());
+#endif
+}
+
+SubCost TracePartFunction::calledCount()
+{
+  if (_dirty) update();
+
+  return _calledCount;
+}
+
+int TracePartFunction::calledContexts()
+{
+  if (_dirty) update();
+
+  return _calledContexts;
+}
+
+SubCost TracePartFunction::callingCount()
+{
+  if (_dirty) update();
+
+  return _callingCount;
+}
+
+
+int TracePartFunction::callingContexts()
+{
+  if (_dirty) update();
+
+  return _callingContexts;
+}
+
+
+void TracePartFunction::update()
+{
+  if (!_dirty) return;
+
+#if TRACE_DEBUG
+  qDebug("TracePartFunction::update %s (Callers %d, Callings %d, lines %d)",
+         name().ascii(), _partCallers.count(), _partCallings.count(),
+         _partLines.count());
+#endif
+
+  _calledCount     = 0;
+  _callingCount    = 0;
+  _calledContexts  = 0;
+  _callingContexts = 0;
+
+  // calculate additional cost metrics
+  TracePartCall *caller, *calling;
+  for (caller=_partCallers.first();caller;caller=_partCallers.next()) {
+
+    // FIXME
+    if (caller->subCost(0)>0)
+      _calledContexts++;
+
+    SubCost c = caller->callCount();
+    if (c>0) {
+      _calledCount += c;
+    }
+  }
+  for (calling=_partCallings.first();calling;calling=_partCallings.next()) {
+    // FIXME
+    if (calling->subCost(0)>0)
+      _callingContexts++;
+
+    SubCost c = calling->callCount();
+    if (c>0) {
+      _callingCount += c;
+    }
+  }
+
+  // self cost
+#if !USE_FIXCOST
+  if (_partLines.count()>0) {
+    TraceCost::clear();
+
+    TracePartLine* line;
+    for (line = _partLines.first(); line; line = _partLines.next())
+      addCost(line);
+  }
+#else
+  if (_firstFixCost) {
+    TraceCost::clear();
+
+    FixCost* item;
+    for (item = _firstFixCost; item; item = item->nextCostOfPartFunction())
+      item->addTo(this);
+  }
+#endif
+
+
+  /* There are two possibilities to calculate inclusive cost:
+   * 1) sum of call costs to this function
+   * 2) sum of call costs from this function + self cost
+   *
+   * 1) is wrong if a function was called spontaneous, but also by a call.
+   * This eventually can happen with thread/process startup functions,
+   * and signal handlers.
+   *
+   * 2) is wrong with "skipped PLT" and the calltree skin, because
+   *    cost of PLT is attributed to called function (?)
+   *
+   * For now, do 1) if there are callers, otherwise 2).
+   * Should this be fixed to take the maximum of 1) and 2) ?
+   */
+  _inclusive.clear();
+  if (_calledCount>0) {
+      // inclusive cost: if possible, use caller sums
+    for (caller=_partCallers.first();caller;caller=_partCallers.next()) {
+      // detect simple recursion (no cycle)
+      if (caller->isRecursion()) continue;
+
+      addInclusive(caller);
+    }
+  }
+  else {
+    // without caller info, use calling sum + line costs
+    for (calling=_partCallings.first();calling;calling=_partCallings.next()) {
+      // detect simple recursion (no cycle)
+      if (calling->isRecursion()) continue;
+
+      addInclusive(calling);
+    }
+    _dirty = false; // don't recurse!
+    addInclusive(this);
+  }
+
+  _dirty = false;
+
+#if TRACE_DEBUG
+  qDebug("   > %s", costString(0).ascii());
+#endif
+}
+
+
+
+//---------------------------------------------------
+// TracePartClass
+
+TracePartClass::TracePartClass(TraceClass* cls)
+{
+  _dep = cls;
+}
+
+TracePartClass::~TracePartClass()
+{}
+
+TQString TracePartClass::prettyName() const
+{
+  return TQString("%1 from %2")
+    .arg( _dep->name().isEmpty() ? TQString("(global)") : _dep->name())
+    .arg(part()->name());
+}
+
+//---------------------------------------------------
+// TracePartFile
+
+TracePartFile::TracePartFile(TraceFile* file)
+{
+  _dep = file;
+}
+
+TracePartFile::~TracePartFile()
+{}
+
+
+//---------------------------------------------------
+// TracePartObject
+
+TracePartObject::TracePartObject(TraceObject* object)
+{
+  _dep = object;
+}
+
+TracePartObject::~TracePartObject()
+{}
+
+
+
+
+//---------------------------------------------------
+// TraceInstrJump
+
+TraceInstrJump::TraceInstrJump(TraceInstr* instrFrom, TraceInstr* instrTo,
+			       bool isCondJump)
+{
+  _first = 0;
+
+  _instrFrom = instrFrom;
+  _instrTo = instrTo;
+  _isCondJump = isCondJump;
+}
+
+TraceInstrJump::~TraceInstrJump()
+{
+  // we are the owner of the TracePartInstrJump's generated in our factory
+  TracePartInstrJump* item = _first, *next;
+  while(item) {
+    next = item->next();
+    delete item;
+    item = next;
+  }
+}
+
+TracePartInstrJump* TraceInstrJump::partInstrJump(TracePart* part)
+{
+  static TracePartInstrJump* item = 0;
+
+  // shortcut
+  if (item && (item->instrJump()==this) && (item->part() == part)) return item;
+
+  for(item = _first; item; item = item->next())
+    if (item->part() == part) break;
+
+  if (!item) {
+    item = new TracePartInstrJump(this, _first);
+    item->setPosition(part);
+    _first = item;
+  }
+  return item;
+}
+
+void TraceInstrJump::update()
+{
+  if (!_dirty) return;
+
+  clear();
+  TracePartInstrJump* item;
+  for (item = _first; item; item = item->next()) {
+    if (!item->part() || !item->part()->isActive()) continue;
+
+    addCost(item);
+  }
+  _dirty = false;
+
+#if TRACE_DEBUG
+  qDebug("updated %s", fullName().ascii());
+#endif
+
+#if TRACE_DEBUG
+  qDebug("   > %s", costString(0).ascii());
+#endif
+}
+
+TQString TraceInstrJump::name() const
+{
+  return TQString("jump at 0x%1 to 0x%2")
+    .arg(_instrFrom->addr().toString())
+    .arg(_instrTo->addr().toString());
+}
+
+
+//---------------------------------------------------
+// TraceInstrJumpList
+
+
+int TraceInstrJumpList::compareItems ( Item item1, Item item2 )
+{
+    TraceInstrJump* ij1 = (TraceInstrJump*) item1;
+    TraceInstrJump* ij2 = (TraceInstrJump*) item2;
+
+    Addr addr1Low  = ij1->instrFrom()->addr();
+    Addr addr2Low  = ij2->instrFrom()->addr();
+    Addr addr1High = ij1->instrTo()->addr();
+    Addr addr2High = ij2->instrTo()->addr();
+    Addr t;
+
+    if (addr1Low > addr1High) {
+	t = addr1Low;
+	addr1Low = addr1High;
+	addr1High = t;
+    }
+
+    if (addr2Low > addr2High) {
+	t = addr2Low;
+	addr2Low = addr2High;
+	addr2High = t;
+    }
+
+    if (_sortLow) {
+	// we sort according to smallest instruction address
+	if (addr1Low != addr2Low) return (addr1Low > addr2Low) ? 1:-1;
+	// jump ends come before jump starts
+	if (addr1Low == ij1->instrTo()->addr()) return -1;
+	if (addr2Low == ij2->instrTo()->addr()) return 1;
+	return (addr1High > addr2High) ? 1:-1;
+    }
+
+    // we sort according to highest instruction address
+    if (addr1High != addr2High) return (addr1High > addr2High) ? 1:-1;
+    // jump ends come before jump starts
+    if (addr1High == ij1->instrTo()->addr()) return -1;
+    if (addr2High == ij2->instrTo()->addr()) return 1;
+    return (addr1Low > addr2Low) ? 1:-1;
+}
+
+
+//---------------------------------------------------
+// TraceLineJump
+
+TraceLineJump::TraceLineJump(TraceLine* lineFrom, TraceLine* lineTo,
+			     bool isCondJump)
+{
+  // we are the owner of TracePartLineJump's generated in our factory
+  _deps.setAutoDelete(true);
+
+  _lineFrom = lineFrom;
+  _lineTo   = lineTo;
+  _isCondJump = isCondJump;
+}
+
+TraceLineJump::~TraceLineJump()
+{}
+
+
+TracePartLineJump* TraceLineJump::partLineJump(TracePart* part)
+{
+  TracePartLineJump* item = (TracePartLineJump*) findDepFromPart(part);
+  if (!item) {
+    item = new TracePartLineJump(this);
+    item->setPosition(part);
+    addDep(item);
+  }
+  return item;
+}
+
+
+TQString TraceLineJump::name() const
+{
+  return TQString("jump at %1 to %2")
+      .arg(_lineFrom->prettyName())
+      .arg(_lineTo->prettyName());
+}
+
+
+//---------------------------------------------------
+// TraceLineJumpList
+
+
+int TraceLineJumpList::compareItems ( Item item1, Item item2 )
+{
+    TraceLineJump* lj1 = (TraceLineJump*) item1;
+    TraceLineJump* lj2 = (TraceLineJump*) item2;
+
+    uint line1Low  = lj1->lineFrom()->lineno();
+    uint line2Low  = lj2->lineFrom()->lineno();
+    uint line1High = lj1->lineTo()->lineno();
+    uint line2High = lj2->lineTo()->lineno();
+    uint t;
+
+    if (line1Low > line1High) {
+	t = line1Low; line1Low = line1High; line1High = t;
+    }
+    if (line2Low > line2High) {
+	t = line2Low; line2Low = line2High; line2High = t;
+    }
+
+    if (_sortLow) {
+	// we sort according to smallest line number
+	if (line1Low != line2Low) return line1Low - line2Low;
+	// jump ends come before jump starts
+	if (line1Low == lj1->lineTo()->lineno()) return -1;
+	if (line2Low == lj2->lineTo()->lineno()) return 1;
+	return line1High - line2High;
+    }
+
+    // we sort according to highest line number
+    if (line1High != line2High) return line1High - line2High;
+    // jump ends come before jump starts
+    if (line1High == lj1->lineTo()->lineno()) return -1;
+    if (line2High == lj2->lineTo()->lineno()) return 1;
+    return line1Low - line2Low;
+}
+
+
+//---------------------------------------------------
+// TraceInstrCall
+
+TraceInstrCall::TraceInstrCall(TraceCall* call, TraceInstr* instr)
+{
+  // we are the owner of TracePartInstrCall's generated in our factory
+  _deps.setAutoDelete(true);
+
+  _call  = call;
+  _instr = instr;
+}
+
+TraceInstrCall::~TraceInstrCall()
+{}
+
+
+TracePartInstrCall* TraceInstrCall::partInstrCall(TracePart* part,
+						  TracePartCall*)
+{
+  TracePartInstrCall* item = (TracePartInstrCall*) findDepFromPart(part);
+  if (!item) {
+    item = new TracePartInstrCall(this);
+    item->setPosition(part);
+    addDep(item);
+    // instruction calls are not registered in function calls
+    // as together with line calls calls are duplicated
+    //partCall->addDep(item);
+  }
+  return item;
+}
+
+
+TQString TraceInstrCall::name() const
+{
+  return TQString("%1 at %2").arg(_call->name()).arg(_instr->name());
+}
+
+
+//---------------------------------------------------
+// TraceLineCall
+
+TraceLineCall::TraceLineCall(TraceCall* call, TraceLine* line)
+{
+  // we are the owner of TracePartLineCall's generated in our factory
+  _deps.setAutoDelete(true);
+
+  _call = call;
+  _line = line;
+}
+
+TraceLineCall::~TraceLineCall()
+{}
+
+
+TracePartLineCall* TraceLineCall::partLineCall(TracePart* part,
+                                               TracePartCall* partCall)
+{
+  TracePartLineCall* item = (TracePartLineCall*) findDepFromPart(part);
+  if (!item) {
+    item = new TracePartLineCall(this);
+    item->setPosition(part);
+    addDep(item);
+    partCall->addDep(item);
+  }
+  return item;
+}
+
+
+TQString TraceLineCall::name() const
+{
+  return TQString("%1 at %2").arg(_call->name()).arg(_line->name());
+}
+
+
+//---------------------------------------------------
+// TraceCall
+
+TraceCall::TraceCall(TraceFunction* caller, TraceFunction* called)
+{
+  // we are the owner of all items generated in our factory
+  _deps.setAutoDelete(true);
+  _lineCalls.setAutoDelete(true);
+
+  _caller = caller;
+  _called = called;
+}
+
+
+TraceCall::~TraceCall()
+{}
+
+TracePartCall* TraceCall::partCall(TracePart* part,
+                                   TracePartFunction* partCaller,
+                                   TracePartFunction* partCalling)
+{
+  TracePartCall* item = (TracePartCall*) findDepFromPart(part);
+  if (!item) {
+    item = new TracePartCall(this);
+    item->setPosition(part);
+    addDep(item);
+    partCaller->addPartCalling(item);
+    partCalling->addPartCaller(item);
+  }
+  return item;
+}
+
+TraceInstrCall* TraceCall::instrCall(TraceInstr* i)
+{
+  TraceInstrCall* icall;
+  for (icall=_instrCalls.first();icall;icall=_instrCalls.next())
+    if (icall->instr() == i)
+      break;
+
+  if (!icall) {
+    icall = new TraceInstrCall(this, i);
+
+    _instrCalls.append(icall);
+    invalidate();
+
+#if TRACE_DEBUG
+    qDebug("Created %s [TraceCall::instrCall]", icall->fullName().ascii());
+#endif
+    i->addInstrCall(icall);
+  }
+  return icall;
+}
+
+
+TraceLineCall* TraceCall::lineCall(TraceLine* l)
+{
+  TraceLineCall* lcall;
+  for (lcall=_lineCalls.first();lcall;lcall=_lineCalls.next())
+    if (lcall->line() == l)
+      break;
+
+  if (!lcall) {
+    lcall = new TraceLineCall(this, l);
+
+    _lineCalls.append(lcall);
+    invalidate();
+
+#if TRACE_DEBUG
+    qDebug("Created %s [TraceCall::lineCall]", lcall->fullName().ascii());
+#endif
+    l->addLineCall(lcall);
+  }
+  return lcall;
+}
+
+
+void TraceCall::invalidateDynamicCost()
+{
+  TraceLineCall* lc;
+  for (lc=_lineCalls.first();lc;lc=_lineCalls.next())
+    lc->invalidate();
+
+  TraceInstrCall* ic;
+  for (ic=_instrCalls.first();ic;ic=_instrCalls.next())
+    ic->invalidate();
+
+  invalidate();
+}
+
+
+TQString TraceCall::name() const
+{
+  return TQString("%1 => %2")
+    .arg(_caller->name())
+    .arg(_called->name());
+}
+
+int TraceCall::inCycle()
+{
+  if (!_caller || !_called) return 0;
+  if (!_caller->cycle()) return 0;
+  if (_caller == _caller->cycle()) return 0;
+  if (_caller->cycle() != _called->cycle()) return 0;
+
+  return _caller->cycle()->cycleNo();
+}
+
+void TraceCall::update()
+{
+  if (!_dirty) return;
+
+  // special handling for cycles
+  if (_caller && _caller->cycle() && _caller==_caller->cycle()) {
+
+    // we have no part calls: use inclusive cost of called function
+    clear();
+    if (_called)
+      addCost(_called->inclusive());
+    _dirty = false;
+    return;
+  }
+
+  TraceCallListCost::update();
+}
+
+TraceFunction* TraceCall::caller(bool /*skipCycle*/) const
+{
+  return _caller;
+}
+
+TraceFunction* TraceCall::called(bool skipCycle) const
+{
+  if (!skipCycle && _called) {
+    // if this is a call to a cycle member from outside of the cycle,
+    // fake it to be a call to the whole cycle
+    if (_called->cycle() && _caller &&
+        (_caller->cycle() != _called->cycle()))
+      return _called->cycle();
+  }
+
+  return _called;
+}
+
+TQString TraceCall::callerName(bool skipCycle) const
+{
+  if (!_caller) return i18n("(no caller)");
+
+  if (!skipCycle) {
+      // if this call goes into a cycle, add the entry function
+      TraceFunctionCycle* c = _called->cycle();
+      if (c && _caller && (_caller->cycle() != c)) {
+	  TQString via = _called->prettyName();
+	  return i18n("%1 via %2").arg(_caller->prettyName()).arg(via);
+      }
+  }
+
+  return _caller->prettyName();
+}
+
+TQString TraceCall::calledName(bool skipCycle) const
+{
+  if (!_called) return i18n("(no callee)");
+
+  if (!skipCycle) {
+      // if this call goes into a cycle, add the entry function
+      TraceFunctionCycle* c = _called->cycle();
+      if (c && _caller && (_caller->cycle() != c)) {
+	  // HACK to get rid of cycle postfix...
+	  _called->setCycle(0);
+	  TQString via = _called->prettyName();
+	  _called->setCycle(c);
+	  return i18n("%1 via %2").arg(c->name()).arg(via);
+      }
+  }
+  return _called->prettyName();
+}
+
+
+//---------------------------------------------------
+// TraceInstr
+
+TraceInstr::TraceInstr()
+{
+  // we are the owner of TracePartInstr's generated in our factory
+  _deps.setAutoDelete(true);
+  _instrJumps.setAutoDelete(true);
+
+  _addr = 0;
+  _line = 0;
+  _function = 0;
+}
+
+TraceInstr::~TraceInstr()
+{}
+
+bool TraceInstr::hasCost(TraceCostType* ct)
+{
+    bool res = subCost(ct) > 0;
+    if (!res) {
+	TraceInstrCall* ic;
+	for(ic=_instrCalls.first();ic;ic=_instrCalls.next())
+	    if (ic->subCost(ct) > 0) break;
+	res = (ic != 0);
+	if (!res) {
+	    TraceInstrJump* ij;
+	    for(ij=_instrJumps.first();ij;ij=_instrJumps.next())
+		if (ij->executedCount() > 0) break;
+	    res = (ij != 0);
+	}
+    }
+
+    return res;
+}
+
+TracePartInstr* TraceInstr::partInstr(TracePart* part,
+				      TracePartFunction* partFunction)
+{
+  TracePartInstr* item = (TracePartInstr*) findDepFromPart(part);
+  if (!item) {
+    item = new TracePartInstr(this);
+    item->setPosition(part);
+    addDep(item);
+    //part->addDep(item);
+    partFunction->addPartInstr(item);
+  }
+  return item;
+}
+
+TraceInstrJump* TraceInstr::instrJump(TraceInstr* to, bool isJmpCond)
+{
+  TraceInstrJump* jump;
+  for (jump=_instrJumps.first();jump;jump=_instrJumps.next())
+    if (jump->instrTo() == to)
+      break;
+
+  if (!jump) {
+    jump = new TraceInstrJump(this, to, isJmpCond);
+
+    _instrJumps.append(jump);
+  }
+  return jump;
+}
+
+
+
+void TraceInstr::addInstrCall(TraceInstrCall* instrCall)
+{
+#if TRACE_ASSERTIONS
+  if (_instrCalls.findRef(instrCall)>=0) return;
+
+  if (instrCall->instr() != this) {
+    qDebug("Can't add instruction call to another instruction!");
+    return;
+  }
+#endif
+
+  _instrCalls.append(instrCall);
+  invalidate();
+
+#if TRACE_DEBUG
+  qDebug("%s added\n %s (now %d)",
+         fullName().ascii(),
+         instrCall->fullName().ascii(), _instrCalls.count());
+#endif
+}
+
+
+TQString TraceInstr::name() const
+{
+    return TQString("0x%1").arg(_addr.toString());
+}
+
+TQString TraceInstr::prettyName() const
+{
+    return TQString("0x%1").arg(_addr.toString());
+}
+
+
+//---------------------------------------------------
+// TraceLine
+
+TraceLine::TraceLine()
+{
+  // we are the owner of TracePartLine's generated in our factory
+  _deps.setAutoDelete(true);
+  _lineJumps.setAutoDelete(true);
+
+  _lineno = 0;
+  _sourceFile = 0;
+}
+
+TraceLine::~TraceLine()
+{}
+
+bool TraceLine::hasCost(TraceCostType* ct)
+{
+    bool res = subCost(ct) > 0;
+    if (!res) {
+	TraceLineCall* lc;
+	for(lc=_lineCalls.first();lc;lc=_lineCalls.next())
+	    if (lc->subCost(ct) > 0) break;
+	res = (lc != 0);
+	if (!res) {
+	    TraceLineJump* lj;
+	    for(lj=_lineJumps.first();lj;lj=_lineJumps.next())
+		if (lj->executedCount() > 0) break;
+	    res = (lj != 0);
+	}
+    }
+
+    return res;
+}
+
+TracePartLine* TraceLine::partLine(TracePart* part,
+                                   TracePartFunction* partFunction)
+{
+  TracePartLine* item = (TracePartLine*) findDepFromPart(part);
+  if (!item) {
+    item = new TracePartLine(this);
+    item->setPosition(part);
+    addDep(item);
+#if !USE_FIXCOST
+    part->addDep(item);
+#endif
+    partFunction->addPartLine(item);
+  }
+  return item;
+}
+
+TraceLineJump* TraceLine::lineJump(TraceLine* to, bool isJmpCond)
+{
+  TraceLineJump* jump;
+  for (jump=_lineJumps.first();jump;jump=_lineJumps.next())
+    if (jump->lineTo() == to)
+      break;
+
+  if (!jump) {
+    jump = new TraceLineJump(this, to, isJmpCond);
+
+    _lineJumps.append(jump);
+  }
+  return jump;
+}
+
+
+void TraceLine::addLineCall(TraceLineCall* lineCall)
+{
+#if TRACE_ASSERTIONS
+  if (_lineCalls.findRef(lineCall)>=0) return;
+
+  if (lineCall->line() != this) {
+    qDebug("Can't add line call to another line!");
+    return;
+  }
+#endif
+
+  TraceFunction* caller = lineCall->call()->caller();
+  TraceFunction* function = _sourceFile->function();
+  if (caller != function) {
+    // We regard 2 functions as the same if they have
+    // same class, name, object
+    if ((caller->cls() != function->cls()) ||
+        (caller->name() != function->name()) ||
+        (caller->object() != function->object())) {
+
+    qDebug("ERROR: Adding line call, line %d\n  of %s to\n  %s ?!",
+           lineCall->line()->lineno(),
+           caller->info().ascii(), function->info().ascii());
+    }
+  }
+
+  _lineCalls.append(lineCall);
+  invalidate();
+
+#if TRACE_DEBUG
+  qDebug("%s added\n %s (now %d)",
+         fullName().ascii(),
+         lineCall->fullName().ascii(), _lineCalls.count());
+#endif
+}
+
+
+TQString TraceLine::name() const
+{
+    TQString fileShortName = _sourceFile->file()->shortName();
+    if (fileShortName.isEmpty())
+	return i18n("(unknown)");
+
+    return TQString("%1:%2")
+	.arg(fileShortName).arg(_lineno);
+}
+
+TQString TraceLine::prettyName() const
+{
+  return TQString("%1 [%2]")
+    .arg(name()).arg(_sourceFile->function()->prettyName());
+}
+
+//---------------------------------------------------
+// TraceCostItem
+
+TraceCostItem::TraceCostItem()
+{
+}
+
+TraceCostItem::~TraceCostItem()
+{}
+
+
+//---------------------------------------------------
+// TraceFunctionSource
+
+TraceFunctionSource::TraceFunctionSource(TraceFunction* function,
+                                                 TraceFile* file)
+{
+  _file = file;
+  _function = function;
+
+  // the function is dependent from our cost sum
+  _dep = _function;
+
+  _lineMap = 0;
+  _lineMapFilled = false;
+  _line0 = 0;
+}
+
+TraceFunctionSource::~TraceFunctionSource()
+{
+    if (_lineMap) delete _lineMap;
+    if (_line0) delete _line0;
+}
+
+TQString TraceFunctionSource::name() const
+{
+  return TQString("%1 for %2").arg(_file->name()).arg(_function->name());
+}
+
+uint TraceFunctionSource::firstLineno()
+{
+  // lazy generate the map if not done up to now
+  TraceLineMap* map = lineMap();
+  // ignore line 0 here
+  if (!map || map->count() == 0) return 0;
+  TraceLineMap::Iterator it = map->begin();
+  return (*it).lineno();
+}
+
+uint TraceFunctionSource::lastLineno()
+{
+  // lazy generate the map if not done up to now
+  TraceLineMap* map = lineMap();
+  // ignore line 0 here
+  if (!map || map->count() == 0) return 0;
+  TraceLineMap::Iterator it = map->end();
+  --it;
+  return (*it).lineno();
+}
+
+/* factory */
+TraceLine* TraceFunctionSource::line(uint lineno, bool createNew)
+{
+    if (lineno == 0) {
+	if (!_line0) {
+	    if (!createNew) return 0;
+	    _line0 = new TraceLine;
+	    _line0->setSourceFile(this);
+	    _line0->setLineno(0);
+	}
+	return _line0;
+    }
+
+  if (!createNew) {
+    if (!_lineMap) return 0;
+    TraceLineMap::Iterator it = _lineMap->find(lineno);
+    if (it == _lineMap->end()) return 0;
+    return &(it.data());
+  }
+
+  if (!_lineMap) _lineMap = new TraceLineMap;
+
+  TraceLine& l = (*_lineMap)[lineno];
+  if (!l.isValid()) {
+    l.setSourceFile(this);
+    l.setLineno(lineno);
+
+#if TRACE_DEBUG
+    qDebug("Created %s [TraceFunctionSource::line]",
+           l.fullName().ascii());
+#endif
+  }
+  return &l;
+}
+
+void TraceFunctionSource::update()
+{
+  if (!_dirty) return;
+
+  clear();
+
+  // no need to create lineMap if not already created
+  if (_lineMap) {
+    TraceLineMap::Iterator lit;
+    for ( lit = _lineMap->begin();
+          lit != _lineMap->end(); ++lit )
+      addCost( &(*lit) );
+  }
+
+  _dirty = false;
+}
+
+void TraceFunctionSource::invalidateDynamicCost()
+{
+  // no need to create lineMap if not already created
+  if (_lineMap) {
+    TraceLineMap::Iterator lit;
+    for ( lit = _lineMap->begin();
+          lit != _lineMap->end(); ++lit )
+      (*lit).invalidate();
+  }
+
+  invalidate();
+}
+
+TraceLineMap* TraceFunctionSource::lineMap()
+{
+#if USE_FIXCOST
+
+    if (_lineMapFilled) return _lineMap;
+    _lineMapFilled = true;
+    if (!_lineMap)
+	_lineMap = new TraceLineMap;
+
+  TraceLine* l = 0;
+  TracePartLine* pl = 0;
+  TraceLineCall* lc = 0;
+  TracePartLineCall* plc = 0;
+
+  /* go over all part objects for this function, and
+   * - build TraceLines (the line map) using FixCost objects
+   * - build TraceJumpLines using FixJump objects
+   */
+  TraceInclusiveCostList pfList = _function->deps();
+  TracePartFunction* pf = (TracePartFunction*) pfList.first();
+  for(; pf; pf = (TracePartFunction*) pfList.next()) {
+
+      if (0) qDebug("PartFunction %s:%d",
+		    pf->function()->name().ascii(), pf->part()->partNumber());
+
+      FixCost* fc = pf->firstFixCost();
+      for(; fc; fc = fc->nextCostOfPartFunction()) {
+	  if (fc->line() == 0) continue;
+	  if (fc->functionSource() != this) continue;
+
+	  if (!l || l->lineno() != fc->line()) {
+	      l = &(*_lineMap)[fc->line()];
+	      if (!l->isValid()) {
+		  l->setSourceFile(this);
+		  l->setLineno(fc->line());
+	      }
+	      pl = 0;
+	  }
+	  if (!pl || pl->part() != fc->part())
+	      pl = l->partLine(fc->part(), pf);
+	  fc->addTo(pl);
+      }
+
+      TraceLine* to = 0;
+      TraceLineJump* lj;
+      TracePartLineJump* plj;
+      FixJump* fj = pf->firstFixJump();
+      for(; fj; fj = fj->nextJumpOfPartFunction()) {
+	  if (fj->line() == 0) continue;
+	  if (fj->source() != this) continue;
+	  if (!fj->targetSource()) {
+	    // be robust against buggy loaders
+	    continue;
+	  }
+
+	  // don't display jumps to same or following line
+	  if ((fj->line() == fj->targetLine()) ||
+	      (fj->line()+1 == fj->targetLine())) continue;
+
+	  if (!l || l->lineno() != fj->line()) {
+	      l = &(*_lineMap)[fj->line()];
+	      if (!l->isValid()) {
+		  l->setSourceFile(this);
+		  l->setLineno(fj->line());
+	      }
+	  }
+
+	  to = fj->targetSource()->line(fj->targetLine(), true);
+
+	  lj = l->lineJump(to, fj->isCondJump());
+	  plj = lj->partLineJump(fj->part());
+
+	  fj->addTo(plj);
+      }
+
+
+      TracePartCallList pcList = pf->partCallings();
+      TracePartCall* pc = pcList.first();
+      for(; pc; pc = pcList.next()) {
+
+	  if (0) qDebug("PartCall %s:%d",
+			pc->call()->name().ascii(),
+			pf->part()->partNumber());
+
+	  FixCallCost* fcc = pc->firstFixCallCost();
+	  for(; fcc; fcc = fcc->nextCostOfPartCall()) {
+	      if (fcc->line() == 0) continue;
+	      if (fcc->functionSource() != this) continue;
+
+	      if (!l || l->lineno() != fcc->line()) {
+		  l = &(*_lineMap)[fcc->line()];
+		  if (!l->isValid()) {
+		      l->setSourceFile(this);
+		      l->setLineno(fcc->line());
+		  }
+	      }
+	      if (!lc || lc->call() != pc->call() || lc->line() != l) {
+		  lc = pc->call()->lineCall(l);
+		  plc = 0;
+	      }
+	      if (!plc || plc->part() != fcc->part())
+		  plc = lc->partLineCall(fcc->part(), pc);
+
+	      fcc->addTo(plc);
+	      if (0) qDebug("Add FixCallCost %s:%d/0x%s, CallCount %s",
+			    fcc->functionSource()->file()->shortName().ascii(),
+			    fcc->line(), fcc->addr().toString().ascii(),
+			    fcc->callCount().pretty().ascii());
+	  }
+      }
+  }
+
+#endif
+
+  return _lineMap;
+}
+
+
+
+//---------------------------------------------------
+// TraceAssoziation
+
+TraceAssoziation::TraceAssoziation()
+{
+  _function = 0;
+  _valid = false;
+}
+
+TraceAssoziation::~TraceAssoziation()
+{
+  // don't delete from TraceFunction
+  if (_function) _function->removeAssoziation(this);
+}
+
+bool TraceAssoziation::isAssoziated()
+{
+  if (!_function) return false;
+
+  return _function->assoziation(rtti())==this;
+}
+
+bool TraceAssoziation::setFunction(TraceFunction* f)
+{
+  if (_function == f)
+    return isAssoziated();
+
+  if (_function) {
+    // don't delete ourself
+    _function->removeAssoziation(this);
+  }
+
+  _function = f;
+  if (f && f->assoziation(rtti()) == 0) {
+    f->addAssoziation(this);
+    return true;
+  }
+  return false;
+}
+
+void TraceAssoziation::clear(TraceData* d, int rtti)
+{
+  TraceFunctionMap::Iterator it;
+  for ( it = d->functionMap().begin();
+        it != d->functionMap().end(); ++it )
+    (*it).removeAssoziation(rtti);
+}
+
+void TraceAssoziation::invalidate(TraceData* d, int rtti)
+{
+  TraceFunctionMap::Iterator it;
+  for ( it = d->functionMap().begin();
+        it != d->functionMap().end(); ++it )
+    (*it).invalidateAssoziation(rtti);
+}
+
+
+//---------------------------------------------------
+// TraceFunction
+
+TraceFunction::TraceFunction()
+{
+  _object = 0;
+  _file = 0;
+  _cls = 0;
+  _cycle = 0;
+
+    // we are the owner of items generated in our factory
+  _deps.setAutoDelete(true);
+  _callings.setAutoDelete(true);
+  _sourceFiles.setAutoDelete(true);
+
+  _calledCount     = 0;
+  _callingCount    = 0;
+  _calledContexts  = 0;
+  _callingContexts = 0;
+
+  _instrMap = 0;
+  _instrMapFilled = false;
+}
+
+
+TraceFunction::~TraceFunction()
+{
+  _assoziations.setAutoDelete(true);
+  _assoziations.clear();
+
+  if (_instrMap) delete _instrMap;
+}
+
+// no unique check is done!
+void TraceFunction::addAssoziation(TraceAssoziation* a)
+{
+  if (!a) return;
+  _assoziations.append(a);
+}
+
+void TraceFunction::removeAssoziation(TraceAssoziation* a)
+{
+  _assoziations.removeRef(a);
+}
+
+void TraceFunction::removeAssoziation(int rtti, bool reallyDelete)
+{
+  if (rtti==0) {
+    if (reallyDelete)
+      _assoziations.setAutoDelete(true);
+    _assoziations.clear();
+    _assoziations.setAutoDelete(false);
+    return;
+  }
+
+  TraceAssoziation* a;
+  for (a=_assoziations.first();a;a=_assoziations.next())
+    if (a->rtti() == rtti) {
+      if (reallyDelete) delete a;
+      _assoziations.remove();
+      return;
+    }
+}
+
+void TraceFunction::invalidateAssoziation(int rtti)
+{
+  TraceAssoziation* a;
+  for (a=_assoziations.first();a;a=_assoziations.next())
+    if ((rtti==0) || (a->rtti() == rtti))
+      a->invalidate();
+}
+
+TraceAssoziation* TraceFunction::assoziation(int rtti)
+{
+  TraceAssoziation* a;
+  for (a=_assoziations.first();a;a=_assoziations.next())
+    if (a->rtti() == rtti)
+      return a;
+  return 0;
+}
+
+
+// helper for prettyName
+bool TraceFunction::isUniquePrefix(TQString prefix) const
+{
+  TraceFunctionMap::ConstIterator it, it2;
+  it = it2 = _myMapIterator;
+  if (it != data()->functionBeginIterator()) {
+    it2--;
+    if ((*it2).name().startsWith(prefix)) return false;
+  }
+  if (it != data()->functionEndIterator()) {
+    it++;
+    if ((*it).name().startsWith(prefix)) return false;
+  }
+  return true;
+}
+
+
+TQString TraceFunction::prettyName() const
+{
+  TQString res = _name;
+
+  if (_name.isEmpty())
+      return i18n("(unknown)");
+
+  int p = _name.find('(');
+  if (p>0) {
+    // handle C++ "operator()" correct
+    if ((_name[p+1] == ')') && (_name[p+2] == '(')) p+=2;
+
+    // we have a C++ symbol with argument types:
+    // check for unique function name (inclusive '(' !)    
+    if (isUniquePrefix(_name.left(p+1)))
+      res = _name.left(p);
+  }
+
+  // cycle members
+  if (_cycle) {
+    if (_cycle != this)
+      res = TQString("%1 <cycle %2>").arg(res).arg(_cycle->cycleNo());
+    else
+      res = TQString("<cycle %2>").arg(_cycle->cycleNo());
+  }
+
+
+  return res;
+}
+
+/*
+ * Returns location string: ELF object and source file(s).
+ */
+TQString TraceFunction::location(int maxFiles) const
+{
+  TQString loc;
+
+  // add object file with address range
+  if (_object) {
+    loc = _object->shortName();
+
+#if 0
+    uint from = firstAddress();
+    uint to = lastAddress();
+    if (from != 0 && to != 0) {
+      if (from == to)
+        loc += TQString(" (0x%1)").arg(to, 0, 16);
+      else
+        loc += TQString(" (0x%1-0x%2)").arg(from, 0, 16).arg(to, 0, 16);
+    }
+#endif   
+  }
+
+  // add all source files
+  int filesAdded = 0;
+  TraceFunctionSourceList list = _sourceFiles;
+  TraceFunctionSource* sourceFile = list.first();
+  for (;sourceFile;sourceFile=list.next()) {
+    if (!sourceFile->file() ||
+	(sourceFile->file()->name().isEmpty()) )
+      continue;
+
+    if (!loc.isEmpty())
+      loc += (filesAdded>0) ? ", " : ": ";
+    filesAdded++;
+
+    if ((maxFiles>0) && (filesAdded>maxFiles)) {
+	loc += "...";
+	break;
+    }
+    loc += sourceFile->file()->shortName();
+
+#if 0
+    from = sourceFile->firstLineno();
+    to = sourceFile->lastLineno();
+    if (from != 0 && to != 0) {
+      if (from == to)
+        loc += TQString(" (%1)").arg(to);
+      else
+        loc += TQString(" (%1-%2)").arg(from).arg(to);
+    }
+#endif
+  }
+
+  return loc;
+}
+
+// pretty version is allowed to mangle the string...
+TQString TraceFunction::prettyLocation(int maxFiles) const
+{
+    TQString l = location(maxFiles);
+    if (l.isEmpty()) return i18n("(unknown)");
+
+    return l;
+}
+
+void TraceFunction::addPrettyLocation(TQString& s, int maxFiles) const
+{
+    TQString l = location(maxFiles);
+    if (l.isEmpty()) return;
+
+    s += TQString(" (%1)").arg(l);
+}
+
+TQString TraceFunction::prettyNameWithLocation(int maxFiles) const
+{
+    TQString l = location(maxFiles);
+    if (l.isEmpty()) return prettyName();
+
+    return TQString("%1 (%2)").arg(prettyName()).arg(l);
+}
+
+TQString TraceFunction::info() const
+{
+    TQString l = location();
+    if (l.isEmpty())
+	return TQString("Function %1").arg(name());
+
+    return TQString("Function %1 (location %2)")
+	.arg(name()).arg(l);
+}
+
+
+Addr TraceFunction::firstAddress() const
+{
+    // ignore address 0 here
+  if (!_instrMap || _instrMap->count() == 0) return 0;
+  TraceInstrMap::ConstIterator it = _instrMap->begin();
+  return (*it).addr();
+}
+
+Addr TraceFunction::lastAddress() const
+{
+    // ignore address 0 here
+  if (!_instrMap || _instrMap->count() == 0) return 0;
+  TraceInstrMap::ConstIterator it = _instrMap->end();
+  --it;
+  return (*it).addr();
+}
+
+/* factory */
+TraceInstr* TraceFunction::instr(Addr addr, bool createNew)
+{
+    // address 0 not allowed
+    if (addr == Addr(0)) return 0;
+
+  if (!createNew) {
+      if (!_instrMap) return 0;
+      TraceInstrMap::Iterator it = _instrMap->find(addr);
+      if (it == _instrMap->end())
+	  return 0;
+      return &(it.data());
+  }
+
+  if (!_instrMap) _instrMap = new TraceInstrMap;
+
+  TraceInstr& i = (*_instrMap)[addr];
+  if (!i.isValid()) {
+    i.setAddr(addr);
+    i.setFunction(this);
+
+#if TRACE_DEBUG
+    qDebug("Created %s [TraceFunction::instr]",
+           i.fullName().ascii());
+#endif
+  }
+  return &i;
+}
+
+void TraceFunction::addCaller(TraceCall* caller)
+{
+#if TRACE_ASSERTIONS
+  if (caller->called() != this) {
+    qDebug("Can't add call to another line!\n");
+    return;
+  }
+
+  if (_callers.findRef(caller)>=0) return;
+#endif
+
+  _callers.append(caller);
+  invalidate();
+
+#if TRACE_DEBUG
+  qDebug("%s added Caller\n %s (now %d)",
+         fullName().ascii(), caller->fullName().ascii(), _callers.count());
+#endif
+}
+
+
+
+TraceCall* TraceFunction::calling(TraceFunction* called)
+{
+  TraceCallMap::Iterator it = _callingMap.find(called);
+  TraceCall* calling = (it == _callingMap.end()) ? 0 : it.data();
+
+  if (!calling) {
+    calling = new TraceCall(this, called);
+
+    _callingMap.insert(called, calling);
+    _callings.append(calling);
+
+    // we have to invalidate ourself so invalidations from item propagate up
+    invalidate();
+
+#if TRACE_DEBUG
+    qDebug("Created %s [TraceFunction::calling]", calling->fullName().ascii());
+#endif
+    called->addCaller(calling);
+  }
+  return calling;
+}
+
+TraceFunctionSource* TraceFunction::sourceFile(TraceFile* file,
+                                                   bool createNew)
+{
+  if (!file) file = _file;
+
+  TraceFunctionSource* sourceFile = _sourceFiles.first();
+  for (;sourceFile;sourceFile=_sourceFiles.next())
+    if (sourceFile->file() == file) break;
+
+  if (!sourceFile && createNew) {
+    sourceFile = new TraceFunctionSource(this, file);
+
+    _sourceFiles.append(sourceFile);
+
+    // we have to invalidate ourself so invalidations from item propagate up
+    invalidate();
+
+#if TRACE_DEBUG
+    qDebug("Created SourceFile %s [TraceFunction::line]",
+           file->name().ascii());
+#endif
+    file->addSourceFile(sourceFile);
+  }
+  return sourceFile;
+}
+
+TraceLine* TraceFunction::line(TraceFile* file, uint lineno,
+                               bool createNew)
+{
+  Q_ASSERT(file!=0);
+
+  TraceFunctionSource* sf = sourceFile(file, createNew);
+  if (!sf)
+    return 0;
+  else
+    return sf->line(lineno, createNew);
+}
+
+
+TracePartFunction* TraceFunction::partFunction(TracePart* part,
+                                               TracePartFile* partFile,
+                                               TracePartObject* partObject)
+{
+  TracePartFunction* item = (TracePartFunction*) findDepFromPart(part);
+  if (!item) {
+    item = new TracePartFunction(this, partObject, partFile);
+    item->setPosition(part);
+    addDep(item);
+#if USE_FIXCOST
+    part->addDep(item);
+#endif
+
+    if (_cls) {
+      TracePartClass* partClass = _cls->partClass(part);
+      partClass->addPartFunction(item);
+      item->setPartClass(partClass);
+    }
+
+    partFile->addPartFunction(item);
+    if (partObject)
+      partObject->addPartFunction(item);
+  }
+  else if (item->partObject()==0 && partObject) {
+    item->setPartObject(partObject);
+    partObject->addPartFunction(item);
+  }
+
+  return item;
+}
+
+
+SubCost TraceFunction::calledCount()
+{
+  if (_dirty) update();
+
+  return _calledCount;
+}
+
+int TraceFunction::calledContexts()
+{
+  if (_dirty) update();
+
+  return _calledContexts;
+}
+
+SubCost TraceFunction::callingCount()
+{
+  if (_dirty) update();
+
+  return _callingCount;
+}
+
+int TraceFunction::callingContexts()
+{
+  if (_dirty) update();
+
+  return _callingContexts;
+}
+
+TQString TraceFunction::prettyCalledCount()
+{
+  return _calledCount.pretty();
+}
+
+TQString TraceFunction::prettyCallingCount()
+{
+  return _callingCount.pretty();
+}
+
+
+TraceCallList TraceFunction::callers(bool skipCycle) const
+{
+    if (skipCycle) return _callers;
+
+  // fake the callers for cycle members
+  if (_cycle && (_cycle != this)) {
+    TraceCallList l;
+    TraceCall* c;
+
+    // inner-cycle-callers
+    TraceCallList list=_callers;
+    for (c=list.first();c;c=list.next())
+      if (c->caller()->cycle() == _cycle)
+        l.append(c);
+
+    // call from cycle itself
+    for (c=_cycle->_callings.first();c;c=_cycle->_callings.next())
+      if (c->called() == this) {
+        l.append(c);
+        return l;
+      }
+  }
+
+  return _callers;
+}
+
+const TraceCallList& TraceFunction::callings(bool /* skipCycle */) const
+{
+  return _callings;
+}
+
+void TraceFunction::invalidateDynamicCost()
+{
+  TraceCall* c;
+  for (c=_callings.first();c;c=_callings.next())
+    c->invalidateDynamicCost();
+
+  TraceFunctionSource* sf;
+  for (sf=_sourceFiles.first();sf;sf=_sourceFiles.next())
+    sf->invalidateDynamicCost();
+
+  if (_instrMap) {
+    TraceInstrMap::Iterator iit;
+    for ( iit = _instrMap->begin();
+          iit != _instrMap->end(); ++iit )
+      (*iit).invalidate();
+  }
+
+  invalidate();
+}
+
+void TraceFunction::update()
+{
+  if (!_dirty) return;
+
+#if TRACE_DEBUG
+  qDebug("Update %s (Callers %d, sourceFiles %d, instrs %d)",
+         _name.ascii(), _callers.count(),
+	 _sourceFiles.count(), _instrMap ? _instrMap->count():0);
+#endif
+
+  _calledCount    = 0;
+  _callingCount    = 0;
+  _calledContexts  = 0;
+  _callingContexts = 0;
+  clear();
+
+  // context count is NOT the sum of part contexts
+  TraceCall *caller, *calling;
+  for (caller=_callers.first();caller;caller=_callers.next()) {
+    // FIXME
+    if (caller->subCost(0)>0)
+      _calledContexts++;
+    _calledCount += caller->callCount();
+  }
+
+  for (calling=_callings.first();calling;calling=_callings.next()) {
+    // FIXME
+    if (calling->subCost(0)>0)  _callingContexts++;
+    _callingCount += calling->callCount();
+  }
+
+  if (data()->inFunctionCycleUpdate() || !_cycle) {
+      // usual case (no cycle member)
+      TraceInclusiveCost* item;
+      for (item=_deps.first();item;item=_deps.next()) {
+	  if (!item->part() || !item->part()->isActive()) continue;
+
+	  addCost(item);
+	  addInclusive(item->inclusive());
+      }
+  }
+  else {
+    // this is a cycle or cycle member
+    for (calling=_callings.first();calling;calling=_callings.next()) {
+
+	// ignore inner-cycle member calls for inclusive cost
+	if ((_cycle != this) &&
+	    (calling->inCycle()>0))  continue;
+
+	addInclusive(calling);
+    }
+
+    // self cost
+    if (type() == FunctionCycle) {
+      // cycle: self cost is sum of cycle member self costs, but
+      //        doesn't add to inclusive cost
+      TraceFunctionList mList = ((TraceFunctionCycle*)this)->members();
+      TraceFunction* m;
+      for (m=mList.first();m;m=mList.next())
+	  addCost(m);
+    }
+    else {
+      // cycle member
+      TraceInclusiveCost* item;
+      for (item=_deps.first();item;item=_deps.next()) {
+	if (!item->part() || !item->part()->isActive()) continue;
+	
+	addCost(item);
+      }
+      _dirty = false; // don't recurse
+      addInclusive(this);
+    }
+  }
+  _dirty = false;
+
+#if TRACE_DEBUG
+  qDebug("> %s", costString(0).ascii());
+#endif
+}
+
+bool TraceFunction::isCycle()
+{
+    return _cycle == this;
+}
+
+bool TraceFunction::isCycleMember()
+{
+    return _cycle && (_cycle != this);
+}
+
+void TraceFunction::cycleReset()
+{
+  _cycle = 0;
+  _cycleStackDown = 0;
+  _cycleLow = 0;
+}
+
+// this doesn't mark functions calling themself !
+void TraceFunction::cycleDFS(int d, int& pNo, TraceFunction** pTop)
+{
+  if (_cycleLow != 0) return;
+
+  if (0)
+      qDebug("%s D%02d > %s (%d)",
+	     TQString().fill(' ', d).ascii(), d, prettyName().ascii(), pNo+1);
+
+
+
+  // initialize with prefix order
+  pNo++;
+  int prefixNo = pNo;
+  _cycleLow = prefixNo;
+
+  // put myself on stack
+  _cycleStackDown = *pTop;
+  *pTop = this;
+
+  /* cycle cut heuristic:
+   * skip calls for cycle detection if they make less than _cycleCut
+   * percent of the cost of the function.
+   * FIXME: Which cost type to use for this heuristic ?!
+   */
+
+  SubCost base = 0;
+  if (_callers.count()>0) {
+      TraceCallList l = _callers;
+      TraceCall *caller;
+
+      for (caller=l.first();caller;caller=l.next())
+	  if (caller->subCost(0) > base)
+	      base = caller->subCost(0);
+  }
+  else base = inclusive()->subCost(0);
+
+  SubCost cutLimit = SubCost(base * Configuration::cycleCut());
+
+  if (0)
+      qDebug("%s       Cum. %s, Max Caller %s, cut limit %s",
+	     TQString().fill(' ', d).ascii(),
+	     inclusive()->subCost(0).pretty().ascii(),
+	     base.pretty().ascii(),
+	     cutLimit.pretty().ascii());
+
+  TraceCall *calling;
+  TraceCallList l = _callings;
+  for (calling=l.first();calling;calling=l.next()) {
+    TraceFunction* called = calling->called();
+
+      // cycle cut heuristic
+      if (calling->subCost(0) < cutLimit) {
+	  if (0) qDebug("%s       Cut call to %s (cum. %s)",
+			TQString().fill(' ', d).ascii(),
+			called->prettyName().ascii(),
+			calling->subCost(0).pretty().ascii());
+
+	  continue;
+      }
+
+    if (called->_cycleLow==0) {
+      // not visited yet
+      called->cycleDFS(d+1, pNo, pTop);
+      if (called->_cycleLow < _cycleLow)
+        _cycleLow = called->_cycleLow;
+    }
+    else if (called->_cycleStackDown) {
+	// backlink to same SCC (still in stack)
+	if (called->_cycleLow < _cycleLow)
+	    _cycleLow = called->_cycleLow;
+
+	if (0)
+	    qDebug("%s D%02d - %s (%d)",
+		   TQString().fill(' ', d+1).ascii(), d+1, 
+		   called->prettyName().ascii(), called->_cycleLow);
+    }
+    else {
+	if (0)
+	    qDebug("%s D%02d - %s (%d) [Not on stack]",
+		   TQString().fill(' ', d+1).ascii(), d+1, 
+		   called->prettyName().ascii(), called->_cycleLow);
+    }
+  }
+
+  if (prefixNo == _cycleLow) {
+    // this is the base of a SCC.
+
+    if (*pTop == this) {
+      *pTop = _cycleStackDown;
+      _cycleStackDown = 0;
+    }
+    else {
+      // a SCC with >1 members
+
+      TraceFunctionCycle* cycle = data()->functionCycle(this);
+      if (0) qDebug("BASE CYC %d %s",
+             cycle->cycleNo(), prettyName().ascii());
+      while(*pTop) {
+        TraceFunction* top = *pTop;
+        cycle->add(top);
+
+        // remove from stack
+        *pTop = top->_cycleStackDown;
+        top->_cycleStackDown = 0;
+
+        if (0) qDebug("CYC %s", top->prettyName().ascii());
+        if (top == this) break;
+      }
+    }
+  }
+  if (0)
+      qDebug("%s D%02d < %s (%d)",
+	     TQString().fill(' ', d).ascii(), d, 
+	     prettyName().ascii(), _cycleLow);
+}
+
+
+TraceInstrMap* TraceFunction::instrMap()
+{
+#if USE_FIXCOST
+
+    if (_instrMapFilled) return _instrMap;
+    _instrMapFilled = true;
+    if (!_instrMap)
+	_instrMap = new TraceInstrMap;
+
+  TraceLine* l = 0;
+  TraceInstr* i = 0;
+  TracePartInstr* pi = 0;
+  TraceInstrCall* ic = 0;
+  TracePartInstrCall* pic = 0;
+
+  TraceInclusiveCostList pfList = deps();
+  TracePartFunction* pf = (TracePartFunction*) pfList.first();
+  for(; pf; pf = (TracePartFunction*) pfList.next()) {
+
+      if (0) qDebug("PartFunction %s:%d",
+		    pf->function()->name().ascii(), pf->part()->partNumber());
+
+      FixCost* fc = pf->firstFixCost();
+      for(; fc; fc = fc->nextCostOfPartFunction()) {
+	  if (fc->addr() == 0) continue;
+
+	  if (!l || (l->lineno() != fc->line()) ||
+	      (l->functionSource() != fc->functionSource()))
+	      l = fc->functionSource()->line(fc->line(),true);
+
+	  if (!i || i->addr() != fc->addr()) {
+	      i = &(*_instrMap)[fc->addr()];
+	      if (!i->isValid()) {
+		  i->setFunction(this);
+		  i->setAddr(fc->addr());
+		  i->setLine(l);
+	      }
+	      pi = 0;
+	  }
+	  if (!pi || pi->part() != fc->part())
+	      pi = i->partInstr(fc->part(), pf);
+	  fc->addTo(pi);
+      }
+
+      TraceInstr* to = 0;
+      TraceInstrJump* ij;
+      TracePartInstrJump* pij;
+      FixJump* fj = pf->firstFixJump();
+      for(; fj; fj = fj->nextJumpOfPartFunction()) {
+	  if (fj->addr() == 0) continue;
+
+	  if (!l || (l->lineno() != fj->line()) ||
+	      (l->functionSource() != fj->source()))
+	      l = fj->source()->line(fj->line(),true);
+
+	  if (!i || i->addr() != fj->addr()) {
+	      i = &(*_instrMap)[fj->addr()];
+	      if (!i->isValid()) {
+		  i->setFunction(this);
+		  i->setAddr(fj->addr());
+		  i->setLine(l);
+	      }
+	  }
+
+	  to = fj->targetFunction()->instr(fj->targetAddr(), true);
+
+	  ij = i->instrJump(to, fj->isCondJump());
+	  pij = ij->partInstrJump(fj->part());
+
+	  fj->addTo(pij);
+      }
+
+      TracePartCallList pcList = pf->partCallings();
+      TracePartCall* pc = pcList.first();
+      for(; pc; pc = pcList.next()) {
+
+	  if (0) qDebug("PartCall %s:%d",
+			pc->call()->name().ascii(),
+			pf->part()->partNumber());
+
+	  FixCallCost* fcc = pc->firstFixCallCost();
+	  for(; fcc; fcc = fcc->nextCostOfPartCall()) {
+	      if (fcc->addr() == 0) continue;
+
+	      if (!l || (l->lineno() != fcc->line()) ||
+		  (l->functionSource() != fcc->functionSource()))
+		  l = fcc->functionSource()->line(fcc->line(),true);
+
+	      if (!i || i->addr() != fcc->addr()) {
+		  i = &(*_instrMap)[fcc->addr()];
+		  if (!i->isValid()) {
+		      i->setFunction(this);
+		      i->setAddr(fcc->addr());
+		      i->setLine(l);
+		  }
+	      }
+	      if (!ic || ic->call() != pc->call() || ic->instr() != i) {
+		  ic = pc->call()->instrCall(i);
+		  pic = 0;
+	      }
+	      if (!pic || pic->part() != fcc->part())
+		  pic = ic->partInstrCall(fcc->part(), pc);
+
+	      fcc->addTo(pic);
+	      if (0) qDebug("Add FixCallCost %s:%d/0x%s, CallCount %s",
+			    fcc->functionSource()->file()->shortName().ascii(),
+			    fcc->line(), fcc->addr().toString().ascii(),
+			    fcc->callCount().pretty().ascii());
+	  }
+      }
+  }
+
+#endif
+
+  return _instrMap;
+}
+
+
+
+//---------------------------------------------------
+// TraceFunctionCycle
+
+TraceFunctionCycle::TraceFunctionCycle(TraceFunction* f, int n)
+{
+  _base = f;
+  _cycleNo = n;
+  _cycle = this;
+
+  setPosition(f->data());
+  setName(TQString("<cycle %1>").arg(n));
+
+  // reset to attributes of base function
+  setFile(_base->file());
+  setClass(_base->cls());
+  setObject(_base->object());
+}
+
+void TraceFunctionCycle::init()
+{
+  _members.clear();
+  _memberSet.clear();
+  _callers.clear();
+  // this deletes all TraceCall's to members
+  _callings.clear();
+
+  invalidate();
+}
+
+void TraceFunctionCycle::add(TraceFunction* f)
+{
+  _members.append(f);
+  _memberSet.insert(f,1);
+}
+
+void TraceFunctionCycle::setup()
+{
+  if (_members.count()==0) return;
+
+  TraceFunction* f;
+  for (f=_members.first();f;f=_members.next()) {
+
+    // the cycle takes all outside callers from its members
+    TraceCall *call;
+    TraceCallList l = f->callers();
+    for (call=l.first();call;call=l.next()) {
+      if ( _memberSet.contains(call->caller()) ) continue;
+      _callers.append(call);
+    }
+
+    // the cycle has a call to each member
+    call = new TraceCall(this, f);
+    call->invalidate();
+    _callings.append(call);
+
+    // now do some faking...
+    f->setCycle(this);
+  }
+  invalidate();
+}
+
+
+//---------------------------------------------------
+// TraceClass
+
+TraceClass::TraceClass()
+{
+  // we are the owner of items generated in our factory
+  _deps.setAutoDelete(true);
+}
+
+TraceClass::~TraceClass()
+{}
+
+TQString TraceClass::prettyName() const
+{
+  if (_name.isEmpty())
+    return TQString("(global)");
+  return _name;
+}
+
+TracePartClass* TraceClass::partClass(TracePart* part)
+{
+  TracePartClass* item = (TracePartClass*) findDepFromPart(part);
+  if (!item) {
+    item = new TracePartClass(this);
+    item->setPosition(part);
+    addDep(item);
+  }
+  return item;
+}
+
+void TraceClass::addFunction(TraceFunction* function)
+{
+#if TRACE_ASSERTIONS
+  if (function->cls() != this) {
+    qDebug("Can't add function to a class not enclosing this function\n");
+    return;
+  }
+
+  if (_functions.findRef(function)>=0) return;
+#endif
+
+  _functions.append(function);
+
+  invalidate();
+
+#if TRACE_DEBUG
+  qDebug("%s added\n %s (now %d)",
+         fullName().ascii(),
+         function->fullName().ascii(), _functions.count());
+#endif
+}
+
+
+
+//---------------------------------------------------
+// TraceFile
+
+TraceFile::TraceFile()
+{
+  // we are the owner of items generated in our factory
+  _deps.setAutoDelete(true);
+}
+
+TraceFile::~TraceFile()
+{}
+
+TracePartFile* TraceFile::partFile(TracePart* part)
+{
+  TracePartFile* item = (TracePartFile*) findDepFromPart(part);
+  if (!item) {
+    item = new TracePartFile(this);
+    item->setPosition(part);
+    addDep(item);
+  }
+  return item;
+}
+
+void TraceFile::addFunction(TraceFunction* function)
+{
+#if TRACE_ASSERTIONS
+  if (function->file() != this) {
+    qDebug("Can't add function to a file not enclosing this function\n");
+    return;
+  }
+
+  if (_functions.findRef(function)>=0) return;
+#endif
+
+  _functions.append(function);
+
+  invalidate();
+
+#if TRACE_DEBUG
+  qDebug("%s added\n %s (now %d)",
+         fullName().ascii(),
+         function->fullName().ascii(), _functions.count());
+#endif
+}
+
+
+void TraceFile::addSourceFile(TraceFunctionSource* sourceFile)
+{
+#if TRACE_ASSERTIONS
+  if (sourceFile->file() != this) {
+    qDebug("Can't add sourceFile to a file not having lines for it\n");
+    return;
+  }
+#endif
+
+  _sourceFiles.append(sourceFile);
+  // not truely needed, as we don't use the sourceFiles for cost update
+  invalidate();
+
+#if TRACE_DEBUG
+  qDebug("%s \n added SourceFile %s (now %d)",
+         fullName().ascii(), sourceFile->fullName().ascii(),
+         _sourceFiles.count());
+#endif
+}
+
+
+
+void TraceFile::setDirectory(const TQString& dir)
+{
+  if (dir.endsWith("/"))
+    _dir = dir.left(dir.length()-1);
+  else
+    _dir = dir;
+}
+
+TQString TraceFile::directory()
+{
+  if (!_dir.isEmpty()) return _dir;
+
+  int lastIndex = 0, index;
+  while ( (index=_name.find("/", lastIndex)) >=0)
+    lastIndex = index+1;
+
+  if (lastIndex==0) return TQString();
+
+  // without ending "/"
+  return _name.left(lastIndex-1);
+}
+
+
+TQString TraceFile::shortName() const
+{
+  int lastIndex = 0, index;
+  while ( (index=_name.find("/", lastIndex)) >=0)
+    lastIndex = index+1;
+
+  return _name.mid(lastIndex);
+}
+
+TQString TraceFile::prettyName() const
+{
+    TQString sn = shortName();
+    
+    if (sn.isEmpty())
+	return i18n("(unknown)");
+
+    return sn;
+}
+
+TQString TraceFile::prettyLongName() const
+{
+  if (_name.isEmpty())
+    return i18n("(unknown)");
+  return _name;
+}
+
+
+//---------------------------------------------------
+// TraceObject
+
+TraceObject::TraceObject()
+{
+  // we are the owner of items generated in our factory
+  _deps.setAutoDelete(true);
+}
+
+TraceObject::~TraceObject()
+{}
+
+TracePartObject* TraceObject::partObject(TracePart* part)
+{
+  TracePartObject* item = (TracePartObject*) findDepFromPart(part);
+  if (!item) {
+    item = new TracePartObject(this);
+    item->setPosition(part);
+    addDep(item);
+  }
+  return item;
+}
+
+void TraceObject::addFunction(TraceFunction* function)
+{
+#if TRACE_ASSERTIONS
+  if (function->object() != this) {
+    qDebug("Can't add function to an object not enclosing this function\n");
+    return;
+  }
+
+  if (_functions.findRef(function)>=0) return;
+#endif
+
+  _functions.append(function);
+
+  invalidate();
+
+#if TRACE_DEBUG
+  qDebug("%s added\n %s (now %d)",
+         fullName().ascii(),
+         function->fullName().ascii(), _functions.count());
+#endif
+}
+
+// strip path
+void TraceObject::setName(const TQString& name)
+{
+  _name = name;
+
+  int lastIndex = 0, index;
+  while ( (index=_name.find("/", lastIndex)) >=0)
+    lastIndex = index+1;
+
+  _shortName = _name.mid(lastIndex);
+}
+
+TQString TraceObject::prettyName() const
+{
+  if (_shortName.isEmpty())
+    return i18n("(unknown)");
+
+  return _shortName;
+}
+
+//---------------------------------------------------
+// TracePart
+
+TracePart::TracePart(TraceData* data, TQFile* file)
+{
+  setPosition(data);
+
+  _dep = data;
+  _file = file;
+  if (_file)
+    _name = _file->name();
+  _active = true;
+
+  _number = 0;
+  _tid = 0;
+  _pid = 0;
+
+  _fixSubMapping = 0;
+}
+
+TracePart::~TracePart()
+{
+  delete _file;
+
+  delete _fixSubMapping;
+}
+
+void TracePart::setPartNumber(int n)
+{
+    if (data()->maxPartNumber() <n) data()->setMaxPartNumber(n);
+    _number = n;
+}
+
+void TracePart::setThreadID(int tid)
+{
+    if (data()->maxThreadID() <tid) data()->setMaxThreadID(tid);
+    _tid = tid;
+}
+
+void TracePart::setProcessID(int pid)
+{
+    _pid = pid;
+}
+
+
+
+// strip path
+TQString TracePart::shortName() const
+{
+  int lastIndex = 0, index;
+  while ( (index=_name.find("/", lastIndex)) >=0)
+    lastIndex = index+1;
+
+  return _name.mid(lastIndex);
+}
+
+TQString TracePart::prettyName() const
+{
+    TQString name = TQString("%1.%2").arg(_pid).arg(_number);
+    if (data()->maxThreadID()>1)
+	name += TQString("-%3").arg(_tid);
+    return name;
+}
+
+bool TracePart::activate(bool active)
+{
+  if (_active == active) return false;
+  _active = active;
+
+  // to be done by the client of this function
+  //  data()->invalidateDynamicCost();
+  // So better use the TraceData functions...
+
+  return true;
+}
+
+
+
+//---------------------------------------------------
+// TracePartList
+
+int TracePartList::compareItems ( Item item1, Item item2 )
+{
+    TracePart* p1 = (TracePart*) item1;
+    TracePart* p2 = (TracePart*) item2;
+    int mTID = p1->data()->maxThreadID()+1;
+    int mNum = p1->data()->maxPartNumber()+1;
+
+    return
+	(p1->processID()  - p2->processID()) * mTID * mNum +
+	(p1->partNumber() - p2->partNumber()) * mTID +
+	(p1->threadID()   - p2->threadID());
+}
+
+TQString TracePartList::names() const
+{
+  TQString res;
+  TracePart* p;
+  TracePartList l = *this;
+  for (p=l.first();p;p=l.next()) {
+    if (!res.isEmpty()) res += ", ";
+    res += p->shortName();
+  }
+
+  return res;
+}
+
+
+
+//---------------------------------------------------
+// TraceData
+
+
+// create vectors with reasonable default sizes, but not wasting memory
+TraceData::TraceData(TopLevel* top)
+{
+    _topLevel = top;
+    init();
+}
+
+TraceData::TraceData(const TQString& base)
+{
+    _topLevel = 0;
+    init();
+    load(base);
+}
+
+void TraceData::init()
+{
+  _parts.setAutoDelete(true);
+
+  _functionCycleCount = 0;
+  _inFunctionCycleUpdate = false;
+
+  _maxThreadID = 0;
+  _maxPartNumber = 0;
+  _fixPool = 0;
+  _dynPool = 0;
+}
+
+TraceData::~TraceData()
+{
+  if (_fixPool) delete _fixPool;
+  if (_dynPool) delete _dynPool;
+}
+
+TQString TraceData::shortTraceName() const
+{
+  int lastIndex = 0, index;
+  while ( (index=_traceName.find("/", lastIndex)) >=0)
+    lastIndex = index+1;
+
+  return _traceName.mid(lastIndex);
+}
+
+FixPool* TraceData::fixPool()
+{
+  if (!_fixPool)
+    _fixPool = new FixPool();
+
+  return _fixPool;
+}
+
+DynPool* TraceData::dynPool()
+{
+  if (!_dynPool)
+    _dynPool = new DynPool();
+
+  return _dynPool;
+}
+
+
+/**
+ * Two cases:
+ *
+ * - <base> is a directory: Load first profile data file available
+ * - <base> is a file name without part/thread suffixes
+ */
+void TraceData::load(const TQString& base)
+{
+  bool baseExisting = true;
+
+  _traceName = base;
+  TQFileInfo finfo(base);
+  TQString file = finfo.fileName();
+  TQDir dir = finfo.dir();
+
+  if (!finfo.exists()) {
+    baseExisting = false;
+  }
+  else if (finfo.isDir()) {
+      // search for first profile data file in directory
+      dir = TQDir(base);
+
+      TQStringList prefixList;
+      prefixList << "callgrind.out" << "cachegrind.out";
+      for ( TQStringList::Iterator it = prefixList.begin();
+	    it != prefixList.end(); ++it ) {
+        file = *it;
+
+	// search for ".pid"
+	TQStringList strList = dir.entryList(file+".*", TQDir::Files);
+	if (strList.count()>0) {
+	  int l = file.length();
+	  file = strList.first();
+	  l++;
+	  while(file[l] >= '0' && file[l] <= '9') l++;
+	  file = file.left(l);
+	  break;
+	}
+      }
+
+      _traceName = dir.path() + "/" + file;
+  }
+
+  TQStringList strList;
+  strList += dir.entryList(file+".*", TQDir::Files);
+  strList += dir.entryList(file+"-*", TQDir::Files);
+
+  baseExisting = TQFile::exists(_traceName);
+  if (baseExisting)
+      strList << file;
+
+  if (strList.count() == 0) {
+      _traceName = base + "/" + file + " " + i18n("(not found)");
+      return;
+  }
+
+
+  // try to guess pid from file name
+  unsigned int pos = file.length();
+  unsigned int pid = 0, f=1;
+  pos--;
+  while(pos>0) {
+      if (file[pos] < '0' || file[pos] > '9') break;
+      pid += f * (file[pos].latin1() - '0');
+      pos--;
+      f *= 10;
+  }
+
+  TQStringList::Iterator it;
+  unsigned int maxNumber = 0;
+  for (it = strList.begin(); it != strList.end(); ++it ) {
+    TracePart* p = addPart( dir.path(), *it );
+
+    if (!p) {
+      kdDebug() << "Error loading " << *it << endl;
+      continue;
+    }
+
+    const TQString& str = *it;
+    unsigned int pos = file.length();
+
+    // try to guess part number from file name
+    unsigned int n = 0;
+    if ((str.length() > pos) && (str[pos] == '.')) {
+	pos++;
+	while(str.length()>pos) {
+	    if ((int)str.at(pos) < '0' || (int)str.at(pos) > '9') break;
+	    n = 10*n + (str[pos++] - '0');
+	}
+    }
+
+    // try to guess thread number from file name
+    unsigned int t = 0;
+    if ((str.length() > pos) && (str[pos] == '-')) {
+	pos++;
+	while(str.length()>pos) {
+	    if ((int)str.at(pos) < '0' || (int)str.at(pos) > '9') break;
+	    t = 10*t + (str[pos++] - '0');
+	}
+    }
+
+    //qDebug("File %s: Part %d, Thread %d", (*it).ascii(), n, t);
+
+    if (p->partNumber()>0) n = p->partNumber();
+    if (n>maxNumber) maxNumber = n;
+    if (n==0) n = maxNumber+1;
+    p->setPartNumber(n);
+
+    if (p->threadID()==0) p->setThreadID(t);
+    if (p->processID()==0) p->setProcessID(pid);
+
+    _parts.append(p);
+  }
+  _parts.sort();
+
+  invalidateDynamicCost();
+  updateFunctionCycles();
+
+  // clear loading messages from status bar
+  if (_topLevel) _topLevel->showStatus(TQString(), 0);
+}
+
+TracePart* TraceData::addPart(const TQString& dir, const TQString& name)
+{
+    TQString filename = TQString("%1/%2").arg(dir).arg(name);
+#if TRACE_DEBUG
+  qDebug("TraceData::addPart('%s')", filename.ascii());
+#endif
+
+  TQFile* file = new TQFile(filename);
+
+  Loader* l = Loader::matchingLoader(file);
+  if (!l) return 0;
+
+  if (_topLevel)
+      _topLevel->connect(l, TQT_SIGNAL(updateStatus(TQString, int)),
+			 TQT_SLOT(showStatus(TQString, int)));
+
+  TracePart* part = new TracePart(this, file);
+
+  if (! l->loadTrace(part)) {
+      delete part;
+      part = 0;
+  }
+
+  if (_topLevel) l->disconnect(_topLevel);
+
+  return part;
+}
+
+bool TraceData::activateParts(const TracePartList& l)
+{
+  bool changed = false;
+
+  TracePart* part;
+  for (part=_parts.first();part;part=_parts.next())
+    if (part->activate(l.containsRef(part)>0))
+        changed = true;
+
+  if (changed) {
+      // because active parts have changed, throw away calculated
+      // costs...
+      invalidateDynamicCost();
+      updateFunctionCycles();
+  }
+
+  return changed;
+}
+
+
+bool TraceData::activateParts(TracePartList l, bool active)
+{
+  bool changed = false;
+
+  TracePart* part;
+  for (part=l.first();part;part=l.next())
+    if (_parts.findRef(part)>=0)
+      if (part->activate(active))
+        changed = true;
+
+  if (changed) {
+      invalidateDynamicCost();
+      updateFunctionCycles();
+  }
+
+  return changed;
+}
+
+bool TraceData::activatePart(TracePart* p, bool active)
+{
+  return p->activate(active);
+}
+
+bool TraceData::activateAll(bool active)
+{
+  return activateParts(_parts, active);
+}
+
+
+TracePart* TraceData::part(TQString& name)
+{
+  TracePart* part;
+  for (part=_parts.first();part;part=_parts.next())
+    if (part->name() == name)
+      return part;
+  return 0;
+}
+
+TQString TraceData::activePartRange()
+{
+  TQString res;
+  int r1=-1, r2=-1, count=1;
+  TracePart* part;
+  for (part=_parts.first();part;part=_parts.next(), count++)
+    if (part->isActive()) {
+      if (r1<0) { r1 = r2 = count; }
+      else if (r2 == count-1) { r2 = count; }
+      else {
+        if (!res.isEmpty()) res += ";";
+        if (r1==r2) res += TQString::number(r1);
+        else res += TQString("%1-%2").arg(r1).arg(r2);
+        r1 = r2 = count;
+      }
+    }
+  if (r1>=0) {
+    if (!res.isEmpty()) res += ";";
+    if (r1==r2) res += TQString::number(r1);
+    else res += TQString("%1-%2").arg(r1).arg(r2);
+  }
+
+  return res;
+}
+
+void TraceData::invalidateDynamicCost()
+{
+  // invalidate all dynamic costs
+
+  TraceObjectMap::Iterator oit;
+  for ( oit = _objectMap.begin();
+        oit != _objectMap.end(); ++oit )
+    (*oit).invalidate();
+
+  TraceClassMap::Iterator cit;
+  for ( cit = _classMap.begin();
+        cit != _classMap.end(); ++cit )
+    (*cit).invalidate();
+
+  TraceFileMap::Iterator fit;
+  for ( fit = _fileMap.begin();
+        fit != _fileMap.end(); ++fit )
+    (*fit).invalidate();
+
+  TraceFunctionMap::Iterator it;
+  for ( it = _functionMap.begin();
+        it != _functionMap.end(); ++it ) {
+    (*it).invalidateDynamicCost();
+  }
+
+  invalidate();
+
+}
+
+
+TraceObject* TraceData::object(const TQString& name)
+{
+  TraceObject& o = _objectMap[name];
+  if (!o.data()) {
+    // was created
+    o.setPosition(this);
+    o.setName(name);
+
+#if TRACE_DEBUG
+    qDebug("Created %s [TraceData::object]",
+           o.fullName().ascii());
+#endif
+  }
+  return &o;
+}
+
+
+TraceFile* TraceData::file(const TQString& name)
+{
+  TraceFile& f = _fileMap[name];
+  if (!f.data()) {
+    // was created
+    f.setPosition(this);
+    f.setName(name);
+
+#if TRACE_DEBUG
+    qDebug("Created %s [TraceData::file]",
+           f.fullName().ascii());
+#endif
+  }
+  return &f;
+}
+
+
+// usually only called by function()
+TraceClass* TraceData::cls(const TQString& fnName, TQString& shortName)
+{
+  int lastIndex = 0, index, pIndex;
+
+  // we ignore any "::" after a '(' or a space
+  pIndex=fnName.find("(", 0);
+
+#if 0
+  int sIndex=fnName.find(" ", 0);
+  if (sIndex>=0)
+    if ((pIndex == -1) || (sIndex < pIndex))
+      pIndex = sIndex;
+#endif
+
+  while ((index=fnName.find("::", lastIndex)) >=0) {
+    if (pIndex>=0 && pIndex<index) break;
+    lastIndex = index+2;
+  }
+
+  TQString clsName = (lastIndex < 3) ? TQString() :
+                    fnName.left(lastIndex-2);
+  shortName = fnName.mid(lastIndex);
+
+  TraceClass& c = _classMap[clsName];
+  if (!c.data()) {
+    // was created
+    c.setPosition(this);
+    c.setName(clsName);
+
+#if TRACE_DEBUG
+    qDebug("Created %s [TraceData::cls]",
+           c.fullName().ascii());
+#endif
+  }
+  return &c;
+}
+
+
+// name is inclusive class/namespace prefix
+TraceFunction* TraceData::function(const TQString& name,
+                                   TraceFile* file, TraceObject* object)
+{
+  // strip class name
+  TQString shortName;
+  TraceClass* c = cls(name, shortName);
+
+  if (!file || !object || !c) {
+    qDebug("ERROR - no file/object/class for %s ?!", name.ascii());
+    return 0;
+  }
+
+  // Don't use file in key: A function can go over many files
+  // (inlined parts), but still is ONE function.
+  TQString key = name + object->shortName();
+
+  TraceFunctionMap::Iterator it;
+  it = _functionMap.find(key);
+  if (it == _functionMap.end()) {
+      it = _functionMap.insert(key, TraceFunction());
+      TraceFunction& f = it.data();
+
+      f.setPosition(this);
+      f.setName(name);
+      f.setClass(c);
+      f.setObject(object);
+      f.setFile(file);
+      f.setMapIterator(it);
+
+#if TRACE_DEBUG
+      qDebug("Created %s [TraceData::function]\n  for %s, %s, %s",
+	     f.fullName().ascii(),
+	     c->fullName().ascii(), file->fullName().ascii(),
+	     object ? object->fullName().ascii() : "(unknown object)");
+#endif
+
+      c->addFunction(&f);
+      object->addFunction(&f);
+      file->addFunction(&f);
+  }
+
+  return &(it.data());
+}
+
+TraceFunctionMap::Iterator TraceData::functionIterator(TraceFunction* f)
+{
+
+  // IMPORTANT: build as SAME key as used in function() above !!
+  TQString key;
+
+  if (f->cls()) key = f->cls()->name() + "::";
+  key += f->name();
+  key += f->object()->shortName();
+
+  return _functionMap.find(key);
+}
+
+TraceFunctionMap::ConstIterator TraceData::functionBeginIterator() const
+{
+  return _functionMap.begin();
+}
+
+TraceFunctionMap::ConstIterator TraceData::functionEndIterator() const
+{
+  return _functionMap.end();
+}
+
+
+void TraceData::resetSourceDirs()
+{
+  TraceFileMap::Iterator fit;
+  for ( fit = _fileMap.begin();
+        fit != _fileMap.end(); ++fit )
+    (*fit).resetDirectory();
+}
+
+void TraceData::update()
+{
+  if (!_dirty) return;
+
+  clear();
+  _totals.clear();
+
+  TracePart* part;
+  for (part=_parts.first();part;part=_parts.next()) {
+    _totals.addCost(part->totals());
+    if (part->isActive())
+	addCost(part->totals());
+  }
+
+  _dirty = false;
+}
+
+TraceCost* TraceData::search(TraceItem::CostType t, TQString name,
+			     TraceCostType* ct, TraceCost* parent)
+{
+    TraceCost* result = 0;
+    TraceItem::CostType pt = parent ? parent->type() : NoCostType;
+    SubCost sc, scTop = 0;
+
+    switch(t) {
+    case Function:
+	{
+	    TraceFunction *f;
+	    TraceFunctionMap::Iterator it;
+	    for ( it = _functionMap.begin();
+		  it != _functionMap.end(); ++it ) {
+		f = &(*it);
+
+		if (f->name() != name) continue;
+
+		if ((pt == Class) && (parent != f->cls())) continue;
+		if ((pt == File) && (parent != f->file())) continue;
+		if ((pt == Object) && (parent != f->object())) continue;
+
+		if (ct) {
+		    sc = f->inclusive()->subCost(ct);
+		    if (sc <= scTop) continue;
+		    scTop = sc;
+		}
+
+		result = f;
+	    }
+	}
+	break;
+
+    case File:
+	{
+	    TraceFile *f;
+	    TraceFileMap::Iterator it;
+	    for ( it = _fileMap.begin();
+		  it != _fileMap.end(); ++it ) {
+		f = &(*it);
+		if (f->name() != name) continue;
+		if (ct) {
+		    sc = f->subCost(ct);
+		    if (sc <= scTop) continue;
+		    scTop = sc;
+		}
+		result = f;
+	    }
+	}
+	break;
+
+    case Class:
+	{
+	    TraceClass *c;
+	    TraceClassMap::Iterator it;
+	    for ( it = _classMap.begin();
+		  it != _classMap.end(); ++it ) {
+		c = &(*it);
+		if (c->name() != name) continue;
+		if (ct) {
+		    sc = c->subCost(ct);
+		    if (sc <= scTop) continue;
+		    scTop = sc;
+		}
+		result = c;
+	    }
+	}
+	break;
+
+    case Object:
+	{
+	    TraceObject *o;
+	    TraceObjectMap::Iterator it;
+	    for ( it = _objectMap.begin();
+		  it != _objectMap.end(); ++it ) {
+		o = &(*it);
+		if (o->name() != name) continue;
+		if (ct) {
+		    sc = o->subCost(ct);
+		    if (sc <= scTop) continue;
+		    scTop = sc;
+		}
+		result = o;
+	    }
+	}
+	break;
+
+    case Instr:
+	if (pt == Function) {
+	    TraceInstrMap* instrMap = ((TraceFunction*)parent)->instrMap();
+	    if (!instrMap) break;
+
+	    TraceInstr *instr;
+	    TraceInstrMap::Iterator it;
+	    for ( it = instrMap->begin();
+		  it != instrMap->end(); ++it ) {
+		instr = &(*it);
+		if (instr->name() != name) continue;
+		result = instr;
+	    }
+	}
+	break;
+
+    case Line:
+	{
+	    TraceFunctionSourceList sList;
+	    if (pt == Function)
+		sList = ((TraceFunction*)parent)->sourceFiles();
+	    else if (pt == FunctionSource)
+		sList.append((TraceFunctionSource*) parent);
+	    else break;
+
+	    TraceLineMap* lineMap;
+	    TraceLine* line;
+	    TraceLineMap::Iterator it;
+	    TraceFunctionSource* fs;
+	    for(fs = sList.first(); fs; fs = sList.next()) {
+		lineMap = fs->lineMap();
+		if (!lineMap) continue;
+
+		for ( it = lineMap->begin();
+		      it != lineMap->end(); ++it ) {
+		    line = &(*it);
+		    if (line->name() != name) continue;
+		    result = line;
+		}
+	    }
+	}
+	break;
+
+    default:
+	break;
+    }
+
+    return result;
+}
+
+
+TraceFunctionCycle* TraceData::functionCycle(TraceFunction* f)
+{
+  TraceFunctionCycle* cycle;
+  for (cycle=_functionCycles.first();cycle;cycle=_functionCycles.next())
+    if (cycle->base() == f) return cycle;
+
+  _functionCycleCount++;
+  cycle = new TraceFunctionCycle(f, _functionCycleCount);
+
+  _functionCycles.append(cycle);
+  return cycle;
+}
+
+
+void TraceData::updateFunctionCycles()
+{
+    //qDebug("Updating cycles...");
+
+  // init cycle info
+  TraceFunctionCycle* cycle;
+  for (cycle=_functionCycles.first();cycle;cycle=_functionCycles.next())
+    cycle->init();
+
+  TraceFunctionMap::Iterator it;
+  for ( it = _functionMap.begin(); it != _functionMap.end(); ++it )
+    (*it).cycleReset();
+
+  if (!Configuration::showCycles()) return;
+
+  _inFunctionCycleUpdate = true;
+
+
+#if 0
+  int fCount = _functionMap.size(), fNo = 0, progress=0, p;
+  TQString msg = i18n("Recalculating Function Cycles...");
+  if (_topLevel) _topLevel->showStatus(msg,0);
+#endif
+
+  // DFS and collapse strong connected components (Tarjan)
+  int pNo = 0;
+  TraceFunction* stackTop;
+  for ( it = _functionMap.begin(); it != _functionMap.end(); ++it ) {
+
+#if 0
+      if (_topLevel) {
+	  fNo++;
+	  p = 100*fNo/fCount;
+	  if (p> progress) {
+	      progress = p;
+	      _topLevel->showStatus(msg, p);
+	  }
+      }
+#endif
+
+    stackTop = 0;
+    (*it).cycleDFS(1, pNo, &stackTop);
+  }
+
+  // postprocess cycles
+  for (cycle=_functionCycles.first();cycle;cycle=_functionCycles.next())
+    cycle->setup();
+
+  _inFunctionCycleUpdate = false;
+  // we have to invalidate costs because cycles are now taken into account
+  invalidateDynamicCost();
+
+#if 0
+  if (0) if (_topLevel) _topLevel->showStatus(TQString(),0);
+#endif
+}
+
+void TraceData::updateObjectCycles()
+{
+}
+
+
+void TraceData::updateClassCycles()
+{
+}
+
+
+void TraceData::updateFileCycles()
+{
+}
+
+
diff --git a/kdecachegrind/kdecachegrind/tracedata.h b/kdecachegrind/kdecachegrind/tracedata.h
new file mode 100644
index 0000000..8fab2b6
--- /dev/null
+++ b/kdecachegrind/kdecachegrind/tracedata.h
@@ -0,0 +1,1967 @@
+/* This file is part of KCachegrind.
+   Copyright (C) 2002, 2003 Josef Weidendorfer <Josef.Weidendorfer@gmx.de>
+
+   KCachegrind 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, version 2.
+
+   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; see the file COPYING.  If not, write to
+   the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+   Boston, MA 02110-1301, USA.
+*/
+
+/*
+ * Classes holding profiling data for
+ * multiple tracefiles for one command.
+ * See class TraceData first.
+ */
+
+#ifndef TRACEDATA_H
+#define TRACEDATA_H
+
+#include <tqstring.h>
+#include <tqstringlist.h>
+#include <tqptrlist.h>
+#include <tqmap.h>
+#include <tqptrvector.h>
+#include <tqcolor.h>
+
+#include "subcost.h"
+#include "utils.h"
+
+class TQFile;
+
+/**
+ * All cost items are classes prefixed with "Trace".
+ * "TraceCost" holds basic cost metrics for the simplest, smallest
+ * trace entity: These are events counted for an instruction at
+ * a specific memory address of the traced program.
+ * All other cost items are derived from TraceCost, and add needed
+ * cost metrics, e.g. for a call the number of calls that happened.
+ *
+ * Abstract, i.e. never instantiated cost items are
+ * - TraceCost: Basic cost metrics (instr/read/write access + cache events)
+ * - TraceCallCost: Additional call count cost metric.
+ * - TraceInclusiveCost: Additional TraceCost aggregated.
+ * - TraceListCost: Adds dependency to a list of TraceCost's
+ * - TraceCallListCost: same for list of TraceCallCost's
+ * - TraceInclusiveListCost: same for list of TraceInclusiveCost's
+ * - TraceCostItem: Base for cost items for "interesting" costs:
+ *              TraceFunction, TraceClass, TraceFile, TraceObject
+ *
+ * The smallest Cachegrind output is trace data indexed by a source
+ * line number, a TracePartLine. Another one is a call from one
+ * source line of a function to another function, a TracePartLineCall.
+ * All other cost items derive the value by summation of cost metrics
+ * from TraceLineItem and TracePartLineCall costs; their cost is
+ * calculated lazy on demand and cached afterwards.
+ *
+ * For cost items, which are sums over all trace files read in, the
+ * summed cost metrics change when e.g. a new trace file is read.
+ * Thus, their cached costs are invalidated, and again recalculated
+ * only on demand. In the following list, theses cost items are called
+ * "dynamic", the other "fixed" (but neverless calculated lazy).
+ *
+ *  Cost Item          Type      Summation of ...
+ *
+ *  TracePartLineCall  fixed     Read from trace file
+ *  TracePartLine      fixed     Read from trace file
+ *  TracePartCall      fixed     TracePartLineCall's
+ *  TraceLineCall      dynamic   TracePartLineCall's
+ *  TraceCall          dynamic   TraceLineCall's
+ *  TraceLine          dynamic   TracePartLine's and TraceLineCall's
+ *  TracePartFunction  fixed     TracePartLine's / TracePartCall's
+ *  TraceFunction      dynamic   TraceLine's / TraceCall's (called from)
+ *  TracePartClass     fixed     TracePartFunction's
+ *  TraceClass         dynamic   TraceFunction's
+ *  TracePartFile      fixed     TracePartFunction's
+ *  TraceFile          dynamic   TraceFunction's
+ *  TracePartObject    fixed     TracePartFunction's
+ *  TraceObject        dynamic   TraceFunction's
+ *  TracePart          fixed     TracePartLine's
+ *  TraceData          dynamic   TracePart's
+ *
+ * As there exists only one TraceData object for a traced program, its the
+ * owner of some "high level" cost items. The following shows the owner
+ * relationship of the cost item classes, together with references.
+ *
+ *  Cost Item          Owner (& back ref)   Other References to
+ *
+ *  TracePartLineCall  TraceLineCall
+ *  TracePartCall      TraceCall            TracePartLineCall's
+ *  TracePartLine      TraceLine            TracePartLineCall's
+ *  TracePartFunction  TraceFunction
+ *  TracePartClass     TraceClass           TracePart
+ *  TracePartFile      TraceFile            TracePart
+ *  TracePartObject    TraceObject          TracePart
+ *  TraceLineCall      TraceCall            TracePartLineCall's
+ *  TraceCall          TraceFunction        TracePartCall's
+ *  TraceLine          TraceData            TraceLineCall's
+ *  TraceFunction      TraceData            TraceCall's (calling)
+ *  TraceClass         TraceData
+ *  TraceFile          TraceData
+ *  TraceObject        TraceData
+ *  TracePart          TraceData
+ *  TraceData          Main Application
+ *
+ * Convention:
+ * - The owner has a factory method for owned objects,
+ *   and calls addXXX() to install references in other objects
+ * - The owner is first arg in a constructor.
+ */
+
+
+class FixString;
+class FixCost;
+class FixCallCost;
+class FixJump;
+class FixPool;
+class DynPool;
+class TopLevel;
+
+class TraceCost;
+class TraceCostType;
+class TraceCostMapping;
+class TraceSubMapping;
+class TraceJumpCost;
+class TraceCallCost;
+class TraceInclusiveCost;
+
+class TracePartInstr;
+class TracePartInstrCall;
+class TracePartLine;
+class TracePartLineCall;
+class TracePartCall;
+class TracePartLineRegion;
+class TracePartFunction;
+class TracePartClass;
+class TracePartObject;
+class TracePartFile;
+
+class TraceInstr;
+class TraceInstrJump;
+class TraceInstrCall;
+class TraceLine;
+class TraceLineJump;
+class TraceLineCall;
+class TraceCall;
+class TraceLineRegion;
+class TraceFunctionSource;
+class TraceFunction;
+class TraceFunctionCycle;
+class TraceClass;
+class TraceObject;
+class TraceFile;
+class TracePart;
+class TraceData;
+
+typedef TQPtrList<TraceCost> TraceCostList;
+typedef TQPtrList<TraceJumpCost> TraceJumpCostList;
+typedef TQPtrList<TraceCallCost> TraceCallCostList;
+typedef TQPtrList<TraceInclusiveCost> TraceInclusiveCostList;
+
+typedef TQPtrList<TracePartCall>  TracePartCallList;
+typedef TQPtrList<TracePartInstr> TracePartInstrList;
+typedef TQPtrList<TracePartLine>  TracePartLineList;
+typedef TQPtrList<TracePartLineRegion>  TracePartLineRegionList;
+typedef TQPtrList<TracePartFunction>  TracePartFunctionList;
+typedef TQPtrList<TracePartInstrCall> TracePartInstrCallList;
+typedef TQPtrList<TracePartLineCall>  TracePartLineCallList;
+
+
+typedef TQPtrList<TraceInstr> TraceInstrList;
+typedef TQPtrList<TraceLine> TraceLineList;
+typedef TQPtrList<TraceInstrCall> TraceInstrCallList;
+typedef TQPtrList<TraceLineCall> TraceLineCallList;
+typedef TQPtrList<TraceCall> TraceCallList;
+typedef TQPtrList<TraceFile> TraceFileList;
+typedef TQPtrList<TraceLineRegion> TraceLineRegionList;
+typedef TQPtrList<TraceFunctionSource> TraceFunctionSourceList;
+typedef TQPtrList<TraceFunction> TraceFunctionList;
+typedef TQPtrList<TraceFunctionCycle> TraceFunctionCycleList;
+typedef TQMap<TQString, TraceObject> TraceObjectMap;
+typedef TQMap<TQString, TraceClass> TraceClassMap;
+typedef TQMap<TQString, TraceFile> TraceFileMap;
+typedef TQMap<TQString, TraceFunction> TraceFunctionMap;
+typedef TQMap<uint, TraceLine> TraceLineMap;
+
+
+/**
+ * Addresses are 64bit values like costs to be able
+ * to always load profile data produced on 64bit
+ * architectures.
+ */
+class Addr
+{
+ public:
+  Addr() { _v=0; }
+  Addr(uint64 v) { _v = v; }
+
+  // Interpretes char data at s as hex (without "0x" prefix)
+  // and return number of interpreted chars.
+  int set(const char *s);
+  bool set(FixString& s);
+  TQString toString() const;
+  // similar to toString(), but adds a space every 4 digits
+  TQString pretty() const;
+
+  // returns true if this address is in [a-distance;a+distance]
+  bool isInRange(Addr a, int distance);
+
+  bool operator==(const Addr& a) const { return (_v == a._v); }
+  bool operator!=(const Addr& a) const { return (_v != a._v); }
+  bool operator>(const Addr& a) const { return _v > a._v; }
+  bool operator>=(const Addr& a) const { return _v >= a._v; }
+  bool operator<(const Addr& a) const { return _v < a._v; }
+  bool operator<=(const Addr& a) const { return _v <= a._v; }
+
+  Addr operator+(int d) const { return Addr(_v + d); }
+  Addr operator-(int d) const { return Addr(_v - d); }
+  
+ private:
+  uint64 _v;
+};
+
+typedef TQMap<Addr, TraceInstr> TraceInstrMap;
+
+
+/**
+ * Base class for cost items.
+ */
+class TraceItem
+{
+public:
+
+  // RTTI for trace item classes, using type() method
+  enum CostType { Item, Cost,
+		  PartInstr, Instr,
+                  PartLine, Line,
+		  PartInstrJump, InstrJump,
+                  PartLineJump, LineJump,
+		  PartInstrCall, InstrCall,
+                  PartLineCall, LineCall,
+                  PartCall, Call,
+		  PartLineRegion, LineRegion,
+                  PartFunction, FunctionSource, Function, FunctionCycle,
+                  PartClass, Class, ClassCycle,
+                  PartFile, File, FileCycle,
+                  PartObject, Object, ObjectCycle,
+                  Part, Data,
+                  MaxCostType, NoCostType };
+
+  TraceItem();
+  virtual ~TraceItem();
+
+  virtual CostType type() const { return Item; }
+
+  // conversion of item type to locale independent string (e.g. for config)
+  static TQString     typeName(CostType);
+  static CostType    costType(TQString);
+  // the versions below should be used for user visible strings, as
+  // these use localisation settings
+  static TQString     i18nTypeName(CostType);
+  static CostType    i18nCostType(TQString);
+  // clean up some static data
+  static void cleanup();
+
+  /**
+   * Returns dynamic name info (without type)
+   */
+  virtual TQString name() const;
+
+  /**
+   * Same as name, but sometimes nicer for humans :-)
+   */
+  virtual TQString prettyName() const;
+
+  /**
+   * Returns text of all cost metrics
+   */
+  virtual TQString costString(TraceCostMapping*);
+
+  /**
+   * Returns type name + dynamic name
+   */
+  TQString fullName() const;
+
+  /**
+   * Returns full name + cost text
+   */
+  TQString toString();
+
+  /**
+   * Set all cost counters to zero
+   */
+  virtual void clear();
+
+  /** Invalidate the cost attributes.
+   * An invalidated object needs to be recalculated when a cost
+   * attribute is requested (e.g. by subCost()).
+   * Has to be overwritten by subclasses when the cost influences costs of
+   * other cost items. If only one item depends on the cost of this item,
+   * it can by set with setDependant() without a need for overwriting.
+   */
+  virtual void invalidate();
+
+  /**
+   * Sets a dependant to be invalidated when this cost is invalidated.
+   * Call this function directly after the constructor.
+   */
+  void setDependant(TraceItem* d) { _dep = d; }
+
+  TraceItem* dependant() { return _dep; }
+
+  /**
+   * If this item is from a single profile data file, position
+   * points to a TracePart, otherwise to a TraceData object.
+   */
+  void setPosition(TraceItem* p) { _position = p; }  
+
+  // getters for specific positions, to be overwritten
+  virtual TracePart* part();
+  virtual const TracePart* part() const;
+  virtual TraceData* data();
+  virtual const TraceData* data() const;
+
+ protected:
+  /** Updates cost attributes.
+   * This has to be called by subclasses that access cost attributes
+   * directly
+   */
+  virtual void update();
+
+  bool _dirty;
+
+  TraceItem* _position;
+  TraceItem* _dep;
+
+ private:
+  static TQString *_typeName, *_i18nTypeName;
+};
+
+
+
+/**
+ * An array of basic cost metrics for a trace item.
+ *
+ * The semantic of specific indexes is stored in the
+ * TraceCostMapping of the TraceData object holding this TraceCost.
+ */
+class TraceCost: public TraceItem
+{
+public:
+  /**
+   * The maximal number of subcosts a TraceCost can have.
+   */
+  static const int MaxRealIndex;
+#define MaxRealIndexValue 13
+  static const int InvalidIndex;
+
+
+  TraceCost();
+  virtual ~TraceCost();
+
+  virtual CostType type() const { return Cost; }
+  virtual TQString costString(TraceCostMapping*);
+
+  virtual void clear();
+
+  // set the cost according to a submapping and a list of ASCII numbers
+  void set(TraceSubMapping*, const char*);
+  void set(TraceSubMapping*, FixString&);
+  // add a cost according to a submapping and a list of ASCII numbers
+  void addCost(TraceSubMapping*, const char*);
+  void addCost(TraceSubMapping*, FixString&);
+  // add the cost of another item
+  void addCost(TraceCost* item);
+  void addCost(int index, SubCost value);
+
+  // maximal cost
+  void maxCost(TraceSubMapping*, FixString&);
+  void maxCost(TraceCost* item);
+  void maxCost(int index, SubCost value);
+  TraceCost diff(TraceCost* item);
+
+  virtual void invalidate();
+
+  /** Returns a sub cost. This automatically triggers
+   * a call to update() if needed.
+   */
+  SubCost subCost(TraceCostType*);
+
+  /**
+   * Same as above, but only for real types
+   */
+  SubCost subCost(int);
+
+  /** Returns a cost attribute converted to a string
+   * (with space after every 3 digits)
+   */
+  TQString prettySubCost(TraceCostType*);
+
+ protected:
+  virtual void update();
+
+  SubCost _cost[MaxRealIndexValue];
+  int _count; // only _count first indexes of _cost are used
+
+  // cache last virtual subcost for faster access
+  SubCost _cachedCost;
+  TraceCostType* _cachedType;
+};
+
+
+
+/**
+ * A cost type, e.g. "L1 Read Miss", short "l1rm".
+ *
+ * We distinguish "real" cost types, where the values come
+ * from the trace file, and "virtual" cost types, which
+ * are calculated from the real ones.
+ *
+ * For a virtual cost type, set a formula to calculate it:
+ * e.g. for "Read Misses" : "l1rm + l2rm".
+ * To allow for parsing, you must specify a TraceCostMapping
+ * with according cost types (e.g. "l1rm" and "l2rm" for above formula).
+ *
+ * The cost type with empty name is the "const" cost type.
+ */
+class TraceCostType
+{
+public:
+
+  /**
+   * <name> is a short (non-localized) identifier for the cost type,
+   *   e.g. "l1rm".
+   * <longName> is a long localized string, e.g. "L1 Read Miss"
+   * <formula> uses short names to reference other types
+   */
+  TraceCostType(TQString name,
+                TQString longName = TQString(),
+                TQString formula = TQString());
+
+  void setName(TQString n) { _name = n; }
+  void setLongName(TQString n) { _longName = n; }
+  void setMapping(TraceCostMapping* m);
+  void setFormula(TQString);
+  // default arg is for specifying a real type, but index unknown
+  void setRealIndex(int r = TraceCost::MaxRealIndex);
+
+  const TQString& name() { return _name; }
+  const TQString& longName() { return _longName; }
+  const TQString& formula() { return _formula; }
+  TraceCostMapping* mapping() { return _mapping; }
+  int realIndex() { return _realIndex; }
+  bool isReal() { return _formula.isEmpty(); }
+  TQColor color();
+
+  /*
+   * returns true if all cost type names can be resolved in formula
+   */
+  bool parseFormula();
+  TQString parsedFormula();
+
+  SubCost subCost(TraceCost*);
+
+  /*
+   * For virtual costs, returns a histogram for use with
+   * partitionPixmap().
+   * Returns maximal real index.
+   */
+  int histCost(TraceCost* c, double total, double* hist);
+
+  // application wide known types, referenced by short name
+  // next 2 functions return a new type object instance
+  static TraceCostType* knownRealType(TQString);
+  static TraceCostType* knownVirtualType(TQString);
+  static void add(TraceCostType*);
+  static bool remove(TQString);
+  static int knownTypeCount();
+  static TraceCostType* knownType(int);
+
+private:
+
+  TQString _name, _longName, _formula;
+  TraceCostMapping* _mapping;
+  bool _parsed, _inParsing;
+  // index MaxRealIndex is for constant addition
+  int _coefficient[MaxRealIndexValue];
+  int _realIndex;
+
+  static TQPtrList<TraceCostType>* _knownTypes;
+};
+
+
+/**
+ * A class for managing a set of cost types.
+ *
+ * Each cost type has an index:
+ * - Real costs are in range [0 .. TraceCost:MaxRealIndex[
+ * - Virtual costs are in range [MaxRealIndex, ...]
+ */
+class TraceCostMapping
+{
+public:
+  TraceCostMapping();
+  ~TraceCostMapping();
+
+  /**
+   * Defines a sub mapping with a list of real types
+   * If <create> is false, checks if this is a existing sub mapping.
+   */
+  TraceSubMapping* subMapping(TQString types, bool create = true);
+
+  // "knows" about some real types
+  int addReal(TQString);
+  int add(TraceCostType*);
+  bool remove(TraceCostType*);
+  int realCount() { return _realCount; }
+  int virtualCount() { return _virtualCount; }
+  int minVirtualIndex() { return TraceCost::MaxRealIndex; }
+  TraceCostType* type(int);
+  TraceCostType* realType(int);
+  TraceCostType* virtualType(int);
+  TraceCostType* type(TQString);
+  TraceCostType* typeForLong(TQString);
+  int realIndex(TQString);
+  int index(TQString);
+  TQColor* realColors() { return _realColor; }
+
+  /**
+   * Adds all known virtual types that can be parsed
+   */
+  int addKnownVirtualTypes();
+
+private:
+  // we support only a fixed number of real and virtual types
+  TraceCostType* _real[MaxRealIndexValue];
+  TQColor _realColor[MaxRealIndexValue];
+  TraceCostType* _virtual[MaxRealIndexValue];
+  int _realCount, _virtualCount;
+};
+
+/**
+ * A submapping of a TraceCostMapping
+ *
+ * This is a fixed ordered list of indexes for real cost types
+ * in a mapping.
+ *
+ * You can define a mapping by requesting submappings. Undefined cost
+ * types will get a new real type index.
+ *  TraceCostMapping m;
+ *  sm1 = m.subMapping("Event1 Cost1 Cost2");  // returns submap [0,1,2]
+ *  sm2 = m.subMapping("Event2 Cost3 Event1"); // returns submap [3,4,0]
+ * Real types of m will be:
+ *  (0:Event1, 1:Cost1, 2:Cost2, 3:Event2, 4:Cost3)
+ */
+class TraceSubMapping
+{
+public:
+  TraceSubMapping(TraceCostMapping*);
+
+  bool append(TQString, bool create=true);
+  bool append(int);
+  void clear();
+
+  /**
+   * Get number of used indexes
+   */
+  int count() { return _count; }
+
+  /**
+   * Is this submapping the identity( i.e. realIndex(i)=i ) ?
+   * This often allows for optimizations.
+   */
+  bool isIdentity() { return _isIdentity; }
+  int realIndex(int i)
+    { return (i<0 || i>=_count) ? TraceCost::InvalidIndex : _realIndex[i]; }
+
+  /*
+   * Allows an iteration over the sorted list of all real indexes not used in
+   * this submapping, up to topIndex (use TraceCost::MaxRealIndex for all).
+   * Usage: for(i = firstUnused(); i < topIndex; i = nextUnused(i)) { LOOP }
+   */
+  int firstUnused() { return _firstUnused; }
+  int nextUnused(int i) {
+      if (i<0 || i>=TraceCost::MaxRealIndex) return TraceCost::InvalidIndex;
+      return _nextUnused[i]; }
+
+private:
+  TraceCostMapping* _mapping;
+  int _count, _firstUnused;
+  bool _isIdentity;
+  int _realIndex[MaxRealIndexValue];
+  int _nextUnused[MaxRealIndexValue];
+};
+
+
+/**
+ * Cost of a (conditional) jump.
+ */
+class TraceJumpCost: public TraceItem
+{
+ public:
+    TraceJumpCost();
+    virtual ~TraceJumpCost();
+
+    // reimplementations for cost addition
+    virtual TQString costString(TraceCostMapping* m);
+    virtual void clear();
+
+    void addCost(TraceJumpCost*);
+
+    // additional cost metrics
+    SubCost followedCount();
+    SubCost executedCount();
+    void addFollowedCount(SubCost c) { _followedCount += c; }
+    void addExecutedCount(SubCost c) { _executedCount += c; }
+
+ protected:
+    SubCost _executedCount, _followedCount;
+};
+
+
+
+/**
+ * Cost item with additional call count metric.
+ */
+class TraceCallCost: public TraceCost
+{
+ public:
+  TraceCallCost();
+  virtual ~TraceCallCost();
+
+  // reimplementations for cost addition
+  virtual TQString costString(TraceCostMapping* m);
+  virtual void clear();
+
+  // additional cost metric
+  SubCost callCount();
+  TQString prettyCallCount();
+  void addCallCount(SubCost c);
+
+ protected:
+  SubCost _callCount;
+};
+
+
+/**
+ * Cost item with additional inclusive metric
+ */
+class TraceInclusiveCost: public TraceCost
+{
+ public:
+  TraceInclusiveCost();
+  virtual ~TraceInclusiveCost();
+
+  // reimplementations for cost addition
+  virtual TQString costString(TraceCostMapping* m);
+  virtual void clear();
+
+  // additional cost metric
+  TraceCost* inclusive();
+  void addInclusive(TraceCost*);
+
+ protected:
+  TraceCost _inclusive;
+};
+
+
+/**
+ * Cost Item
+ * dependend on a list of cost items.
+ */
+class TraceListCost: public TraceCost
+{
+ public:
+  TraceListCost();
+  virtual ~TraceListCost();
+
+  // reimplementation for dependency list
+  virtual void update();
+
+  TraceCostList& deps() { return _deps; }
+  void addDep(TraceCost*);
+  TraceCost* findDepFromPart(TracePart*);
+
+ protected:
+  // overwrite in subclass to change update behaviour
+  virtual bool onlyActiveParts() { return false; }
+
+  TraceCostList _deps;
+
+ private:
+  // very temporary: cached
+  TraceCost* _lastDep;
+};
+
+
+/**
+ * Jump Cost Item
+ * dependend on a list of Jump cost items.
+ */
+class TraceJumpListCost: public TraceJumpCost
+{
+ public:
+  TraceJumpListCost();
+  virtual ~TraceJumpListCost();
+
+  // reimplementation for dependency list
+  virtual void update();
+
+  TraceJumpCostList deps() { return _deps; }
+  void addDep(TraceJumpCost*);
+  TraceJumpCost* findDepFromPart(TracePart*);
+
+ protected:
+  // overwrite in subclass to change update behaviour
+  virtual bool onlyActiveParts() { return false; }
+
+  TraceJumpCostList _deps;
+
+ private:
+  // very temporary: cached
+  TraceJumpCost* _lastDep;
+};
+
+
+
+
+/**
+ * Call Cost Item
+ * dependend on a list of Call cost items.
+ */
+class TraceCallListCost: public TraceCallCost
+{
+ public:
+  TraceCallListCost();
+  virtual ~TraceCallListCost();
+
+  // reimplementation for dependency list
+  virtual void update();
+
+  TraceCallCostList deps() { return _deps; }
+  void addDep(TraceCallCost*);
+  TraceCallCost* findDepFromPart(TracePart*);
+
+ protected:
+  // overwrite in subclass to change update behaviour
+  virtual bool onlyActiveParts() { return false; }
+
+  TraceCallCostList _deps;
+
+ private:
+  // very temporary: cached
+  TraceCallCost* _lastDep;
+};
+
+
+/**
+ * Inclusive Cost Item dependend on a list of inclusive cost items.
+ */
+class TraceInclusiveListCost: public TraceInclusiveCost
+{
+ public:
+  TraceInclusiveListCost();
+  virtual ~TraceInclusiveListCost();
+
+  // reimplementation for dependency
+  virtual void update();
+
+  TraceInclusiveCostList deps() { return _deps; }
+  void addDep(TraceInclusiveCost*);
+  TraceInclusiveCost* findDepFromPart(TracePart*);
+
+ protected:
+  // overwrite in subclass to change update behaviour
+  virtual bool onlyActiveParts() { return false; }
+
+  TraceInclusiveCostList _deps;
+
+ private:
+  // very temporary: cached
+  TraceInclusiveCost* _lastDep;
+};
+
+
+
+
+
+/*-----------------------------------------------------------------
+ * Classes for cost items of one trace file, i.e. a "trace part"
+ *-----------------------------------------------------------------
+ */
+
+/**
+ * Cost of jump at a instruction code address from a trace file.
+ */
+class TracePartInstrJump: public TraceJumpCost
+{
+ public:
+  TracePartInstrJump(TraceInstrJump*, TracePartInstrJump*);
+  virtual ~TracePartInstrJump();
+
+    virtual CostType type() const { return PartInstrJump; }
+    // fix cost item
+    virtual void update() {}
+    TraceInstrJump* instrJump() const { return (TraceInstrJump*) _dep; }
+    TracePartInstrJump* next() const { return _next; }
+
+ private:
+    // chaining all parts for InstrJump
+    TracePartInstrJump* _next;
+};
+
+
+/**
+ * Cost of a call at a instruction code address from a trace file.
+ * Cost is always up to date, no lazy update needed.
+ */
+class TracePartInstrCall: public TraceCallCost
+{
+public:
+  TracePartInstrCall(TraceInstrCall*);
+  virtual ~TracePartInstrCall();
+
+  virtual CostType type() const { return PartInstrCall; }
+  // fix cost item
+  virtual void update() {}
+  TraceInstrCall* instrCall() const { return (TraceInstrCall*) _dep; }
+};
+
+
+/**
+ * Cost of a code instruction address from a trace file.
+ * Cost is always up to date, no lazy update needed.
+ */
+class TracePartInstr: public TraceCost
+{
+public:
+  TracePartInstr(TraceInstr*);
+  virtual ~TracePartInstr();
+
+  virtual CostType type() const { return PartInstr; }
+  // fix cost item
+  virtual void update() {}
+
+  TraceInstr* instr() const { return (TraceInstr*)_dep; }
+};
+
+
+/**
+ * Cost of jump at a source line from a trace file.
+ */
+class TracePartLineJump: public TraceJumpCost
+{
+ public:
+    TracePartLineJump(TraceLineJump*);
+    virtual ~TracePartLineJump();
+
+    virtual CostType type() const { return PartLineJump; }
+    // fix cost item
+    virtual void update() {}
+    TraceLineJump* lineJump() const { return (TraceLineJump*) _dep; }
+};
+
+
+/**
+ * Cost of a call at a line from a trace file.
+ * Cost is always up to date, no lazy update needed.
+ */
+class TracePartLineCall: public TraceCallCost
+{
+public:
+  TracePartLineCall(TraceLineCall*);
+  virtual ~TracePartLineCall();
+
+  virtual CostType type() const { return PartLineCall; }
+  // fix cost item
+  virtual void update() {}
+  TraceLineCall* lineCall() const { return (TraceLineCall*) _dep; }
+};
+
+
+
+/**
+ * Cost of a line from a trace file.
+ * Cost is always up to date, no lazy update needed.
+ */
+class TracePartLine: public TraceCost
+{
+public:
+  TracePartLine(TraceLine*);
+  virtual ~TracePartLine();
+
+  virtual CostType type() const { return PartLine; }
+  // fix cost item
+  virtual void update() {}
+
+  TraceLine* line() const { return (TraceLine*)_dep; }
+};
+
+
+/**
+ * Cost of a source region.
+ */
+class TracePartLineRegion: public TraceInclusiveCost
+{
+public:
+  TracePartLineRegion(TraceLineRegion*);
+  virtual ~TracePartLineRegion();
+
+  virtual CostType type() const { return PartLineRegion; }
+  virtual void update();
+
+  TraceLineRegion* region() const { return (TraceLineRegion*)_dep; }
+};
+
+
+/**
+ * Cost of a call at a function to another function,
+ * from a single trace file.
+ */
+class TracePartCall: public TraceCallListCost
+{
+public:
+  TracePartCall(TraceCall* call);
+  virtual ~TracePartCall();
+
+  virtual CostType type() const { return PartCall; }
+  // calls a function itself?
+  bool isRecursion();
+
+  // reimplementation for dependency list
+  virtual void update();
+
+  TraceCall* call() const { return (TraceCall*)_dep; }
+
+  FixCallCost* setFirstFixCallCost(FixCallCost* fc)
+    { FixCallCost* t = _firstFixCallCost; _firstFixCallCost = fc; return t; }
+  FixCallCost* firstFixCallCost() const { return _firstFixCallCost; }
+
+private:
+  FixCallCost* _firstFixCallCost;
+};
+
+
+/**
+ * Cost of a function,
+ * from a single trace file.
+ */
+class TracePartFunction: public TraceInclusiveCost
+{
+public:
+  TracePartFunction(TraceFunction*,
+		    TracePartObject*, TracePartFile*);
+  virtual ~TracePartFunction();
+
+  virtual CostType type() const { return PartFunction; }
+  virtual void update();
+  virtual TQString costString(TraceCostMapping* m);
+
+  void addPartInstr(TracePartInstr*);
+  void addPartLine(TracePartLine*);
+  void addPartCaller(TracePartCall*);
+  void addPartCalling(TracePartCall*);
+
+  TraceFunction* function() { return (TraceFunction*) _dep; }
+  TracePartObject* partObject() { return _partObject; }
+  TracePartClass* partClass() { return _partClass; }
+  TracePartFile* partFile() { return _partFile; }
+  const TracePartCallList& partCallers() { return _partCallers; }
+  const TracePartCallList& partCallings() { return _partCallings; }
+  void setPartObject(TracePartObject* o) { _partObject = o; }
+  void setPartClass(TracePartClass* c) { _partClass = c; }
+  void setPartFile(TracePartFile* f) { _partFile = f; }
+
+  /* for linked list of FixXXX objects */
+  FixCost* setFirstFixCost(FixCost* fc)
+      { FixCost* t = _firstFixCost; _firstFixCost = fc; return t; }
+  FixCost* firstFixCost() const { return _firstFixCost; }
+  FixJump* setFirstFixJump(FixJump* fj)
+      { FixJump* t = _firstFixJump; _firstFixJump = fj; return t; }
+  FixJump* firstFixJump() const { return _firstFixJump; }
+
+  // additional cost metrics
+  SubCost calledCount();
+  SubCost callingCount();
+  TQString prettyCalledCount();
+  TQString prettyCallingCount();
+  int calledContexts();
+  int callingContexts();
+
+private:
+  TracePartObject* _partObject;
+  TracePartClass* _partClass;
+  TracePartFile* _partFile;
+
+  TracePartCallList _partCallings;
+  TracePartCallList _partCallers;
+  TracePartInstrList _partInstr;
+  TracePartLineList _partLines;
+
+  // cached
+  SubCost _calledCount, _callingCount;
+  int _calledContexts, _callingContexts;
+
+  FixCost* _firstFixCost;
+  FixJump* _firstFixJump;
+};
+
+
+/**
+ * Cost of a class,
+ * from a single trace file.
+ */
+class TracePartClass: public TraceInclusiveListCost
+{
+public:
+  TracePartClass(TraceClass*);
+  virtual ~TracePartClass();
+
+  virtual CostType type() const { return PartClass; }
+  TQString prettyName() const;
+
+  TraceClass* cls() { return (TraceClass*)_dep; }
+  void addPartFunction(TracePartFunction* f) { addDep(f); }
+};
+
+
+/**
+ * Cost of a source file,
+ * from a single trace file.
+ */
+class TracePartFile: public TraceInclusiveListCost
+{
+public:
+  TracePartFile(TraceFile*);
+  virtual ~TracePartFile();
+
+  virtual CostType type() const { return PartFile; }
+  TraceFile* file() { return (TraceFile*)_dep; }
+  void addPartFunction(TracePartFunction* f) { addDep(f); }
+};
+
+
+/**
+ * Cost of a object,
+ * from a single trace file.
+ */
+class TracePartObject: public TraceInclusiveListCost
+{
+public:
+  TracePartObject(TraceObject*);
+  virtual ~TracePartObject();
+
+  virtual CostType type() const { return PartObject; }
+  TraceObject* object() const { return (TraceObject*)_dep; }
+  void addPartFunction(TracePartFunction* f) { addDep(f); }
+};
+
+
+
+/**
+ * A Trace Part: All data read from a trace file, containing all costs
+ * that happened in a specified time interval of the executed command.
+ */
+class TracePart: public TraceListCost
+{
+public:
+  TracePart(TraceData*, TQFile* file);
+  virtual ~TracePart();
+
+  virtual CostType type() const { return Part; }
+  virtual TracePart* part() { return this; }
+  virtual const TracePart* part() const { return this; }
+
+  TQString shortName() const;
+  TQString prettyName() const;
+  TQFile* file() const { return _file; }
+  TQString name() const { return _name; }
+  TQString description() const { return _descr; }
+  TQString trigger() const { return _trigger; }
+  TQString timeframe() const { return _timeframe; }
+  TQString version() const { return _version; }
+  int partNumber() { return _number; }
+  int threadID() { return _tid; }
+  int processID() { return _pid; }
+  void setDescription(const TQString& d) { _descr = d; }
+  void setTrigger(const TQString& t) { _trigger = t; }
+  void setTimeframe(const TQString& t) { _timeframe = t; }
+  void setVersion(const TQString& v) { _version = v; }
+  void setPartNumber(int n);
+  void setThreadID(int t);
+  void setProcessID(int p);
+  TraceCost* totals() { return &_totals; }
+  /* we get owner of the submapping */
+  void setFixSubMapping(TraceSubMapping* sm) { _fixSubMapping = sm; }
+  TraceSubMapping* fixSubMapping() { return _fixSubMapping; }
+
+  // returns true if something changed
+  bool activate(bool);
+  bool isActive() { return _active; }
+
+private:
+  TQFile* _file;
+  TQString _name;
+  TQString _descr;
+  TQString _trigger;
+  TQString _timeframe;
+  TQString _version;
+
+  int _number, _tid, _pid;
+
+  bool _active;
+
+  // the totals line
+  TraceCost _totals;
+
+  // submapping for all fix costs of this part
+  TraceSubMapping* _fixSubMapping;
+};
+
+
+class TracePartList: public TQPtrList<TracePart>
+{
+ public:
+  TQString names() const;
+ protected:
+  int compareItems ( Item item1, Item item2 );
+};
+
+
+/*-----------------------------------------------------------------
+ * Classes for cost items summed up from multiple trace parts
+ *-----------------------------------------------------------------
+ */
+
+
+/**
+ * A jump from an instruction to another inside of a function
+ */
+class TraceInstrJump: public TraceJumpCost
+{
+public:
+    TraceInstrJump(TraceInstr* instrFrom, TraceInstr* instrTo,
+		   bool isCondJump);
+    virtual ~TraceInstrJump();
+
+    virtual CostType type() const { return InstrJump; }
+    virtual TQString name() const;
+
+    virtual void update();
+
+    TraceInstr* instrFrom() const { return _instrFrom; }
+    TraceInstr* instrTo() const { return _instrTo; }
+    bool isCondJump() const { return _isCondJump; }
+
+    // part factory
+    TracePartInstrJump* partInstrJump(TracePart*);
+
+ private:
+    TraceInstr *_instrFrom, *_instrTo;
+    bool _isCondJump;
+    // list of parts for this InstrJump
+    TracePartInstrJump* _first;
+};
+
+class TraceInstrJumpList: public TQPtrList<TraceInstrJump>
+{
+ public:
+    TraceInstrJumpList() { _sortLow = true; }
+    void setSortLow(bool s) { _sortLow = s; }
+
+ protected:
+  int compareItems ( Item item1, Item item2 );
+
+ private:
+  bool _sortLow;
+};
+
+
+/**
+ * A jump from one line to another inside of a function.
+ */
+class TraceLineJump: public TraceJumpListCost
+{
+ public:
+  TraceLineJump(TraceLine* lineFrom, TraceLine* lineTo,
+		bool isCondJump);
+  virtual ~TraceLineJump();
+
+  virtual CostType type() const { return LineJump; }
+  virtual TQString name() const;
+
+  TraceLine* lineFrom() const { return _lineFrom; }
+  TraceLine* lineTo() const { return _lineTo; }
+  bool isCondJump() { return _isCondJump; }
+
+  // part factory
+  TracePartLineJump* partLineJump(TracePart*);
+
+ protected:
+  bool onlyActiveParts() { return true; }
+
+ private:
+  TraceLine *_lineFrom, *_lineTo;
+  bool _isCondJump;
+};
+
+
+class TraceLineJumpList: public TQPtrList<TraceLineJump>
+{
+ public:
+    TraceLineJumpList() { _sortLow = true; }
+    void setSortLow(bool s) { _sortLow = s; }
+
+ protected:
+  int compareItems ( Item item1, Item item2 );
+
+ private:
+  bool _sortLow;
+};
+
+
+/**
+ * A call from an instruction of one function to another function
+ */
+class TraceInstrCall: public TraceCallListCost
+{
+ public:
+  TraceInstrCall(TraceCall* call, TraceInstr* instr);
+  virtual ~TraceInstrCall();
+
+  virtual CostType type() const { return InstrCall; }
+  virtual TQString name() const;
+
+  TraceInstr* instr() const { return _instr; }
+  TraceCall* call() const { return _call; }
+
+  // part factory
+  TracePartInstrCall* partInstrCall(TracePart*, TracePartCall*);
+
+ protected:
+  bool onlyActiveParts() { return true; }
+
+ private:
+  TraceInstr* _instr;
+  TraceCall* _call;
+};
+
+
+/**
+ * A call from a line of one function to another function.
+ */
+class TraceLineCall: public TraceCallListCost
+{
+ public:
+  TraceLineCall(TraceCall* call, TraceLine* line);
+  virtual ~TraceLineCall();
+
+  virtual CostType type() const { return LineCall; }
+  virtual TQString name() const;
+
+  TraceLine* line() const { return _line; }
+  TraceCall* call() const { return _call; }
+
+  // part factory
+  TracePartLineCall* partLineCall(TracePart*, TracePartCall*);
+
+ protected:
+  bool onlyActiveParts() { return true; }
+
+ private:
+  TraceLine* _line;
+  TraceCall* _call;
+};
+
+
+/**
+ * A call from one to another function.
+ * Consists of a list a TraceLineCalls
+ */
+class TraceCall: public TraceCallListCost
+{
+ public:
+  TraceCall(TraceFunction* caller, TraceFunction* called);
+  virtual ~TraceCall();
+
+  virtual CostType type() const { return Call; }
+  virtual TQString name() const;
+
+  // calls a function itself?
+  bool isRecursion() { return _caller == _called; }
+
+  // return cycle number >0 if call is inside of a cycle
+  int inCycle();
+  // we need some special handling for cycle calls
+  void update();
+
+  void invalidateDynamicCost();
+
+  // factories
+  TracePartCall* partCall(TracePart*,
+                          TracePartFunction*, TracePartFunction*);
+  TraceLineCall* lineCall(TraceLine*);
+  TraceInstrCall* instrCall(TraceInstr*);
+
+  TraceFunction* caller(bool skipCycle=false) const;
+  TraceFunction* called(bool skipCycle=false) const;
+  TQString callerName(bool skipCycle=false) const;
+  TQString calledName(bool skipCycle=false) const;
+  const TraceLineCallList& lineCalls() const { return _lineCalls; }
+  const TraceInstrCallList& instrCalls() const { return _instrCalls; }
+
+  FixCallCost* setFirstFixCost(FixCallCost* fc)
+    { FixCallCost* t = _firstFixCost; _firstFixCost = fc; return t; }
+
+ protected:
+  bool onlyActiveParts() { return true; }
+
+ private:
+  TraceInstrCallList _instrCalls;
+  TraceLineCallList _lineCalls;
+  TraceFunction* _caller;
+  TraceFunction* _called;
+
+  FixCallCost* _firstFixCost;
+};
+
+
+/**
+ * A code instruction address of the program.
+ * Consists of a list a TracePartInstr from different trace files
+ * and a list of TraceInstrCalls if there are calls from this address.
+ */
+class TraceInstr: public TraceListCost
+{
+ public:
+  TraceInstr();
+  virtual ~TraceInstr();
+
+  virtual CostType type() const { return Instr; }
+  virtual TQString name() const;
+  TQString prettyName() const;
+
+  bool isValid() { return _addr != Addr(0); }
+
+  // factories
+  TracePartInstr* partInstr(TracePart* part,
+			    TracePartFunction* partFunction);
+  TraceInstrJump* instrJump(TraceInstr* to, bool isCondJump);
+
+  void addInstrCall(TraceInstrCall*);
+
+  Addr addr() const { return _addr; }
+  TraceFunction* function() const { return _function; }
+  TraceLine* line() const { return _line; }
+  const TraceInstrJumpList& instrJumps() const { return _instrJumps; }
+  const TraceInstrCallList& instrCalls() const { return _instrCalls; }
+  bool hasCost(TraceCostType*);
+
+  // only to be called after default constructor
+  void setAddr(const Addr addr) { _addr = addr; }
+  void setFunction(TraceFunction* f) { _function = f; }
+  void setLine(TraceLine* l) { _line = l; }
+
+ protected:
+  bool onlyActiveParts() { return true; }
+
+ private:
+  Addr _addr;
+  TraceFunction* _function;
+  TraceLine* _line;
+
+  TraceInstrJumpList _instrJumps;
+  TraceInstrCallList _instrCalls;
+};
+
+
+/**
+ * A source line of the program.
+ * Consists of a list a TracePartLines from different trace files
+ * and a list of TraceLineCalls if there are calls from this line.
+ */
+class TraceLine: public TraceListCost
+{
+public:
+  TraceLine();
+  virtual ~TraceLine();
+
+  virtual CostType type() const { return Line; }
+  virtual TQString name() const;
+  TQString prettyName() const;
+
+  // factories
+  TracePartLine* partLine(TracePart* part,
+                          TracePartFunction* partFunction);
+  TraceLineJump* lineJump(TraceLine* to, bool isCondJump);
+
+  void addLineCall(TraceLineCall*);
+
+
+  bool isValid() { return _sourceFile != 0; }
+  bool hasCost(TraceCostType*);
+  TraceFunctionSource* functionSource() const { return _sourceFile; }
+  uint lineno() const { return _lineno; }
+  const TraceLineCallList& lineCalls() const { return _lineCalls; }
+  const TraceLineJumpList& lineJumps() const { return _lineJumps; }
+
+  // only to be called after default constructor
+  void setSourceFile(TraceFunctionSource* sf) { _sourceFile = sf; }
+  void setLineno(uint lineno) { _lineno = lineno; }
+
+ protected:
+  bool onlyActiveParts() { return true; }
+
+ private:
+  TraceFunctionSource* _sourceFile;
+  uint _lineno;
+
+  TraceLineJumpList _lineJumps;
+  TraceLineCallList _lineCalls;
+};
+
+
+/*
+ * Base class for all costs which
+ * represent "interesting" items or group of items
+ * with settable name and inclusive cost
+ */
+class TraceCostItem: public TraceInclusiveListCost
+{
+ public:
+  TraceCostItem();
+  virtual ~TraceCostItem();
+
+  virtual TQString name() const { return _name; }
+  virtual void setName(const TQString& name) { _name = name; }
+
+ protected:
+  bool onlyActiveParts() { return true; }
+
+ protected:
+  TQString _name;
+};
+
+
+/**
+ * Cost of a source region.
+ */
+class TraceLineRegion: public TraceInclusiveListCost
+{
+public:
+  TraceLineRegion(uint from, uint to, TQString name);
+  virtual ~TraceLineRegion();
+
+  virtual CostType type() const { return LineRegion; }
+  virtual void update();
+
+  uint from() const { return _from; }
+  uint to() const { return _to; }
+  TQString name() const { return _name; }
+
+  // factories
+  TracePartLine* partLineRegion(TracePart* part,
+			    TracePartFunction* partFunction);
+ private:
+  uint _from, _to;
+  TQString _name;
+};
+
+
+/**
+ * A container helper class for TraceFunction for source lines
+ * where a function is implemented in.
+ * With inlining, lines of the same function can come from
+ * different source files.
+ * An instance of this class holds all lines of one source file
+ * for a function in a map
+ */
+class TraceFunctionSource: public TraceCost
+{
+public:
+  TraceFunctionSource(TraceFunction*, TraceFile*);
+  virtual ~TraceFunctionSource();
+
+  virtual CostType type() const { return FunctionSource; }
+  virtual TQString name() const;
+
+  // reimplementation for dependency map
+  virtual void update();
+
+  TraceFile* file() const { return _file; }
+  TraceFunction* function() const { return _function; }
+  uint firstLineno();
+  uint lastLineno();
+  TraceLineMap* lineMap();
+
+  void invalidateDynamicCost();
+
+  /* factories */
+  TraceLine* line(uint lineno, bool createNew = true);
+  TraceLineRegion* region(uint from, uint to, TQString name,
+		      bool createNew = true);
+
+ private:
+  TraceFile* _file;
+  TraceFunction* _function;
+  TraceLineMap* _lineMap;
+  TraceLine* _line0;
+  TraceLineRegionList* _regions;
+
+  bool _lineMapFilled;
+};
+
+
+/**
+ * For temporary assoziation of objects with TraceFunctions.
+ * Used in coverage analysis and TreeMap drawing.
+ */
+class TraceAssoziation
+{
+ public:
+  /**
+   * Creates an invalid assoziation.
+   */
+  TraceAssoziation();
+  virtual ~TraceAssoziation();
+
+  // for runtime detection
+  virtual int rtti() { return 0; }
+
+  /**
+   * Could we set the function assoziation to ourself?
+   * This only can return false if this is a unique assoziation.
+   */
+  bool isAssoziated();
+
+  /**
+   * reset function to assoziate this object to.
+   * returns true if assoziation could be established
+   */
+  bool setFunction(TraceFunction*);
+  TraceFunction* function() { return _function; }
+
+  void invalidate() { _valid = false; }
+  bool isValid() { return _valid; }
+
+  /**
+   * Delete all assoziations in TraceFunctions of data with
+   * rtti runtime info. rtti = 0: delete ALL assoziations.
+   */
+  static void clear(TraceData* data, int rtti);
+
+  /**
+   * Invalidate all assoziations in TraceFunctions of data with
+   * rtti runtime info. rtti = 0: Invalidate ALL assoziations.
+   */
+  static void invalidate(TraceData* data, int rtti);
+
+ protected:
+  TraceFunction* _function;
+  bool _valid;
+};
+
+typedef TQPtrList<TraceAssoziation> TraceAssoziationList;
+typedef TQMap<TraceFunction*, TraceCall*> TraceCallMap;
+
+/**
+ * A traced function
+ *
+ * References to functions are stored in
+ *  (1) a function map in TraceData (by value)
+ *  (2) a TraceClass
+ */
+class TraceFunction: public TraceCostItem
+{
+ public:
+  TraceFunction();
+  TraceFunction(TraceData* data, const TQString& name,
+                TraceClass* cls, TraceFile* file, TraceObject* object);
+  virtual ~TraceFunction();
+
+  virtual CostType type() const { return Function; }
+  virtual void update();
+
+  // this invalidate all subcosts of function depending on
+  // active status of parts
+  void invalidateDynamicCost();
+
+  void addCaller(TraceCall*);
+
+  // factories
+  TraceCall* calling(TraceFunction* called);
+  TraceLine* line(TraceFile*, uint lineno, bool createNew = true);
+  TraceInstr* instr(Addr addr, bool createNew = true);
+  TracePartFunction* partFunction(TracePart*,
+                                  TracePartFile*, TracePartObject*);
+
+  /**
+   * Returns empty string if location is fully unknown.
+   * Use prettyLocation for single user-visible string.
+   * A function can have a lot of code from different sources (inlined);
+   * maxItems limits this list. Default is full list
+   */
+  TQString location(int maxFiles = 0) const;
+
+  TQString prettyName() const;
+  TQString prettyLocation(int maxFiles = 0) const;
+  TQString prettyNameWithLocation(int maxFiles = 1) const;
+  void addPrettyLocation(TQString&, int maxFiles = 1) const;
+  // type + name + location
+  TQString info() const; 
+
+  TraceClass* cls() const { return _cls; }
+  TraceFile* file() const { return _file; }
+  TraceObject* object() const { return _object; }
+  // get the source file with lines from function declaration (not inlined)
+  TraceFunctionSource* sourceFile(TraceFile* file = 0,
+                                      bool createNew = false);
+  const TraceFunctionSourceList& sourceFiles() const
+    { return _sourceFiles; }
+  TraceCallList callers(bool skipCycle=false) const;
+  const TraceCallList& callings(bool skipCycle=false) const;
+
+  Addr firstAddress() const;
+  Addr lastAddress() const;
+  TraceInstrMap* instrMap();
+
+  // cost metrics
+  SubCost calledCount();
+  SubCost callingCount();
+  TQString prettyCalledCount();
+  TQString prettyCallingCount();
+  int calledContexts();
+  int callingContexts();
+
+  // only to be called after default constructor
+  void setFile(TraceFile* file) { _file = file; }
+  void setObject(TraceObject* object) { _object = object; }
+  void setClass(TraceClass* cls) { _cls = cls; }
+  void setMapIterator(TraceFunctionMap::Iterator it) { _myMapIterator = it; }
+
+  // see TraceFunctionAssoziation
+  void addAssoziation(TraceAssoziation* a);
+  void removeAssoziation(TraceAssoziation* a);
+  void removeAssoziation(int rtti, bool reallyDelete = true);
+  void invalidateAssoziation(int rtti);
+  TraceAssoziation* assoziation(int rtti);
+
+  // cycles
+  void setCycle(TraceFunctionCycle* c) { _cycle = c; }
+  TraceFunctionCycle* cycle() { return _cycle; }
+  bool isCycle();
+  bool isCycleMember();
+  void cycleReset();
+  void cycleDFS(int d, int& pNo, TraceFunction** pTop);
+
+ protected:
+  TraceCallList _callers; // list of calls we are called from
+  TraceCallList _callings; // list of calls we are calling (we are owner)
+  TraceCallMap _callingMap; // contains the same as _callings in a map
+  TraceFunctionCycle* _cycle;
+
+ private:
+  bool isUniquePrefix(TQString) const;
+  TraceFunctionMap::Iterator _myMapIterator;
+
+  TraceClass* _cls;
+  TraceObject* _object;
+  TraceFile* _file;
+
+  TraceFunctionSourceList _sourceFiles; // we are owner
+  TraceInstrMap* _instrMap; // we are owner
+  bool _instrMapFilled;
+
+  // see TraceAssoziation
+  TraceAssoziationList _assoziations;
+
+  // for cycle detection
+  int _cycleLow;
+  TraceFunction* _cycleStackDown;
+
+  // cached
+  SubCost _calledCount, _callingCount;
+  int _calledContexts, _callingContexts;
+};
+
+typedef TQMap<TraceFunction*,int> TraceFunctionSet;
+
+/**
+ * A cycle of recursive calling functions.
+ *
+ * This is itself shown as a function
+ */
+class TraceFunctionCycle: public TraceFunction
+{
+ public:
+  TraceFunctionCycle(TraceFunction*, int n);
+
+  virtual CostType type() const { return FunctionCycle; }
+
+  // this removes all members from this cycle
+  void init();
+  void add(TraceFunction*);
+  // this sets up the cycle once members are added
+  void setup();
+
+  TraceFunction* base() const { return _base; }
+  int cycleNo() const { return _cycleNo; }
+  const TraceFunctionList& members() const { return _members; }
+
+ private:
+  TraceFunction* _base;
+  int _cycleNo;
+
+  TraceFunctionList _members;
+  TraceFunctionSet _memberSet;
+};
+
+
+/**
+ * A C++ Class / Namespace
+ *
+ * If a function symbol has a prefix ending in "::",
+ * the prefix is supposed to be a class/namespace specifier.
+ * Without such a prefix, we put a symbol in the "(global)" namespace.
+ */
+class TraceClass: public TraceCostItem
+{
+ public:
+  TraceClass();
+  virtual ~TraceClass();
+
+  virtual CostType type() const { return Class; }
+  virtual TQString prettyName() const;
+
+  void addFunction(TraceFunction*);
+  const TraceFunctionList& functions() const { return _functions; }
+
+  // part factory
+  TracePartClass* partClass(TracePart*);
+
+ private:
+  TraceFunctionList _functions;
+};
+
+
+
+/**
+ * A source file containing function definitions
+ */
+class TraceFile: public TraceCostItem
+{
+ public:
+  TraceFile();
+  virtual ~TraceFile();
+
+  virtual CostType type() const { return File; }
+  void setDirectory(const TQString& dir);
+  void resetDirectory() { _dir = TQString(); }
+  TQString directory();
+
+  void addFunction(TraceFunction*);
+  void addSourceFile(TraceFunctionSource*);
+
+  // without path
+  TQString shortName() const;
+  TQString prettyName() const;
+  TQString prettyLongName() const;
+  const TraceFunctionList& functions() const { return _functions; }
+  const TraceFunctionSourceList& sourceFiles() const
+    { return _sourceFiles; }
+
+  // part factory
+  TracePartFile* partFile(TracePart*);
+
+ private:
+  TraceFunctionList _functions;
+  TraceFunctionSourceList _sourceFiles;
+  TQString _dir;
+};
+
+
+/**
+ * A object containing a text segment (shared lib/executable)
+ * with defined functions
+ */
+class TraceObject: public TraceCostItem
+{
+ public:
+  TraceObject();
+  virtual ~TraceObject();
+
+  virtual CostType type() const { return Object; }
+
+  void addFunction(TraceFunction*);
+
+  virtual void setName(const TQString& name);
+  TQString shortName() const { return _shortName; }
+  TQString prettyName() const;
+  const TraceFunctionList& functions() const { return _functions; }
+
+  // part factory
+  TracePartObject* partObject(TracePart*);
+
+ private:
+  TraceFunctionList _functions;
+  TQString _shortName;
+};
+
+
+
+/**
+ * This class holds profiling data of multiple tracefiles
+ * generated with cachegrind on one command.
+ *
+ */
+class TraceData: public TraceCost
+{
+ public:
+  TraceData(TopLevel* top = 0);
+  TraceData(const TQString& base);
+  virtual ~TraceData();
+
+  virtual CostType type() const { return Data; }
+  virtual TraceData* data() { return this; }
+  virtual const TraceData* data() const { return this; }
+
+  /**
+   * Loads a trace file.
+   *
+   * This adjusts the TraceCostMapping according to given cost types
+   */
+  void load(const TQString&);
+
+  /** returns true if something changed. These do NOT
+   * invalidate the dynamic costs on a activation change,
+   * i.e. all cost items dependend on active parts.
+   * This has to be done by the caller when true is returned by
+   * calling invalidateDynamicCost().
+   */
+  bool activateParts(const TracePartList&);
+  bool activateParts(TracePartList, bool active);
+  bool activatePart(TracePart*, bool active);
+  bool activateAll(bool active=true);
+
+  TracePartList parts() const { return _parts; }
+  TracePart* part(TQString& name);
+
+  // with path
+  TQString traceName() const { return _traceName; }
+
+  // without path
+  TQString shortTraceName() const;
+  TQString activePartRange();
+
+  TraceCostMapping* mapping() { return &_mapping; }
+
+  // memory pools
+  FixPool* fixPool();
+  DynPool* dynPool();
+
+  // factories for object/file/class/function/line instances
+  TraceObject* object(const TQString& name);
+  TraceFile* file(const TQString& name);
+  TraceClass* cls(const TQString& fnName, TQString& shortName);
+  // function creation involves class creation if needed
+  TraceFunction* function(const TQString& name, TraceFile*, TraceObject*);
+  // factory for function cycles
+  TraceFunctionCycle* functionCycle(TraceFunction*);
+
+  /**
+   * Search for item with given name and highest subcost of given cost type.
+   *
+   * For some items, they will only be found if the parent cost is given:
+   *  Instr, Line, Call  => need parent of type Function
+   * For Function, a parent of type Obj/File/Class can be given, but
+   * isn't needed.
+   */
+  TraceCost* search(TraceItem::CostType, TQString,
+		    TraceCostType* ct = 0, TraceCost* parent = 0);
+
+  // for pretty function names without signature if unique...
+  TraceFunctionMap::Iterator functionIterator(TraceFunction*);
+  TraceFunctionMap::ConstIterator functionBeginIterator() const;
+  TraceFunctionMap::ConstIterator functionEndIterator() const;
+
+  TraceObjectMap& objectMap() { return _objectMap; }
+  TraceFileMap& fileMap() { return _fileMap; }
+  TraceClassMap& classMap() { return _classMap; }
+  TraceFunctionMap& functionMap() { return _functionMap; }
+
+  const TraceFunctionCycleList& functionCycles() { return _functionCycles; }
+  
+  TraceCost* callMax() { return &_callMax; }
+
+  void setCommand(const TQString& command) { _command = command; }
+  TQString command() const { return _command; }
+  TraceCost* totals() { return &_totals; }
+  void setMaxThreadID(int tid) { _maxThreadID = tid; }
+  int maxThreadID() const { return _maxThreadID; }
+  void setMaxPartNumber(int n) { _maxPartNumber = n; }
+  int maxPartNumber() const { return _maxPartNumber; }
+
+  // reset all manually set directories for source files
+  void resetSourceDirs();
+
+  virtual void update();
+
+  // invalidates all cost items dependant on active state of parts
+  void invalidateDynamicCost();
+
+  // cycle detection
+  void updateFunctionCycles();
+  void updateObjectCycles();
+  void updateClassCycles();
+  void updateFileCycles();
+  bool inFunctionCycleUpdate() { return _inFunctionCycleUpdate; }
+
+ private:
+  void init();
+  // add trace part: events from one trace file
+  TracePart* addPart(const TQString& dir, const TQString& file);
+
+  // for progress bar callbacks
+  TopLevel* _topLevel;
+
+  TracePartList _parts;
+
+  // The mapping for all costs
+  TraceCostMapping _mapping;
+
+  FixPool* _fixPool;
+  DynPool* _dynPool;
+
+  // always the trace totals (not dependent on active parts)
+  TraceCost _totals;
+  int _maxThreadID;
+  int _maxPartNumber;
+
+  TraceObjectMap _objectMap;
+  TraceClassMap _classMap;
+  TraceFileMap _fileMap;
+  TraceFunctionMap _functionMap;
+  TQString _command;
+  TQString _traceName;
+
+  // Max of all costs of calls: This allows to see if the incl. cost can
+  // be hidden for a cost type, as it's always the same as self cost
+  TraceCost _callMax;
+
+  // cycles
+  TraceFunctionCycleList _functionCycles;
+  int _functionCycleCount;
+  bool _inFunctionCycleUpdate;
+};
+
+
+
+#endif
diff --git a/kdecachegrind/kdecachegrind/traceitemview.cpp b/kdecachegrind/kdecachegrind/traceitemview.cpp
new file mode 100644
index 0000000..d11f02b
--- /dev/null
+++ b/kdecachegrind/kdecachegrind/traceitemview.cpp
@@ -0,0 +1,443 @@
+/* This file is part of KCachegrind.
+   Copyright (C) 2003 Josef Weidendorfer <Josef.Weidendorfer@gmx.de>
+
+   KCachegrind 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, version 2.
+
+   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; see the file COPYING.  If not, write to
+   the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+   Boston, MA 02110-1301, USA.
+*/
+
+/*
+ * Trace Item View
+ */
+
+#include <tqwidget.h>
+#include <kconfig.h>
+#include <klocale.h>
+#include <kdebug.h>
+
+#include "traceitemview.h"
+#include "toplevel.h"
+
+#define TRACE_UPDATES 0
+
+TraceItemView::TraceItemView(TraceItemView* parentView, TopLevel* top)
+{
+  _parentView = parentView;
+  _topLevel = top ? top : parentView->topLevel();
+
+  _data = _newData = 0;
+  // _partList and _newPartList is empty
+  _activeItem = _newActiveItem = 0;
+  _selectedItem = _newSelectedItem = 0;
+  _costType = _newCostType = 0;
+  _costType2 = _newCostType2 = 0;
+  _groupType = _newGroupType = TraceItem::NoCostType;
+
+  _status = nothingChanged;
+  _inUpdate = false;
+  _pos = Hidden;
+}
+
+TQString TraceItemView::whatsThis() const
+{
+    return i18n("No description available");
+}
+
+void TraceItemView::select(TraceItem* i)
+{
+    _newSelectedItem = i;
+}
+
+KConfigGroup* TraceItemView::configGroup(KConfig* c,
+					 TQString group, TQString post)
+{
+    TQStringList gList = c->groupList();
+    if (gList.contains((group+post).ascii()) ) group += post;
+    return new KConfigGroup(c, group);
+}
+
+void TraceItemView::writeConfigEntry(KConfigBase* c, const char* pKey,
+				     TQString value, const char* def, bool bNLS)
+{
+    if (!c) return;
+    if ((value.isEmpty() && ((def == 0) || (*def == 0))) ||
+	(value == TQString(def)))
+	c->deleteEntry(pKey);
+    else
+	c->writeEntry(pKey, value, true, false, bNLS);
+}
+
+void TraceItemView::writeConfigEntry(KConfigBase* c, const char* pKey,
+				     int value, int def)
+{
+    if (!c) return;
+    if (value == def)
+	c->deleteEntry(pKey);
+    else
+	c->writeEntry(pKey, value);
+}
+
+void TraceItemView::writeConfigEntry(KConfigBase* c, const char* pKey,
+				     double value, double def)
+{
+    if (!c) return;
+    if (value == def)
+	c->deleteEntry(pKey);
+    else
+	c->writeEntry(pKey, value);
+}
+
+void TraceItemView::writeConfigEntry(KConfigBase* c, const char* pKey,
+				     bool value, bool def)
+{
+    if (!c) return;
+    if (value == def)
+	c->deleteEntry(pKey);
+    else
+	c->writeEntry(pKey, value);
+}
+
+void TraceItemView::readViewConfig(KConfig*, TQString, TQString, bool)
+{}
+
+#if 1
+void TraceItemView::saveViewConfig(KConfig*, TQString, TQString, bool)
+{}
+#else
+void TraceItemView::saveViewConfig(KConfig* c, 
+				   TQString prefix, TQString postfix, bool)
+{
+    // write a dummy config entry to see missing virtual functions
+    KConfigGroup g(c, (prefix+postfix).ascii());
+    g.writeEntry("SaveNotImplemented", true);
+}
+#endif
+
+bool TraceItemView::activate(TraceItem* i)
+{
+    i = canShow(i);
+    _newActiveItem = i;
+
+    return (i != 0);
+}
+
+TraceFunction* TraceItemView::activeFunction()
+{
+    TraceItem::CostType t = _activeItem->type();
+    switch(t) {
+    case TraceItem::Function:
+    case TraceItem::FunctionCycle:
+	return (TraceFunction*) _activeItem;
+    default:
+	break;
+    }
+    return 0;
+}
+
+bool TraceItemView::set(int changeType, TraceData* d,
+			TraceCostType* t1, TraceCostType* t2,
+			TraceItem::CostType g, const TracePartList& l,
+                        TraceItem* a, TraceItem* s)
+{
+  _status |= changeType;
+  _newData = d;
+  _newGroupType = g;
+  _newCostType = t1;
+  _newCostType2 = t2;
+  _newPartList = l;
+  _newSelectedItem = s;
+  _newActiveItem = canShow(a);
+  if (!_newActiveItem) {
+      _newSelectedItem = 0;
+      return false;
+  }
+
+  return true;
+}
+
+
+bool TraceItemView::isViewVisible()
+{
+  TQWidget* w = widget();
+  if (w)
+    return w->isVisible();
+  return false;
+}
+
+void TraceItemView::setData(TraceData* d)
+{
+  _newData = d;
+
+  // invalidate all pointers to old data
+  _activeItem = _newActiveItem = 0;
+  _selectedItem = _newSelectedItem = 0;
+  _costType = _newCostType = 0;
+  _costType2 = _newCostType2 = 0;
+  _groupType = _newGroupType = TraceItem::NoCostType;
+  _partList.clear();
+  _newPartList.clear();
+
+  // updateView will change this to dataChanged
+  _status = nothingChanged;
+}
+
+void TraceItemView::updateView(bool force)
+{
+  if (!force && !isViewVisible()) return;
+
+  if (_newData != _data) {
+    _status |= dataChanged;
+    _data = _newData;
+  }
+  else {
+    _status &= ~dataChanged;
+
+    // if there's no data change and data is 0, no update needed
+    if (!_data) return;
+  }
+
+  if (!(_newPartList == _partList)) {
+    _status |= partsChanged;
+    _partList = _newPartList;
+  }
+  else
+    _status &= ~partsChanged;
+
+  if (_newActiveItem != _activeItem) {
+
+      // when setting a new active item, there's no selection
+      _selectedItem = 0;
+
+      _status |= activeItemChanged;
+      _activeItem = _newActiveItem;
+  }
+  else
+    _status &= ~activeItemChanged;
+
+  if (_newCostType != _costType) {
+    _status |= costTypeChanged;
+    _costType = _newCostType;
+  }
+  else
+    _status &= ~costTypeChanged;
+
+  if (_newCostType2 != _costType2) {
+    _status |= costType2Changed;
+    _costType2 = _newCostType2;
+  }
+  else
+    _status &= ~costType2Changed;
+
+  if (_newGroupType != _groupType) {
+    _status |= groupTypeChanged;
+    _groupType = _newGroupType;
+  }
+  else
+    _status &= ~groupTypeChanged;
+
+
+  if (_newSelectedItem != _selectedItem) {
+    _status |= selectedItemChanged;
+    _selectedItem = _newSelectedItem;
+  }
+  else
+    _status &= ~selectedItemChanged;
+
+
+  if (!force && (_status == nothingChanged)) return;
+
+#if TRACE_UPDATES
+  kdDebug() << (widget() ? widget()->name() : "TraceItemView")
+            << "::doUpdate ( "
+            << ((_status & dataChanged) ? "data ":"")
+            << ((_status & configChanged) ? "config ":"")
+            << ")" << endl;
+
+  if (_status & partsChanged)
+    kdDebug() << "  Part List "
+              << _partList.names()
+              << endl;
+
+  if (_status & costTypeChanged)
+    kdDebug() << "  Cost type "
+              << (_costType ? _costType->name().ascii() : "?")
+              << endl;
+
+  if (_status & costType2Changed)
+    kdDebug() << "  Cost type 2 "
+              << (_costType2 ? _costType2->name().ascii() : "?")
+              << endl;
+
+  if (_status & groupTypeChanged)
+    kdDebug() << "  Group type "
+              << TraceItem::typeName(_groupType)
+              << endl;
+
+  if (_status & activeItemChanged)
+    kdDebug() << "  Active: "
+              << (_activeItem ? _activeItem->fullName().ascii() : "?")
+              << endl;
+
+  if (_status & selectedItemChanged)
+    kdDebug() << "  Selected: "
+              << (_selectedItem ? _selectedItem->fullName().ascii() : "?")
+              << endl;
+#endif
+
+  int st = _status;
+  _status = nothingChanged;
+  doUpdate(st);
+  return;
+
+  if (_inUpdate) return;
+  _inUpdate = true;
+  doUpdate(_status);
+  _inUpdate = false;
+}
+
+
+void TraceItemView::selected(TraceItemView* /*sender*/, TraceItem* i)
+{
+#if TRACE_UPDATES
+  kdDebug() << (widget() ? widget()->name() : "TraceItemView")
+            << "::selected "
+            << (i ? i->name().ascii(): "(nil)")
+            << ", sender "
+            << sender->widget()->name() << endl;
+#endif
+
+  if (_parentView) _parentView->selected(this, i);
+}
+
+void TraceItemView::selected(TraceItemView* /*sender*/, const TracePartList& l)
+{
+#if TRACE_UPDATES
+  kdDebug() << (widget() ? widget()->name() : "TraceItemView")
+            << "::selected "
+            << l.names()
+            << ", sender "
+            << sender->widget()->name() << endl;
+#endif
+
+  if (_parentView)
+    _parentView->selected(this, l);
+  else
+    if (_topLevel) _topLevel->activePartsChangedSlot(l);
+}
+
+void TraceItemView::activated(TraceItemView* /*sender*/, TraceItem* i)
+{
+#if TRACE_UPDATES
+  kdDebug() << (widget() ? widget()->name() : "TraceItemView")
+            << "::activated "
+            << (i ? i->name().ascii(): "(nil)")
+            << ", sender "
+            << sender->widget()->name() << endl;
+#endif
+
+  if (_parentView)
+      _parentView->activated(this, i);
+  else
+      if (_topLevel) _topLevel->setTraceItemDelayed(i);
+}
+
+void TraceItemView::selectedCostType(TraceItemView*, TraceCostType* t)
+{
+  if (_parentView)
+      _parentView->selectedCostType(this, t);
+  else
+      if (_topLevel) _topLevel->setCostTypeDelayed(t);
+}
+
+void TraceItemView::selectedCostType2(TraceItemView*, TraceCostType* t)
+{
+  if (_parentView)
+      _parentView->selectedCostType2(this, t);
+  else
+      if (_topLevel) _topLevel->setCostType2Delayed(t);
+}
+
+void TraceItemView::activated(TraceItemView*, Direction d)
+{
+  if (_parentView)
+      _parentView->activated(this, d);
+  else
+      if (_topLevel) _topLevel->setDirectionDelayed(d);
+}
+
+void TraceItemView::doUpdate(int)
+{
+}
+
+void TraceItemView::selected(TraceItem* i)
+{
+  if (_parentView)
+      _parentView->selected(this, i);
+
+}
+
+void TraceItemView::selected(const TracePartList& l)
+{
+  if (_parentView)
+      _parentView->selected(this, l);
+  else
+      if (_topLevel) _topLevel->activePartsChangedSlot(l);
+}
+
+void TraceItemView::activated(TraceItem* i)
+{
+#if TRACE_UPDATES
+  kdDebug() << (widget() ? widget()->name() : "TraceItemView")
+            << "::activated "
+            << (i ? i->name().ascii(): "(nil)") << endl;
+#endif
+
+  if (_parentView)
+      _parentView->activated(this, i);
+  else
+      if (_topLevel) _topLevel->setTraceItemDelayed(i);
+}
+
+void TraceItemView::selectedCostType(TraceCostType* t)
+{
+  if (_parentView)
+      _parentView->selectedCostType(this, t);
+  else
+      if (_topLevel) _topLevel->setCostTypeDelayed(t);
+}
+
+void TraceItemView::selectedCostType2(TraceCostType* t)
+{
+  if (_parentView)
+      _parentView->selectedCostType2(this, t);
+  else
+      if (_topLevel) _topLevel->setCostType2Delayed(t);
+}
+
+void TraceItemView::activated(Direction d)
+{
+  if (_parentView)
+      _parentView->activated(this, d);
+  else
+      if (_topLevel) _topLevel->setDirectionDelayed(d);
+}
+
+void TraceItemView::addCostMenu(TQPopupMenu* p, bool withCost2)
+{
+  if (_topLevel) _topLevel->addCostMenu(p, withCost2);
+}
+
+void TraceItemView::addGoMenu(TQPopupMenu* p)
+{
+  if (_topLevel) _topLevel->addGoMenu(p);
+}
diff --git a/kdecachegrind/kdecachegrind/traceitemview.h b/kdecachegrind/kdecachegrind/traceitemview.h
new file mode 100644
index 0000000..f83aa89
--- /dev/null
+++ b/kdecachegrind/kdecachegrind/traceitemview.h
@@ -0,0 +1,206 @@
+/* This file is part of KCachegrind.
+   Copyright (C) 2003 Josef Weidendorfer <Josef.Weidendorfer@gmx.de>
+
+   KCachegrind 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, version 2.
+
+   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; see the file COPYING.  If not, write to
+   the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+   Boston, MA 02110-1301, USA.
+*/
+
+/*
+ * Trace Item View
+ */
+
+#ifndef TRACEITEMVIEW_H
+#define TRACEITEMVIEW_H
+
+#include "tracedata.h"
+
+class TQWidget;
+class TQPopupMenu;
+
+class KConfig;
+class KConfigGroup;
+class KConfigBase;
+
+class TopLevel;
+
+/**
+ * Abstract Base Class for KCachegrind Views
+ *
+ * This class delivers the shared functionality of all KCachegrind
+ * Views for one TraceItem (like Function, Object...), the "active"
+ * item. Additional view attributes are current primary cost type,
+ * an optional secondary cost type, group type,
+ * and possibly a selected costitem in this view.
+ * Note that there is a difference in changing the selected item of
+ * a view (this usually changes selection in other views, too), and
+ * activating that item.
+ */
+class TraceItemView
+{
+public:
+
+  /**
+   * Change type for update functions
+   * - <dataChanged> is used if e.g. cycles are recalculated
+   */
+  enum { nothingChanged      = 0,
+	 costTypeChanged     = 1,
+	 costType2Changed    = 2,
+	 groupTypeChanged    = 4,
+	 partsChanged        = 8,
+	 activeItemChanged   = 16,
+	 selectedItemChanged = 32,
+	 dataChanged         = 64,
+	 configChanged       = 128 };
+
+  enum Direction { None, Back, Forward, Up };
+
+  // a TraceItemView can have a position in a parent container
+  enum Position { Hidden, Top, Right, Left, Bottom };
+
+  TraceItemView(TraceItemView* parentView, TopLevel* top = 0);
+  virtual ~TraceItemView() {}
+
+  virtual TQString whatsThis() const;
+
+  static KConfigGroup* configGroup(KConfig*, TQString prefix, TQString postfix);
+  static void writeConfigEntry(KConfigBase*, const char* pKey, TQString value,
+                               const char* def, bool bNLS = false);
+  static void writeConfigEntry(KConfigBase*, const char* pKey,
+                               int value, int def);
+  static void writeConfigEntry(KConfigBase*, const char* pKey,
+                               bool value, bool def);
+  static void writeConfigEntry(KConfigBase*, const char* pKey,
+                               double value, double def);
+  virtual void readViewConfig(KConfig*, TQString prefix, TQString postfix,
+			      bool withOptions);
+  virtual void saveViewConfig(KConfig*, TQString prefix, TQString postfix,
+			      bool withOptions);
+
+  // Immediate remove all references to old data, and set the new.
+  // This resets the visualization state.
+  // A GUI update has to be triggered with updateView().
+  // Overwrite in container views to also set new data for all members.
+  virtual void setData(TraceData* d);
+
+  // change from parent, call updateView() to update lazily (only if visible)
+  void setCostType(TraceCostType* t) { _newCostType = t; }
+  void setCostType2(TraceCostType* t) { _newCostType2 = t; }
+  void set(TraceItem::CostType g) { _newGroupType = g; }
+  void set(const TracePartList& l) { _newPartList = l; }
+  // returns false if nothing can be shown for this trace item
+  bool activate(TraceItem* i);
+  void select(TraceItem* i);
+  void notifyChange(int changeType) { _status |= changeType; }
+  // all in one
+  bool set(int, TraceData*, TraceCostType*, TraceCostType*,
+	   TraceItem::CostType, const TracePartList&,
+	   TraceItem*, TraceItem*);
+
+  // general update request, call if view is/gets visible
+  void updateView(bool force = false);
+
+  /**
+   * Notification from child views.
+   * Default implementation notifies parent
+   */
+  virtual void selected(TraceItemView* sender, TraceItem*);
+  virtual void selected(TraceItemView* sender, const TracePartList&);
+  virtual void activated(TraceItemView* sender, Direction);
+  virtual void selectedCostType(TraceItemView* sender, TraceCostType*);
+  virtual void selectedCostType2(TraceItemView* sender, TraceCostType*);
+  virtual void activated(TraceItemView* sender, TraceItem*);
+
+  // getters...
+  // always get the newest values
+  TraceData* data() const { return _newData; }
+  TraceItem* activeItem() const { return _newActiveItem; }
+  TraceItem* selectedItem() const { return _newSelectedItem; }
+  TraceCostType* costType() const { return _newCostType; }
+  TraceCostType* costType2() const { return _newCostType2; }
+  TraceItem::CostType groupType() const { return _newGroupType; }
+  const TracePartList& partList() const { return _newPartList; }
+
+  TraceFunction* activeFunction();
+  int status() const { return _status; }
+
+  // pointer to top level window to e.g. show status messages
+  void setTopLevel(TopLevel* t) { _topLevel = t; }
+  TopLevel* topLevel() const { return _topLevel; }
+
+  void setPosition(Position p) { _pos = p; }
+  Position position() const { return _pos; }
+
+  void setTitle(TQString t) { _title = t; }
+  TQString title() const { return _title; }
+
+  // We depend on derived class to be a widget.
+  // Force overiding by making this abstract.
+  virtual TQWidget* widget() = 0;
+
+  /**
+   * This function is called when a new item should become active.
+   * Reimplement this in subclasses.
+   *
+   * Returns the real item to become active. You can call select() here.
+   * Return 0 if nothing can be shown.
+   * Use the methods like data() instead of _data here, as
+   * _data possibly will give old/wrong information.
+   */
+  virtual TraceItem* canShow(TraceItem* i) { return i; }
+
+  /* convenience functions for often used context menu items */
+  void addCostMenu(TQPopupMenu*,bool withCost2 = true);
+  void addGoMenu(TQPopupMenu*);
+
+protected:
+  // helpers to call selected()/activated() of parentView
+  void selected(TraceItem*);
+  void selected(const TracePartList&);
+  void activated(TraceItem*);
+  void selectedCostType(TraceCostType*);
+  void selectedCostType2(TraceCostType*);
+  void activated(Direction);
+
+  /* Is this view visible?
+   * if not, doUpdate() won't be called by updateView()
+   */
+  virtual bool isViewVisible();
+
+  // update handler (to be reimplemented)
+  virtual void doUpdate(int changeType);
+
+  TraceItemView* _parentView;
+  TopLevel* _topLevel;
+
+  TraceData* _data;
+  TracePartList _partList;
+  TraceItem *_activeItem, *_selectedItem;
+  TraceCostType *_costType, *_costType2;
+  TraceItem::CostType _groupType;
+
+private:
+  TraceData* _newData;
+  TracePartList _newPartList;
+  TraceItem *_newActiveItem, *_newSelectedItem;
+  TraceCostType *_newCostType, *_newCostType2;
+  TraceItem::CostType _newGroupType;
+
+  TQString _title;
+  int _status;
+  bool _inUpdate;
+  Position _pos;
+};
+
+#endif
diff --git a/kdecachegrind/kdecachegrind/treemap.cpp b/kdecachegrind/kdecachegrind/treemap.cpp
new file mode 100644
index 0000000..0d4b8dc
--- /dev/null
+++ b/kdecachegrind/kdecachegrind/treemap.cpp
@@ -0,0 +1,3214 @@
+/* This file is part of KCachegrind.
+   Copyright (C) 2002, 2003 Josef Weidendorfer <Josef.Weidendorfer@gmx.de>
+
+   KCachegrind 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, version 2.
+
+   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; see the file COPYING.  If not, write to
+   the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+   Boston, MA 02110-1301, USA.
+*/
+
+/*
+ * A Widget for visualizing hierarchical metrics as areas.
+ * The API is similar to TQListView.
+ */
+
+#include <math.h>
+
+#include <tqpainter.h>
+#include <tqtooltip.h>
+#include <tqregexp.h>
+#include <tqstyle.h>
+#include <tqpopupmenu.h>
+
+#include <klocale.h>
+#include <kconfig.h>
+#include <kdebug.h>
+
+#include "treemap.h"
+
+
+// set this to 1 to enable debug output
+#define DEBUG_DRAWING 0
+#define MAX_FIELD 12
+
+
+//
+// StoredDrawParams
+//
+StoredDrawParams::StoredDrawParams()
+{
+  _selected = false;
+  _current = false;
+  _shaded = true;
+  _rotated = false;
+
+  _backColor = TQt::white;
+
+  // field array has size 0
+}
+
+StoredDrawParams::StoredDrawParams(TQColor c,
+                                   bool selected, bool current)
+{
+  _backColor = c;
+
+  _selected = selected;
+  _current = current;
+  _shaded = true;
+  _rotated = false;
+  _drawFrame = true;
+
+  // field array has size 0
+}
+
+TQString StoredDrawParams::text(int f) const
+{
+  if ((f<0) || (f >= (int)_field.size()))
+    return TQString();
+
+  return _field[f].text;
+}
+
+TQPixmap StoredDrawParams::pixmap(int f) const
+{
+  if ((f<0) || (f >= (int)_field.size()))
+    return TQPixmap();
+
+  return _field[f].pix;
+}
+
+DrawParams::Position StoredDrawParams::position(int f) const
+{
+  if ((f<0) || (f >= (int)_field.size()))
+    return Default;
+
+  return _field[f].pos;
+}
+
+int StoredDrawParams::maxLines(int f) const
+{
+  if ((f<0) || (f >= (int)_field.size()))
+    return 0;
+
+  return _field[f].maxLines;
+}
+
+const TQFont& StoredDrawParams::font() const
+{
+  static TQFont* f = 0;
+  if (!f) f = new TQFont(TQApplication::font());
+
+  return *f;
+}
+
+void StoredDrawParams::ensureField(int f)
+{
+  static Field* def = 0;
+  if (!def) {
+    def = new Field();
+    def->pos = Default;
+    def->maxLines = 0;
+  }
+
+  if (f<0 || f>=MAX_FIELD) return;
+
+  if ((int)_field.size() < f+1) _field.resize(f+1, *def);
+}
+
+
+void StoredDrawParams::setField(int f, const TQString& t, TQPixmap pm,
+                           Position p, int maxLines)
+{
+  if (f<0 || f>=MAX_FIELD) return;
+  ensureField(f);
+
+  _field[f].text = t;
+  _field[f].pix  = pm;
+  _field[f].pos  = p;
+  _field[f].maxLines = maxLines;
+}
+
+void StoredDrawParams::setText(int f, const TQString& t)
+{
+  if (f<0 || f>=MAX_FIELD) return;
+  ensureField(f);
+
+  _field[f].text = t;
+}
+
+void StoredDrawParams::setPixmap(int f, const TQPixmap& pm)
+{
+  if (f<0 || f>=MAX_FIELD) return;
+  ensureField(f);
+
+  _field[f].pix = pm;
+}
+
+void StoredDrawParams::setPosition(int f, Position p)
+{
+  if (f<0 || f>=MAX_FIELD) return;
+  ensureField(f);
+
+  _field[f].pos = p;
+}
+
+void StoredDrawParams::setMaxLines(int f, int m)
+{
+  if (f<0 || f>=MAX_FIELD) return;
+  ensureField(f);
+
+  _field[f].maxLines = m;
+}
+
+
+
+//
+// RectDrawing
+//
+
+RectDrawing::RectDrawing(TQRect r)
+{
+  _fm = 0;
+  _dp = 0;
+  setRect(r);
+}
+
+
+RectDrawing::~RectDrawing()
+{
+  delete _fm;
+  delete _dp;
+}
+
+DrawParams* RectDrawing::drawParams()
+{
+  if (!_dp)
+    _dp = new StoredDrawParams();
+
+  return _dp;
+}
+
+
+void RectDrawing::setDrawParams(DrawParams* dp)
+{
+  if (_dp) delete _dp;
+  _dp = dp;
+}
+
+void RectDrawing::setRect(TQRect r)
+{
+  _rect = r;
+
+  _usedTopLeft = 0;
+  _usedTopCenter = 0;
+  _usedTopRight = 0;
+  _usedBottomLeft = 0;
+  _usedBottomCenter = 0;
+  _usedBottomRight = 0;
+
+  _fontHeight = 0;
+}
+
+TQRect RectDrawing::remainingRect(DrawParams* dp)
+{
+  if (!dp) dp = drawParams();
+
+  if ((_usedTopLeft >0) ||
+      (_usedTopCenter >0) ||
+      (_usedTopRight >0)) {
+    if (dp->rotated())
+      _rect.setLeft(_rect.left() + _fontHeight);
+    else
+      _rect.setTop(_rect.top() + _fontHeight);
+  }
+
+  if ((_usedBottomLeft >0) ||
+      (_usedBottomCenter >0) ||
+      (_usedBottomRight >0)) {
+    if (dp->rotated())
+      _rect.setRight(_rect.right() - _fontHeight);
+    else
+      _rect.setBottom(_rect.bottom() - _fontHeight);
+  }
+  return _rect;
+}
+
+
+void RectDrawing::drawBack(TQPainter* p, DrawParams* dp)
+{
+  if (!dp) dp = drawParams();
+  if (_rect.width()<=0 || _rect.height()<=0) return;
+
+  TQRect r = _rect;
+  TQColor normal = dp->backColor();
+  if (dp->selected()) normal = normal.light();
+  bool isCurrent = dp->current();
+
+  if (dp->drawFrame() || isCurrent) {
+    // 3D raised/sunken frame effect...
+    TQColor high = normal.light();
+    TQColor low = normal.dark();
+    p->setPen( isCurrent ? low:high);
+    p->drawLine(r.left(), r.top(), r.right(), r.top());
+    p->drawLine(r.left(), r.top(), r.left(), r.bottom());
+    p->setPen( isCurrent ? high:low);
+    p->drawLine(r.right(), r.top(), r.right(), r.bottom());
+    p->drawLine(r.left(), r.bottom(), r.right(), r.bottom());
+    r.setRect(r.x()+1, r.y()+1, r.width()-2, r.height()-2);
+  }
+  if (r.width()<=0 || r.height()<=0) return;
+
+  if (dp->shaded()) {
+    // some shading
+    bool goDark = tqGray(normal.rgb())>128;
+    int rBase, gBase, bBase;
+    normal.rgb(&rBase, &gBase, &bBase);
+    p->setBrush(TQBrush::NoBrush);
+
+    // shade parameters:
+    int d = 7;
+    float factor = 0.1, forth=0.7, back1 =0.9, toBack2 = .7, back2 = 0.97;
+
+    // coefficient corrections because of rectangle size
+    int s = r.width();
+    if (s > r.height()) s = r.height();
+    if (s<100) {
+      forth -= .3  * (100-s)/100;
+      back1 -= .2  * (100-s)/100;
+      back2 -= .02 * (100-s)/100;
+    }
+
+
+    // maximal color difference
+    int rDiff = goDark ? -rBase/d : (255-rBase)/d;
+    int gDiff = goDark ? -gBase/d : (255-gBase)/d;
+    int bDiff = goDark ? -bBase/d : (255-bBase)/d;
+
+    TQColor shadeColor;
+    while (factor<.95) {
+      shadeColor.setRgb((int)(rBase+factor*rDiff+.5),
+                        (int)(gBase+factor*gDiff+.5),
+                        (int)(bBase+factor*bDiff+.5));
+      p->setPen(shadeColor);
+      p->drawRect(r);
+      r.setRect(r.x()+1, r.y()+1, r.width()-2, r.height()-2);
+      if (r.width()<=0 || r.height()<=0) return;
+      factor = 1.0 - ((1.0 - factor) * forth);
+    }
+
+    // and back (1st half)
+    while (factor>toBack2) {
+      shadeColor.setRgb((int)(rBase+factor*rDiff+.5),
+                        (int)(gBase+factor*gDiff+.5),
+                        (int)(bBase+factor*bDiff+.5));
+      p->setPen(shadeColor);
+      p->drawRect(r);
+      r.setRect(r.x()+1, r.y()+1, r.width()-2, r.height()-2);
+      if (r.width()<=0 || r.height()<=0) return;
+      factor = 1.0 - ((1.0 - factor) / back1);
+    }
+
+    // and back (2nd half)
+    while ( factor>.01) {
+      shadeColor.setRgb((int)(rBase+factor*rDiff+.5),
+                        (int)(gBase+factor*gDiff+.5),
+                        (int)(bBase+factor*bDiff+.5));
+      p->setPen(shadeColor);
+      p->drawRect(r);
+      r.setRect(r.x()+1, r.y()+1, r.width()-2, r.height()-2);
+      if (r.width()<=0 || r.height()<=0) return;
+
+      factor = factor * back2;
+    }
+  }
+
+  // fill inside
+  p->setPen(TQPen::NoPen);
+  p->setBrush(normal);
+  p->drawRect(r);
+}
+
+
+bool RectDrawing::drawField(TQPainter* p, int f, DrawParams* dp)
+{
+  if (!dp) dp = drawParams();
+
+  if (!_fm) {
+    _fm = new TQFontMetrics(dp->font());
+    _fontHeight = _fm->height();
+  }
+
+  TQRect r = _rect;
+
+  if (0) kdDebug(90100) << "DrawField: Rect " << r.x() << "/" << r.y()
+		   << " - " << r.width() << "x" << r.height() << endl;
+
+  int h = _fontHeight;
+  bool rotate = dp->rotated();
+  int width   = (rotate ? r.height() : r.width()) -4;
+  int height  = (rotate ? r.width() : r.height());
+  int lines   = height / h;
+
+  // stop if we have no space available
+  if (lines<1) return false;
+
+  // calculate free space in first line (<unused>)
+  int pos = dp->position(f);
+  if (pos == DrawParams::Default) {
+    switch(f%4) {
+    case 0: pos = DrawParams::TopLeft; break;
+    case 1: pos = DrawParams::TopRight; break;
+    case 2: pos = DrawParams::BottomRight; break;
+    case 3: pos = DrawParams::BottomLeft; break;
+    }
+  }
+
+  int unused = 0;
+  bool isBottom = false;
+  bool isCenter = false;
+  bool isRight = false;
+  int* used = 0;
+  switch(pos) {
+  case DrawParams::TopLeft:
+    used = &_usedTopLeft;
+    if (_usedTopLeft == 0) {
+      if (_usedTopCenter)
+        unused = (width - _usedTopCenter)/2;
+      else
+        unused = width - _usedTopRight;
+    }
+    break;
+
+  case DrawParams::TopCenter:
+    isCenter = true;
+    used = &_usedTopCenter;
+    if (_usedTopCenter == 0) {
+      if (_usedTopLeft > _usedTopRight)
+        unused = width - 2 * _usedTopLeft;
+      else
+        unused = width - 2 * _usedTopRight;
+    }
+    break;
+
+  case DrawParams::TopRight:
+    isRight = true;
+    used = &_usedTopRight;
+    if (_usedTopRight == 0) {
+      if (_usedTopCenter)
+        unused = (width - _usedTopCenter)/2;
+      else
+        unused = width - _usedTopLeft;
+    }
+    break;
+
+  case DrawParams::BottomLeft:
+    isBottom = true;
+    used = &_usedBottomLeft;
+    if (_usedBottomLeft == 0) {
+      if (_usedBottomCenter)
+        unused = (width - _usedBottomCenter)/2;
+      else
+        unused = width - _usedBottomRight;
+    }
+    break;
+
+  case DrawParams::BottomCenter:
+    isCenter = true;
+    isBottom = true;
+    used = &_usedBottomCenter;
+    if (_usedBottomCenter == 0) {
+      if (_usedBottomLeft > _usedBottomRight)
+        unused = width - 2 * _usedBottomLeft;
+      else
+        unused = width - 2 * _usedBottomRight;
+    }
+    break;
+
+  case DrawParams::BottomRight:
+    isRight = true;
+    isBottom = true;
+    used = &_usedBottomRight;
+    if (_usedBottomRight == 0) {
+      if (_usedBottomCenter)
+        unused = (width - _usedBottomCenter)/2;
+      else
+        unused = width - _usedBottomLeft;
+    }
+    break;
+  }
+
+  if (isBottom) {
+    if ((_usedTopLeft >0) ||
+        (_usedTopCenter >0) ||
+        (_usedTopRight >0))
+      lines--;
+  }
+  else if (!isBottom) {
+    if ((_usedBottomLeft >0) ||
+        (_usedBottomCenter >0) ||
+        (_usedBottomRight >0))
+      lines--;
+  }
+  if (lines<1) return false;
+
+
+  int y = isBottom ? height - h : 0;
+
+  if (unused < 0) unused = 0;
+  if (unused == 0) {
+    // no space available in last line at this position
+    y = isBottom ? (y-h) : (y+h);
+    lines--;
+
+    if (lines<1) return false;
+
+    // new line: reset used space
+    if (isBottom)
+      _usedBottomLeft = _usedBottomCenter = _usedBottomRight = 0;
+    else
+      _usedTopLeft = _usedTopCenter = _usedTopRight = 0;
+
+    unused = width;
+  }
+
+  // stop as soon as possible when there's no space for "..."
+  static int dotW = 0;
+  if (!dotW) dotW = _fm->width("...");
+  if (width < dotW) return false;
+
+  // get text and pixmap now, only if we need to, because it is possible
+  // that they are calculated on demand (and this can take some time)
+  TQString name = dp->text(f);
+  if (name.isEmpty()) return 0;
+  TQPixmap pix = dp->pixmap(f);
+
+  // check if pixmap can be drawn
+  int pixW = pix.width();
+  int pixH = pix.height();
+  int pixY = 0;
+  bool pixDrawn = true;
+  if (pixW>0) {
+    pixW += 2; // X distance from pix
+    if ((width < pixW + dotW) || (height < pixH)) {
+      // don't draw
+      pixW = 0;
+    }
+    else
+      pixDrawn = false;
+  }
+
+  // width of text and pixmap to be drawn
+  int w = pixW + _fm->width(name);
+
+  if (0) kdDebug(90100) << "  For '" << name << "': Unused " << unused
+		   << ", StrW " << w << ", Width " << width << endl;
+
+  // if we have limited space at 1st line:
+  // use it only if whole name does fit in last line...
+  if ((unused < width) && (w > unused)) {
+    y = isBottom ? (y-h) : (y+h);
+    lines--;
+
+    if (lines<1) return false;
+
+    // new line: reset used space
+    if (isBottom)
+      _usedBottomLeft = _usedBottomCenter = _usedBottomRight = 0;
+    else
+      _usedTopLeft = _usedTopCenter = _usedTopRight = 0;
+  }
+
+  p->save();
+  p->setPen( (tqGray(dp->backColor().rgb())>100) ? TQt::black : TQt::white);
+  p->setFont(dp->font());
+  if (rotate) {
+    //p->translate(r.x()+2, r.y()+r.height());
+    p->translate(r.x(), r.y()+r.height()-2);
+    p->rotate(270);
+  }
+  else
+    p->translate(r.x()+2, r.y());
+
+
+  // adjust available lines according to maxLines
+  int max = dp->maxLines(f);
+  if ((max > 0) && (lines>max)) lines = max;
+
+  /* loop over name parts to break up string depending on available width.
+   * every char category change is supposed a possible break,
+   * with the exception Uppercase=>Lowercase.
+   * It's good enough for numbers, Symbols...
+   *
+   * If the text is to be written at the bottom, we start with the
+   * end of the string (so everything is reverted)
+   */
+  TQString remaining;
+  int origLines = lines;
+  while (lines>0) {
+
+    if (w>width && lines>1) {
+      int lastBreakPos = name.length(), lastWidth = w;
+      int len = name.length();
+      TQChar::Category caOld, ca;
+
+      if (!isBottom) {
+        // start with comparing categories of last 2 chars
+        caOld = name[len-1].category();
+        while (len>2) {
+          len--;
+          ca = name[len-1].category();
+          if (ca != caOld) {
+            // "Aa" has no break between...
+            if (ca == TQChar::Letter_Uppercase &&
+                caOld == TQChar::Letter_Lowercase) {
+              caOld = ca;
+              continue;
+            }
+            caOld = ca;
+            lastBreakPos = len;
+            w = pixW + _fm->width(name, len);
+            lastWidth = w;
+            if (w <= width) break;
+          }
+        }
+        w = lastWidth;
+        remaining = name.mid(lastBreakPos);
+        // remove space on break point
+        if (name[lastBreakPos-1].category() == TQChar::Separator_Space)
+          name = name.left(lastBreakPos-1);
+        else
+          name = name.left(lastBreakPos);
+      }
+      else { // bottom
+        int l = len;
+        caOld = name[l-len].category();
+        while (len>2) {
+          len--;
+          ca = name[l-len].category();
+
+          if (ca != caOld) {
+            // "Aa" has no break between...
+            if (caOld == TQChar::Letter_Uppercase &&
+                ca == TQChar::Letter_Lowercase) {
+              caOld = ca;
+              continue;
+            }
+            caOld = ca;
+            lastBreakPos = len;
+            w = pixW + _fm->width(name.right(len));
+            lastWidth = w;
+            if (w <= width) break;
+          }
+        }
+        w = lastWidth;
+        remaining = name.left(l-lastBreakPos);
+        // remove space on break point
+        if (name[l-lastBreakPos].category() == TQChar::Separator_Space)
+          name = name.right(lastBreakPos-1);
+        else
+          name = name.right(lastBreakPos);
+      }
+    }
+    else
+      remaining = TQString();
+
+    /* truncate and add ... if needed */
+    if (w>width) {
+      int len = name.length();
+      w += dotW;
+      while (len>2 && (w > width)) {
+        len--;
+        w = pixW + _fm->width(name, len) + dotW;
+      }
+      // stop drawing: we cannot draw 2 chars + "..."
+      if (w>width) break;
+
+      name = name.left(len) + "...";
+    }
+
+    int x = 0;
+    if (isCenter)
+      x = (width - w)/2;
+    else if (isRight)
+      x = width - w;
+
+    if (!pixDrawn) {
+        pixY = y+(h-pixH)/2; // default: center vertically
+        if (pixH > h) pixY = isBottom ? y-(pixH-h) : y;
+
+	p->drawPixmap( x, pixY, pix);
+
+        // for distance to next text
+	pixY = isBottom ? (pixY - h - 2) : (pixY + pixH + 2);
+	pixDrawn = true;
+    }
+
+
+    if (0) kdDebug(90100) << "  Drawing '" << name << "' at " 
+		     << x+pixW << "/" << y << endl;
+
+    p->drawText( x+pixW, y,
+		 width - pixW, h,
+		 TQt::AlignLeft, name);
+    y = isBottom ? (y-h) : (y+h);
+    lines--;
+
+    if (remaining.isEmpty()) break;
+    name = remaining;
+    w = pixW + _fm->width(name);
+  }
+
+  // make sure the pix stays visible
+  if (pixDrawn && (pixY>0)) {
+    if (isBottom && (pixY<y)) y = pixY;
+    if (!isBottom && (pixY>y)) y = pixY;
+  }
+
+  if (origLines > lines) {
+    // if only 1 line written, don't reset _used* vars
+    if (lines - origLines >1) {
+      if (isBottom)
+        _usedBottomLeft = _usedBottomCenter = _usedBottomRight = 0;
+      else
+        _usedTopLeft = _usedTopCenter = _usedTopRight = 0;
+    }
+
+    // take back one line
+    y = isBottom ? (y+h) : (y-h);
+    if (used) *used = w;
+  }
+
+  // update free space
+  if (!isBottom) {
+    if (rotate)
+      _rect.setRect(r.x()+y, r.y(), r.width()-y, r.height());
+    else
+      _rect.setRect(r.x(), r.y()+y, r.width(), r.height()-y);
+  }
+  else {
+    if (rotate)
+      _rect.setRect(r.x(), r.y(), y+h, r.height());
+    else
+      _rect.setRect(r.x(), r.y(), r.width(), y+h);
+  }
+
+  p->restore();
+
+  return true;
+}
+
+
+
+
+
+
+//
+// TreeMapItemList
+//
+
+int TreeMapItemList::compareItems ( Item item1, Item item2 )
+{
+  bool ascending;
+  int result;
+
+  TreeMapItem* parent = ((TreeMapItem*)item1)->parent();
+  // shouldn't happen
+  if (!parent) return 0;
+
+  int textNo = parent->sorting(&ascending);
+
+  if (textNo < 0) {
+    double diff = ((TreeMapItem*)item1)->value() -
+                  ((TreeMapItem*)item2)->value();
+    result = (diff < -.9) ? -1 : (diff > .9) ? 1 : 0;
+  }
+  else
+    result = (((TreeMapItem*)item1)->text(textNo) <
+	      ((TreeMapItem*)item2)->text(textNo)) ? -1 : 1;
+
+  return ascending ? result : -result;
+}
+
+
+TreeMapItem* TreeMapItemList::commonParent()
+{
+  TreeMapItem* parent, *item;
+  parent = first();
+  if (parent)
+    while( (item = next()) != 0)
+      parent = parent->commonParent(item);
+
+  return parent;
+}
+
+
+// TreeMapItem
+
+TreeMapItem::TreeMapItem(TreeMapItem* parent, double value)
+{
+  _value = value;
+  _parent = parent;
+
+  _sum = 0;
+  _children = 0;
+  _widget = 0;
+  _index = -1;
+  _depth = -1; // not set
+  _unused_self = 0;
+  _freeRects = 0;
+
+  if (_parent) {
+    // take sorting from parent
+    _sortTextNo = _parent->sorting(&_sortAscending);
+    _parent->addItem(this);
+  }
+  else {
+    _sortAscending = false;
+    _sortTextNo = -1; // default: no sorting
+  }
+}
+
+
+TreeMapItem::TreeMapItem(TreeMapItem* parent, double value,
+                         TQString text1, TQString text2,
+                         TQString text3, TQString text4)
+{
+  _value = value;
+  _parent = parent;
+
+  // this resizes the text vector only if needed
+  if (!text4.isEmpty()) setText(3, text4);
+  if (!text3.isEmpty()) setText(2, text3);
+  if (!text2.isEmpty()) setText(1, text2);
+  setText(0, text1);
+
+  _sum = 0;
+  _children = 0;
+  _widget = 0;
+  _index = -1;
+  _depth = -1; // not set
+  _unused_self = 0;
+  _freeRects = 0;
+
+  if (_parent) _parent->addItem(this);
+}
+
+TreeMapItem::~TreeMapItem()
+{
+  if (_children) delete _children;
+  if (_freeRects) delete _freeRects;
+
+  // finally, notify widget about deletion
+  if (_widget) _widget->deletingItem(this);
+}
+
+void TreeMapItem::setParent(TreeMapItem* p)
+{
+  _parent = p;
+  if (p) _widget = p->_widget;
+}
+
+bool TreeMapItem::isChildOf(TreeMapItem* item)
+{
+  if (!item) return false;
+
+  TreeMapItem* i = this;
+  while (i) {
+    if (item == i) return true;
+    i = i->_parent;
+  }
+  return false;
+}
+
+TreeMapItem* TreeMapItem::commonParent(TreeMapItem* item)
+{
+  while (item && !isChildOf(item)) {
+    item = item->parent();
+  }
+  return item;
+}
+
+void TreeMapItem::redraw()
+{
+  if (_widget)
+    _widget->redraw(this);
+}
+
+void TreeMapItem::clear()
+{
+  if (_children) {
+    // delete selected items below this item from selection
+    if (_widget) _widget->clearSelection(this);
+
+    delete _children;
+    _children = 0;
+  }
+}
+
+
+// invalidates current children and forces redraw
+// this is only usefull when children are created on demand in items()
+void TreeMapItem::refresh()
+{
+  clear();
+  redraw();
+}
+
+
+TQStringList TreeMapItem::path(int textNo) const
+{
+  TQStringList list(text(textNo));
+
+  TreeMapItem* i = _parent;
+  while (i) {
+    TQString text = i->text(textNo);
+    if (!text.isEmpty())
+        list.prepend(i->text(textNo));
+    i = i->_parent;
+  }
+  return list;
+}
+
+int TreeMapItem::depth() const
+{
+  if (_depth>0) return _depth;
+
+  if (_parent)
+    return _parent->depth() + 1;
+  return 1;
+}
+
+
+bool TreeMapItem::initialized()
+{
+  if (!_children) {
+    _children = new TreeMapItemList;
+    _children->setAutoDelete(true);
+    return false;
+  }
+  return true;
+}
+
+void TreeMapItem::addItem(TreeMapItem* i)
+{
+  if (!i) return;
+
+  if (!_children) {
+    _children = new TreeMapItemList;
+    _children->setAutoDelete(true);
+  }
+  i->setParent(this);
+
+  if (sorting(0) == -1)
+    _children->append(i); // preserve insertion order
+  else
+    _children->inSort(i);
+}
+
+
+// default implementations of virtual functions
+
+double TreeMapItem::value() const
+{
+  return _value;
+}
+
+double TreeMapItem::sum() const
+{
+  return _sum;
+}
+
+DrawParams::Position TreeMapItem::position(int f) const
+{
+  Position p = StoredDrawParams::position(f);
+  if (_widget && (p == Default))
+    p = _widget->fieldPosition(f);
+
+  return p;
+}
+
+// use widget font
+const TQFont& TreeMapItem::font() const
+{
+  return _widget->currentFont();
+}
+
+
+bool TreeMapItem::isMarked(int) const
+{
+    return false;
+}
+
+
+int TreeMapItem::borderWidth() const
+{
+  if (_widget)
+    return _widget->borderWidth();
+
+  return 2;
+}
+
+int TreeMapItem::sorting(bool* ascending) const
+{
+  if (ascending) *ascending = _sortAscending;
+  return _sortTextNo;
+}
+
+// do *not* set sorting recursively
+void TreeMapItem::setSorting(int textNo, bool ascending)
+{
+    if (_sortTextNo == textNo) {
+	if(_sortAscending == ascending) return;
+	if (textNo == -1) {
+	    // when no sorting is done, order change doesn't do anything
+	    _sortAscending = ascending;
+	    return;
+	}
+    }
+    _sortAscending = ascending;
+    _sortTextNo = textNo;
+
+    if (_children && _sortTextNo != -1) _children->sort();
+}
+
+void TreeMapItem::resort(bool recursive)
+{
+  if (!_children) return;
+
+  if (_sortTextNo != -1) _children->sort();
+
+  if (recursive)
+    for (TreeMapItem* i=_children->first(); i; i=_children->next())
+      i->resort(recursive);
+}
+
+
+TreeMapItem::SplitMode TreeMapItem::splitMode() const
+{
+  if (_widget)
+    return _widget->splitMode();
+
+  return Best;
+}
+
+int TreeMapItem::rtti() const
+{
+  return 0;
+}
+
+TreeMapItemList* TreeMapItem::children()
+{
+  if (!_children) {
+    _children = new TreeMapItemList;
+    _children->setAutoDelete(true);
+  }
+  return _children;
+}
+
+void TreeMapItem::clearItemRect()
+{
+    _rect = TQRect();
+    clearFreeRects();
+}
+
+void TreeMapItem::clearFreeRects()
+{
+    if (_freeRects) _freeRects->clear();
+}
+
+void TreeMapItem::addFreeRect(const TQRect& r)
+{
+    // don't add invalid rects
+    if ((r.width() < 1) || (r.height() < 1)) return;
+
+    if (!_freeRects) {
+	_freeRects = new TQPtrList<TQRect>;
+	_freeRects->setAutoDelete(true);
+    }
+
+    if (0) kdDebug(90100) << "addFree(" << path(0).join("/") << ", "
+		     << r.x() << "/" << r.y() << "-"
+		     << r.width() << "x" << r.height() << ")" << endl;
+
+    TQRect* last = _freeRects->last();
+    if (!last) {
+	_freeRects->append(new TQRect(r));
+	return;
+    }
+
+    // join rect with last rect if possible
+    // this saves memory and doesn't make the tooltip flicker
+
+    bool replaced = false;
+    if ((last->left() == r.left()) && (last->width() == r.width())) {
+	if ((last->bottom()+1 == r.top()) || (r.bottom()+1 == last->top())) {
+	    *last |= r;
+	    replaced = true;
+	}
+    }
+    else if ((last->top() == r.top()) && (last->height() == r.height())) {
+	if ((last->right()+1 == r.left()) || (r.right()+1 == last->left())) {
+	    *last |= r;
+	    replaced = true;
+	}
+    }
+
+    if (!replaced) {
+	_freeRects->append(new TQRect(r));
+	return;
+    }
+
+    if (0) kdDebug(90100) << "  united with last to (" 
+		     << last->x() << "/" << last->y() << "-"
+		     << last->width() << "x" << last->height() << ")" << endl;
+}
+
+
+// Tooltips for TreeMapWidget
+
+class TreeMapTip: public TQToolTip
+{
+public:
+  TreeMapTip( TQWidget* p ):TQToolTip(p) {}
+
+protected:
+    void maybeTip( const TQPoint & );
+};
+
+void TreeMapTip::maybeTip( const TQPoint& pos )
+{
+  if ( !parentWidget()->inherits( "TreeMapWidget" ) )
+        return;
+
+  TreeMapWidget* p = (TreeMapWidget*)parentWidget();
+  TreeMapItem* i;
+  i = p->item(pos.x(), pos.y());
+  TQPtrList<TQRect>* rList = i ? i->freeRects() : 0;
+  if (rList) {
+      TQRect* r;
+      for(r=rList->first();r;r=rList->next())
+	  if (r->contains(pos))
+	      tip(*r, p->tipString(i));
+  }
+}
+
+
+
+// TreeMapWidget
+
+TreeMapWidget::TreeMapWidget(TreeMapItem* base,
+			     TQWidget* parent, const char* name)
+    : TQWidget(parent, name)
+{
+    _base = base;
+    _base->setWidget(this);
+
+    _font = font();
+    _fontHeight = fontMetrics().height();
+
+
+  // default behaviour
+  _selectionMode = Single;
+  _splitMode = TreeMapItem::AlwaysBest;
+  _visibleWidth = 2;
+  _reuseSpace = false;
+  _skipIncorrectBorder = false;
+  _drawSeparators = false;
+  _allowRotation = true;
+  _borderWidth = 2;
+  _shading = true; // beautiful is default!
+  _maxSelectDepth = -1; // unlimited
+  _maxDrawingDepth = -1; // unlimited
+  _minimalArea = -1; // unlimited
+  _markNo = 0;
+
+  for(int i=0;i<4;i++) {
+    _drawFrame[i] = true;
+    _transparent[i] = false;
+  }
+
+  // _stopAtText will be unset on resizing (per default)
+  // _textVisible will be true on resizing (per default)
+  // _forceText will be false on resizing (per default)
+
+  // start state: _selection is an empty list
+  _current = 0;
+  _oldCurrent = 0;
+  _pressed = 0;
+  _lastOver = 0;
+  _needsRefresh = _base;
+
+  setBackgroundMode(TQt::NoBackground);
+  setFocusPolicy(TQ_StrongFocus);
+  _tip = new TreeMapTip(this);
+}
+
+TreeMapWidget::~TreeMapWidget()
+{
+  delete _base;
+  delete _tip;
+}
+
+const TQFont& TreeMapWidget::currentFont() const
+{
+  return _font;
+}
+
+void TreeMapWidget::setSplitMode(TreeMapItem::SplitMode m)
+{
+  if (_splitMode == m) return;
+
+  _splitMode = m;
+  redraw();
+}
+
+TreeMapItem::SplitMode TreeMapWidget::splitMode() const
+{
+  return _splitMode;
+}
+
+bool TreeMapWidget::setSplitMode(TQString mode)
+{
+  if (mode == "Bisection") setSplitMode(TreeMapItem::Bisection);
+  else if (mode == "Columns") setSplitMode(TreeMapItem::Columns);
+  else if (mode == "Rows") setSplitMode(TreeMapItem::Rows);
+  else if (mode == "AlwaysBest") setSplitMode(TreeMapItem::AlwaysBest);
+  else if (mode == "Best")       setSplitMode(TreeMapItem::Best);
+  else if (mode == "HAlternate") setSplitMode(TreeMapItem::HAlternate);
+  else if (mode == "VAlternate") setSplitMode(TreeMapItem::VAlternate);
+  else if (mode == "Horizontal") setSplitMode(TreeMapItem::Horizontal);
+  else if (mode == "Vertical")   setSplitMode(TreeMapItem::Vertical);
+  else return false;
+
+  return true;
+}
+
+TQString TreeMapWidget::splitModeString() const
+{
+  TQString mode;
+  switch(splitMode()) {
+    case TreeMapItem::Bisection:  mode = "Bisection"; break;
+    case TreeMapItem::Columns:    mode = "Columns"; break;
+    case TreeMapItem::Rows:       mode = "Rows"; break;
+    case TreeMapItem::AlwaysBest: mode = "AlwaysBest"; break;
+    case TreeMapItem::Best:       mode = "Best"; break;
+    case TreeMapItem::HAlternate: mode = "HAlternate"; break;
+    case TreeMapItem::VAlternate: mode = "VAlternate"; break;
+    case TreeMapItem::Horizontal: mode = "Horizontal"; break;
+    case TreeMapItem::Vertical:   mode = "Vertical"; break;
+    default: mode = "Unknown"; break;
+  }
+  return mode;
+}
+
+
+void TreeMapWidget::setShadingEnabled(bool s)
+{
+  if (_shading == s) return;
+
+  _shading = s;
+  redraw();
+}
+
+void TreeMapWidget::drawFrame(int d, bool b)
+{
+  if ((d<0) || (d>=4) || (_drawFrame[d]==b)) return;
+
+  _drawFrame[d] = b;
+  redraw();
+}
+
+void TreeMapWidget::setTransparent(int d, bool b)
+{
+  if ((d<0) || (d>=4) || (_transparent[d]==b)) return;
+
+  _transparent[d] = b;
+  redraw();
+}
+
+void TreeMapWidget::setAllowRotation(bool enable)
+{
+  if (_allowRotation == enable) return;
+
+  _allowRotation = enable;
+  redraw();
+}
+
+void TreeMapWidget::setVisibleWidth(int width, bool reuseSpace)
+{
+  if (_visibleWidth == width && _reuseSpace == reuseSpace) return;
+
+  _visibleWidth = width;
+  _reuseSpace = reuseSpace;
+  redraw();
+}
+
+void TreeMapWidget::setSkipIncorrectBorder(bool enable)
+{
+  if (_skipIncorrectBorder == enable) return;
+
+  _skipIncorrectBorder = enable;
+  redraw();
+}
+
+void TreeMapWidget::setBorderWidth(int w)
+{
+  if (_borderWidth == w) return;
+
+  _borderWidth = w;
+  redraw();
+}
+
+void TreeMapWidget::setMaxDrawingDepth(int d)
+{
+  if (_maxDrawingDepth == d) return;
+
+  _maxDrawingDepth = d;
+  redraw();
+}
+
+TQString TreeMapWidget::defaultFieldType(int f) const
+{
+  return i18n("Text %1").arg(f+1);
+}
+
+TQString TreeMapWidget::defaultFieldStop(int) const
+{
+  return TQString();
+}
+
+bool TreeMapWidget::defaultFieldVisible(int f) const
+{
+  return (f<2);
+}
+
+bool TreeMapWidget::defaultFieldForced(int) const
+{
+  return false;
+}
+
+DrawParams::Position TreeMapWidget::defaultFieldPosition(int f) const
+{
+  switch(f%4) {
+  case 0: return DrawParams::TopLeft;
+  case 1: return DrawParams::TopRight;
+  case 2: return DrawParams::BottomRight;
+  case 3: return DrawParams::BottomLeft;
+  default:break;
+  }
+  return DrawParams::TopLeft;
+}
+
+bool TreeMapWidget::resizeAttr(int size)
+{
+  if (size<0 || size>=MAX_FIELD) return false;
+
+  if (size>(int)_attr.size()) {
+    struct FieldAttr a;
+    int oldSize = _attr.size();
+    _attr.resize(size, a);
+    while (oldSize<size) {
+      _attr[oldSize].type    = defaultFieldType(oldSize);
+      _attr[oldSize].stop    = defaultFieldStop(oldSize);
+      _attr[oldSize].visible = defaultFieldVisible(oldSize);
+      _attr[oldSize].forced  = defaultFieldForced(oldSize);
+      _attr[oldSize].pos     = defaultFieldPosition(oldSize);
+      oldSize++;
+    }
+  }
+  return true;
+}
+
+void TreeMapWidget::setFieldType(int f, TQString type)
+{
+  if (((int)_attr.size() < f+1) &&
+      (type == defaultFieldType(f))) return;
+  if (resizeAttr(f+1)) _attr[f].type = type;
+
+  // no need to redraw: the type string is not visible in the TreeMap
+}
+
+TQString TreeMapWidget::fieldType(int f) const
+{
+  if (f<0 || (int)_attr.size()<f+1) return defaultFieldType(f);
+  return _attr[f].type;
+}
+
+void TreeMapWidget::setFieldStop(int f, TQString stop)
+{
+  if (((int)_attr.size() < f+1) &&
+      (stop == defaultFieldStop(f))) return;
+  if (resizeAttr(f+1)) {
+    _attr[f].stop = stop;
+    redraw();
+  }
+}
+
+TQString TreeMapWidget::fieldStop(int f) const
+{
+  if (f<0 || (int)_attr.size()<f+1) return defaultFieldStop(f);
+  return _attr[f].stop;
+}
+
+void TreeMapWidget::setFieldVisible(int f, bool enable)
+{
+  if (((int)_attr.size() < f+1) &&
+      (enable == defaultFieldVisible(f))) return;
+
+  if (resizeAttr(f+1)) {
+    _attr[f].visible = enable;
+    redraw();
+  }
+}
+
+bool TreeMapWidget::fieldVisible(int f) const
+{
+  if (f<0 || (int)_attr.size()<f+1)
+    return defaultFieldVisible(f);
+
+  return _attr[f].visible;
+}
+
+void TreeMapWidget::setFieldForced(int f, bool enable)
+{
+  if (((int)_attr.size() < f+1) &&
+      (enable == defaultFieldForced(f))) return;
+
+  if (resizeAttr(f+1)) {
+    _attr[f].forced = enable;
+    if (_attr[f].visible) redraw();
+  }
+}
+
+bool TreeMapWidget::fieldForced(int f) const
+{
+  if (f<0 || (int)_attr.size()<f+1)
+    return defaultFieldForced(f);
+
+  return _attr[f].forced;
+}
+
+void TreeMapWidget::setFieldPosition(int f, TreeMapItem::Position pos)
+{
+  if (((int)_attr.size() < f+1) &&
+      (pos == defaultFieldPosition(f))) return;
+
+  if (resizeAttr(f+1)) {
+    _attr[f].pos = pos;
+    if (_attr[f].visible) redraw();
+  }
+}
+
+DrawParams::Position TreeMapWidget::fieldPosition(int f) const
+{
+  if (f<0 || (int)_attr.size()<f+1)
+    return defaultFieldPosition(f);
+
+  return _attr[f].pos;
+}
+
+void TreeMapWidget::setFieldPosition(int f, TQString pos)
+{
+  if (pos == "TopLeft")
+    setFieldPosition(f, DrawParams::TopLeft);
+  else if (pos == "TopCenter")
+    setFieldPosition(f, DrawParams::TopCenter);
+  else if (pos == "TopRight")
+    setFieldPosition(f, DrawParams::TopRight);
+  else if (pos == "BottomLeft")
+    setFieldPosition(f, DrawParams::BottomLeft);
+  else if (pos == "BottomCenter")
+    setFieldPosition(f, DrawParams::BottomCenter);
+  else if (pos == "BottomRight")
+    setFieldPosition(f, DrawParams::BottomRight);
+  else if (pos == "Default")
+    setFieldPosition(f, DrawParams::Default);
+}
+
+TQString TreeMapWidget::fieldPositionString(int f) const
+{
+  TreeMapItem::Position pos = fieldPosition(f);
+  if (pos == DrawParams::TopLeft) return TQString("TopLeft");
+  if (pos == DrawParams::TopCenter) return TQString("TopCenter");
+  if (pos == DrawParams::TopRight) return TQString("TopRight");
+  if (pos == DrawParams::BottomLeft) return TQString("BottomLeft");
+  if (pos == DrawParams::BottomCenter) return TQString("BottomCenter");
+  if (pos == DrawParams::BottomRight) return TQString("BottomRight");
+  if (pos == DrawParams::Default) return TQString("Default");
+  return TQString("unknown");
+}
+
+void TreeMapWidget::setMinimalArea(int area)
+{
+  if (_minimalArea == area) return;
+
+  _minimalArea = area;
+  redraw();
+}
+
+
+void TreeMapWidget::deletingItem(TreeMapItem* i)
+{
+  // remove any references to the item to be deleted
+  while(_selection.findRef(i) > -1)
+    _selection.remove();
+
+  while(_tmpSelection.findRef(i) > -1)
+    _tmpSelection.remove();
+
+  if (_current == i) _current = 0;
+  if (_oldCurrent == i) _oldCurrent = 0;
+  if (_pressed == i) _pressed = 0;
+  if (_lastOver == i) _lastOver = 0;
+
+  // don't redraw a deleted item
+  if (_needsRefresh == i) {
+    // we can savely redraw the parent, as deleting order is
+    // from child to parent; i.e. i->parent() is existing. 
+    _needsRefresh = i->parent();
+  }
+}
+
+
+TQString TreeMapWidget::tipString(TreeMapItem* i) const
+{
+  TQString tip, itemTip;
+
+  while (i) {
+    if (!i->text(0).isEmpty()) {
+      itemTip = i->text(0);
+      if (!i->text(1).isEmpty())
+        itemTip += " (" + i->text(1) + ")";
+
+      if (!tip.isEmpty())
+        tip += "\n";
+
+      tip += itemTip;
+    }
+    i = i->parent();
+  }
+  return tip;
+}
+
+TreeMapItem* TreeMapWidget::item(int x, int y) const
+{
+  TreeMapItem* p = _base;
+  TreeMapItem* i;
+
+  if (!TQT_TQRECT_OBJECT(rect()).contains(x, y)) return 0;
+  if (DEBUG_DRAWING) kdDebug(90100) << "item(" << x << "," << y << "):" << endl;
+
+  while (1) {
+    TreeMapItemList* list = p->children();
+    if (!list)
+      i = 0;
+    else {
+      int idx=0;
+      for (i=list->first();i;i=list->next(),idx++) {
+
+        if (DEBUG_DRAWING)
+	    kdDebug(90100) << "  Checking " << i->path(0).join("/") << " ("
+		      << i->itemRect().x() << "/" << i->itemRect().y()
+		      << "-" << i->itemRect().width() 
+		      << "x" << i->itemRect().height() << ")" << endl;
+
+        if (i->itemRect().contains(x, y)) {
+
+	    if (DEBUG_DRAWING) kdDebug(90100) << "  .. Got. Index " << idx << endl;
+
+	    p->setIndex(idx);
+	    break;
+        }
+      }
+    }
+
+    if (!i) {
+      static TreeMapItem* last = 0;
+      if (p != last) {
+        last = p;
+
+        if (DEBUG_DRAWING)
+	    kdDebug(90100) << "item(" << x << "," << y << "): Got " 
+		      << p->path(0).join("/") << " (Size " 
+		      << p->itemRect().width() << "x" << p->itemRect().height()
+		      << ", Val " << p->value() << ")" << endl;
+      }
+
+      return p;
+    }
+    p = i;
+  }
+  return 0;
+}
+
+TreeMapItem* TreeMapWidget::possibleSelection(TreeMapItem* i) const
+{
+  if (i) {
+    if (_maxSelectDepth>=0) {
+      int depth = i->depth();
+      while(i && depth > _maxSelectDepth) {
+        i = i->parent();
+        depth--;
+      }
+    }
+  }
+  return i;
+}
+
+TreeMapItem* TreeMapWidget::visibleItem(TreeMapItem* i) const
+{
+  if (i) {
+    /* Must have a visible area */
+    while(i && ((i->itemRect().width() <1) ||
+                (i->itemRect().height() <1))) {
+      TreeMapItem* p = i->parent();
+      if (!p) break;
+      int idx = p->children()->findRef(i);
+      idx--;
+      if (idx<0)
+        i = p;
+      else
+        i = p->children()->at(idx);
+    }
+  }
+  return i;
+}
+
+void TreeMapWidget::setSelected(TreeMapItem* item, bool selected)
+{
+    item = possibleSelection(item);
+    setCurrent(item);
+
+    TreeMapItem* changed = setTmpSelected(item, selected);
+    if (!changed) return;
+
+    _selection = _tmpSelection;
+    if (_selectionMode == Single)
+      emit selectionChanged(item);
+    emit selectionChanged();
+    redraw(changed);
+    
+    if (0) kdDebug(90100) << (selected ? "S":"Des") << "elected Item "
+		     << (item ? item->path(0).join("") : TQString("(null)"))
+		     << " (depth " << (item ? item->depth() : -1) 
+		     << ")" << endl;
+}
+
+void TreeMapWidget::setMarked(int markNo, bool redrawWidget)
+{
+    // if there's no marking, return
+    if ((_markNo == 0) && (markNo == 0)) return;
+
+    _markNo = markNo;
+    if (!clearSelection() && redrawWidget) redraw();
+}
+
+/* Returns all items which appear only in one of the given lists */
+TreeMapItemList TreeMapWidget::diff(TreeMapItemList& l1,
+				    TreeMapItemList& l2)
+{
+  TreeMapItemList l;
+  TreeMapItemListIterator it1(l1), it2(l2);
+
+  TreeMapItem* item;
+  while ( (item = it1.current()) != 0 ) {
+    ++it1;
+    if (l2.containsRef(item) > 0) continue;
+    l.append(item);
+  }
+  while ( (item = it2.current()) != 0 ) {
+    ++it2;
+    if (l1.containsRef(item) > 0) continue;
+    l.append(item);
+  }
+
+  return l;
+}
+
+/* Only modifies _tmpSelection.
+ * Returns 0 when no change happened, otherwise the TreeMapItem that has
+ * to be redrawn for all changes.
+ */
+TreeMapItem* TreeMapWidget::setTmpSelected(TreeMapItem* item, bool selected)
+{
+  if (!item) return 0;
+  if (_selectionMode == NoSelection) return 0;
+
+  TreeMapItemList old = _tmpSelection;
+
+  if (_selectionMode == Single) {
+    _tmpSelection.clear();
+    if (selected) _tmpSelection.append(item);
+  }
+  else {
+    if (selected) {
+      TreeMapItem* i=_tmpSelection.first();
+      while (i) {
+	if (i->isChildOf(item) || item->isChildOf(i)) {
+	  _tmpSelection.remove();
+	  i = _tmpSelection.current();
+	}
+	else
+	  i = _tmpSelection.next();
+      }
+      _tmpSelection.append(item);
+    }
+    else
+      _tmpSelection.removeRef(item);
+  }
+
+  return diff(old, _tmpSelection).commonParent();
+}
+
+
+bool TreeMapWidget::clearSelection(TreeMapItem* parent)
+{
+  TreeMapItemList old = _selection;
+
+  TreeMapItem* i=_selection.first();
+  while (i) {
+    if (i->isChildOf(parent)) {
+      _selection.remove();
+      i = _selection.current();
+    }
+    else
+      i = _selection.next();
+  }
+
+  TreeMapItem* changed = diff(old, _selection).commonParent();
+  if (changed) {
+    changed->redraw();
+    emit selectionChanged();
+  }
+  return (changed != 0);
+}
+
+bool TreeMapWidget::isSelected(TreeMapItem* i) const
+{
+  return _selection.containsRef(i)>0;
+}
+
+bool TreeMapWidget::isTmpSelected(TreeMapItem* i)
+{
+  return _tmpSelection.containsRef(i)>0;
+}
+
+
+void TreeMapWidget::setCurrent(TreeMapItem* i, bool kbd)
+{
+    TreeMapItem* old = _current;
+    _current = i;
+
+    if (_markNo >0) {
+	// remove mark
+	_markNo = 0;
+
+	if (1) kdDebug(90100) << "setCurrent(" << i->path(0).join("/")
+			 << ") - mark removed" << endl;
+
+	// always complete redraw needed to remove mark
+	redraw();
+
+	if (old == _current) return;
+    }
+    else {
+	if (old == _current) return;
+
+	if (old) old->redraw();
+	if (i) i->redraw();
+    }
+
+    //kdDebug(90100) << "Current Item " << (i ? i->path().ascii() : "(null)") << endl;
+
+    emit currentChanged(i, kbd);
+}
+
+void TreeMapWidget::setRangeSelection(TreeMapItem* i1,
+				      TreeMapItem* i2, bool selected)
+{
+  i1 = possibleSelection(i1);
+  i2 = possibleSelection(i2);
+  setCurrent(i2);
+
+  TreeMapItem* changed = setTmpRangeSelection(i1, i2, selected);
+  if (!changed) return;
+
+  _selection = _tmpSelection;
+  if (_selectionMode == Single)
+    emit selectionChanged(i2);
+  emit selectionChanged();
+  redraw(changed);
+}
+
+TreeMapItem* TreeMapWidget::setTmpRangeSelection(TreeMapItem* i1,
+						 TreeMapItem* i2,
+						 bool selected)
+{
+  if ((i1 == 0) && (i2 == 0)) return 0;
+  if ((i1 == 0) || i1->isChildOf(i2)) return setTmpSelected(i2, selected);
+  if ((i2 == 0) || i2->isChildOf(i1)) return setTmpSelected(i1, selected);
+
+  TreeMapItem* changed = setTmpSelected(i1, selected);
+  TreeMapItem* changed2 = setTmpSelected(i2, selected);
+  if (changed2) changed = changed2->commonParent(changed);
+
+  TreeMapItem* commonParent = i1;
+  while (commonParent && !i2->isChildOf(commonParent)) {
+    i1 = commonParent;
+    commonParent = commonParent->parent();
+  }
+  if (!commonParent) return changed;
+  while (i2 && i2->parent() != commonParent)
+    i2 = i2->parent();
+  if (!i2) return changed;
+
+  TreeMapItemList* list = commonParent->children();
+  if (!list) return changed;
+
+  TreeMapItem* i = list->first();
+  bool between = false;
+  while (i) {
+    if (between) {
+      if (i==i1 || i==i2) break;
+      changed2 = setTmpSelected(i, selected);
+      if (changed2) changed = changed2->commonParent(changed);
+    }
+    else if (i==i1 || i==i2) 
+      between = true;
+    i = list->next();
+  }
+
+  return changed;
+}
+
+void TreeMapWidget::contextMenuEvent( TQContextMenuEvent* e )
+{
+  //kdDebug(90100) << "TreeMapWidget::contextMenuEvent" << endl;
+
+  if ( receivers( TQT_SIGNAL(contextMenuRequested(TreeMapItem*, const TQPoint &)) ) )
+    e->accept();
+
+  if ( e->reason() == TQContextMenuEvent::Keyboard ) {
+    TQRect r = (_current) ? _current->itemRect() : _base->itemRect();
+    TQPoint p = TQPoint(r.left() + r.width()/2, r.top() + r.height()/2);
+    emit contextMenuRequested(_current, p);
+  }
+  else {
+    TreeMapItem* i = item(e->x(), e->y());
+    emit contextMenuRequested(i, e->pos());
+  }
+}
+
+
+void TreeMapWidget::mousePressEvent( TQMouseEvent* e )
+{
+  //kdDebug(90100) << "TreeMapWidget::mousePressEvent" << endl;
+
+  _oldCurrent = _current;
+
+  TreeMapItem* i = item(e->x(), e->y());
+
+  _pressed = i;
+
+  _inShiftDrag = e->state() & ShiftButton;
+  _inControlDrag = e->state() & ControlButton;
+  _lastOver = _pressed;
+
+  TreeMapItem* changed = 0;
+  TreeMapItem* item = possibleSelection(_pressed);
+
+  switch(_selectionMode) {
+  case Single:
+    changed = setTmpSelected(item, true);
+    break;
+  case Multi:
+    changed = setTmpSelected(item, !isTmpSelected(item));
+    break;
+  case Extended:
+    if (_inControlDrag)
+      changed = setTmpSelected(item, !isTmpSelected(item));
+    else if (_inShiftDrag) {
+      TreeMapItem* sCurrent = possibleSelection(_current);
+      changed = setTmpRangeSelection(sCurrent, item,
+                                     !isTmpSelected(item));
+    }
+    else {
+      _selectionMode = Single;
+      changed = setTmpSelected(item, true);
+      _selectionMode = Extended;
+    }
+    break;
+  default:
+    break;
+  }
+
+  // item under mouse always selected on right button press
+  if (e->button() == Qt::RightButton) {
+    TreeMapItem* changed2 = setTmpSelected(item, true);
+    if (changed2) changed = changed2->commonParent(changed);
+  }
+
+  setCurrent(_pressed);
+
+  if (changed)
+    redraw(changed);
+
+  if (e->button() == Qt::RightButton) {
+
+    // emit selection change
+    if (! (_tmpSelection == _selection)) {
+      _selection = _tmpSelection;
+      if (_selectionMode == Single)
+	emit selectionChanged(_lastOver);
+      emit selectionChanged();
+    }
+    _pressed = 0;
+    _lastOver = 0;
+    emit rightButtonPressed(i, e->pos());
+  }
+}
+
+void TreeMapWidget::mouseMoveEvent( TQMouseEvent* e )
+{
+  //kdDebug(90100) << "TreeMapWidget::mouseMoveEvent" << endl;
+
+  if (!_pressed) return;
+  TreeMapItem* over = item(e->x(), e->y());
+  if (_lastOver == over) return;
+
+  setCurrent(over);
+  if (over == 0) {
+    _lastOver = 0;
+    return;
+  }
+
+  TreeMapItem* changed = 0;
+  TreeMapItem* item = possibleSelection(over);
+
+  switch(_selectionMode) {
+  case Single:
+    changed = setTmpSelected(item, true);
+    break;
+  case Multi:
+    changed = setTmpSelected(item, !isTmpSelected(item));
+    break;
+  case Extended:
+    if (_inControlDrag)
+      changed = setTmpSelected(item, !isTmpSelected(item));
+    else {
+      TreeMapItem* sLast = possibleSelection(_lastOver);
+      changed = setTmpRangeSelection(sLast, item, true);
+    }
+    break;
+
+  default:
+    break;
+  }
+
+  _lastOver = over;
+
+  if (changed)
+    redraw(changed);
+}
+
+void TreeMapWidget::mouseReleaseEvent( TQMouseEvent* )
+{
+  //kdDebug(90100) << "TreeMapWidget::mouseReleaseEvent" << endl;
+
+  if (!_pressed) return;
+
+  if (!_lastOver) {
+    // take back
+    setCurrent(_oldCurrent);
+    TreeMapItem* changed = diff(_tmpSelection, _selection).commonParent();
+    _tmpSelection = _selection;
+    if (changed)
+      redraw(changed);
+  }
+  else {
+    if (! (_tmpSelection == _selection)) {
+      _selection = _tmpSelection;
+      if (_selectionMode == Single)
+        emit selectionChanged(_lastOver);
+      emit selectionChanged();
+    }
+    if (!_inControlDrag && !_inShiftDrag && (_pressed == _lastOver))
+      emit clicked(_lastOver);
+  }
+
+  _pressed = 0;
+  _lastOver = 0;
+}
+
+
+void TreeMapWidget::mouseDoubleClickEvent( TQMouseEvent* e )
+{
+  TreeMapItem* over = item(e->x(), e->y());
+
+  emit doubleClicked(over);
+}
+
+
+/* returns -1 if nothing visible found */
+int nextVisible(TreeMapItem* i)
+{
+  TreeMapItem* p = i->parent();
+  if (!p || p->itemRect().isEmpty()) return -1;
+
+  int idx = p->children()->findRef(i);
+  if (idx<0) return -1;
+
+  while (idx < (int)p->children()->count()-1) {
+    idx++;
+    TQRect r = p->children()->at(idx)->itemRect();
+    if (r.width()>1 && r.height()>1)
+      return idx;
+  }
+  return -1;
+}
+
+/* returns -1 if nothing visible found */
+int prevVisible(TreeMapItem* i)
+{
+  TreeMapItem* p = i->parent();
+  if (!p || p->itemRect().isEmpty()) return -1;
+
+  int idx = p->children()->findRef(i);
+  if (idx<0) return -1;
+
+  while (idx > 0) {
+    idx--;
+    TQRect r = p->children()->at(idx)->itemRect();
+    if (r.width()>1 && r.height()>1)
+      return idx;
+  }
+  return -1;
+}
+
+
+
+
+void TreeMapWidget::keyPressEvent( TQKeyEvent* e )
+{
+  if (e->key() == Key_Escape && _pressed) {
+
+    // take back
+    if (_oldCurrent != _lastOver)
+      setCurrent(_oldCurrent);
+    if (! (_tmpSelection == _selection)) {
+      TreeMapItem* changed = diff(_tmpSelection, _selection).commonParent();
+      _tmpSelection = _selection;
+      if (changed)
+	redraw(changed);
+    }
+    _pressed = 0;
+    _lastOver = 0;
+  }
+
+  if ((e->key() == Key_Space) ||
+      (e->key() == Key_Return)) {
+
+    switch(_selectionMode) {
+    case NoSelection:
+      break;
+    case Single:
+      setSelected(_current, true);
+      break;
+    case Multi:
+      setSelected(_current, !isSelected(_current));
+      break;
+    case Extended:
+      if ((e->state() & ControlButton) || (e->state() & ShiftButton))
+        setSelected(_current, !isSelected(_current));
+      else {
+        _selectionMode = Single;
+        setSelected(_current, true);
+        _selectionMode = Extended;
+      }
+    }
+
+    if (_current && (e->key() == Key_Return))
+      emit returnPressed(_current);
+
+    return;
+  }
+
+  if (!_current) {
+    if (e->key() == Key_Down) {
+      setCurrent(_base, true);
+    }
+    return;
+  }
+
+  TreeMapItem* old = _current,  *newItem;
+  TreeMapItem* p = _current->parent();
+
+  bool goBack;
+  if (_current->sorting(&goBack) == -1) {
+    // noSorting
+    goBack = false;
+  }
+
+
+  if ((e->key() == Key_Backspace) ||
+      (e->key() == Key_Up)) {
+    newItem = visibleItem(p);
+    setCurrent(newItem, true);
+  }
+  else if (e->key() == Key_Left) {
+    int newIdx = goBack ? nextVisible(_current) : prevVisible(_current);
+    if (p && newIdx>=0) {
+      p->setIndex(newIdx);
+      setCurrent(p->children()->at(newIdx), true);
+    }
+  }
+  else if (e->key() == Key_Right) {
+    int newIdx = goBack ? prevVisible(_current) : nextVisible(_current);
+    if (p && newIdx>=0) {
+      p->setIndex(newIdx);
+      setCurrent(p->children()->at(newIdx), true);
+    }
+  }
+  else if (e->key() == Key_Down) {
+    if (_current->children() && _current->children()->count()>0) {
+      int newIdx = _current->index();
+      if (newIdx<0)
+        newIdx = goBack ? (_current->children()->count()-1) : 0;
+      if (newIdx>=(int)_current->children()->count())
+        newIdx = _current->children()->count()-1;
+      newItem = visibleItem(_current->children()->at(newIdx));
+      setCurrent(newItem, true);
+    }
+  }
+
+  if (old == _current) return;
+  if (! (e->state() & ControlButton)) return;
+  if (! (e->state() & ShiftButton)) return;
+
+  switch(_selectionMode) {
+  case NoSelection:
+    break;
+  case Single:
+    setSelected(_current, true);
+    break;
+  case Multi:
+    setSelected(_current, !isSelected(_current));
+    break;
+  case Extended:
+    if (e->state() & ControlButton)
+      setSelected(_current, !isSelected(_current));
+    else
+      setSelected(_current, isSelected(old));
+  }
+}
+
+void TreeMapWidget::fontChange( const TQFont& )
+{
+  redraw();
+}
+
+
+void TreeMapWidget::resizeEvent( TQResizeEvent * )
+{
+  // this automatically redraws (as size is changed)
+  drawTreeMap();
+}
+
+void TreeMapWidget::paintEvent( TQPaintEvent * )
+{
+  drawTreeMap();
+}
+
+void TreeMapWidget::showEvent( TQShowEvent * )
+{
+  // refresh only if needed
+  drawTreeMap();
+}
+
+// Updates screen from shadow buffer,
+// but redraws before if needed
+void TreeMapWidget::drawTreeMap()
+{
+  // no need to draw if hidden
+  if (!isVisible()) return;
+
+  if (_pixmap.size() != size())
+    _needsRefresh = _base;
+
+  if (_needsRefresh) {
+
+    if (DEBUG_DRAWING)
+      kdDebug(90100) << "Redrawing " << _needsRefresh->path(0).join("/") << endl;
+    
+    if (_needsRefresh == _base) {
+      // redraw whole widget
+      _pixmap = TQPixmap(size());
+      _pixmap.fill(backgroundColor());
+    }
+    TQPainter p(&_pixmap);
+    if (_needsRefresh == _base) {
+      p.setPen(black);
+      p.drawRect(TQRect(2, 2, TQWidget::width()-4, TQWidget::height()-4));
+      _base->setItemRect(TQRect(3, 3, TQWidget::width()-6, TQWidget::height()-6));
+    }
+    else {
+      // only subitem
+      if (!_needsRefresh->itemRect().isValid()) return;
+    }
+
+    // reset cached font object; it could have been changed
+    _font = font();
+    _fontHeight = fontMetrics().height();
+
+    drawItems(&p, _needsRefresh);
+    _needsRefresh = 0;
+  }
+
+  bitBlt( TQT_TQPAINTDEVICE(this), 0, 0, TQT_TQPAINTDEVICE(&_pixmap), 0, 0,
+          TQWidget::width(), TQWidget::height(), CopyROP, true);
+
+  if (hasFocus()) {
+    TQPainter p(this);
+    style().tqdrawPrimitive( TQStyle::PE_FocusRect, &p,
+                           TQRect(0, 0, TQWidget::width(), TQWidget::height()),
+                           colorGroup() );
+  }
+}
+
+
+
+void TreeMapWidget::redraw(TreeMapItem* i)
+{
+  if (!i) return;
+
+  if (!_needsRefresh)
+    _needsRefresh = i;
+  else {
+    if (!i->isChildOf(_needsRefresh))
+      _needsRefresh = _needsRefresh->commonParent(i);
+  }
+
+  if (isVisible()) {
+    // delayed drawing if we have multiple redraw requests
+    update();
+  }
+}
+
+void TreeMapWidget::drawItem(TQPainter* p,
+                             TreeMapItem* item)
+{
+  bool isSelected = false;
+  TreeMapItem* i;
+
+  if (_markNo>0) {
+      for(i = item;i;i=i->parent())
+	  if (i->isMarked(_markNo)) break;
+
+      isSelected = (i!=0);
+  }
+  else {
+      for (i=_tmpSelection.first();i;i=_tmpSelection.next())
+	  if (item->isChildOf(i)) break;
+
+      isSelected = (i!=0);
+  }
+
+  bool isCurrent = _current && item->isChildOf(_current);
+  int dd = item->depth();
+  if (isTransparent(dd)) return;
+
+  RectDrawing d(item->itemRect());
+  item->setSelected(isSelected);
+  item->setCurrent(isCurrent);
+  item->setShaded(_shading);
+  item->drawFrame(drawFrame(dd));
+  d.drawBack(p, item);
+}
+
+
+bool TreeMapWidget::horizontal(TreeMapItem* i, const TQRect& r)
+{
+  switch(i->splitMode()) {
+  case TreeMapItem::HAlternate:
+    return (i->depth()%2)==1;
+  case TreeMapItem::VAlternate:
+    return (i->depth()%2)==0;
+  case TreeMapItem::Horizontal:
+    return true;
+  case TreeMapItem::Vertical:
+    return false;
+  default:
+    return r.width() > r.height();
+  }
+  return false;
+}
+
+
+/**
+ * Draw TreeMapItems recursive, starting from item
+ */
+void TreeMapWidget::drawItems(TQPainter* p,
+                              TreeMapItem* item)
+{
+    if (DEBUG_DRAWING)
+	kdDebug(90100) << "+drawItems(" << item->path(0).join("/") << ", "
+		  << item->itemRect().x() << "/" << item->itemRect().y()
+		  << "-" << item->itemRect().width() << "x"
+		  << item->itemRect().height() << "), Val " << item->value()
+		  << ", Sum " << item->sum() << endl;
+
+  drawItem(p, item);
+  item->clearFreeRects();
+
+  TQRect origRect = item->itemRect();
+  int bw = item->borderWidth();
+  TQRect r = TQRect(origRect.x()+bw, origRect.y()+bw,
+                  origRect.width()-2*bw, origRect.height()-2*bw);
+
+  TreeMapItemList* list = item->children();
+  TreeMapItem* i;
+
+  bool stopDrawing = false;
+
+  // only subdivide if there are children
+  if (!list || list->count()==0)
+    stopDrawing = true;
+
+  // only subdivide if there is enough space
+  if (!stopDrawing && (r.width()<=0 || r.height()<=0))
+    stopDrawing = true;
+
+  // stop drawing if maximum depth is reached
+  if (!stopDrawing &&
+      (_maxDrawingDepth>=0 && item->depth()>=_maxDrawingDepth))
+    stopDrawing = true;
+
+  // stop drawing if stopAtText is reached
+  if (!stopDrawing)
+    for (int no=0;no<(int)_attr.size();no++) {
+      TQString stopAt = fieldStop(no);
+      if (!stopAt.isEmpty() && (item->text(no) == stopAt)) {
+        stopDrawing = true;
+        break;
+      }
+    }
+
+  // area size is checked later...
+#if 0
+  // stop drawing if minimal area size is reached
+  if (!stopDrawing &&
+      (_minimalArea > 0) &&
+      (r.width() * r.height() < _minimalArea)) stopDrawing = true;
+#endif
+
+  if (stopDrawing) {
+    if (list) {
+      // invalidate rects
+      for (i=list->first();i;i=list->next())
+        i->clearItemRect();
+    }
+    // tooltip apears on whole item rect
+    item->addFreeRect(item->itemRect());
+
+    // if we have space for text...
+    if ((r.height() < _fontHeight) || (r.width() < _fontHeight)) return;
+
+    RectDrawing d(r);
+    item->setRotated(_allowRotation && (r.height() > r.width()));
+    for (int no=0;no<(int)_attr.size();no++) {
+      if (!fieldVisible(no)) continue;
+      d.drawField(p, no, item);
+    }
+    r = d.remainingRect(item);
+
+    if (DEBUG_DRAWING)
+	kdDebug(90100) << "-drawItems(" << item->path(0).join("/") << ")" << endl;
+    return;
+  }
+
+  double user_sum, child_sum, self;
+
+  // user supplied sum
+  user_sum = item->sum();
+
+  // own sum
+  child_sum = 0;
+  for (i=list->first();i;i=list->next()) {
+    child_sum += i->value();
+    if (DEBUG_DRAWING)
+      kdDebug(90100) << "  child: " << i->text(0) << ", value " 
+		<< i->value() << endl;
+  }
+
+  TQRect orig = r;
+
+  // if we have space for text...
+  if ((r.height() >= _fontHeight) && (r.width() >= _fontHeight)) {
+
+    RectDrawing d(r);
+    item->setRotated(_allowRotation && (r.height() > r.width()));
+    for (int no=0;no<(int)_attr.size();no++) {
+      if (!fieldVisible(no)) continue;
+      if (!fieldForced(no)) continue;
+      d.drawField(p, no, item);
+    }
+    r = d.remainingRect(item);
+  }
+
+  if (orig.x() == r.x()) {
+    // Strings on top
+    item->addFreeRect(TQRect(orig.x(), orig.y(),
+			    orig.width(), orig.height()-r.height()));
+  }
+  else {
+    // Strings on the left
+    item->addFreeRect(TQRect(orig.x(), orig.y(),
+			    orig.width()-r.width(), orig.height()));
+  }
+
+  if (user_sum == 0) {
+    // user didn't supply any sum
+    user_sum = child_sum;
+    self = 0;
+  }
+  else {
+    self = user_sum - child_sum;
+
+    if (user_sum < child_sum) {
+      //kdDebug(90100) << "TreeMWidget " <<
+      //       item->path() << ": User sum " << user_sum << " < Child Items sum " << child_sum << endl;
+
+      // invalid user supplied sum: ignore and use calculate sum
+      user_sum = child_sum;
+      self = 0.0;
+    }
+    else {
+      // Try to put the border waste in self
+      // percent of wasted space on border...
+      float borderArea = origRect.width() * origRect.height();
+      borderArea = (borderArea - r.width()*r.height())/borderArea;
+      unsigned borderValue = (unsigned)(borderArea * user_sum);
+
+      if (borderValue > self) {
+        if (_skipIncorrectBorder) {
+          r = origRect;
+          // should add my self to nested self and set my self =0
+        }
+        else
+          self = 0.0;
+      }
+      else
+        self -= borderValue;
+
+      user_sum = child_sum + self;
+    }
+  }
+
+  bool rotate = (_allowRotation && (r.height() > r.width()));
+  int self_length = (int)( ((rotate) ? r.width() : r.height()) *
+			   self / user_sum + .5);
+  if (self_length > 0) {
+    // take space for self cost
+    TQRect sr = r;
+    if (rotate) {
+      sr.setWidth( self_length );
+      r.setRect(r.x()+sr.width(), r.y(), r.width()-sr.width(), r.height());
+    }
+    else {
+      sr.setHeight( self_length );
+      r.setRect(r.x(), r.y()+sr.height(), r.width(), r.height()-sr.height());
+    }
+
+    // set selfRect (not occupied by children) for tooltip
+    item->addFreeRect(sr);
+
+    if (0) kdDebug(90100) << "Item " << item->path(0).join("/") << ": SelfR "
+		     << sr.x() << "/" << sr.y() << "-" << sr.width()
+		     << "/" << sr.height() << ", self " << self << "/"
+		     << user_sum << endl;
+
+    if ((sr.height() >= _fontHeight) && (sr.width() >= _fontHeight)) {
+
+      RectDrawing d(sr);
+      item->setRotated(_allowRotation && (r.height() > r.width()));
+      for (int no=0;no<(int)_attr.size();no++) {
+	if (!fieldVisible(no)) continue;
+	if (fieldForced(no)) continue;
+	d.drawField(p, no, item);
+      }
+    }
+
+    user_sum -= self;
+  }
+
+  bool goBack;
+  if (item->sorting(&goBack) == -1) {
+    // noSorting
+    goBack = false;
+  }
+
+  TreeMapItemListIterator it(*list);
+  if (goBack) it.toLast();
+
+  if (item->splitMode() == TreeMapItem::Columns) {
+    int len = list->count();
+    bool drawDetails = true;
+
+    while (len>0 && user_sum>0) {
+      TreeMapItemListIterator first = it;
+      double valSum = 0;
+      int lenLeft = len;
+      int columns = (int)(sqrt((double)len * r.width()/r.height())+.5);
+      if (columns==0) columns = 1; //should never be needed
+
+      while (lenLeft>0 && ((double)valSum*(len-lenLeft) <
+                           (double)len*user_sum/columns/columns)) {
+        valSum += it.current()->value();
+        if (goBack) --it; else ++it;
+        lenLeft--;
+      }
+
+      // we always split horizontally
+      int nextPos = (int)((double)r.width() * valSum / user_sum);
+      TQRect firstRect = TQRect(r.x(), r.y(), nextPos, r.height());
+
+      if (nextPos < _visibleWidth) {
+	  if (item->sorting(0) == -1) {
+	      // fill current rect with hash pattern
+	      drawFill(item, p, firstRect);
+	  }
+	  else {
+	      // fill rest with hash pattern
+	      drawFill(item, p, r, first, len, goBack);
+	      break;
+	  }
+      }
+      else {
+        drawDetails = drawItemArray(p, item, firstRect,
+                                    valSum, first, len-lenLeft, goBack);
+      }
+      r.setRect(r.x()+nextPos, r.y(), r.width()-nextPos, r.height());
+      user_sum -= valSum;
+      len = lenLeft;
+
+      if (!drawDetails) {
+        if (item->sorting(0) == -1)
+          drawDetails = true;
+        else {
+          drawFill(item, p, r, it, len, goBack);
+          break;
+        }
+      }
+    }
+  }
+  else if (item->splitMode() == TreeMapItem::Rows) {
+    int len = list->count();
+    bool drawDetails = true;
+
+    while (len>0 && user_sum>0) {
+      TreeMapItemListIterator first = it;
+      double valSum = 0;
+      int lenLeft = len;
+      int rows = (int)(sqrt((double)len * r.height()/r.width())+.5);
+      if (rows==0) rows = 1; //should never be needed
+
+      while (lenLeft>0 && ((double)valSum*(len-lenLeft) <
+                           (double)len*user_sum/rows/rows)) {
+        valSum += it.current()->value();
+        if (goBack) --it; else ++it;
+        lenLeft--;
+      }
+
+      // we always split horizontally
+      int nextPos = (int)((double)r.height() * valSum / user_sum);
+      TQRect firstRect = TQRect(r.x(), r.y(), r.width(), nextPos);
+
+      if (nextPos < _visibleWidth) {
+        if (item->sorting(0) == -1) {
+	    drawFill(item, p, firstRect);
+        }
+        else {
+	    drawFill(item, p, r, first, len, goBack);
+	    break;
+        }
+      }
+      else {
+        drawDetails = drawItemArray(p, item, firstRect,
+                                    valSum, first, len-lenLeft, goBack);
+      }
+      r.setRect(r.x(), r.y()+nextPos, r.width(), r.height()-nextPos);
+      user_sum -= valSum;
+      len = lenLeft;
+
+      if (!drawDetails) {
+        if (item->sorting(0) == -1)
+          drawDetails = true;
+        else {
+          drawFill(item, p, r, it, len, goBack);
+          break;
+        }
+      }
+    }
+  }
+  else
+    drawItemArray(p, item, r, user_sum, it, list->count(), goBack);
+
+  if (DEBUG_DRAWING)
+      kdDebug(90100) << "-drawItems(" << item->path(0).join("/") << ")" << endl;
+}
+
+// fills area with a pattern if to small to draw children
+void TreeMapWidget::drawFill(TreeMapItem* i, TQPainter* p, TQRect& r)
+{
+  p->setBrush(TQt::Dense4Pattern);
+  p->setPen(TQt::NoPen);
+  p->drawRect(r);
+  i->addFreeRect(r);
+}
+
+// fills area with a pattern if to small to draw children
+void TreeMapWidget::drawFill(TreeMapItem* i, TQPainter* p, TQRect& r,
+                             TreeMapItemListIterator it, int len, bool goBack)
+{
+  if (DEBUG_DRAWING)
+      kdDebug(90100) << "  +drawFill(" << r.x() << "/" << r.y()
+		<< "-" << r.width() << "x" << r.height()
+		<< ", len " << len << ")" << endl;
+
+  p->setBrush(TQt::Dense4Pattern);
+  p->setPen(TQt::NoPen);
+  p->drawRect(r);
+  i->addFreeRect(r);
+
+  // reset rects
+  while (len>0 && it.current()) {
+
+      if (DEBUG_DRAWING)
+	  kdDebug(90100) << "   Reset Rect " << (*it)->path(0).join("/") << endl;
+
+      (*it)->clearItemRect();
+      if (goBack) --it; else ++it;
+      len--;
+  }
+  if (DEBUG_DRAWING)
+      kdDebug(90100) << "  -drawFill(" << r.x() << "/" << r.y()
+		<< "-" << r.width() << "x" << r.height()
+		<< ", len " << len << ")" << endl;
+}
+
+// returns false if rect gets to small
+bool TreeMapWidget::drawItemArray(TQPainter* p, TreeMapItem* item,
+                                  TQRect& r, double user_sum,
+                                  TreeMapItemListIterator it, int len,
+				  bool goBack)
+{
+  if (user_sum == 0) return false;
+
+  static bool b2t = true;
+
+  // stop recursive bisection for small rectangles
+  if (((r.height() < _visibleWidth) &&
+       (r.width() < _visibleWidth)) ||
+      ((_minimalArea > 0) &&
+       (r.width() * r.height() < _minimalArea))) {
+
+    drawFill(item, p, r, it, len, goBack);
+    return false;
+  }
+
+  if (DEBUG_DRAWING)
+      kdDebug(90100) << " +drawItemArray(" << item->path(0).join("/") 
+		<< ", " << r.x() << "/" << r.y() << "-" << r.width()
+		<< "x" << r.height() << ")" << endl;
+
+  if (len>2 && (item->splitMode() == TreeMapItem::Bisection)) {
+
+    TreeMapItemListIterator first = it;
+    double valSum = 0;
+    int lenLeft = len;
+    //while (lenLeft>0 && valSum<user_sum/2) {
+    while (lenLeft>len/2) {
+      valSum += it.current()->value();
+      if (goBack) --it; else ++it;
+      lenLeft--;
+    }
+
+    // draw first half...
+    bool drawOn;
+
+    if (r.width() > r.height()) {
+      int halfPos = (int)((double)r.width() * valSum / user_sum);
+      TQRect firstRect = TQRect(r.x(), r.y(), halfPos, r.height());
+      drawOn = drawItemArray(p, item, firstRect,
+                             valSum, first, len-lenLeft, goBack);
+      r.setRect(r.x()+halfPos, r.y(), r.width()-halfPos, r.height());
+    }
+    else {
+      int halfPos = (int)((double)r.height() * valSum / user_sum);
+      TQRect firstRect = TQRect(r.x(), r.y(), r.width(), halfPos);
+      drawOn = drawItemArray(p, item, firstRect,
+                             valSum, first, len-lenLeft, goBack);
+      r.setRect(r.x(), r.y()+halfPos, r.width(), r.height()-halfPos);
+    }
+
+    // if no sorting, don't stop drawing
+    if (item->sorting(0) == -1) drawOn = true;
+
+    // second half
+    if (drawOn)
+      drawOn = drawItemArray(p, item, r, user_sum - valSum,
+                             it, lenLeft, goBack);
+    else {
+      drawFill(item, p, r, it, len, goBack);
+    }
+
+    if (DEBUG_DRAWING)
+	kdDebug(90100) << " -drawItemArray(" << item->path(0).join("/")
+		  << ")" << endl;
+
+    return drawOn;
+  }
+
+  bool hor = horizontal(item,r);
+
+  TreeMapItem* i;
+  while (len>0) {
+    i = it.current();
+    if (user_sum <= 0) {
+
+      if (DEBUG_DRAWING)
+	  kdDebug(90100) << "drawItemArray: Reset " << i->path(0).join("/") << endl;
+
+      i->clearItemRect();
+      if (goBack) --it; else ++it;
+      len--;
+      continue;
+    }
+
+    // stop drawing for small rectangles
+    if (((r.height() < _visibleWidth) &&
+         (r.width() < _visibleWidth)) ||
+        ((_minimalArea > 0) &&
+         (r.width() * r.height() < _minimalArea))) {
+
+      drawFill(item, p, r, it, len, goBack);
+      if (DEBUG_DRAWING)
+	  kdDebug(90100) << " -drawItemArray(" << item->path(0).join("/")
+		    << "): Stop" << endl;
+      return false;
+    }
+
+    if (i->splitMode() == TreeMapItem::AlwaysBest)
+      hor = r.width() > r.height();
+
+    int lastPos = hor ? r.width() : r.height();
+    double val = i->value();
+    int nextPos = (user_sum <= 0.0) ? 0: (int)(lastPos * val / user_sum +.5);
+    if (nextPos>lastPos) nextPos = lastPos;
+
+    if ((item->sorting(0) != -1) && (nextPos < _visibleWidth)) {
+      drawFill(item, p, r, it, len, goBack);
+      if (DEBUG_DRAWING)
+	  kdDebug(90100) << " -drawItemArray(" << item->path(0).join("/")
+		    << "): Stop" << endl;
+      return false;
+    }
+
+    TQRect currRect = r;
+
+    if (hor)
+      currRect.setWidth(nextPos);
+    else {
+      if (b2t)
+        currRect.setRect(r.x(), r.bottom()-nextPos+1, r.width(), nextPos);
+      else
+        currRect.setHeight(nextPos);
+    }
+
+    // don't draw very small rectangles:
+    if (nextPos >= _visibleWidth) {
+	i->setItemRect(currRect);
+	drawItems(p, i);
+    }
+    else {
+	i->clearItemRect();
+	drawFill(item, p, currRect);
+    }
+
+    // draw Separator
+    if (_drawSeparators && (nextPos<lastPos)) {
+      p->setPen(black);
+      if (hor) {
+        if (r.top()<=r.bottom())
+          p->drawLine(r.x() + nextPos, r.top(), r.x() + nextPos, r.bottom());
+      }
+      else {
+        if (r.left()<=r.right())
+        p->drawLine(r.left(), r.y() + nextPos, r.right(), r.y() + nextPos);
+      }
+      nextPos++;
+    }
+
+    if (hor)
+      r.setRect(r.x() + nextPos, r.y(), lastPos-nextPos, r.height());
+    else {
+      if (b2t)
+        r.setRect(r.x(), r.y(), r.width(), lastPos-nextPos);
+      else
+        r.setRect(r.x(), r.y() + nextPos, r.width(), lastPos-nextPos);
+    }
+
+    user_sum -= val;
+    if (goBack) --it; else ++it;
+    len--;
+  }
+
+  if (DEBUG_DRAWING)
+      kdDebug(90100) << " -drawItemArray(" << item->path(0).join("/")
+		<< "): Continue" << endl;
+
+  return true;
+}
+
+
+/*----------------------------------------------------------------
+ * Popup menus for option setting
+ */
+
+void TreeMapWidget::splitActivated(int id)
+{
+  if      (id == _splitID)   setSplitMode(TreeMapItem::Bisection);
+  else if (id == _splitID+1) setSplitMode(TreeMapItem::Columns);
+  else if (id == _splitID+2) setSplitMode(TreeMapItem::Rows);
+  else if (id == _splitID+3) setSplitMode(TreeMapItem::AlwaysBest);
+  else if (id == _splitID+4) setSplitMode(TreeMapItem::Best);
+  else if (id == _splitID+5) setSplitMode(TreeMapItem::VAlternate);
+  else if (id == _splitID+6) setSplitMode(TreeMapItem::HAlternate);
+  else if (id == _splitID+7) setSplitMode(TreeMapItem::Horizontal);
+  else if (id == _splitID+8) setSplitMode(TreeMapItem::Vertical);
+}
+
+
+void TreeMapWidget::addSplitDirectionItems(TQPopupMenu* popup, int id)
+{
+  _splitID = id;
+  popup->setCheckable(true);
+
+  connect(popup, TQT_SIGNAL(activated(int)),
+          this, TQT_SLOT(splitActivated(int)));
+
+  popup->insertItem(i18n("Recursive Bisection"), id);
+  popup->insertItem(i18n("Columns"),         id+1);
+  popup->insertItem(i18n("Rows"),            id+2);
+  popup->insertItem(i18n("Always Best"),     id+3);
+  popup->insertItem(i18n("Best"),            id+4);
+  popup->insertItem(i18n("Alternate (V)"),   id+5);
+  popup->insertItem(i18n("Alternate (H)"),   id+6);
+  popup->insertItem(i18n("Horizontal"),      id+7);
+  popup->insertItem(i18n("Vertical"),        id+8);
+
+  switch(splitMode()) {
+    case TreeMapItem::Bisection:  popup->setItemChecked(id,true); break;
+    case TreeMapItem::Columns:    popup->setItemChecked(id+1,true); break;
+    case TreeMapItem::Rows:       popup->setItemChecked(id+2,true); break;
+    case TreeMapItem::AlwaysBest: popup->setItemChecked(id+3,true); break;
+    case TreeMapItem::Best:       popup->setItemChecked(id+4,true); break;
+    case TreeMapItem::VAlternate: popup->setItemChecked(id+5,true); break;
+    case TreeMapItem::HAlternate: popup->setItemChecked(id+6,true); break;
+    case TreeMapItem::Horizontal: popup->setItemChecked(id+7,true); break;
+    case TreeMapItem::Vertical:   popup->setItemChecked(id+8,true); break;
+    default: break;
+  }
+}
+
+void TreeMapWidget::visualizationActivated(int id)
+{
+  if (id == _visID+2) setSkipIncorrectBorder(!skipIncorrectBorder());
+  else if (id == _visID+3) setBorderWidth(0);
+  else if (id == _visID+4) setBorderWidth(1);
+  else if (id == _visID+5) setBorderWidth(2);
+  else if (id == _visID+6) setBorderWidth(3);
+  else if (id == _visID+10) setAllowRotation(!allowRotation());
+  else if (id == _visID+11) setShadingEnabled(!isShadingEnabled());
+  else if (id<_visID+19 || id>_visID+100) return;
+
+  id -= 20+_visID;
+  int f = id/10;
+  if      ((id%10) == 1) setFieldVisible(f, !fieldVisible(f));
+  else if ((id%10) == 2) setFieldForced(f, !fieldForced(f));
+  else if ((id%10) == 3) setFieldPosition(f, DrawParams::TopLeft);
+  else if ((id%10) == 4) setFieldPosition(f, DrawParams::TopCenter);
+  else if ((id%10) == 5) setFieldPosition(f, DrawParams::TopRight);
+  else if ((id%10) == 6) setFieldPosition(f, DrawParams::BottomLeft);
+  else if ((id%10) == 7) setFieldPosition(f, DrawParams::BottomCenter);
+  else if ((id%10) == 8) setFieldPosition(f, DrawParams::BottomRight);
+}
+
+void TreeMapWidget::addVisualizationItems(TQPopupMenu* popup, int id)
+{
+  _visID = id;
+
+  popup->setCheckable(true);
+
+  TQPopupMenu* bpopup = new TQPopupMenu();
+  bpopup->setCheckable(true);
+
+  connect(popup, TQT_SIGNAL(activated(int)),
+          this, TQT_SLOT(visualizationActivated(int)));
+  connect(bpopup, TQT_SIGNAL(activated(int)),
+          this, TQT_SLOT(visualizationActivated(int)));
+
+  TQPopupMenu* spopup = new TQPopupMenu();
+  addSplitDirectionItems(spopup, id+100);
+  popup->insertItem(i18n("Nesting"), spopup, id);
+
+  popup->insertItem(i18n("Border"), bpopup, id+1);
+  bpopup->insertItem(i18n("Correct Borders Only"), id+2);
+  bpopup->insertSeparator();
+  bpopup->insertItem(i18n("Width %1").arg(0), id+3);
+  bpopup->insertItem(i18n("Width %1").arg(1), id+4);
+  bpopup->insertItem(i18n("Width %1").arg(2), id+5);
+  bpopup->insertItem(i18n("Width %1").arg(3), id+6);
+  bpopup->setItemChecked(id+2, skipIncorrectBorder());
+  bpopup->setItemChecked(id+3, borderWidth()==0);
+  bpopup->setItemChecked(id+4, borderWidth()==1);
+  bpopup->setItemChecked(id+5, borderWidth()==2);
+  bpopup->setItemChecked(id+6, borderWidth()==3);
+
+  popup->insertItem(i18n("Allow Rotation"), id+10);
+  popup->setItemChecked(id+10,allowRotation());
+  popup->insertItem(i18n("Shading"), id+11);
+  popup->setItemChecked(id+11,isShadingEnabled());
+
+  if (_attr.size() ==0) return;
+
+  popup->insertSeparator();
+  int f;
+  TQPopupMenu* tpopup;
+  id += 20;
+  for (f=0;f<(int)_attr.size();f++, id+=10) {
+    tpopup = new TQPopupMenu();
+    tpopup->setCheckable(true);
+    popup->insertItem(_attr[f].type, tpopup, id);
+    tpopup->insertItem(i18n("Visible"), id+1);
+    tpopup->insertItem(i18n("Take Space From Children"), id+2);
+    tpopup->insertSeparator();
+    tpopup->insertItem(i18n("Top Left"), id+3);
+    tpopup->insertItem(i18n("Top Center"), id+4);
+    tpopup->insertItem(i18n("Top Right"), id+5);
+    tpopup->insertItem(i18n("Bottom Left"), id+6);
+    tpopup->insertItem(i18n("Bottom Center"), id+7);
+    tpopup->insertItem(i18n("Bottom Right"), id+8);
+
+    tpopup->setItemChecked(id+1,_attr[f].visible);
+    tpopup->setItemEnabled(id+2,_attr[f].visible);
+    tpopup->setItemEnabled(id+3,_attr[f].visible);
+    tpopup->setItemEnabled(id+4,_attr[f].visible);
+    tpopup->setItemEnabled(id+5,_attr[f].visible);
+    tpopup->setItemEnabled(id+6,_attr[f].visible);
+    tpopup->setItemEnabled(id+7,_attr[f].visible);
+    tpopup->setItemEnabled(id+8,_attr[f].visible);
+    tpopup->setItemChecked(id+2,_attr[f].forced);
+    tpopup->setItemChecked(id+3,_attr[f].pos == DrawParams::TopLeft);
+    tpopup->setItemChecked(id+4,_attr[f].pos == DrawParams::TopCenter);
+    tpopup->setItemChecked(id+5,_attr[f].pos == DrawParams::TopRight);
+    tpopup->setItemChecked(id+6,_attr[f].pos == DrawParams::BottomLeft);
+    tpopup->setItemChecked(id+7,_attr[f].pos == DrawParams::BottomCenter);
+    tpopup->setItemChecked(id+8,_attr[f].pos == DrawParams::BottomRight);
+
+    connect(tpopup, TQT_SIGNAL(activated(int)),
+            this, TQT_SLOT(visualizationActivated(int)));
+  }
+}
+
+void TreeMapWidget::selectionActivated(int id)
+{
+  TreeMapItem* i = _menuItem;
+  id -= _selectionID;
+  while (id>0 && i) {
+    i=i->parent();
+    id--;
+  }
+  if (i)
+    setSelected(i, true);
+}
+
+void TreeMapWidget::addSelectionItems(TQPopupMenu* popup,
+				      int id, TreeMapItem* i)
+{
+  if (!i) return;
+
+  _selectionID = id;
+  _menuItem = i;
+
+  connect(popup, TQT_SIGNAL(activated(int)),
+          this, TQT_SLOT(selectionActivated(int)));
+
+  while (i) {
+    TQString name = i->text(0);
+    if (name.isEmpty()) break;
+    popup->insertItem(i->text(0), id++);
+    i = i->parent();
+  }
+}
+
+void TreeMapWidget::fieldStopActivated(int id)
+{
+  if (id == _fieldStopID) setFieldStop(0, TQString());
+  else {
+    TreeMapItem* i = _menuItem;
+    id -= _fieldStopID+1;
+    while (id>0 && i) {
+      i=i->parent();
+      id--;
+    }
+    if (i)
+      setFieldStop(0, i->text(0));
+  }
+}
+
+void TreeMapWidget::addFieldStopItems(TQPopupMenu* popup,
+				      int id, TreeMapItem* i)
+{
+  _fieldStopID = id;
+
+  connect(popup, TQT_SIGNAL(activated(int)),
+          this, TQT_SLOT(fieldStopActivated(int)));
+
+  popup->insertItem(i18n("No %1 Limit").arg(fieldType(0)), id);
+  popup->setItemChecked(id, fieldStop(0).isEmpty());
+  _menuItem = i;
+  bool foundFieldStop = false;
+  if (i) {
+    popup->insertSeparator();
+
+    while (i) {
+      id++;
+      TQString name = i->text(0);
+      if (name.isEmpty()) break;
+      popup->insertItem(i->text(0), id);
+      if (fieldStop(0) == i->text(0)) {
+        popup->setItemChecked(id, true);
+        foundFieldStop = true;
+      }
+      i = i->parent();
+    }
+  }
+
+  if (!foundFieldStop && !fieldStop(0).isEmpty()) {
+    popup->insertSeparator();
+    popup->insertItem(fieldStop(0), id+1);
+    popup->setItemChecked(id+1, true);
+  }
+}
+
+void TreeMapWidget::areaStopActivated(int id)
+{
+  if (id == _areaStopID) setMinimalArea(-1);
+  else if (id == _areaStopID+1) {
+    int area = _menuItem ? (_menuItem->width() * _menuItem->height()) : -1;
+    setMinimalArea(area);
+  }
+  else if (id == _areaStopID+2) setMinimalArea(100);
+  else if (id == _areaStopID+3) setMinimalArea(400);
+  else if (id == _areaStopID+4) setMinimalArea(1000);
+  else if (id == _areaStopID+5) setMinimalArea(minimalArea()*2);
+  else if (id == _areaStopID+6) setMinimalArea(minimalArea()/2);
+}
+
+void TreeMapWidget::addAreaStopItems(TQPopupMenu* popup,
+				     int id, TreeMapItem* i)
+{
+  _areaStopID = id;
+  _menuItem = i;
+
+  connect(popup, TQT_SIGNAL(activated(int)),
+          this, TQT_SLOT(areaStopActivated(int)));
+
+  bool foundArea = false;
+
+  popup->insertItem(i18n("No Area Limit"), id);
+  popup->setItemChecked(id, minimalArea() == -1);
+
+  if (i) {
+    int area = i->width() * i->height();
+    popup->insertSeparator();
+    popup->insertItem(i18n("Area of '%1' (%2)")
+                       .arg(i->text(0)).arg(area), id+1);
+    if (area == minimalArea()) {
+      popup->setItemChecked(id+1, true);
+      foundArea = true;
+    }
+  }
+
+  popup->insertSeparator();
+  int area = 100, count;
+  for (count=0;count<3;count++) {
+    popup->insertItem(i18n("1 Pixel", "%n Pixels", area), id+2+count);
+    if (area == minimalArea()) {
+      popup->setItemChecked(id+2+count, true);
+      foundArea = true;
+    }
+    area = (area==100) ? 400 : (area==400) ? 1000 : 4000;
+  }
+
+  if (minimalArea()>0) {
+    popup->insertSeparator();
+    if (!foundArea) {
+      popup->insertItem(i18n("1 Pixel", "%n Pixels", minimalArea()), id+10);
+      popup->setItemChecked(id+10, true);
+    }
+
+    popup->insertItem(i18n("Double Area Limit (to %1)")
+                       .arg(minimalArea()*2), id+5);
+    popup->insertItem(i18n("Halve Area Limit (to %1)")
+                       .arg(minimalArea()/2), id+6);
+  }
+}
+
+
+void TreeMapWidget::depthStopActivated(int id)
+{
+  if (id == _depthStopID) setMaxDrawingDepth(-1);
+  else if (id == _depthStopID+1) {
+    int d = _menuItem ? _menuItem->depth() : -1;
+    setMaxDrawingDepth(d);
+  }
+  else if (id == _depthStopID+2) setMaxDrawingDepth(maxDrawingDepth()-1);
+  else if (id == _depthStopID+3) setMaxDrawingDepth(maxDrawingDepth()+1);
+}
+
+void TreeMapWidget::addDepthStopItems(TQPopupMenu* popup,
+				      int id, TreeMapItem* i)
+{
+  _depthStopID = id;
+  _menuItem = i;
+
+  connect(popup, TQT_SIGNAL(activated(int)),
+          this, TQT_SLOT(depthStopActivated(int)));
+
+  bool foundDepth = false;
+
+  popup->insertItem(i18n("No Depth Limit"), id);
+  popup->setItemChecked(id, maxDrawingDepth() == -1);
+
+  if (i) {
+    int d = i->depth();
+    popup->insertSeparator();
+    popup->insertItem(i18n("Depth of '%1' (%2)")
+                       .arg(i->text(0)).arg(d), id+1);
+    if (d == maxDrawingDepth()) {
+      popup->setItemChecked(id+1, true);
+      foundDepth = true;
+    }
+  }
+
+  if (maxDrawingDepth()>1) {
+    popup->insertSeparator();
+    if (!foundDepth) {
+      popup->insertItem(i18n("Depth %1").arg(maxDrawingDepth()), id+10);
+      popup->setItemChecked(id+10, true);
+    }
+
+    popup->insertItem(i18n("Decrement (to %1)")
+                       .arg(maxDrawingDepth()-1), id+2);
+    popup->insertItem(i18n("Increment (to %1)")
+                       .arg(maxDrawingDepth()+1), id+3);
+  }
+}
+
+
+
+/*----------------------------------------------------------------
+ * Option saving/restoring
+ */
+
+void TreeMapWidget::saveOptions(KConfigGroup* config, TQString prefix)
+{
+  config->writeEntry(prefix+"Nesting", splitModeString());
+  config->writeEntry(prefix+"AllowRotation", allowRotation());
+  config->writeEntry(prefix+"ShadingEnabled", isShadingEnabled());
+  config->writeEntry(prefix+"OnlyCorrectBorder", skipIncorrectBorder());
+  config->writeEntry(prefix+"BorderWidth", borderWidth());
+  config->writeEntry(prefix+"MaxDepth", maxDrawingDepth());
+  config->writeEntry(prefix+"MinimalArea", minimalArea());
+
+  int f, fCount = _attr.size();
+  config->writeEntry(prefix+"FieldCount", fCount);
+  for (f=0;f<fCount;f++) {
+    config->writeEntry(TQString(prefix+"FieldVisible%1").arg(f),
+                       _attr[f].visible);
+    config->writeEntry(TQString(prefix+"FieldForced%1").arg(f),
+                       _attr[f].forced);
+    config->writeEntry(TQString(prefix+"FieldStop%1").arg(f),
+                       _attr[f].stop);
+    config->writeEntry(TQString(prefix+"FieldPosition%1").arg(f),
+                       fieldPositionString(f));
+  }
+}
+
+
+void TreeMapWidget::restoreOptions(KConfigGroup* config, TQString prefix)
+{
+  bool enabled;
+  int num;
+  TQString str;
+
+  str = config->readEntry(prefix+"Nesting");
+  if (!str.isEmpty()) setSplitMode(str);
+
+  if (config->hasKey(prefix+"AllowRotation")) {
+    enabled = config->readBoolEntry(prefix+"AllowRotation", true);
+    setAllowRotation(enabled);
+  }
+
+  if (config->hasKey(prefix+"ShadingEnabled")) {
+    enabled = config->readBoolEntry(prefix+"ShadingEnabled", true);
+    setShadingEnabled(enabled);
+  }
+
+  if (config->hasKey(prefix+"OnlyCorrectBorder")) {
+    enabled = config->readBoolEntry(prefix+"OnlyCorrectBorder", false);
+    setSkipIncorrectBorder(enabled);
+  }
+
+  num = config->readNumEntry(prefix+"BorderWidth", -2);
+  if (num!=-2) setBorderWidth(num);
+
+  num = config->readNumEntry(prefix+"MaxDepth", -2);
+  if (num!=-2) setMaxDrawingDepth(num);
+
+  num = config->readNumEntry(prefix+"MinimalArea", -2);
+  if (num!=-2) setMinimalArea(num);
+
+  num = config->readNumEntry(prefix+"FieldCount", -2);
+  if (num<=0 || num>MAX_FIELD) return;
+
+  int f;
+  for (f=0;f<num;f++) {
+    str = TQString(prefix+"FieldVisible%1").arg(f);
+    if (config->hasKey(str))
+      setFieldVisible(f, config->readBoolEntry(str));
+
+    str = TQString(prefix+"FieldForced%1").arg(f);
+    if (config->hasKey(str))
+      setFieldForced(f, config->readBoolEntry(str));
+
+    str = config->readEntry(TQString(prefix+"FieldStop%1").arg(f));
+    setFieldStop(f, str);
+
+    str = config->readEntry(TQString(prefix+"FieldPosition%1").arg(f));
+    if (!str.isEmpty()) setFieldPosition(f, str);
+  }
+}
+
+#include "treemap.moc"
diff --git a/kdecachegrind/kdecachegrind/treemap.h b/kdecachegrind/kdecachegrind/treemap.h
new file mode 100644
index 0000000..422cd35
--- /dev/null
+++ b/kdecachegrind/kdecachegrind/treemap.h
@@ -0,0 +1,759 @@
+/* This file is part of KCachegrind.
+   Copyright (C) 2002, 2003 Josef Weidendorfer <Josef.Weidendorfer@gmx.de>
+
+   KCachegrind 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, version 2.
+
+   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; see the file COPYING.  If not, write to
+   the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+   Boston, MA 02110-1301, USA.
+*/
+
+/**
+ * A Widget for visualizing hierarchical metrics as areas.
+ * The API is similar to TQListView.
+ *
+ * This file defines the following classes:
+ *  DrawParams, RectDrawing, TreeMapItem, TreeMapWidget
+ *
+ * DrawParams/RectDrawing allows reusing of TreeMap drawing
+ * functions in other widgets.
+ */
+
+#ifndef TREEMAP_H
+#define TREEMAP_H
+
+#include <tqstring.h>
+#include <tqwidget.h>
+#include <tqpixmap.h>
+#include <tqptrlist.h>
+#include <tqvaluevector.h>
+#include <tqcolor.h>
+#include <tqapplication.h>
+#include <tqstringlist.h>
+
+class TQPopupMenu;
+class TreeMapTip;
+class TreeMapWidget;
+class TreeMapItem;
+class TreeMapItemList;
+class TQString;
+
+class KConfigGroup;
+
+
+/**
+ * Drawing parameters for an object.
+ * A Helper Interface for RectDrawing.
+ */
+class DrawParams
+{
+public:
+  /**
+   * Positions for drawing into a rectangle.
+   *
+   * The specified position assumes no rotation.
+   * If there is more than one text for one position, it is put
+   * nearer to the center of the item.
+   *
+   * Drawing at top positions cuts free space from top,
+   * drawing at bottom positions cuts from bottom.
+   * Default usually gives positions clockwise according to field number.
+   */
+  enum Position { TopLeft, TopCenter, TopRight,
+                  BottomLeft, BottomCenter, BottomRight,
+                  Default, Unknown};
+
+  // no constructor as this is an abstract class
+  virtual ~DrawParams() {}
+
+  virtual TQString  text(int) const = 0;
+  virtual TQPixmap  pixmap(int) const = 0;
+  virtual Position position(int) const = 0;
+  // 0: no limit, negative: leave at least -maxLines() free
+  virtual int      maxLines(int) const { return 0; }
+  virtual int      fieldCount() const { return 0; }
+
+  virtual TQColor   backColor() const { return TQt::white; }
+  virtual const TQFont& font() const = 0;
+
+  virtual bool selected() const { return false; }
+  virtual bool current() const { return false; }
+  virtual bool shaded() const { return true; }
+  virtual bool rotated() const { return false; }
+  virtual bool drawFrame() const { return true; }
+};
+
+
+/*
+ * DrawParam with attributes stored
+ */
+class StoredDrawParams: public DrawParams
+{
+public:
+  StoredDrawParams();
+  StoredDrawParams(TQColor c,
+                   bool selected = false, bool current = false);
+
+  // getters
+  TQString  text(int) const;
+  TQPixmap  pixmap(int) const;
+  Position position(int) const;
+  int      maxLines(int) const;
+  int      fieldCount() const { return _field.size(); }
+
+  TQColor   backColor() const { return _backColor; }
+  bool selected() const { return _selected; }
+  bool current() const { return _current; }
+  bool shaded() const { return _shaded; }
+  bool rotated() const { return _rotated; }
+  bool drawFrame() const { return _drawFrame; }
+
+  const TQFont& font() const;
+
+  // attribute setters
+  void setField(int f, const TQString& t, TQPixmap pm = TQPixmap(),
+                Position p = Default, int maxLines = 0);
+  void setText(int f, const TQString&);
+  void setPixmap(int f, const TQPixmap&);
+  void setPosition(int f, Position);
+  void setMaxLines(int f, int);
+  void setBackColor(const TQColor& c) { _backColor = c; }
+  void setSelected(bool b) { _selected = b; }
+  void setCurrent(bool b) { _current = b; }
+  void setShaded(bool b) { _shaded = b; }
+  void setRotated(bool b) { _rotated = b; }
+  void drawFrame(bool b) { _drawFrame = b; }
+
+protected:
+  TQColor _backColor;
+  bool _selected :1;
+  bool _current :1;
+  bool _shaded :1;
+  bool _rotated :1;
+  bool _drawFrame :1;
+
+private:
+  // resize field array if needed to allow to access field <f>
+  void ensureField(int f);
+
+  struct Field {
+    TQString text;
+    TQPixmap pix;
+    Position pos;
+    int maxLines;
+  };
+
+  TQValueVector<Field> _field;
+};
+
+
+/* State for drawing on a rectangle.
+ *
+ * Following drawing functions are provided:
+ * - background drawing with shading and 3D frame
+ * - successive pixmap/text drawing at various positions with wrap-around
+ *   optimized for minimal space usage (e.g. if a text is drawn at top right
+ *   after text on top left, the same line is used if space allows)
+ *
+ */
+class RectDrawing
+{
+public:
+  RectDrawing(TQRect);
+  ~RectDrawing();
+
+  // The default DrawParams object used.
+  DrawParams* drawParams();
+  // we take control over the given object (i.e. delete at destruction)
+  void setDrawParams(DrawParams*);
+
+  // draw on a given TQPainter, use this class as info provider per default
+  void drawBack(TQPainter*, DrawParams* dp = 0);
+  /* Draw field at position() from pixmap()/text() with maxLines().
+   * Returns true if something was drawn
+   */
+  bool drawField(TQPainter*, int f, DrawParams* dp = 0);
+
+  // resets rectangle for free space
+  void setRect(TQRect);
+
+  // Returns the rectangle area still free of text/pixmaps after
+  // a number of drawText() calls.
+  TQRect remainingRect(DrawParams* dp = 0);
+
+private:
+  int _usedTopLeft, _usedTopCenter, _usedTopRight;
+  int _usedBottomLeft, _usedBottomCenter, _usedBottomRight;
+  TQRect _rect;
+
+  // temporary
+  int _fontHeight;
+  TQFontMetrics* _fm;
+  DrawParams* _dp;
+};
+
+
+class TreeMapItemList: public TQPtrList<TreeMapItem>
+{
+public:
+  TreeMapItem* commonParent();
+protected:
+  int compareItems ( Item item1, Item item2 );
+};
+
+typedef TQPtrListIterator<TreeMapItem> TreeMapItemListIterator;
+
+
+/**
+ * Base class of items in TreeMap.
+ *
+ * This class supports an arbitrary number of text() strings
+ * positioned counterclock-wise starting at TopLeft. Each item
+ * has its own static value(), sum() and sorting(). The
+ * splitMode() and borderWidth() is taken from a TreeMapWidget.
+ *
+ * If you want more flexibility, reimplement TreeMapItem and
+ * override the corresponding methods. For dynamic creation of child
+ * items on demand, reimplement children().
+ */
+class TreeMapItem: public StoredDrawParams
+{
+public:
+
+  /**
+   * Split direction for nested areas:
+   *  AlwaysBest: Choose split direction for every subitem according to
+   *              longest side of rectangle left for drawing
+   *  Best:       Choose split direction for all subitems of an area
+   *              depending on longest side
+   *  HAlternate:Qt::Horizontal at top;  alternate direction on depth step
+   *  VAlternate:Qt::Vertical at top; alternate direction on depth step
+   * Qt::Horizontal: Always horizontal split direction
+   * Qt::Vertical:   Always vertical split direction
+   */
+  enum SplitMode { Bisection, Columns, Rows,
+                   AlwaysBest, Best,
+                   HAlternate, VAlternate,
+                   Horizontal, Vertical };
+
+  TreeMapItem(TreeMapItem* parent = 0, double value = 1.0 );
+  TreeMapItem(TreeMapItem* parent, double value,
+              TQString text1, TQString text2 = TQString(),
+              TQString text3 = TQString(), TQString text4 = TQString());
+  virtual ~TreeMapItem();
+
+  bool isChildOf(TreeMapItem*);
+
+  TreeMapItem* commonParent(TreeMapItem* item);
+
+  // force a redraw of this item
+  void redraw();
+
+  // delete all children
+  void clear();
+
+  // force new child generation & refresh
+  void refresh();
+
+  // call in a reimplemented items() method to check if already called
+  // after a clear(), this will return false
+  bool initialized();
+
+  /**
+   * Adds an item to a parent.
+   * When no sorting is used, the item is appended (drawn at bottom).
+   * This is only needed if the parent was not already specified in the
+   * construction of the item.
+   */
+  void addItem(TreeMapItem*);
+
+  /**
+   * Returns a list of text strings of specified text number,
+   * from root up to this item.
+   */
+  TQStringList path(int) const;
+
+  /**
+   * Depth of this item. This is the distance to root.
+   */
+  int depth() const;
+
+  /**
+   * Parent Item
+   */
+  TreeMapItem* parent() const { return _parent; }
+
+  /**
+   * Temporary rectangle used for drawing this item the last time.
+   * This is internally used to map from a point to an item.
+   */
+  void setItemRect(const TQRect& r) { _rect = r; }
+  void clearItemRect();
+  const TQRect& itemRect() const { return _rect; }
+  int width() const { return _rect.width(); }
+  int height() const { return _rect.height(); }
+
+  /**
+   * Temporary rectangle list of free space of this item.
+   * Used internally to enable tooltip.
+   */
+  void clearFreeRects();
+  TQPtrList<TQRect>* freeRects() const { return _freeRects; }
+  void addFreeRect(const TQRect& r);
+
+  /**
+   * Temporary child item index of the child that was current() recently.
+   */
+  int index() const { return _index; }
+  void setIndex(int i) { _index = i; }
+
+
+  /**
+   * TreeMap widget this item is put in.
+   */
+  TreeMapWidget* widget() const { return _widget; }
+
+  void setParent(TreeMapItem* p);
+  void setWidget(TreeMapWidget* w) { _widget = w; }
+  void setSum(double s) { _sum = s; }
+  void setValue(double s) { _value = s; }
+
+  virtual double sum() const;
+  virtual double value() const;
+  // replace "Default" position with setting from TreeMapWidget
+  virtual Position position(int) const;
+  virtual const TQFont& font() const;
+  virtual bool isMarked(int) const;
+
+  virtual int borderWidth() const;
+
+  /**
+   * Returns the text number after that sorting is done or
+   * -1 for no sorting, -2 for value() sorting (default).
+   * If ascending != 0, a bool value is written at that location
+   * to indicate if sorting should be ascending.
+   */
+  virtual int sorting(bool* ascending) const;
+
+  /**
+   * Set the sorting for child drawing.
+   *
+   * Default is no sorting: <textNo> = -1
+   * For value() sorting, use <textNo> = -2
+   *
+   * For fast sorting, set this to -1 before child insertions and call
+   * again after inserting all children.
+   */
+  void setSorting(int textNo, bool ascending = true);
+
+  /**
+   * Resort according to the already set sorting.
+   *
+   * This has to be done if the sorting base changes (e.g. text or values
+   * change). If this is only true for the children of this item, you can
+   * set the recursive parameter to false.
+   */
+  void resort(bool recursive = true);
+
+  virtual SplitMode splitMode() const;
+  virtual int rtti() const;
+  // not const as this can create children on demand
+  virtual TreeMapItemList* children();
+
+protected:
+  TreeMapItemList* _children;
+  double _sum, _value;
+
+private:
+  TreeMapWidget* _widget;
+  TreeMapItem* _parent;
+
+  int _sortTextNo;
+  bool _sortAscending;
+
+  // temporary layout
+  TQRect _rect;
+  TQPtrList<TQRect>* _freeRects;
+  int _depth;
+
+  // temporary self value (when using level skipping)
+  double _unused_self;
+
+  // index of last active subitem
+  int _index;
+};
+
+
+/**
+ * Class for visualization of a metric of hierarchically
+ * nested items as 2D areas.
+ */
+class TreeMapWidget: public TQWidget
+{
+  Q_OBJECT
+  TQ_OBJECT
+
+public:
+
+  /**
+   * Same as in TQListBox/TQListView
+   */
+  enum SelectionMode { Single, Multi, Extended, NoSelection };
+
+  /* The widget becomes owner of the base item */
+  TreeMapWidget(TreeMapItem* base, TQWidget* parent=0, const char* name=0);
+  ~TreeMapWidget();
+
+  /**
+   * Returns the TreeMapItem filling out the widget space
+   */
+  TreeMapItem* base() const { return _base; }
+
+  /**
+   * Returns a reference to the current widget font.
+   */
+  const TQFont& currentFont() const;
+
+  /**
+   * Returns the area item at position x/y, independent from any
+   * maxSelectDepth setting.
+   */
+  TreeMapItem* item(int x, int y) const;
+
+  /**
+   * Returns the nearest item with a visible area; this
+   * can be the given item itself.
+   */
+  TreeMapItem* visibleItem(TreeMapItem*) const;
+
+  /**
+   * Returns the item possible for selection. this returns the
+   * given item itself or a parent thereof,
+   * depending on setting of maxSelectDepth().
+   */
+  TreeMapItem* possibleSelection(TreeMapItem*) const;
+
+  /**
+   * Selects or unselects an item.
+   * In multiselection mode, the constrain that a selected item
+   * has no selected children or parents stays true.
+   */
+  void setSelected(TreeMapItem*, bool selected = true);
+
+  /**
+   * Switches on the marking <markNo>. Marking 0 switches off marking.
+   * This is mutually exclusive to selection, and is automatically
+   * switched off when selection is changed (also by the user).
+   * Marking is visually the same as selection, and is based on
+   * TreeMapItem::isMarked(<markNo>).
+   * This enables to programmatically show multiple selected items
+   * at once even in single selection mode.
+   */
+  void setMarked(int markNo = 1, bool redraw = true);
+
+  /**
+   * Clear selection of all selected items which are children of
+   * parent. When parent == 0, clears whole selection
+   * Returns true if selection changed.
+   */
+  bool clearSelection(TreeMapItem* parent = 0);
+
+  /**
+   * Selects or unselects items in a range.
+   * This is needed internally for Shift-Click in Extented mode.
+   * Range means for a hierarchical widget:
+   * - select/unselect i1 and i2 according selected
+   * - search common parent of i1 and i2, and select/unselect the
+   *   range of direct children between but excluding the child
+   *   leading to i1 and the child leading to i2.
+   */
+  void setRangeSelection(TreeMapItem* i1,
+                         TreeMapItem* i2, bool selected);
+
+  /**
+   * Sets the current item.
+   * The current item is mainly used for keyboard navigation.
+   */
+  void setCurrent(TreeMapItem*, bool kbd=false);
+
+  /**
+   * Set the maximal depth a selected item can have.
+   * If you try to select a item with higher depth, the ancestor holding
+   * this condition is used.
+   *
+   * See also possibleSelection().
+   */
+  void setMaxSelectDepth(int d) { _maxSelectDepth = d; }
+
+
+  void setSelectionMode(SelectionMode m) { _selectionMode = m; }
+
+  /**
+   * for setting/getting global split direction
+   */
+  void setSplitMode(TreeMapItem::SplitMode m);
+  TreeMapItem::SplitMode splitMode() const;
+  // returns true if string was recognized
+  bool setSplitMode(TQString);
+  TQString splitModeString() const;
+
+
+  /*
+   * Shading of rectangles enabled ?
+   */
+  void setShadingEnabled(bool s);
+  bool isShadingEnabled() const { return _shading; }
+
+  /* Setting for a whole depth level: draw 3D frame (default) or solid */
+  void drawFrame(int d, bool b);
+  bool drawFrame(int d) const { return (d<4)?_drawFrame[d]:true; }
+
+  /* Setting for a whole depth level: draw items (default) or transparent */
+  void setTransparent(int d, bool b);
+  bool isTransparent(int d) const { return (d<4)?_transparent[d]:false; }
+
+  /**
+   * Items usually have a size proportional to their value().
+   * With <width>, you can give the minimum width
+   * of the resulting rectangle to still be drawn.
+   * For space not used because of to small items, you can specify
+   * with <reuseSpace> if the background should shine through or
+   * the space will be used to enlarge the next item to be drawn
+   * at this level.
+   */
+  void setVisibleWidth(int width, bool reuseSpace = false);
+
+  /**
+   * If a children value() is almost the parents sum(),
+   * it can happen that the border to be drawn for visibilty of
+   * nesting relations takes to much space, and the
+   * parent/child size relation can not be mapped to a correct
+   * area size relation.
+   *
+   * Either
+   * (1) Ignore the incorrect drawing, or
+   * (2) Skip drawing of the parent level alltogether.
+   */
+  void setSkipIncorrectBorder(bool enable = true);
+  bool skipIncorrectBorder() const { return _skipIncorrectBorder; }
+
+  /**
+   * Maximal nesting depth
+   */
+  void setMaxDrawingDepth(int d);
+  int maxDrawingDepth() const { return _maxDrawingDepth; }
+
+  /**
+   * Minimal area for rectangles to draw
+   */
+  void setMinimalArea(int area);
+  int minimalArea() const { return _minimalArea; }
+
+  /* defaults for text attributes */
+  TQString defaultFieldType(int) const;
+  TQString defaultFieldStop(int) const;
+  bool    defaultFieldVisible(int) const;
+  bool    defaultFieldForced(int) const;
+  DrawParams::Position defaultFieldPosition(int) const;
+
+  /**
+   * Set the type name of a field.
+   * This is important for the visualization menu generated
+   * with visualizationMenu()
+   */
+  void setFieldType(int, TQString);
+  TQString fieldType(int) const;
+
+  /**
+   * Stop drawing at item with name
+   */
+  void setFieldStop(int, TQString);
+  TQString fieldStop(int) const;
+
+  /**
+   * Should the text with number textNo be visible?
+   * This is only done if remaining space is enough to allow for
+   * proportional size constrains.
+   */
+  void setFieldVisible(int, bool);
+  bool fieldVisible(int) const;
+
+  /**
+   * Should the drawing of the name into the rectangle be forced?
+   * This enables drawing of the name before drawing subitems, and
+   * thus destroys proportional constrains.
+   */
+  void setFieldForced(int, bool);
+  bool fieldForced(int) const;
+
+  /**
+   * Set the field position in the area. See TreeMapItem::Position
+   */
+  void setFieldPosition(int, DrawParams::Position);
+  DrawParams::Position fieldPosition(int) const;
+  void setFieldPosition(int, TQString);
+  TQString fieldPositionString(int) const;
+
+  /**
+   * Do we allow the texts to be rotated by 90 degrees for better fitting?
+   */
+  void setAllowRotation(bool);
+  bool allowRotation() const { return _allowRotation; }
+
+  void setBorderWidth(int w);
+  int borderWidth() const { return _borderWidth; }
+
+  /**
+   * Save/restore options.
+   */
+  void saveOptions(KConfigGroup*, TQString prefix = TQString());
+  void restoreOptions(KConfigGroup*, TQString prefix = TQString());
+
+  /**
+   * These functions populate given popup menus.
+   * The added items are already connected to handlers.
+   *
+   * The int is the menu id where to start for the items (100 IDs reserved).
+   */
+  void addSplitDirectionItems(TQPopupMenu*, int);
+  void addSelectionItems(TQPopupMenu*, int, TreeMapItem*);
+  void addFieldStopItems(TQPopupMenu*, int, TreeMapItem*);
+  void addAreaStopItems(TQPopupMenu*, int, TreeMapItem*);
+  void addDepthStopItems(TQPopupMenu*, int, TreeMapItem*);
+  void addVisualizationItems(TQPopupMenu*, int);
+
+  TreeMapWidget* widget() { return this; }
+  TreeMapItem* current() const { return _current; }
+  TreeMapItemList selection() const { return _selection; }
+  bool isSelected(TreeMapItem* i) const;
+  int maxSelectDepth() const { return _maxSelectDepth; }
+  SelectionMode selectionMode() const { return _selectionMode; }
+
+  /**
+   * Return tooltip string to show for a item (can be rich text)
+   * Default implementation gives lines with "text0 (text1)" going to root.
+   */
+  virtual TQString tipString(TreeMapItem* i) const;
+
+  /**
+   * Redraws an item with all children.
+   * This takes changed values(), sums(), colors() and text() into account.
+   */
+  void redraw(TreeMapItem*);
+  void redraw() { redraw(_base); }
+
+  /**
+   * Resort all TreeMapItems. See TreeMapItem::resort().
+   */
+  void resort() { _base->resort(true); }
+
+  // internal
+  void drawTreeMap();
+
+  // used internally when items are destroyed
+  void deletingItem(TreeMapItem*);
+
+protected slots:
+  void splitActivated(int);
+  void selectionActivated(int);
+  void fieldStopActivated(int);
+  void areaStopActivated(int);
+  void depthStopActivated(int);
+  void visualizationActivated(int);
+
+signals:
+  void selectionChanged();
+  void selectionChanged(TreeMapItem*);
+
+  /**
+   * This signal is emitted if the current item changes.
+   * If the change is done because of keyboard navigation,
+   * the <kbd> is set to true
+   */
+  void currentChanged(TreeMapItem*, bool keyboard);
+  void clicked(TreeMapItem*);
+  void returnPressed(TreeMapItem*);
+  void doubleClicked(TreeMapItem*);
+  void rightButtonPressed(TreeMapItem*, const TQPoint &);
+  void contextMenuRequested(TreeMapItem*, const TQPoint &);
+
+protected:
+  void mousePressEvent( TQMouseEvent * );
+  void contextMenuEvent( TQContextMenuEvent * );
+  void mouseReleaseEvent( TQMouseEvent * );
+  void mouseMoveEvent( TQMouseEvent * );
+  void mouseDoubleClickEvent( TQMouseEvent * );
+  void keyPressEvent( TQKeyEvent* );
+  void paintEvent( TQPaintEvent * );
+  void resizeEvent( TQResizeEvent * );
+  void showEvent( TQShowEvent * );
+  void fontChange( const TQFont& );
+
+private:
+  TreeMapItemList diff(TreeMapItemList&, TreeMapItemList&);
+  // returns true if selection changed
+  TreeMapItem* setTmpSelected(TreeMapItem*, bool selected = true);
+  TreeMapItem* setTmpRangeSelection(TreeMapItem* i1,
+				    TreeMapItem* i2, bool selected);
+  bool isTmpSelected(TreeMapItem* i);
+
+  void drawItem(TQPainter* p, TreeMapItem*);
+  void drawItems(TQPainter* p, TreeMapItem*);
+  bool horizontal(TreeMapItem* i, const TQRect& r);
+  void drawFill(TreeMapItem*,TQPainter* p, TQRect& r);
+  void drawFill(TreeMapItem*,TQPainter* p, TQRect& r,
+                TreeMapItemListIterator it, int len, bool goBack);
+  bool drawItemArray(TQPainter* p, TreeMapItem*, TQRect& r, double,
+                     TreeMapItemListIterator it, int len, bool);
+  bool resizeAttr(int);
+
+  TreeMapItem* _base;
+  TreeMapItem *_current, *_pressed, *_lastOver, *_oldCurrent;
+  TreeMapTip* _tip;
+  int _maxSelectDepth, _maxDrawingDepth;
+
+  // attributes for field, per textNo
+  struct FieldAttr {
+    TQString type, stop;
+    bool visible, forced;
+    DrawParams::Position pos;
+  };
+  TQValueVector<FieldAttr> _attr;
+
+  SelectionMode _selectionMode;
+  TreeMapItem::SplitMode _splitMode;
+  int _visibleWidth, _stopArea, _minimalArea, _borderWidth;
+  bool _reuseSpace, _skipIncorrectBorder, _drawSeparators, _shading;
+  bool _allowRotation;  
+  bool _transparent[4], _drawFrame[4];
+  TreeMapItem * _needsRefresh;
+  TreeMapItemList _selection;
+  int _markNo;
+
+  // for the context menus: start IDs
+  int _splitID, _selectionID, _visID;
+  int _fieldStopID, _areaStopID, _depthStopID;
+  TreeMapItem* _menuItem;
+
+  // temporary selection while dragging, used for drawing
+  // most of the time, _selection == _tmpSelection
+  TreeMapItemList _tmpSelection;
+  bool _inShiftDrag, _inControlDrag;
+
+  // temporary widget font metrics while drawing
+  TQFont _font;
+  int _fontHeight;
+
+  // back buffer pixmap
+  TQPixmap _pixmap;
+};
+
+#endif
diff --git a/kdecachegrind/kdecachegrind/utils.cpp b/kdecachegrind/kdecachegrind/utils.cpp
new file mode 100644
index 0000000..65c7e34
--- /dev/null
+++ b/kdecachegrind/kdecachegrind/utils.cpp
@@ -0,0 +1,483 @@
+/* This file is part of KCachegrind.
+   Copyright (C) 2003 Josef Weidendorfer <Josef.Weidendorfer@gmx.de>
+
+   KCachegrind 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, version 2.
+
+   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; see the file COPYING.  If not, write to
+   the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+   Boston, MA 02110-1301, USA.
+*/
+
+/*
+ * Utility classes for KCachegrind
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#ifdef HAVE_MMAP
+#include <unistd.h>
+#include <sys/mman.h>
+#endif
+
+#include <tqfile.h>
+#include <errno.h>
+
+#include "utils.h"
+
+
+// class FixString
+
+FixString::FixString(const char* str, int len)
+{
+    _str = str;
+    _len = len;
+}
+
+bool FixString::stripFirst(char& c)
+{
+    if (!_len) {
+	c = 0;
+	return false;
+    }
+
+    c = *_str;
+    _str++;
+    _len--;
+    return true;
+ }
+
+bool FixString::stripPrefix(const char* p)
+{
+    if (_len == 0) return false;
+    if (!p || (*p != *_str)) return false;
+
+    const char* s = _str+1;
+    int l = _len-1;
+    p++;
+    while(*p) {
+	if (l==0) return false;
+	if (*s != *p) return false;
+	p++;
+	s++;
+	l--;
+    }
+    _str = s;
+    _len = l;
+    return true;
+}
+
+
+// this parses hexadecimal (with prefix '0x' too)
+bool FixString::stripUInt(unsigned int& v, bool stripSpaces)
+{
+    if (_len==0) {
+	v = 0;
+	return false;
+    }
+
+    char c = *_str;
+    if (c<'0' || c>'9') {
+	v = 0;
+	return false;
+    }
+
+    v = c-'0';
+    const char* s = _str+1;
+    int l = _len-1;
+    c = *s;
+
+    if ((l>0) && (c == 'x') && (v==0)) {
+	// hexadecimal
+	s++;
+	c = *s;
+	l--;
+
+	while(l>0) {
+	    if (c>='0' && c<='9')
+		v = 16*v + (c-'0');
+	    else if (c>='a' && c<='f')
+		v = 16*v + 10 + (c-'a');
+	    else if (c>='A' && c<='F')
+		v = 16*v + 10 + (c-'A');
+	    else
+		break;
+	    s++;
+	    c = *s;
+	    l--;
+	}
+    }
+    else {
+	// decimal
+
+	while(l>0) {
+	    if (c<'0' || c>'9') break;
+	    v = 10*v + (c-'0');
+	    s++;
+	    c = *s;
+	    l--;
+	}
+    }
+
+    if (stripSpaces)
+      while(l>0) {
+        if (c != ' ') break;
+        s++;
+        c = *s;
+        l--;
+      }
+
+    _str = s;
+    _len = l;
+    return true;
+}
+
+
+void FixString::stripSurroundingSpaces()
+{
+    if (_len==0) return;
+
+    // leading spaces
+    while((_len>0) && (*_str==' ')) {
+	_len--;
+	_str++;
+    }
+
+    // trailing spaces
+    while((_len>0) && (_str[_len-1]==' ')) {
+	_len--;
+    }
+}
+
+void FixString::stripSpaces()
+{
+    while((_len>0) && (*_str==' ')) {
+	_len--;
+	_str++;
+    }
+}
+
+bool FixString::stripName(FixString& s)
+{
+    if (_len==0) return false;
+
+    // first char has to be a letter or "_"
+    if (!TQChar(*_str).isLetter() && (*_str != '_')) return false;
+
+    int newLen = 1;
+    const char* newStr = _str;
+
+    _str++;
+    _len--;
+
+    while(_len>0) {
+      if (!TQChar(*_str).isLetterOrNumber()
+	  && (*_str != '_')) break;
+
+      newLen++;
+      _str++;
+      _len--;
+    }
+    
+    s.set(newStr, newLen);
+    return true;
+}
+
+FixString FixString::stripUntil(char c)
+{
+  if (_len == 0) return FixString();
+
+  const char* newStr = _str;
+  int newLen = 0;
+
+  while(_len>0) {
+    if (*_str == c) {
+      _str++;
+      _len--;
+      break;
+    }
+    
+    _str++;
+    _len--;
+    newLen++;
+  }
+  return FixString(newStr, newLen);
+}
+
+bool FixString::stripUInt64(uint64& v, bool stripSpaces)
+{
+    if (_len==0) {
+	v = 0;
+	return false;
+    }
+
+    char c = *_str;
+    if (c<'0' || c>'9') {
+	v = 0;
+	return false;
+    }
+
+    v = c-'0';
+    const char* s = _str+1;
+    int l = _len-1;
+    c = *s;
+
+    if ((l>0) && (c == 'x') && (v==0)) {
+	// hexadecimal
+	s++;
+	c = *s;
+	l--;
+
+	while(l>0) {
+	    if (c>='0' && c<='9')
+		v = 16*v + (c-'0');
+	    else if (c>='a' && c<='f')
+		v = 16*v + 10 + (c-'a');
+	    else if (c>='A' && c<='F')
+		v = 16*v + 10 + (c-'A');
+	    else
+		break;
+	    s++;
+	    c = *s;
+	    l--;
+	}
+    }
+    else {
+      // decimal
+      while(l>0) {
+	if (c<'0' || c>'9') break;
+	v = 10*v + (c-'0');
+	s++;
+	c = *s;
+	l--;
+      }
+    }
+
+    if (stripSpaces)
+      while(l>0) {
+        if (c != ' ') break;
+        s++;
+        c = *s;
+        l--;
+      }
+
+    _str = s;
+    _len = l;
+    return true;
+}
+
+
+bool FixString::stripInt64(int64& v, bool stripSpaces)
+{
+    if (_len==0) {
+	v = 0;
+	return false;
+    }
+
+    char c = *_str;
+    if (c<'0' || c>'9') {
+	v = 0;
+	return false;
+    }
+
+    v = c-'0';
+    const char* s = _str+1;
+    int l = _len-1;
+    c = *s;
+
+    if ((l>0) && (c == 'x') && (v==0)) {
+	// hexadecimal
+	s++;
+	c = *s;
+	l--;
+
+	while(l>0) {
+	    if (c>='0' && c<='9')
+		v = 16*v + (c-'0');
+	    else if (c>='a' && c<='f')
+		v = 16*v + 10 + (c-'a');
+	    else if (c>='A' && c<='F')
+		v = 16*v + 10 + (c-'A');
+	    else
+		break;
+	    s++;
+	    c = *s;
+	    l--;
+	}
+    }
+    else {
+      // decimal
+
+      while(l>0) {
+	if (c<'0' || c>'9') break;
+	v = 10*v + (c-'0');
+	s++;
+	c = *s;
+	l--;
+      }
+    }
+
+    if (stripSpaces)
+      while(l>0) {
+        if (c != ' ') break;
+        s++;
+        c = *s;
+        l--;
+      }
+
+    _str = s;
+    _len = l;
+    return true;
+}
+
+
+
+// class FixFile
+
+FixFile::FixFile(TQFile* file)
+{
+  if (!file) {
+    _len = 0;
+    _currentLeft = 0;
+    _openError = true;
+    return;
+  }
+
+  _filename = file->name();
+  if (!file->isOpen() && !file->open( IO_ReadOnly ) ) {
+    qWarning( "%s: %s", (const char*) TQFile::encodeName(_filename),
+	      strerror( errno ) );
+    _len = 0;
+    _currentLeft = 0;
+    _openError = true;
+    return;
+  }
+
+  _openError = false;
+  _used_mmap = false;
+
+#ifdef HAVE_MMAP
+    char *addr = 0;
+    size_t len = file->size();
+    if (len>0) addr = (char *) mmap( addr, len,
+                                     PROT_READ, MAP_PRIVATE,
+                                     file->handle(), 0 );
+    if (addr && (addr != MAP_FAILED)) {
+      // mmap succeeded
+        _base = addr;
+        _len = len;
+	_used_mmap = true;
+
+	if (0) qDebug("Mapped '%s'", _filename.ascii());
+    } else {
+#endif // HAVE_MMAP
+        // try reading the data into memory instead
+        _data = file->readAll();
+        _base = _data.data();
+        _len  = _data.size();
+#ifdef HAVE_MMAP
+    }
+#endif // HAVE_MMAP
+
+    _current     = _base;
+    _currentLeft = _len;
+}
+
+FixFile::~FixFile()
+{
+    // if the file was read into _data, it will be deleted automatically
+
+#ifdef HAVE_MMAP
+    if (_used_mmap) {
+	if (0) qDebug("Unmapping '%s'", _filename.ascii());
+	if (munmap(_base, _len) != 0)
+	    qWarning( "munmap: %s", strerror( errno ) );
+    }
+#endif // HAVE_MMAP
+}
+
+bool FixFile::nextLine(FixString& str)
+{
+    if (_currentLeft == 0) return false;
+
+    unsigned left = _currentLeft;
+    char* current = _current;
+
+    while(left>0) {
+	if (*current == 0 || *current == '\n') break;
+	current++;
+	left--;
+    }
+
+    if (0) {
+	char tmp[200];
+	int l = _currentLeft-left;
+	if (l>199) l = 199;
+	strncpy(tmp, _current, l);
+	tmp[l] = 0;
+	qDebug("[FixFile::nextLine] At %d, len %d: '%s'",
+	       _current - _base, _currentLeft-left, tmp);
+    }
+
+    str.set(_current, _currentLeft-left);
+
+    if (*current == '\n') {
+	current++;
+	left--;
+    }
+    _current = current;
+    _currentLeft = left;
+
+    return true;
+}
+
+bool FixFile::setCurrent(unsigned pos)
+{
+    if (pos > _len) return false;
+
+    _current = _base + pos;
+    _currentLeft = _len - pos;
+    return true;
+}
+
+
+#if 0
+
+// class AppendList
+
+
+AppendList::AppendList()
+{
+  _next = 0;
+  _current = 0;
+  _last = 0;
+
+  _count = 0;
+  _currentIndex = 0;
+  _lastIndex = 0;
+  _autoDelete = false;
+}
+
+
+void AppendList::clear()
+{
+  int count = _count;
+  int i;
+
+  if (count <= firstLen) {
+    if (_autoDelete)
+      for (i=0;i<count;i++)
+        delete _first[i];
+  }
+}
+
+#endif
diff --git a/kdecachegrind/kdecachegrind/utils.h b/kdecachegrind/kdecachegrind/utils.h
new file mode 100644
index 0000000..7256f05
--- /dev/null
+++ b/kdecachegrind/kdecachegrind/utils.h
@@ -0,0 +1,164 @@
+/* This file is part of KCachegrind.
+   Copyright (C) 2003 Josef Weidendorfer <Josef.Weidendorfer@gmx.de>
+
+   KCachegrind 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, version 2.
+
+   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; see the file COPYING.  If not, write to
+   the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+   Boston, MA 02110-1301, USA.
+*/
+
+/*
+ * Utility classes for KCachegrind
+ */
+
+#ifndef UTILS_H
+#define UTILS_H
+
+#include <tqstring.h>
+
+class TQFile;
+
+typedef unsigned long long uint64;
+typedef long long int64;
+
+/**
+ * A simple, constant string class
+ *
+ * For use with zero-copy strings from mapped files.
+ */
+class FixString {
+
+ public:
+    // constructor for an invalid string
+    FixString() { _len = 0; _str = 0; }
+
+    /**
+     * FixString never does a deep copy! You have to make sure that
+     * the string starting at the char pointer is valid trough the
+     * lifetime of FixString.
+     */
+    FixString(const char*, int len);
+
+    int len() { return _len; }
+    const char* ascii() { return _str; }
+    bool isEmpty() { return _len == 0; }
+    bool isValid() { return _str != 0; }
+
+    // sets <c> to first character and returns true if length >0
+    bool first(char& c)
+	{ if (_len==0) return false; c=_str[0]; return true; }
+
+    void set(const char* s, int l) { _str=s; _len=l; }
+    bool stripFirst(char&);
+    bool stripPrefix(const char*);
+
+    /**
+     * Strip leading and trailing spaces
+     */
+    void stripSurroundingSpaces();
+
+    /**
+     * Strip leading spaces
+     */
+    void stripSpaces();
+
+    /**
+     * Strip name: [A-Za-z_][0-9A_Za-z_]*
+     */
+    bool stripName(FixString&);
+
+    /**
+     * Strip string until char appears or end. Strips char, too.
+     */
+    FixString stripUntil(char);
+
+    bool stripUInt(uint&, bool stripSpaces = true);
+    bool stripUInt64(uint64&, bool stripSpaces = true);
+    bool stripInt64(int64&, bool stripSpaces = true);
+
+    operator TQString() const
+	{ return TQString::fromLatin1(_str,_len); }
+
+ private:
+    const char* _str;
+    int _len;
+};
+
+
+/**
+ * A class for fast line by line reading of a read-only ASCII file
+ */
+class FixFile {
+
+ public:
+    FixFile(TQFile*);
+    ~FixFile();
+
+    /**
+     * Read next line into <str>. Returns false on error or EOF.
+     */
+    bool nextLine(FixString& str);
+    bool exists() { return !_openError; }
+    unsigned len() { return _len; }
+    unsigned current() { return _current - _base; }
+    bool setCurrent(unsigned pos);
+    void rewind() { setCurrent(0); }
+
+ private:
+    char *_base, *_current;
+    TQByteArray _data;
+    unsigned _len, _currentLeft;
+    bool _used_mmap, _openError;
+    TQString _filename;
+};
+
+
+/**
+ * A list of pointers, only able to append items.
+ * Optimized for speed, not space.
+ */
+template<class type>
+class AppendList {
+
+ public:
+  AppendList();
+    ~AppendList() { clear(); }
+
+    void setAutoDelete(bool);
+    void clear();
+    void append(const type*);
+
+    unsigned count() const { return _count; }
+    unsigned containsRef(const type*) const;
+
+    type* current();
+    type* first();
+    type* next();
+
+ private:
+    static const int firstLen = 8;
+    static const int maxLen = 256;
+
+    struct AppendListChunk {
+	int size;
+	struct AppendListChunk* next;
+	type* data[1];
+    };
+
+    struct AppendListChunk *_next, *_current, *_last;
+    int _count, _currentIndex, _lastIndex;
+    bool _autoDelete;
+    type* _first[firstLen];
+};
+
+
+#endif
diff --git a/kdecachegrind/kdecachegrind/x-kcachegrind.desktop b/kdecachegrind/kdecachegrind/x-kcachegrind.desktop
new file mode 100644
index 0000000..b9bf93a
--- /dev/null
+++ b/kdecachegrind/kdecachegrind/x-kcachegrind.desktop
@@ -0,0 +1,44 @@
+[Desktop Entry]
+Comment=Cachegrind/Callgrind Profile Dump
+Comment[ca]=Resultat del anàlisis de Cachegrind/Callgring
+Comment[cs]=Data profilace Cachegrind/Callgrind
+Comment[cy]=Tomen Proffil Cachegrind/Callgrind
+Comment[da]=Cachegrind/Callgrind profile-dump
+Comment[de]=Cachegrind/Callgrind Profil-Ausgabe
+Comment[el]=Αποτύπωση προφίλ Cachegrind/Callgrind
+Comment[es]=Resultado de análisis de Cachegrind/Callgring
+Comment[et]=Cachegrind/Callgrind profileerimistõmmis
+Comment[eu]=Cachegrind/Callgrind profil iraulketa
+Comment[fa]=تخلیۀ Profile Cachegrind/Callgrind
+Comment[fi]=Cachegrind/Callgrind-profiilivedos
+Comment[fr]=Dépôt de profil Cachegrind / Callgrind
+Comment[gl]=Resultado da análise de Cachegrind/Callgrind
+Comment[hi]=केश-ग्रिंड/काल-ग्रिंड प्रोफ़ाइल डम्प
+Comment[hu]=Cachegrind/Callgrind teljesítményprofil-fájl
+Comment[is]=Niðurstaða afkastakönnunar á Cachegrind/Callgrind
+Comment[it]=Dump del profilo di Cachegrind/Callgrind
+Comment[ja]=Callgrind/Callgrind プロファイルダンプ
+Comment[ka]=Cachegrind/Callgrind პროფილის დამპი
+Comment[kk]=Cachegrind/Callgrind профилінің дампы
+Comment[nds]=Cachegrind/Callgrind-Profilutgaav
+Comment[ne]=Cachegrind/Callgrind प्रोफाइल डम्प
+Comment[nl]=Cachegrind/Callgrind Profieldump
+Comment[nn]=Cachegrind/Callgrind-profildump
+Comment[pl]=Zrzut profilowania Cachegrind/Callgrind
+Comment[pt]=Resultado da Análise do Cachegrind/Callgrind
+Comment[pt_BR]=Depósito de Perfil Cachegrind/Callgrind
+Comment[ru]=Дамп профилирования Cachegrind/Callgrind
+Comment[sk]=Výpis volaní Cachegrind/Callgrind
+Comment[sr]=Cachegrind-ов/Callgrind-ов избачај профила
+Comment[sr@Latn]=Cachegrind-ov/Callgrind-ov izbačaj profila
+Comment[sv]=Profileringsdump från Cachegrind/Callgrind
+Comment[ta]=இடைமாற்றகட்டம்/ அழைப்பு கட்டம் விவரக்குறி திணிப்பு
+Comment[tg]=Дампи профилкунии Cachegrind/Callgrind
+Comment[uk]=Звалювання профілювання Cachegrind/Callgrind
+Comment[zh_CN]=Cachegrind/Callgrind 配置文件转存
+Comment[zh_TW]=Cachegrind/Callgrind 分析資料傾印
+DefaultApp=kdecachegrind
+Icon=kdecachegrind
+Type=MimeType
+MimeType=application/x-kcachegrind
+Patterns=cachegrind.out*;callgrind.out*
diff --git a/kdecachegrind/tests/cg-badcompression1 b/kdecachegrind/tests/cg-badcompression1
new file mode 100644
index 0000000..6076bf9
--- /dev/null
+++ b/kdecachegrind/tests/cg-badcompression1
@@ -0,0 +1,17 @@
+# Test with bad callgrind format
+# Expected:
+#  :13 - Redefinition of compressed file index 2 (was 'file1.c') to ''
+#  :14 - Redefinition of compressed function index 1 (was 'main') to 'main2'
+#  :16 - Undefined compressed function index 2
+#  :16 - Invalid function, setting to unknown
+
+events: Ir
+
+fl=(2) file1.c
+fn=(1) main
+10 9
+fl=(2 ) 
+fn=(1) main2
+11 1
+fn=(2)
+12 1
diff --git a/kdecachegrind/tests/cg-badcostline1 b/kdecachegrind/tests/cg-badcostline1
new file mode 100644
index 0000000..224ff67
--- /dev/null
+++ b/kdecachegrind/tests/cg-badcostline1
@@ -0,0 +1,11 @@
+# Test with bad callgrind format
+# Expected:
+#  :10 - ignored garbage at end of cost line ('30')
+#  :11 - ignored garbage at end of cost line ('hello')
+
+events: Ir
+
+fn=main
+10 20 30
+11 hello
+12 10                     
diff --git a/kdecachegrind/tests/cg-badposition b/kdecachegrind/tests/cg-badposition
new file mode 100644
index 0000000..1be582c
--- /dev/null
+++ b/kdecachegrind/tests/cg-badposition
@@ -0,0 +1,15 @@
+# Test with bad callgrind format
+# Expected:
+#  :11 - Negative line number -20
+#  :12 - Garbage at end of cost line ('a 21')
+#  :13 - Negative line number -91
+#  :15 - Invalid line 'aa 40'
+
+events: Ir
+
+fn=main
+-20 1
+9a 21
+-100 20
+0x9a 30
+aa 40
diff --git a/kdecachegrind/version.h.in b/kdecachegrind/version.h.in
new file mode 100644
index 0000000..d88081b
--- /dev/null
+++ b/kdecachegrind/version.h.in
@@ -0,0 +1 @@
+#define KCACHEGRIND_VERSION "@KCACHEGRIND_VERSION@"