tCorrectly commit the 3rdparty code - sailfish-safe - Sailfish frontend for safe(1)
 (HTM) git clone git://git.z3bra.org/sailfish-safe.git
 (DIR) Log
 (DIR) Files
 (DIR) Refs
 (DIR) README
 (DIR) LICENSE
       ---
 (DIR) commit c4b4cd735668f3a768b1d9fab0b4811c249a5148
 (DIR) parent baf991466ec058c55a8245efafc02903b8476826
 (HTM) Author: Daniel Vrátil <dvratil@kde.org>
       Date:   Thu,  7 Feb 2019 19:05:17 +0100
       
       Correctly commit the 3rdparty code
       
       Diffstat:
         D .gitmodules                         |       3 ---
         D 3rdparty/kitemmodels                |       1 -
         A 3rdparty/kitemmodels/COPYING.LIB    |     510 +++++++++++++++++++++++++++++++
         A 3rdparty/kitemmodels/README.md      |       4 ++++
         A 3rdparty/kitemmodels/kbihash_p.h    |     624 +++++++++++++++++++++++++++++++
         A 3rdparty/kitemmodels/kdescendantsp… |    1001 +++++++++++++++++++++++++++++++
         A 3rdparty/kitemmodels/kdescendantsp… |     206 +++++++++++++++++++++++++++++++
       
       7 files changed, 2345 insertions(+), 4 deletions(-)
       ---
 (DIR) diff --git a/.gitmodules b/.gitmodules
       t@@ -1,3 +0,0 @@
       -[submodule "3rdparty/kitemmodels"]
       -        path = 3rdparty/kitemmodels
       -        url = git://anongit.kde.org/kitemmodels.git
 (DIR) diff --git a/3rdparty/kitemmodels b/3rdparty/kitemmodels
       t@@ -1 +0,0 @@
       -Subproject commit 18244542c2bc895dfd1615468eb917aae06519ab
 (DIR) diff --git a/3rdparty/kitemmodels/COPYING.LIB b/3rdparty/kitemmodels/COPYING.LIB
       t@@ -0,0 +1,510 @@
       +
       +                  GNU LESSER GENERAL PUBLIC LICENSE
       +                       Version 2.1, February 1999
       +
       + Copyright (C) 1991, 1999 Free Software Foundation, Inc.
       +        51 Franklin St, 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.
       +
       +[This is the first released version of the Lesser GPL.  It also counts
       + as the successor of the GNU Library Public License, version 2, hence
       + the version number 2.1.]
       +
       +                            Preamble
       +
       +  The licenses for most software are designed to take away your
       +freedom to share and change it.  By contrast, the GNU General Public
       +Licenses are intended to guarantee your freedom to share and change
       +free software--to make sure the software is free for all its users.
       +
       +  This license, the Lesser General Public License, applies to some
       +specially designated software packages--typically libraries--of the
       +Free Software Foundation and other authors who decide to use it.  You
       +can use it too, but we suggest you first think carefully about whether
       +this license or the ordinary General Public License is the better
       +strategy to use in any particular case, based on the explanations
       +below.
       +
       +  When we speak of free software, we are referring to freedom of use,
       +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 and use pieces of
       +it in new free programs; and that you are informed that you can do
       +these things.
       +
       +  To protect your rights, we need to make restrictions that forbid
       +distributors to deny you these rights or to ask you to surrender these
       +rights.  These restrictions translate to certain responsibilities for
       +you if you distribute copies of the library or if you modify it.
       +
       +  For example, if you distribute copies of the library, whether gratis
       +or for a fee, you must give the recipients all the rights that we gave
       +you.  You must make sure that they, too, receive or can get the source
       +code.  If you link other code with the library, you must provide
       +complete object files to the recipients, so that they can relink them
       +with the library after making changes to the library and recompiling
       +it.  And you must show them these terms so they know their rights.
       +
       +  We protect your rights with a two-step method: (1) we copyright the
       +library, and (2) we offer you this license, which gives you legal
       +permission to copy, distribute and/or modify the library.
       +
       +  To protect each distributor, we want to make it very clear that
       +there is no warranty for the free library.  Also, if the library is
       +modified by someone else and passed on, the recipients should know
       +that what they have is not the original version, so that the original
       +author's reputation will not be affected by problems that might be
       +introduced by others.
       +
       +  Finally, software patents pose a constant threat to the existence of
       +any free program.  We wish to make sure that a company cannot
       +effectively restrict the users of a free program by obtaining a
       +restrictive license from a patent holder.  Therefore, we insist that
       +any patent license obtained for a version of the library must be
       +consistent with the full freedom of use specified in this license.
       +
       +  Most GNU software, including some libraries, is covered by the
       +ordinary GNU General Public License.  This license, the GNU Lesser
       +General Public License, applies to certain designated libraries, and
       +is quite different from the ordinary General Public License.  We use
       +this license for certain libraries in order to permit linking those
       +libraries into non-free programs.
       +
       +  When a program is linked with a library, whether statically or using
       +a shared library, the combination of the two is legally speaking a
       +combined work, a derivative of the original library.  The ordinary
       +General Public License therefore permits such linking only if the
       +entire combination fits its criteria of freedom.  The Lesser General
       +Public License permits more lax criteria for linking other code with
       +the library.
       +
       +  We call this license the "Lesser" General Public License because it
       +does Less to protect the user's freedom than the ordinary General
       +Public License.  It also provides other free software developers Less
       +of an advantage over competing non-free programs.  These disadvantages
       +are the reason we use the ordinary General Public License for many
       +libraries.  However, the Lesser license provides advantages in certain
       +special circumstances.
       +
       +  For example, on rare occasions, there may be a special need to
       +encourage the widest possible use of a certain library, so that it
       +becomes a de-facto standard.  To achieve this, non-free programs must
       +be allowed to use the library.  A more frequent case is that a free
       +library does the same job as widely used non-free libraries.  In this
       +case, there is little to gain by limiting the free library to free
       +software only, so we use the Lesser General Public License.
       +
       +  In other cases, permission to use a particular library in non-free
       +programs enables a greater number of people to use a large body of
       +free software.  For example, permission to use the GNU C Library in
       +non-free programs enables many more people to use the whole GNU
       +operating system, as well as its variant, the GNU/Linux operating
       +system.
       +
       +  Although the Lesser General Public License is Less protective of the
       +users' freedom, it does ensure that the user of a program that is
       +linked with the Library has the freedom and the wherewithal to run
       +that program using a modified version of the Library.
       +
       +  The precise terms and conditions for copying, distribution and
       +modification follow.  Pay close attention to the difference between a
       +"work based on the library" and a "work that uses the library".  The
       +former contains code derived from the library, whereas the latter must
       +be combined with the library in order to run.
       +
       +                  GNU LESSER GENERAL PUBLIC LICENSE
       +   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
       +
       +  0. This License Agreement applies to any software library or other
       +program which contains a notice placed by the copyright holder or
       +other authorized party saying it may be distributed under the terms of
       +this Lesser General Public License (also called "this License").
       +Each licensee is addressed as "you".
       +
       +  A "library" means a collection of software functions and/or data
       +prepared so as to be conveniently linked with application programs
       +(which use some of those functions and data) to form executables.
       +
       +  The "Library", below, refers to any such software library or work
       +which has been distributed under these terms.  A "work based on the
       +Library" means either the Library or any derivative work under
       +copyright law: that is to say, a work containing the Library or a
       +portion of it, either verbatim or with modifications and/or translated
       +straightforwardly into another language.  (Hereinafter, translation is
       +included without limitation in the term "modification".)
       +
       +  "Source code" for a work means the preferred form of the work for
       +making modifications to it.  For a library, 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 library.
       +
       +  Activities other than copying, distribution and modification are not
       +covered by this License; they are outside its scope.  The act of
       +running a program using the Library is not restricted, and output from
       +such a program is covered only if its contents constitute a work based
       +on the Library (independent of the use of the Library in a tool for
       +writing it).  Whether that is true depends on what the Library does
       +and what the program that uses the Library does.
       +
       +  1. You may copy and distribute verbatim copies of the Library's
       +complete 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 distribute a copy of this License along with the
       +Library.
       +
       +  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 Library or any portion
       +of it, thus forming a work based on the Library, 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) The modified work must itself be a software library.
       +
       +    b) You must cause the files modified to carry prominent notices
       +    stating that you changed the files and the date of any change.
       +
       +    c) You must cause the whole of the work to be licensed at no
       +    charge to all third parties under the terms of this License.
       +
       +    d) If a facility in the modified Library refers to a function or a
       +    table of data to be supplied by an application program that uses
       +    the facility, other than as an argument passed when the facility
       +    is invoked, then you must make a good faith effort to ensure that,
       +    in the event an application does not supply such function or
       +    table, the facility still operates, and performs whatever part of
       +    its purpose remains meaningful.
       +
       +    (For example, a function in a library to compute square roots has
       +    a purpose that is entirely well-defined independent of the
       +    application.  Therefore, Subsection 2d requires that any
       +    application-supplied function or table used by this function must
       +    be optional: if the application does not supply it, the square
       +    root function must still compute square roots.)
       +
       +These requirements apply to the modified work as a whole.  If
       +identifiable sections of that work are not derived from the Library,
       +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 Library, 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 Library.
       +
       +In addition, mere aggregation of another work not based on the Library
       +with the Library (or with a work based on the Library) on a volume of
       +a storage or distribution medium does not bring the other work under
       +the scope of this License.
       +
       +  3. You may opt to apply the terms of the ordinary GNU General Public
       +License instead of this License to a given copy of the Library.  To do
       +this, you must alter all the notices that refer to this License, so
       +that they refer to the ordinary GNU General Public License, version 2,
       +instead of to this License.  (If a newer version than version 2 of the
       +ordinary GNU General Public License has appeared, then you can specify
       +that version instead if you wish.)  Do not make any other change in
       +these notices.
       +
       +  Once this change is made in a given copy, it is irreversible for
       +that copy, so the ordinary GNU General Public License applies to all
       +subsequent copies and derivative works made from that copy.
       +
       +  This option is useful when you wish to copy part of the code of
       +the Library into a program that is not a library.
       +
       +  4. You may copy and distribute the Library (or a portion or
       +derivative of it, under Section 2) in object code or executable form
       +under the terms of Sections 1 and 2 above provided that you 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.
       +
       +  If distribution of 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 satisfies the requirement to
       +distribute the source code, even though third parties are not
       +compelled to copy the source along with the object code.
       +
       +  5. A program that contains no derivative of any portion of the
       +Library, but is designed to work with the Library by being compiled or
       +linked with it, is called a "work that uses the Library".  Such a
       +work, in isolation, is not a derivative work of the Library, and
       +therefore falls outside the scope of this License.
       +
       +  However, linking a "work that uses the Library" with the Library
       +creates an executable that is a derivative of the Library (because it
       +contains portions of the Library), rather than a "work that uses the
       +library".  The executable is therefore covered by this License.
       +Section 6 states terms for distribution of such executables.
       +
       +  When a "work that uses the Library" uses material from a header file
       +that is part of the Library, the object code for the work may be a
       +derivative work of the Library even though the source code is not.
       +Whether this is true is especially significant if the work can be
       +linked without the Library, or if the work is itself a library.  The
       +threshold for this to be true is not precisely defined by law.
       +
       +  If such an object file uses only numerical parameters, data
       +structure layouts and accessors, and small macros and small inline
       +functions (ten lines or less in length), then the use of the object
       +file is unrestricted, regardless of whether it is legally a derivative
       +work.  (Executables containing this object code plus portions of the
       +Library will still fall under Section 6.)
       +
       +  Otherwise, if the work is a derivative of the Library, you may
       +distribute the object code for the work under the terms of Section 6.
       +Any executables containing that work also fall under Section 6,
       +whether or not they are linked directly with the Library itself.
       +
       +  6. As an exception to the Sections above, you may also combine or
       +link a "work that uses the Library" with the Library to produce a
       +work containing portions of the Library, and distribute that work
       +under terms of your choice, provided that the terms permit
       +modification of the work for the customer's own use and reverse
       +engineering for debugging such modifications.
       +
       +  You must give prominent notice with each copy of the work that the
       +Library is used in it and that the Library and its use are covered by
       +this License.  You must supply a copy of this License.  If the work
       +during execution displays copyright notices, you must include the
       +copyright notice for the Library among them, as well as a reference
       +directing the user to the copy of this License.  Also, you must do one
       +of these things:
       +
       +    a) Accompany the work with the complete corresponding
       +    machine-readable source code for the Library including whatever
       +    changes were used in the work (which must be distributed under
       +    Sections 1 and 2 above); and, if the work is an executable linked
       +    with the Library, with the complete machine-readable "work that
       +    uses the Library", as object code and/or source code, so that the
       +    user can modify the Library and then relink to produce a modified
       +    executable containing the modified Library.  (It is understood
       +    that the user who changes the contents of definitions files in the
       +    Library will not necessarily be able to recompile the application
       +    to use the modified definitions.)
       +
       +    b) Use a suitable shared library mechanism for linking with the
       +    Library.  A suitable mechanism is one that (1) uses at run time a
       +    copy of the library already present on the user's computer system,
       +    rather than copying library functions into the executable, and (2)
       +    will operate properly with a modified version of the library, if
       +    the user installs one, as long as the modified version is
       +    interface-compatible with the version that the work was made with.
       +
       +    c) Accompany the work with a written offer, valid for at least
       +    three years, to give the same user the materials specified in
       +    Subsection 6a, above, for a charge no more than the cost of
       +    performing this distribution.
       +
       +    d) If distribution of the work is made by offering access to copy
       +    from a designated place, offer equivalent access to copy the above
       +    specified materials from the same place.
       +
       +    e) Verify that the user has already received a copy of these
       +    materials or that you have already sent this user a copy.
       +
       +  For an executable, the required form of the "work that uses the
       +Library" must include any data and utility programs needed for
       +reproducing the executable from it.  However, as a special exception,
       +the materials to be 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.
       +
       +  It may happen that this requirement contradicts the license
       +restrictions of other proprietary libraries that do not normally
       +accompany the operating system.  Such a contradiction means you cannot
       +use both them and the Library together in an executable that you
       +distribute.
       +
       +  7. You may place library facilities that are a work based on the
       +Library side-by-side in a single library together with other library
       +facilities not covered by this License, and distribute such a combined
       +library, provided that the separate distribution of the work based on
       +the Library and of the other library facilities is otherwise
       +permitted, and provided that you do these two things:
       +
       +    a) Accompany the combined library with a copy of the same work
       +    based on the Library, uncombined with any other library
       +    facilities.  This must be distributed under the terms of the
       +    Sections above.
       +
       +    b) Give prominent notice with the combined library of the fact
       +    that part of it is a work based on the Library, and explaining
       +    where to find the accompanying uncombined form of the same work.
       +
       +  8. You may not copy, modify, sublicense, link with, or distribute
       +the Library except as expressly provided under this License.  Any
       +attempt otherwise to copy, modify, sublicense, link with, or
       +distribute the Library 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.
       +
       +  9. 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 Library or its derivative works.  These actions are
       +prohibited by law if you do not accept this License.  Therefore, by
       +modifying or distributing the Library (or any work based on the
       +Library), you indicate your acceptance of this License to do so, and
       +all its terms and conditions for copying, distributing or modifying
       +the Library or works based on it.
       +
       +  10. Each time you redistribute the Library (or any work based on the
       +Library), the recipient automatically receives a license from the
       +original licensor to copy, distribute, link with or modify the Library
       +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 with
       +this License.
       +
       +  11. 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 Library at all.  For example, if a patent
       +license would not permit royalty-free redistribution of the Library 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 Library.
       +
       +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.
       +
       +  12. If the distribution and/or use of the Library is restricted in
       +certain countries either by patents or by copyrighted interfaces, the
       +original copyright holder who places the Library 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.
       +
       +  13. The Free Software Foundation may publish revised and/or new
       +versions of the Lesser 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 Library
       +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 Library does not specify a
       +license version number, you may choose any version ever published by
       +the Free Software Foundation.
       +
       +  14. If you wish to incorporate parts of the Library into other free
       +programs whose distribution conditions are incompatible with these,
       +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
       +
       +  15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
       +WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
       +EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
       +OTHER PARTIES PROVIDE THE LIBRARY "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
       +LIBRARY IS WITH YOU.  SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
       +THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
       +
       +  16. 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 LIBRARY 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
       +LIBRARY (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 LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), 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 Libraries
       +
       +  If you develop a new library, and you want it to be of the greatest
       +possible use to the public, we recommend making it free software that
       +everyone can redistribute and change.  You can do so by permitting
       +redistribution under these terms (or, alternatively, under the terms
       +of the ordinary General Public License).
       +
       +  To apply these terms, attach the following notices to the library.
       +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 library's name and a brief idea of what it does.>
       +    Copyright (C) <year>  <name of author>
       +
       +    This library is free software; you can redistribute it and/or
       +    modify it under the terms of the GNU Lesser General Public
       +    License as published by the Free Software Foundation; either
       +    version 2.1 of the License, or (at your option) any later version.
       +
       +    This library 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
       +    Lesser General Public License for more details.
       +
       +    You should have received a copy of the GNU Lesser General Public
       +    License along with this library; if not, write to the Free Software
       +    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
       +
       +Also add information on how to contact you by electronic and paper mail.
       +
       +You should also get your employer (if you work as a programmer) or
       +your school, if any, to sign a "copyright disclaimer" for the library,
       +if necessary.  Here is a sample; alter the names:
       +
       +  Yoyodyne, Inc., hereby disclaims all copyright interest in the
       +  library `Frob' (a library for tweaking knobs) written by James
       +  Random Hacker.
       +
       +  <signature of Ty Coon>, 1 April 1990
       +  Ty Coon, President of Vice
       +
       +That's all there is to it!
       +
       +
 (DIR) diff --git a/3rdparty/kitemmodels/README.md b/3rdparty/kitemmodels/README.md
       t@@ -0,0 +1,4 @@
       +The files here are part of KItemModels library by KDE.
       +
       +The entire source code of the library is available here: https://cgit.kde.org/kitemmodels.git
       +
 (DIR) diff --git a/3rdparty/kitemmodels/kbihash_p.h b/3rdparty/kitemmodels/kbihash_p.h
       t@@ -0,0 +1,624 @@
       +/*
       +
       +    Copyright (C) 2010 Klarälvdalens Datakonsult AB,
       +        a KDAB Group company, info@kdab.net,
       +        author Stephen Kelly <stephen@kdab.com>
       +
       +    This library is free software; you can redistribute it and/or modify it
       +    under the terms of the GNU Library General Public License as published by
       +    the Free Software Foundation; either version 2 of the License, or (at your
       +    option) any later version.
       +
       +    This library 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 Library General Public
       +    License for more details.
       +
       +    You should have received a copy of the GNU Library General Public License
       +    along with this library; see the file COPYING.LIB.  If not, write to the
       +    Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
       +    02110-1301, USA.
       +*/
       +
       +#ifndef KBIHASH_P_H
       +#define KBIHASH_P_H
       +
       +#include <QHash>
       +#include <QMap>
       +
       +#include <QDebug>
       +
       +template<typename LeftContainer, typename RightContainer>
       +class KBiAssociativeContainer;
       +
       +template<typename LeftContainer, typename RightContainer>
       +QDebug operator<<(QDebug out, const KBiAssociativeContainer<LeftContainer, RightContainer> &container);
       +
       +template<typename LeftContainer, typename RightContainer>
       +QDataStream &operator<<(QDataStream &out, const KBiAssociativeContainer<LeftContainer, RightContainer> &container);
       +
       +template<typename LeftContainer, typename RightContainer>
       +QDataStream &operator>>(QDataStream &in, KBiAssociativeContainer<LeftContainer, RightContainer> &container);
       +
       +template<typename LeftContainer, typename RightContainer>
       +class KBiAssociativeContainer
       +{
       +    // We need to convert from a QHash::iterator or QMap::iterator
       +    // to a KBiAssociativeContainer::iterator (left or right)
       +    // Do do that we use this implicit ctor. We partially specialize
       +    // it for QHash and QMap types.
       +    // Our iterator inherits from this struct to get the implicit ctor,
       +    // and this struct must inherit from the QHash or QMap iterator.
       +    template<typename Container, typename T, typename U>
       +    struct _iterator_impl_ctor : public Container::iterator {
       +        _iterator_impl_ctor(typename Container::iterator it);
       +    };
       +
       +    template<typename T, typename U>
       +    struct _iterator_impl_ctor<QHash<T, U>, T, U>  : public QHash<T, U>::iterator {
       +        /* implicit */ _iterator_impl_ctor(const typename QHash<T, U>::iterator it)
       +            : QHash<T, U>::iterator(it)
       +        {
       +
       +        }
       +    };
       +
       +    template<typename T, typename U>
       +    struct _iterator_impl_ctor<QMap<T, U>, T, U> : public QMap<T, U>::iterator {
       +        /* implicit */ _iterator_impl_ctor(const typename QMap<T, U>::iterator it)
       +            : QMap<T, U>::iterator(it)
       +        {
       +
       +        }
       +    };
       +public:
       +    typedef typename RightContainer::mapped_type left_type;
       +    typedef typename LeftContainer::mapped_type right_type;
       +
       +    template <typename Container>
       +    class _iterator : public _iterator_impl_ctor<Container, typename Container::key_type, typename Container::mapped_type>
       +    {
       +    public:
       +        explicit inline _iterator(void *data) : Container::iterator(data) {}
       +
       +        /* implicit */ _iterator(const typename Container::iterator it)
       +            : _iterator_impl_ctor<Container, typename Container::key_type, typename Container::mapped_type>(it)
       +        {
       +
       +        }
       +
       +        inline const typename Container::mapped_type &value() const
       +        {
       +            return Container::iterator::value();
       +        }
       +        inline const typename Container::mapped_type &operator*() const
       +        {
       +            return Container::iterator::operator*();
       +        }
       +        inline const typename Container::mapped_type *operator->() const
       +        {
       +            return Container::iterator::operator->();
       +        }
       +
       +    private:
       +#ifndef Q_CC_MSVC
       +        using Container::iterator::operator*;
       +        using Container::iterator::operator->;
       +        using Container::iterator::value;
       +#endif
       +    };
       +
       +    typedef _iterator<LeftContainer>                      left_iterator;
       +    typedef typename LeftContainer::const_iterator        left_const_iterator;
       +    typedef _iterator<RightContainer>                     right_iterator;
       +    typedef typename RightContainer::const_iterator       right_const_iterator;
       +
       +    inline KBiAssociativeContainer() {}
       +    inline KBiAssociativeContainer(const KBiAssociativeContainer<LeftContainer, RightContainer> &other)
       +    {
       +        *this = other;
       +    }
       +
       +    const KBiAssociativeContainer<LeftContainer, RightContainer> &operator=(const KBiAssociativeContainer<LeftContainer, RightContainer> &other)
       +    {
       +        _leftToRight = other._leftToRight; _rightToLeft = other._rightToLeft; return *this;
       +    }
       +
       +    inline bool removeLeft(left_type t)
       +    {
       +        const right_type u = _leftToRight.take(t);
       +        return _rightToLeft.remove(u) != 0;
       +    }
       +
       +    inline bool removeRight(right_type u)
       +    {
       +        const left_type t = _rightToLeft.take(u);
       +        return _leftToRight.remove(t) != 0;
       +    }
       +
       +    inline right_type takeLeft(left_type t)
       +    {
       +        const right_type u = _leftToRight.take(t);
       +        _rightToLeft.remove(u);
       +        return u;
       +    }
       +
       +    inline left_type takeRight(right_type u)
       +    {
       +        const left_type t = _rightToLeft.take(u);
       +        _leftToRight.remove(t);
       +        return t;
       +    }
       +
       +    inline left_type rightToLeft(right_type u) const
       +    {
       +        return _rightToLeft.value(u);
       +    }
       +
       +    inline right_type leftToRight(left_type t) const
       +    {
       +        return _leftToRight.value(t);
       +    }
       +
       +    inline bool leftContains(left_type t) const
       +    {
       +        return _leftToRight.contains(t);
       +    }
       +
       +    inline bool rightContains(right_type u) const
       +    {
       +        return _rightToLeft.contains(u);
       +    }
       +
       +    inline int size() const
       +    {
       +        return _leftToRight.size();
       +    }
       +
       +    inline int count() const
       +    {
       +        return _leftToRight.count();
       +    }
       +
       +    inline int capacity() const
       +    {
       +        return _leftToRight.capacity();
       +    }
       +
       +    void reserve(int size)
       +    {
       +        _leftToRight.reserve(size); _rightToLeft.reserve(size);
       +    }
       +
       +    inline void squeeze()
       +    {
       +        _leftToRight.squeeze(); _rightToLeft.squeeze();
       +    }
       +
       +    inline void detach()
       +    {
       +        _leftToRight.detach(); _rightToLeft.detach();
       +    }
       +
       +    inline bool isDetached() const
       +    {
       +        return _leftToRight.isDetached();
       +    }
       +
       +    inline void setSharable(bool sharable)
       +    {
       +        _leftToRight.setSharable(sharable); _rightToLeft.setSharable(sharable);
       +    }
       +
       +    inline bool isSharedWith(const KBiAssociativeContainer<RightContainer, LeftContainer> &other) const
       +    {
       +        return _leftToRight.isSharedWith(other._leftToRight) && _rightToLeft.isSharedWith(other._leftToRight);
       +    }
       +
       +    void clear()
       +    {
       +        _leftToRight.clear(); _rightToLeft.clear();
       +    }
       +
       +    QList<left_type> leftValues() const
       +    {
       +        return _leftToRight.keys();
       +    }
       +
       +    QList<right_type> rightValues() const
       +    {
       +        return _rightToLeft.keys();
       +    }
       +
       +    right_iterator eraseRight(right_iterator it)
       +    {
       +        Q_ASSERT(it != rightEnd());
       +        _leftToRight.remove(it.value());
       +        return _rightToLeft.erase(it);
       +    }
       +
       +    left_iterator eraseLeft(left_iterator it)
       +    {
       +        Q_ASSERT(it != leftEnd());
       +        _rightToLeft.remove(it.value());
       +        return _leftToRight.erase(it);
       +    }
       +
       +    left_iterator findLeft(left_type t)
       +    {
       +        return _leftToRight.find(t);
       +    }
       +
       +    left_const_iterator findLeft(left_type t) const
       +    {
       +        return _leftToRight.find(t);
       +    }
       +
       +    left_const_iterator constFindLeft(left_type t) const
       +    {
       +        return _leftToRight.constFind(t);
       +    }
       +
       +    right_iterator findRight(right_type u)
       +    {
       +        return _rightToLeft.find(u);
       +    }
       +
       +    right_const_iterator findRight(right_type u) const
       +    {
       +        return _rightToLeft.find(u);
       +    }
       +
       +    right_const_iterator constFindRight(right_type u) const
       +    {
       +        return _rightToLeft.find(u);
       +    }
       +
       +    left_iterator insert(left_type t, right_type u)
       +    {
       +        // biHash.insert(5, 7); // creates 5->7 in _leftToRight and 7->5 in _rightToLeft
       +        // biHash.insert(5, 9); // replaces 5->7 with 5->9 in _leftToRight and inserts 9->5 in _rightToLeft.
       +        // The 7->5 in _rightToLeft would be dangling, so we remove it before insertion.
       +
       +        // This means we need to hash u and t up to twice each. Could probably be done better using QHashNode.
       +
       +        if (_leftToRight.contains(t)) {
       +            _rightToLeft.remove(_leftToRight.take(t));
       +        }
       +        if (_rightToLeft.contains(u)) {
       +            _leftToRight.remove(_rightToLeft.take(u));
       +        }
       +
       +        _rightToLeft.insert(u, t);
       +        return _leftToRight.insert(t, u);
       +    }
       +
       +    KBiAssociativeContainer<LeftContainer, RightContainer> &intersect(const KBiAssociativeContainer<LeftContainer, RightContainer> &other)
       +    {
       +        typename KBiAssociativeContainer<RightContainer, LeftContainer>::left_iterator it = leftBegin();
       +        while (it != leftEnd()) {
       +            if (!other.leftContains(it.key())) {
       +                it = eraseLeft(it);
       +            } else {
       +                ++it;
       +            }
       +        }
       +        return *this;
       +    }
       +
       +    KBiAssociativeContainer<LeftContainer, RightContainer> &subtract(const KBiAssociativeContainer<LeftContainer, RightContainer> &other)
       +    {
       +        typename KBiAssociativeContainer<RightContainer, LeftContainer>::left_iterator it = leftBegin();
       +        while (it != leftEnd()) {
       +            if (other._leftToRight.contains(it.key())) {
       +                it = eraseLeft(it);
       +            } else {
       +                ++it;
       +            }
       +        }
       +        return *this;
       +    }
       +
       +    KBiAssociativeContainer<LeftContainer, RightContainer> &unite(const KBiAssociativeContainer<LeftContainer, RightContainer> &other)
       +    {
       +        typename LeftContainer::const_iterator it = other._leftToRight.constBegin();
       +        const typename LeftContainer::const_iterator end = other._leftToRight.constEnd();
       +        while (it != end) {
       +            const left_type key = it.key();
       +            if (!_leftToRight.contains(key)) {
       +                insert(key, it.value());
       +            }
       +            ++it;
       +        }
       +        return *this;
       +    }
       +
       +    void updateRight(left_iterator it, right_type u)
       +    {
       +        Q_ASSERT(it != leftEnd());
       +        const left_type key = it.key();
       +        _rightToLeft.remove(_leftToRight.value(key));
       +        _leftToRight[key] = u;
       +        _rightToLeft[u] = key;
       +    }
       +
       +    void updateLeft(right_iterator it, left_type t)
       +    {
       +        Q_ASSERT(it != rightEnd());
       +        const right_type key = it.key();
       +        _leftToRight.remove(_rightToLeft.value(key));
       +        _rightToLeft[key] = t;
       +        _leftToRight[t] = key;
       +    }
       +
       +    inline bool isEmpty() const
       +    {
       +        return _leftToRight.isEmpty();
       +    }
       +
       +    const right_type operator[](const left_type &t) const
       +    {
       +        return _leftToRight.operator[](t);
       +    }
       +
       +    bool operator==(const KBiAssociativeContainer<LeftContainer, RightContainer> &other)
       +    {
       +        return _leftToRight.operator == (other._leftToRight);
       +    }
       +
       +    bool operator!=(const KBiAssociativeContainer<LeftContainer, RightContainer> &other)
       +    {
       +        return _leftToRight.operator != (other._leftToRight);
       +    }
       +
       +    left_iterator toLeftIterator(right_iterator it) const
       +    {
       +        Q_ASSERT(it != rightEnd());
       +        return _leftToRight.find(it.value());
       +    }
       +
       +    right_iterator toRightIterator(left_iterator it) const
       +    {
       +        Q_ASSERT(it != leftEnd());
       +        return _rightToLeft.find(it.value());
       +    }
       +
       +    inline left_iterator leftBegin()
       +    {
       +        return _leftToRight.begin();
       +    }
       +
       +    inline left_iterator leftEnd()
       +    {
       +        return _leftToRight.end();
       +    }
       +
       +    inline left_const_iterator leftBegin() const
       +    {
       +        return _leftToRight.begin();
       +    }
       +
       +    inline left_const_iterator leftEnd() const
       +    {
       +        return _leftToRight.end();
       +    }
       +
       +    inline left_const_iterator leftConstBegin() const
       +    {
       +        return _leftToRight.constBegin();
       +    }
       +
       +    inline left_const_iterator leftConstEnd() const
       +    {
       +        return _leftToRight.constEnd();
       +    }
       +
       +    inline right_iterator rightBegin()
       +    {
       +        return _rightToLeft.begin();
       +    }
       +
       +    inline right_iterator rightEnd()
       +    {
       +        return _rightToLeft.end();
       +    }
       +
       +    inline right_const_iterator rightBegin() const
       +    {
       +        return _rightToLeft.begin();
       +    }
       +
       +    inline right_const_iterator rightEnd() const
       +    {
       +        return _rightToLeft.end();
       +    }
       +    inline right_const_iterator rightConstBegin() const
       +    {
       +        return _rightToLeft.constBegin();
       +    }
       +
       +    inline right_const_iterator rightConstEnd() const
       +    {
       +        return _rightToLeft.constEnd();
       +    }
       +
       +    static KBiAssociativeContainer<LeftContainer, RightContainer> fromHash(const QHash<left_type, right_type> &hash)
       +    {
       +        KBiAssociativeContainer<LeftContainer, RightContainer> container;
       +        typename QHash<left_type, right_type>::const_iterator it = hash.constBegin();
       +        const typename QHash<left_type, right_type>::const_iterator end = hash.constEnd();
       +        for (; it != end; ++it) {
       +            container.insert(it.key(), it.value());
       +        }
       +        return container;
       +    }
       +
       +    static KBiAssociativeContainer<LeftContainer, RightContainer> fromMap(const QMap<left_type, right_type> &hash)
       +    {
       +        KBiAssociativeContainer<LeftContainer, RightContainer> container;
       +        typename QMap<left_type, right_type>::const_iterator it = hash.constBegin();
       +        const typename QMap<left_type, right_type>::const_iterator end = hash.constEnd();
       +        for (; it != end; ++it) {
       +            container.insert(it.key(), it.value());
       +        }
       +        return container;
       +    }
       +
       +    friend QDataStream &operator<< <LeftContainer, RightContainer>(QDataStream &out, const KBiAssociativeContainer<LeftContainer, RightContainer> &bihash);
       +    friend QDataStream &operator>> <LeftContainer, RightContainer>(QDataStream &in, KBiAssociativeContainer<LeftContainer, RightContainer> &biHash);
       +    friend QDebug operator<< <LeftContainer, RightContainer>(QDebug out, const KBiAssociativeContainer<LeftContainer, RightContainer> &biHash);
       +protected:
       +    LeftContainer _leftToRight;
       +    RightContainer _rightToLeft;
       +};
       +
       +template<typename LeftContainer, typename RightContainer>
       +QDataStream &operator<<(QDataStream &out, const KBiAssociativeContainer<LeftContainer, RightContainer> &container)
       +{
       +    return out << container._leftToRight;
       +}
       +
       +template<typename LeftContainer, typename RightContainer>
       +QDataStream &operator>>(QDataStream &in, KBiAssociativeContainer<LeftContainer, RightContainer> &container)
       +{
       +    LeftContainer leftToRight;
       +    in >> leftToRight;
       +    typename LeftContainer::const_iterator it = leftToRight.constBegin();
       +    const typename LeftContainer::const_iterator end = leftToRight.constEnd();
       +    for (; it != end; ++it) {
       +        container.insert(it.key(), it.value());
       +    }
       +
       +    return in;
       +}
       +
       +template<typename Container, typename T, typename U>
       +struct _containerType {
       +    operator const char *();
       +};
       +
       +template<typename T, typename U>
       +struct _containerType<QHash<T, U>, T, U> {
       +    operator const char *()
       +    {
       +        return "QHash";
       +    }
       +};
       +
       +template<typename T, typename U>
       +struct _containerType<QMap<T, U>, T, U> {
       +    operator const char *()
       +    {
       +        return "QMap";
       +    }
       +};
       +
       +template<typename Container>
       +static const char *containerType()
       +{
       +    return _containerType<Container, typename Container::key_type, typename Container::mapped_type>();
       +}
       +
       +template<typename LeftContainer, typename RightContainer>
       +QDebug operator<<(QDebug out, const KBiAssociativeContainer<LeftContainer, RightContainer> &container)
       +{
       +    typename KBiAssociativeContainer<LeftContainer, RightContainer>::left_const_iterator it = container.leftConstBegin();
       +
       +    const typename KBiAssociativeContainer<LeftContainer, RightContainer>::left_const_iterator end = container.leftConstEnd();
       +    out.nospace() << "KBiAssociativeContainer<" << containerType<LeftContainer>() << ", " << containerType<RightContainer>() << ">" << "(";
       +    for (; it != end; ++it) {
       +        out << "(" << it.key() << " <=> " << it.value() << ") ";
       +    }
       +
       +    out << ")";
       +    return out;
       +}
       +
       +/**
       + * @brief KBiHash provides a bi-directional hash container
       + *
       + * @note This class is designed to make mapping easier in proxy model implementations.
       + *
       + * @todo Figure out whether to discard this and use boost::bimap instead, submit it Qt or keep it here and make more direct use of QHashNode.
       + */
       +template <typename T, typename U>
       +struct KBiHash : public KBiAssociativeContainer<QHash<T, U>, QHash<U, T> > {
       +    KBiHash()
       +        : KBiAssociativeContainer<QHash<T, U>, QHash<U, T> > ()
       +    {
       +
       +    }
       +
       +    KBiHash(const KBiAssociativeContainer<QHash<T, U>, QHash<U, T> > &container)
       +        : KBiAssociativeContainer<QHash<T, U>, QHash<U, T> > (container)
       +    {
       +
       +    }
       +};
       +
       +template<typename T, typename U>
       +QDebug operator<<(QDebug out, const KBiHash<T, U> &biHash)
       +{
       +    typename KBiHash<T, U>::left_const_iterator it = biHash.leftConstBegin();
       +
       +    const typename KBiHash<T, U>::left_const_iterator end = biHash.leftConstEnd();
       +    out.nospace() << "KBiHash(";
       +    for (; it != end; ++it) {
       +        out << "(" << it.key() << " <=> " << it.value() << ") ";
       +    }
       +
       +    out << ")";
       +    return out;
       +}
       +
       +template <typename T, typename U>
       +struct KHash2Map : public KBiAssociativeContainer<QHash<T, U>, QMap<U, T> > {
       +    KHash2Map()
       +        : KBiAssociativeContainer<QHash<T, U>, QMap<U, T> > ()
       +    {
       +
       +    }
       +
       +    KHash2Map(const KBiAssociativeContainer<QHash<T, U>, QMap<U, T> > &container)
       +        : KBiAssociativeContainer<QHash<T, U>, QMap<U, T> > (container)
       +    {
       +
       +    }
       +
       +    typename KBiAssociativeContainer<QHash<T, U>, QMap<U, T> >::right_iterator rightLowerBound(const U &key)
       +    {
       +        return this->_rightToLeft.lowerBound(key);
       +    }
       +
       +    typename KBiAssociativeContainer<QHash<T, U>, QMap<U, T> >::right_const_iterator rightLowerBound(const U &key) const
       +    {
       +        return this->_rightToLeft.lowerBound(key);
       +    }
       +
       +    typename KBiAssociativeContainer<QHash<T, U>, QMap<U, T> >::right_iterator rightUpperBound(const U &key)
       +    {
       +        return this->_rightToLeft.upperBound(key);
       +    }
       +
       +    typename KBiAssociativeContainer<QHash<T, U>, QMap<U, T> >::right_const_iterator rightUpperBound(const U &key) const
       +    {
       +        return this->_rightToLeft.upperBound(key);
       +    }
       +};
       +
       +template<typename T, typename U>
       +QDebug operator<<(QDebug out, const KHash2Map<T, U> &container)
       +{
       +    typename KHash2Map<T, U>::left_const_iterator it = container.leftConstBegin();
       +
       +    const typename KHash2Map<T, U>::left_const_iterator end = container.leftConstEnd();
       +    out.nospace() << "KHash2Map(";
       +    for (; it != end; ++it) {
       +        out << "(" << it.key() << " <=> " << it.value() << ") ";
       +    }
       +
       +    out << ")";
       +    return out;
       +}
       +
       +#endif
 (DIR) diff --git a/3rdparty/kitemmodels/kdescendantsproxymodel.cpp b/3rdparty/kitemmodels/kdescendantsproxymodel.cpp
       t@@ -0,0 +1,1001 @@
       +/*
       +    Copyright (c) 2009 Stephen Kelly <steveire@gmail.com>
       +    Copyright (C) 2010 Klarälvdalens Datakonsult AB,
       +        a KDAB Group company, info@kdab.net,
       +        author Stephen Kelly <stephen@kdab.com>
       +
       +    This library is free software; you can redistribute it and/or modify it
       +    under the terms of the GNU Library General Public License as published by
       +    the Free Software Foundation; either version 2 of the License, or (at your
       +    option) any later version.
       +
       +    This library 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 Library General Public
       +    License for more details.
       +
       +    You should have received a copy of the GNU Library General Public License
       +    along with this library; see the file COPYING.LIB.  If not, write to the
       +    Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
       +    02110-1301, USA.
       +*/
       +
       +#include "kdescendantsproxymodel.h"
       +
       +#include <QStringList>
       +#include <QTimer>
       +#include <QDebug>
       +
       +#include "kbihash_p.h"
       +
       +typedef KHash2Map<QPersistentModelIndex, int> Mapping;
       +
       +class KDescendantsProxyModelPrivate
       +{
       +    KDescendantsProxyModelPrivate(KDescendantsProxyModel *qq)
       +        : q_ptr(qq),
       +          m_rowCount(0),
       +          m_ignoreNextLayoutAboutToBeChanged(false),
       +          m_ignoreNextLayoutChanged(false),
       +          m_relayouting(false),
       +          m_displayAncestorData(false),
       +          m_ancestorSeparator(QStringLiteral(" / "))
       +    {
       +    }
       +
       +    Q_DECLARE_PUBLIC(KDescendantsProxyModel)
       +    KDescendantsProxyModel *const q_ptr;
       +
       +    mutable QVector<QPersistentModelIndex> m_pendingParents;
       +
       +    void scheduleProcessPendingParents() const;
       +    void processPendingParents();
       +
       +    void synchronousMappingRefresh();
       +
       +    void updateInternalIndexes(int start, int offset);
       +
       +    void resetInternalData();
       +
       +    void sourceRowsAboutToBeInserted(const QModelIndex &, int, int);
       +    void sourceRowsInserted(const QModelIndex &, int, int);
       +    void sourceRowsAboutToBeRemoved(const QModelIndex &, int, int);
       +    void sourceRowsRemoved(const QModelIndex &, int, int);
       +    void sourceRowsAboutToBeMoved(const QModelIndex &, int, int, const QModelIndex &, int);
       +    void sourceRowsMoved(const QModelIndex &, int, int, const QModelIndex &, int);
       +    void sourceModelAboutToBeReset();
       +    void sourceModelReset();
       +    void sourceLayoutAboutToBeChanged();
       +    void sourceLayoutChanged();
       +    void sourceDataChanged(const QModelIndex &, const QModelIndex &);
       +    void sourceModelDestroyed();
       +
       +    Mapping m_mapping;
       +    int m_rowCount;
       +    QPair<int, int> m_removePair;
       +    QPair<int, int> m_insertPair;
       +
       +    bool m_ignoreNextLayoutAboutToBeChanged;
       +    bool m_ignoreNextLayoutChanged;
       +    bool m_relayouting;
       +
       +    bool m_displayAncestorData;
       +    QString m_ancestorSeparator;
       +
       +    QList<QPersistentModelIndex> m_layoutChangePersistentIndexes;
       +    QModelIndexList m_proxyIndexes;
       +};
       +
       +void KDescendantsProxyModelPrivate::resetInternalData()
       +{
       +    m_rowCount = 0;
       +    m_mapping.clear();
       +    m_layoutChangePersistentIndexes.clear();
       +    m_proxyIndexes.clear();
       +}
       +
       +void KDescendantsProxyModelPrivate::synchronousMappingRefresh()
       +{
       +    m_rowCount = 0;
       +    m_mapping.clear();
       +    m_pendingParents.clear();
       +
       +    m_pendingParents.append(QModelIndex());
       +
       +    m_relayouting = true;
       +    while (!m_pendingParents.isEmpty()) {
       +        processPendingParents();
       +    }
       +    m_relayouting = false;
       +}
       +
       +void KDescendantsProxyModelPrivate::scheduleProcessPendingParents() const
       +{
       +    const_cast<KDescendantsProxyModelPrivate *>(this)->processPendingParents();
       +}
       +
       +void KDescendantsProxyModelPrivate::processPendingParents()
       +{
       +    Q_Q(KDescendantsProxyModel);
       +    const QVector<QPersistentModelIndex>::iterator begin = m_pendingParents.begin();
       +    QVector<QPersistentModelIndex>::iterator it = begin;
       +
       +    const QVector<QPersistentModelIndex>::iterator end = m_pendingParents.end();
       +
       +    QVector<QPersistentModelIndex> newPendingParents;
       +
       +    while (it != end && it != m_pendingParents.end()) {
       +        const QModelIndex sourceParent = *it;
       +        if (!sourceParent.isValid() && m_rowCount > 0) {
       +            // It was removed from the source model before it was inserted.
       +            it = m_pendingParents.erase(it);
       +            continue;
       +        }
       +        const int rowCount = q->sourceModel()->rowCount(sourceParent);
       +
       +        Q_ASSERT(rowCount > 0);
       +        const QPersistentModelIndex sourceIndex = q->sourceModel()->index(rowCount - 1, 0, sourceParent);
       +
       +        Q_ASSERT(sourceIndex.isValid());
       +
       +        const QModelIndex proxyParent = q->mapFromSource(sourceParent);
       +
       +        Q_ASSERT(sourceParent.isValid() == proxyParent.isValid());
       +        const int proxyEndRow = proxyParent.row() + rowCount;
       +        const int proxyStartRow = proxyEndRow - rowCount + 1;
       +
       +        if (!m_relayouting) {
       +            q->beginInsertRows(QModelIndex(), proxyStartRow, proxyEndRow);
       +        }
       +
       +        updateInternalIndexes(proxyStartRow, rowCount);
       +        m_mapping.insert(sourceIndex, proxyEndRow);
       +        it = m_pendingParents.erase(it);
       +        m_rowCount += rowCount;
       +
       +        if (!m_relayouting) {
       +            q->endInsertRows();
       +        }
       +
       +        for (int sourceRow = 0; sourceRow < rowCount; ++sourceRow) {
       +            static const int column = 0;
       +            const QModelIndex child = q->sourceModel()->index(sourceRow, column, sourceParent);
       +            Q_ASSERT(child.isValid());
       +
       +            if (q->sourceModel()->hasChildren(child)) {
       +                Q_ASSERT(q->sourceModel()->rowCount(child) > 0);
       +                newPendingParents.append(child);
       +            }
       +        }
       +    }
       +    m_pendingParents += newPendingParents;
       +    if (!m_pendingParents.isEmpty()) {
       +        processPendingParents();
       +    }
       +//   scheduleProcessPendingParents();
       +}
       +
       +void KDescendantsProxyModelPrivate::updateInternalIndexes(int start, int offset)
       +{
       +    // TODO: Make KHash2Map support key updates and do this backwards.
       +    QHash<int, QPersistentModelIndex> updates;
       +    {
       +        Mapping::right_iterator it = m_mapping.rightLowerBound(start);
       +        const Mapping::right_iterator end = m_mapping.rightEnd();
       +
       +        while (it != end) {
       +            updates.insert(it.key() + offset, *it);
       +            ++it;
       +        }
       +    }
       +
       +    {
       +        QHash<int, QPersistentModelIndex>::const_iterator it = updates.constBegin();
       +        const QHash<int, QPersistentModelIndex>::const_iterator end = updates.constEnd();
       +
       +        for (; it != end; ++it) {
       +            m_mapping.insert(it.value(), it.key());
       +        }
       +    }
       +
       +}
       +
       +KDescendantsProxyModel::KDescendantsProxyModel(QObject *parent)
       +    : QAbstractProxyModel(parent), d_ptr(new KDescendantsProxyModelPrivate(this))
       +{
       +}
       +
       +KDescendantsProxyModel::~KDescendantsProxyModel()
       +{
       +    delete d_ptr;
       +}
       +
       +void KDescendantsProxyModel::setRootIndex(const QModelIndex &index)
       +{
       +    Q_UNUSED(index)
       +}
       +
       +QModelIndexList KDescendantsProxyModel::match(const QModelIndex &start, int role, const QVariant &value, int hits, Qt::MatchFlags flags) const
       +{
       +    return QAbstractProxyModel::match(start, role, value, hits, flags);
       +}
       +
       +namespace {
       +    // we only work on DisplayRole for now
       +    static const QVector<int> changedRoles = {Qt::DisplayRole};
       +}
       +
       +void KDescendantsProxyModel::setDisplayAncestorData(bool display)
       +{
       +    Q_D(KDescendantsProxyModel);
       +    bool displayChanged = (display != d->m_displayAncestorData);
       +    d->m_displayAncestorData = display;
       +    if (displayChanged) {
       +        // send out big hammer. Everything needs to be updated.
       +        emit dataChanged(index(0,0),index(rowCount()-1,columnCount()-1),  changedRoles);
       +    }
       +}
       +
       +bool KDescendantsProxyModel::displayAncestorData() const
       +{
       +    Q_D(const KDescendantsProxyModel);
       +    return d->m_displayAncestorData;
       +}
       +
       +void KDescendantsProxyModel::setAncestorSeparator(const QString &separator)
       +{
       +    Q_D(KDescendantsProxyModel);
       +    bool separatorChanged = (separator != d->m_ancestorSeparator);
       +    d->m_ancestorSeparator = separator;
       +    if (separatorChanged && d->m_displayAncestorData) {
       +        // send out big hammer. Everything needs to be updated.
       +        emit dataChanged(index(0,0),index(rowCount()-1,columnCount()-1),  changedRoles);
       +    }
       +}
       +
       +QString KDescendantsProxyModel::ancestorSeparator() const
       +{
       +    Q_D(const KDescendantsProxyModel);
       +    return d->m_ancestorSeparator;
       +}
       +
       +void KDescendantsProxyModel::setSourceModel(QAbstractItemModel *_sourceModel)
       +{
       +    Q_D(KDescendantsProxyModel);
       +
       +    beginResetModel();
       +
       +    static const char *const modelSignals[] = {
       +        SIGNAL(rowsAboutToBeInserted(QModelIndex,int,int)),
       +        SIGNAL(rowsInserted(QModelIndex,int,int)),
       +        SIGNAL(rowsAboutToBeRemoved(QModelIndex,int,int)),
       +        SIGNAL(rowsRemoved(QModelIndex,int,int)),
       +        SIGNAL(rowsAboutToBeMoved(QModelIndex,int,int,QModelIndex,int)),
       +        SIGNAL(rowsMoved(QModelIndex,int,int,QModelIndex,int)),
       +        SIGNAL(modelAboutToBeReset()),
       +        SIGNAL(modelReset()),
       +        SIGNAL(dataChanged(QModelIndex,QModelIndex)),
       +        SIGNAL(layoutAboutToBeChanged()),
       +        SIGNAL(layoutChanged()),
       +        SIGNAL(destroyed())
       +    };
       +    static const char *const proxySlots[] = {
       +        SLOT(sourceRowsAboutToBeInserted(QModelIndex,int,int)),
       +        SLOT(sourceRowsInserted(QModelIndex,int,int)),
       +        SLOT(sourceRowsAboutToBeRemoved(QModelIndex,int,int)),
       +        SLOT(sourceRowsRemoved(QModelIndex,int,int)),
       +        SLOT(sourceRowsAboutToBeMoved(QModelIndex,int,int,QModelIndex,int)),
       +        SLOT(sourceRowsMoved(QModelIndex,int,int,QModelIndex,int)),
       +        SLOT(sourceModelAboutToBeReset()),
       +        SLOT(sourceModelReset()),
       +        SLOT(sourceDataChanged(QModelIndex,QModelIndex)),
       +        SLOT(sourceLayoutAboutToBeChanged()),
       +        SLOT(sourceLayoutChanged()),
       +        SLOT(sourceModelDestroyed())
       +    };
       +
       +    if (sourceModel()) {
       +        for (int i = 0; i < int(sizeof modelSignals / sizeof * modelSignals); ++i) {
       +            disconnect(sourceModel(), modelSignals[i], this, proxySlots[i]);
       +        }
       +    }
       +
       +    QAbstractProxyModel::setSourceModel(_sourceModel);
       +
       +    if (_sourceModel) {
       +        for (int i = 0; i < int(sizeof modelSignals / sizeof * modelSignals); ++i) {
       +            connect(_sourceModel, modelSignals[i], this, proxySlots[i]);
       +        }
       +    }
       +
       +    resetInternalData();
       +    if (_sourceModel && _sourceModel->hasChildren()) {
       +        d->synchronousMappingRefresh();
       +    }
       +
       +    endResetModel();
       +}
       +
       +QModelIndex KDescendantsProxyModel::parent(const QModelIndex &index) const
       +{
       +    Q_UNUSED(index)
       +    return QModelIndex();
       +}
       +
       +bool KDescendantsProxyModel::hasChildren(const QModelIndex &parent) const
       +{
       +    Q_D(const KDescendantsProxyModel);
       +    return !(d->m_mapping.isEmpty() || parent.isValid());
       +}
       +
       +int KDescendantsProxyModel::rowCount(const QModelIndex &parent) const
       +{
       +    Q_D(const KDescendantsProxyModel);
       +    if (d->m_pendingParents.contains(parent) || parent.isValid() || !sourceModel()) {
       +        return 0;
       +    }
       +
       +    if (d->m_mapping.isEmpty() && sourceModel()->hasChildren()) {
       +        Q_ASSERT(sourceModel()->rowCount() > 0);
       +        const_cast<KDescendantsProxyModelPrivate *>(d)->synchronousMappingRefresh();
       +    }
       +    return d->m_rowCount;
       +}
       +
       +QModelIndex KDescendantsProxyModel::index(int row, int column, const QModelIndex &parent) const
       +{
       +    if (parent.isValid()) {
       +        return QModelIndex();
       +    }
       +
       +    if (!hasIndex(row, column, parent)) {
       +        return QModelIndex();
       +    }
       +
       +    return createIndex(row, column);
       +}
       +
       +QModelIndex KDescendantsProxyModel::mapToSource(const QModelIndex &proxyIndex) const
       +{
       +    Q_D(const KDescendantsProxyModel);
       +    if (d->m_mapping.isEmpty() || !proxyIndex.isValid() || !sourceModel()) {
       +        return QModelIndex();
       +    }
       +
       +    const Mapping::right_const_iterator result = d->m_mapping.rightLowerBound(proxyIndex.row());
       +    Q_ASSERT(result != d->m_mapping.rightEnd());
       +
       +    const int proxyLastRow = result.key();
       +    const QModelIndex sourceLastChild = result.value();
       +    Q_ASSERT(sourceLastChild.isValid());
       +
       +    // proxyLastRow is greater than proxyIndex.row().
       +    // sourceLastChild is vertically below the result we're looking for
       +    // and not necessarily in the correct parent.
       +    // We travel up through its parent hierarchy until we are in the
       +    // right parent, then return the correct sibling.
       +
       +    // Source:           Proxy:    Row
       +    // - A               - A       - 0
       +    // - B               - B       - 1
       +    // - C               - C       - 2
       +    // - D               - D       - 3
       +    // - - E             - E       - 4
       +    // - - F             - F       - 5
       +    // - - G             - G       - 6
       +    // - - H             - H       - 7
       +    // - - I             - I       - 8
       +    // - - - J           - J       - 9
       +    // - - - K           - K       - 10
       +    // - - - L           - L       - 11
       +    // - - M             - M       - 12
       +    // - - N             - N       - 13
       +    // - O               - O       - 14
       +
       +    // Note that L, N and O are lastChildIndexes, and therefore have a mapping. If we
       +    // are trying to map G from the proxy to the source, We at this point have an iterator
       +    // pointing to (L -> 11). The proxy row of G is 6. (proxyIndex.row() == 6). We seek the
       +    // sourceIndex which is vertically above L by the distance proxyLastRow - proxyIndex.row().
       +    // In this case the verticalDistance is 5.
       +
       +    int verticalDistance = proxyLastRow - proxyIndex.row();
       +
       +    // We traverse the ancestors of L, until we can index the desired row in the source.
       +
       +    QModelIndex ancestor = sourceLastChild;
       +    while (ancestor.isValid()) {
       +        const int ancestorRow = ancestor.row();
       +        if (verticalDistance <= ancestorRow) {
       +            return ancestor.sibling(ancestorRow - verticalDistance, proxyIndex.column());
       +        }
       +        verticalDistance -= (ancestorRow + 1);
       +        ancestor = ancestor.parent();
       +    }
       +    Q_ASSERT(!"Didn't find target row.");
       +    return QModelIndex();
       +}
       +
       +QModelIndex KDescendantsProxyModel::mapFromSource(const QModelIndex &sourceIndex) const
       +{
       +    Q_D(const KDescendantsProxyModel);
       +
       +    if (!sourceModel()) {
       +        return QModelIndex();
       +    }
       +
       +    if (d->m_mapping.isEmpty()) {
       +        return QModelIndex();
       +    }
       +
       +    {
       +        // TODO: Consider a parent Mapping to speed this up.
       +
       +        Mapping::right_const_iterator it = d->m_mapping.rightConstBegin();
       +        const Mapping::right_const_iterator end = d->m_mapping.rightConstEnd();
       +        const QModelIndex sourceParent = sourceIndex.parent();
       +        Mapping::right_const_iterator result = end;
       +
       +        for (; it != end; ++it) {
       +            QModelIndex index = it.value();
       +            bool found_block = false;
       +            while (index.isValid()) {
       +                const QModelIndex ancestor = index.parent();
       +                if (ancestor == sourceParent && index.row() >= sourceIndex.row()) {
       +                    found_block = true;
       +                    if (result == end || it.key() < result.key()) {
       +                        result = it;
       +                        break; // Leave the while loop. index is still valid.
       +                    }
       +                }
       +                index = ancestor;
       +            }
       +            if (found_block && !index.isValid())
       +                // Looked through the ascendants of it.key() without finding sourceParent.
       +                // That means we've already got the result we need.
       +            {
       +                break;
       +            }
       +        }
       +        Q_ASSERT(result != end);
       +        const QModelIndex sourceLastChild = result.value();
       +        int proxyRow = result.key();
       +        QModelIndex index = sourceLastChild;
       +        while (index.isValid()) {
       +            const QModelIndex ancestor = index.parent();
       +            if (ancestor == sourceParent) {
       +                return createIndex(proxyRow - (index.row() - sourceIndex.row()), sourceIndex.column());
       +            }
       +            proxyRow -= (index.row() + 1);
       +            index = ancestor;
       +        }
       +        Q_ASSERT(!"Didn't find valid proxy mapping.");
       +        return QModelIndex();
       +    }
       +
       +}
       +
       +int KDescendantsProxyModel::columnCount(const QModelIndex &parent) const
       +{
       +    if (parent.isValid() /* || rowCount(parent) == 0 */ || !sourceModel()) {
       +        return 0;
       +    }
       +
       +    return sourceModel()->columnCount();
       +}
       +
       +QVariant KDescendantsProxyModel::data(const QModelIndex &index, int role) const
       +{
       +    Q_D(const KDescendantsProxyModel);
       +
       +    if (!sourceModel()) {
       +        return QVariant();
       +    }
       +
       +    if (!index.isValid()) {
       +        return sourceModel()->data(index, role);
       +    }
       +
       +    QModelIndex sourceIndex = mapToSource(index);
       +
       +    if ((d->m_displayAncestorData) && (role == Qt::DisplayRole)) {
       +        if (!sourceIndex.isValid()) {
       +            return QVariant();
       +        }
       +        QString displayData = sourceIndex.data().toString();
       +        sourceIndex = sourceIndex.parent();
       +        while (sourceIndex.isValid()) {
       +            displayData.prepend(d->m_ancestorSeparator);
       +            displayData.prepend(sourceIndex.data().toString());
       +            sourceIndex = sourceIndex.parent();
       +        }
       +        return displayData;
       +    } else {
       +        return sourceIndex.data(role);
       +    }
       +}
       +
       +QVariant KDescendantsProxyModel::headerData(int section, Qt::Orientation orientation, int role) const
       +{
       +    if (!sourceModel() || columnCount() <= section) {
       +        return QVariant();
       +    }
       +
       +    return QAbstractProxyModel::headerData(section, orientation, role);
       +}
       +
       +Qt::ItemFlags KDescendantsProxyModel::flags(const QModelIndex &index) const
       +{
       +    if (!index.isValid() || !sourceModel()) {
       +        return QAbstractProxyModel::flags(index);
       +    }
       +
       +    const QModelIndex srcIndex = mapToSource(index);
       +    Q_ASSERT(srcIndex.isValid());
       +    return sourceModel()->flags(srcIndex);
       +}
       +
       +void KDescendantsProxyModelPrivate::sourceRowsAboutToBeInserted(const QModelIndex &parent, int start, int end)
       +{
       +    Q_Q(KDescendantsProxyModel);
       +
       +    if (!q->sourceModel()->hasChildren(parent)) {
       +        Q_ASSERT(q->sourceModel()->rowCount(parent) == 0);
       +        // parent was not a parent before.
       +        return;
       +    }
       +
       +    int proxyStart = -1;
       +
       +    const int rowCount = q->sourceModel()->rowCount(parent);
       +
       +    if (rowCount > start) {
       +        const QModelIndex belowStart = q->sourceModel()->index(start, 0, parent);
       +        proxyStart = q->mapFromSource(belowStart).row();
       +    } else if (rowCount == 0) {
       +        proxyStart = q->mapFromSource(parent).row() + 1;
       +    } else {
       +        Q_ASSERT(rowCount == start);
       +        static const int column = 0;
       +        QModelIndex idx = q->sourceModel()->index(rowCount - 1, column, parent);
       +        while (q->sourceModel()->hasChildren(idx)) {
       +            Q_ASSERT(q->sourceModel()->rowCount(idx) > 0);
       +            idx = q->sourceModel()->index(q->sourceModel()->rowCount(idx) - 1, column, idx);
       +        }
       +        // The last item in the list is getting a sibling below it.
       +        proxyStart = q->mapFromSource(idx).row() + 1;
       +    }
       +    const int proxyEnd = proxyStart + (end - start);
       +
       +    m_insertPair = qMakePair(proxyStart, proxyEnd);
       +    q->beginInsertRows(QModelIndex(), proxyStart, proxyEnd);
       +}
       +
       +void KDescendantsProxyModelPrivate::sourceRowsInserted(const QModelIndex &parent, int start, int end)
       +{
       +    Q_Q(KDescendantsProxyModel);
       +
       +    Q_ASSERT(q->sourceModel()->index(start, 0, parent).isValid());
       +
       +    const int rowCount = q->sourceModel()->rowCount(parent);
       +    Q_ASSERT(rowCount > 0);
       +
       +    const int difference = end - start + 1;
       +
       +    if (rowCount == difference) {
       +        // @p parent was not a parent before.
       +        m_pendingParents.append(parent);
       +        scheduleProcessPendingParents();
       +        return;
       +    }
       +
       +    const int proxyStart = m_insertPair.first;
       +
       +    Q_ASSERT(proxyStart >= 0);
       +
       +    updateInternalIndexes(proxyStart, difference);
       +
       +    if (rowCount - 1 == end) {
       +        // The previously last row (the mapped one) is no longer the last.
       +        // For example,
       +
       +        // - A            - A           0
       +        // - - B          - B           1
       +        // - - C          - C           2
       +        // - - - D        - D           3
       +        // - - - E   ->   - E           4
       +        // - - F          - F           5
       +        // - - G     ->   - G           6
       +        // - H            - H           7
       +        // - I       ->   - I           8
       +
       +        // As last children, E, F and G have mappings.
       +        // Consider that 'J' is appended to the children of 'C', below 'E'.
       +
       +        // - A            - A           0
       +        // - - B          - B           1
       +        // - - C          - C           2
       +        // - - - D        - D           3
       +        // - - - E   ->   - E           4
       +        // - - - J        - ???         5
       +        // - - F          - F           6
       +        // - - G     ->   - G           7
       +        // - H            - H           8
       +        // - I       ->   - I           9
       +
       +        // The updateInternalIndexes call above will have updated the F and G mappings correctly because proxyStart is 5.
       +        // That means that E -> 4 was not affected by the updateInternalIndexes call.
       +        // Now the mapping for E -> 4 needs to be updated so that it's a mapping for J -> 5.
       +
       +        Q_ASSERT(!m_mapping.isEmpty());
       +        static const int column = 0;
       +        const QModelIndex oldIndex = q->sourceModel()->index(rowCount - 1 - difference, column, parent);
       +        Q_ASSERT(m_mapping.leftContains(oldIndex));
       +
       +        const QModelIndex newIndex = q->sourceModel()->index(rowCount - 1, column, parent);
       +
       +        QModelIndex indexAbove = oldIndex;
       +
       +        if (start > 0) {
       +            // If we have something like this:
       +            //
       +            // - A
       +            // - - B
       +            // - - C
       +            //
       +            // and we then insert D as a sibling of A below it, we need to remove the mapping for A,
       +            // and the row number used for D must take into account the descendants of A.
       +
       +            while (q->sourceModel()->hasChildren(indexAbove)) {
       +                Q_ASSERT(q->sourceModel()->rowCount(indexAbove) > 0);
       +                indexAbove = q->sourceModel()->index(q->sourceModel()->rowCount(indexAbove) - 1,  column, indexAbove);
       +            }
       +            Q_ASSERT(q->sourceModel()->rowCount(indexAbove) == 0);
       +        }
       +
       +        Q_ASSERT(m_mapping.leftContains(indexAbove));
       +
       +        const int newProxyRow = m_mapping.leftToRight(indexAbove) + difference;
       +
       +        // oldIndex is E in the source. proxyRow is 4.
       +        m_mapping.removeLeft(oldIndex);
       +
       +        // newIndex is J. (proxyRow + difference) is 5.
       +        m_mapping.insert(newIndex, newProxyRow);
       +    }
       +
       +    for (int row = start; row <= end; ++row) {
       +        static const int column = 0;
       +        const QModelIndex idx = q->sourceModel()->index(row, column, parent);
       +        Q_ASSERT(idx.isValid());
       +        if (q->sourceModel()->hasChildren(idx)) {
       +            Q_ASSERT(q->sourceModel()->rowCount(idx) > 0);
       +            m_pendingParents.append(idx);
       +        }
       +    }
       +
       +    m_rowCount += difference;
       +
       +    q->endInsertRows();
       +    scheduleProcessPendingParents();
       +}
       +
       +void KDescendantsProxyModelPrivate::sourceRowsAboutToBeRemoved(const QModelIndex &parent, int start, int end)
       +{
       +    Q_Q(KDescendantsProxyModel);
       +
       +    const int proxyStart = q->mapFromSource(q->sourceModel()->index(start, 0, parent)).row();
       +
       +    static const int column = 0;
       +    QModelIndex idx = q->sourceModel()->index(end, column, parent);
       +    while (q->sourceModel()->hasChildren(idx)) {
       +        Q_ASSERT(q->sourceModel()->rowCount(idx) > 0);
       +        idx = q->sourceModel()->index(q->sourceModel()->rowCount(idx) - 1, column, idx);
       +    }
       +    const int proxyEnd = q->mapFromSource(idx).row();
       +
       +    m_removePair = qMakePair(proxyStart, proxyEnd);
       +
       +    q->beginRemoveRows(QModelIndex(), proxyStart, proxyEnd);
       +}
       +
       +static QModelIndex getFirstDeepest(QAbstractItemModel *model, const QModelIndex &parent, int *count)
       +{
       +    static const int column = 0;
       +    Q_ASSERT(model->hasChildren(parent));
       +    Q_ASSERT(model->rowCount(parent) > 0);
       +    for (int row = 0; row < model->rowCount(parent); ++row) {
       +        (*count)++;
       +        const QModelIndex child = model->index(row, column, parent);
       +        Q_ASSERT(child.isValid());
       +        if (model->hasChildren(child)) {
       +            return getFirstDeepest(model, child, count);
       +        }
       +    }
       +    return model->index(model->rowCount(parent) - 1, column, parent);
       +}
       +
       +void KDescendantsProxyModelPrivate::sourceRowsRemoved(const QModelIndex &parent, int start, int end)
       +{
       +    Q_Q(KDescendantsProxyModel);
       +    Q_UNUSED(end)
       +
       +    const int rowCount = q->sourceModel()->rowCount(parent);
       +
       +    const int proxyStart = m_removePair.first;
       +    const int proxyEnd = m_removePair.second;
       +
       +    const int difference = proxyEnd - proxyStart + 1;
       +    {
       +        Mapping::right_iterator it = m_mapping.rightLowerBound(proxyStart);
       +        const Mapping::right_iterator endIt = m_mapping.rightUpperBound(proxyEnd);
       +
       +        if (endIt != m_mapping.rightEnd())
       +            while (it != endIt) {
       +                it = m_mapping.eraseRight(it);
       +            }
       +        else
       +            while (it != m_mapping.rightUpperBound(proxyEnd)) {
       +                it = m_mapping.eraseRight(it);
       +            }
       +    }
       +
       +    m_removePair = qMakePair(-1, -1);
       +    m_rowCount -= difference;
       +    Q_ASSERT(m_rowCount >= 0);
       +
       +    updateInternalIndexes(proxyStart, -1 * difference);
       +
       +    if (rowCount != start || rowCount == 0) {
       +        q->endRemoveRows();
       +        return;
       +    }
       +
       +    static const int column = 0;
       +    const QModelIndex newEnd = q->sourceModel()->index(rowCount - 1, column, parent);
       +    Q_ASSERT(newEnd.isValid());
       +
       +    if (m_mapping.isEmpty()) {
       +        m_mapping.insert(newEnd, newEnd.row());
       +        q->endRemoveRows();
       +        return;
       +    }
       +    if (q->sourceModel()->hasChildren(newEnd)) {
       +        int count = 0;
       +        const QModelIndex firstDeepest = getFirstDeepest(q->sourceModel(), newEnd, &count);
       +        Q_ASSERT(firstDeepest.isValid());
       +        const int firstDeepestProxy = m_mapping.leftToRight(firstDeepest);
       +
       +        m_mapping.insert(newEnd, firstDeepestProxy - count);
       +        q->endRemoveRows();
       +        return;
       +    }
       +    Mapping::right_iterator lowerBound = m_mapping.rightLowerBound(proxyStart);
       +    if (lowerBound == m_mapping.rightEnd()) {
       +        int proxyRow = (lowerBound - 1).key();
       +
       +        for (int row = newEnd.row(); row >= 0; --row) {
       +            const QModelIndex newEndSibling = q->sourceModel()->index(row, column, parent);
       +            if (!q->sourceModel()->hasChildren(newEndSibling)) {
       +                ++proxyRow;
       +            } else {
       +                break;
       +            }
       +        }
       +        m_mapping.insert(newEnd, proxyRow);
       +        q->endRemoveRows();
       +        return;
       +    } else if (lowerBound == m_mapping.rightBegin()) {
       +        int proxyRow = rowCount - 1;
       +        QModelIndex trackedParent = parent;
       +        while (trackedParent.isValid()) {
       +            proxyRow += (trackedParent.row() + 1);
       +            trackedParent = trackedParent.parent();
       +        }
       +        m_mapping.insert(newEnd, proxyRow);
       +        q->endRemoveRows();
       +        return;
       +    }
       +    const Mapping::right_iterator boundAbove = lowerBound - 1;
       +
       +    QVector<QModelIndex> targetParents;
       +    targetParents.push_back(parent);
       +    {
       +        QModelIndex target = parent;
       +        int count = 0;
       +        while (target.isValid()) {
       +            if (target == boundAbove.value()) {
       +                m_mapping.insert(newEnd, count + boundAbove.key() + newEnd.row() + 1);
       +                q->endRemoveRows();
       +                return;
       +            }
       +            count += (target.row() + 1);
       +            target = target.parent();
       +            if (target.isValid()) {
       +                targetParents.push_back(target);
       +            }
       +        }
       +    }
       +
       +    QModelIndex boundParent = boundAbove.value().parent();
       +    QModelIndex prevParent = boundParent;
       +    Q_ASSERT(boundParent.isValid());
       +    while (boundParent.isValid()) {
       +        prevParent = boundParent;
       +        boundParent = boundParent.parent();
       +
       +        if (targetParents.contains(prevParent)) {
       +            break;
       +        }
       +
       +        if (!m_mapping.leftContains(prevParent)) {
       +            break;
       +        }
       +
       +        if (m_mapping.leftToRight(prevParent) > boundAbove.key()) {
       +            break;
       +        }
       +    }
       +
       +    QModelIndex trackedParent = parent;
       +
       +    int proxyRow = boundAbove.key();
       +
       +    Q_ASSERT(prevParent.isValid());
       +    proxyRow -= prevParent.row();
       +    while (trackedParent != boundParent) {
       +        proxyRow += (trackedParent.row() + 1);
       +        trackedParent = trackedParent.parent();
       +    }
       +    m_mapping.insert(newEnd, proxyRow + newEnd.row());
       +    q->endRemoveRows();
       +}
       +
       +void KDescendantsProxyModelPrivate::sourceRowsAboutToBeMoved(const QModelIndex &srcParent, int srcStart, int srcEnd, const QModelIndex &destParent, int destStart)
       +{
       +    Q_UNUSED(srcParent)
       +    Q_UNUSED(srcStart)
       +    Q_UNUSED(srcEnd)
       +    Q_UNUSED(destParent)
       +    Q_UNUSED(destStart)
       +    sourceLayoutAboutToBeChanged();
       +}
       +
       +void KDescendantsProxyModelPrivate::sourceRowsMoved(const QModelIndex &srcParent, int srcStart, int srcEnd, const QModelIndex &destParent, int destStart)
       +{
       +    Q_UNUSED(srcParent)
       +    Q_UNUSED(srcStart)
       +    Q_UNUSED(srcEnd)
       +    Q_UNUSED(destParent)
       +    Q_UNUSED(destStart)
       +    sourceLayoutChanged();
       +}
       +
       +void KDescendantsProxyModelPrivate::sourceModelAboutToBeReset()
       +{
       +    Q_Q(KDescendantsProxyModel);
       +    q->beginResetModel();
       +}
       +
       +void KDescendantsProxyModelPrivate::sourceModelReset()
       +{
       +    Q_Q(KDescendantsProxyModel);
       +    resetInternalData();
       +    if (q->sourceModel()->hasChildren()) {
       +        Q_ASSERT(q->sourceModel()->rowCount() > 0);
       +        m_pendingParents.append(QModelIndex());
       +        scheduleProcessPendingParents();
       +    }
       +    q->endResetModel();
       +}
       +
       +void KDescendantsProxyModelPrivate::sourceLayoutAboutToBeChanged()
       +{
       +    Q_Q(KDescendantsProxyModel);
       +
       +    if (m_ignoreNextLayoutChanged) {
       +        m_ignoreNextLayoutChanged = false;
       +        return;
       +    }
       +
       +    if (m_mapping.isEmpty()) {
       +        return;
       +    }
       +
       +    emit q->layoutAboutToBeChanged();
       +
       +    QPersistentModelIndex srcPersistentIndex;
       +    Q_FOREACH (const QPersistentModelIndex &proxyPersistentIndex, q->persistentIndexList()) {
       +        m_proxyIndexes << proxyPersistentIndex;
       +        Q_ASSERT(proxyPersistentIndex.isValid());
       +        srcPersistentIndex = q->mapToSource(proxyPersistentIndex);
       +        Q_ASSERT(srcPersistentIndex.isValid());
       +        m_layoutChangePersistentIndexes << srcPersistentIndex;
       +    }
       +}
       +
       +void KDescendantsProxyModelPrivate::sourceLayoutChanged()
       +{
       +    Q_Q(KDescendantsProxyModel);
       +
       +    if (m_ignoreNextLayoutAboutToBeChanged) {
       +        m_ignoreNextLayoutAboutToBeChanged = false;
       +        return;
       +    }
       +
       +    if (m_mapping.isEmpty()) {
       +        return;
       +    }
       +
       +    m_rowCount = 0;
       +
       +    synchronousMappingRefresh();
       +
       +    for (int i = 0; i < m_proxyIndexes.size(); ++i) {
       +        q->changePersistentIndex(m_proxyIndexes.at(i), q->mapFromSource(m_layoutChangePersistentIndexes.at(i)));
       +    }
       +
       +    m_layoutChangePersistentIndexes.clear();
       +    m_proxyIndexes.clear();
       +
       +    emit q->layoutChanged();
       +}
       +
       +void KDescendantsProxyModelPrivate::sourceDataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight)
       +{
       +    Q_Q(KDescendantsProxyModel);
       +    Q_ASSERT(topLeft.model() == q->sourceModel());
       +    Q_ASSERT(bottomRight.model() == q->sourceModel());
       +
       +    const int topRow = topLeft.row();
       +    const int bottomRow = bottomRight.row();
       +
       +    for (int i = topRow; i <= bottomRow; ++i) {
       +        const QModelIndex sourceTopLeft = q->sourceModel()->index(i, topLeft.column(), topLeft.parent());
       +        Q_ASSERT(sourceTopLeft.isValid());
       +        const QModelIndex proxyTopLeft = q->mapFromSource(sourceTopLeft);
       +        // TODO. If an index does not have any descendants, then we can emit in blocks of rows.
       +        // As it is we emit once for each row.
       +        const QModelIndex sourceBottomRight = q->sourceModel()->index(i, bottomRight.column(), bottomRight.parent());
       +        const QModelIndex proxyBottomRight = q->mapFromSource(sourceBottomRight);
       +        Q_ASSERT(proxyTopLeft.isValid());
       +        Q_ASSERT(proxyBottomRight.isValid());
       +        emit q->dataChanged(proxyTopLeft, proxyBottomRight);
       +    }
       +}
       +
       +void KDescendantsProxyModelPrivate::sourceModelDestroyed()
       +{
       +    resetInternalData();
       +}
       +
       +QMimeData *KDescendantsProxyModel::mimeData(const QModelIndexList &indexes) const
       +{
       +    if (!sourceModel()) {
       +        return QAbstractProxyModel::mimeData(indexes);
       +    }
       +    Q_ASSERT(sourceModel());
       +    QModelIndexList sourceIndexes;
       +    Q_FOREACH (const QModelIndex &index, indexes) {
       +        sourceIndexes << mapToSource(index);
       +    }
       +    return sourceModel()->mimeData(sourceIndexes);
       +}
       +
       +QStringList KDescendantsProxyModel::mimeTypes() const
       +{
       +    if (!sourceModel()) {
       +        return QAbstractProxyModel::mimeTypes();
       +    }
       +    Q_ASSERT(sourceModel());
       +    return sourceModel()->mimeTypes();
       +}
       +
       +Qt::DropActions KDescendantsProxyModel::supportedDropActions() const
       +{
       +    if (!sourceModel()) {
       +        return QAbstractProxyModel::supportedDropActions();
       +    }
       +    return sourceModel()->supportedDropActions();
       +}
       +
       +#include "moc_kdescendantsproxymodel.cpp"
 (DIR) diff --git a/3rdparty/kitemmodels/kdescendantsproxymodel.h b/3rdparty/kitemmodels/kdescendantsproxymodel.h
       t@@ -0,0 +1,206 @@
       +/*
       +    Copyright (c) 2009 Stephen Kelly <steveire@gmail.com>
       +
       +    This library is free software; you can redistribute it and/or modify it
       +    under the terms of the GNU Library General Public License as published by
       +    the Free Software Foundation; either version 2 of the License, or (at your
       +    option) any later version.
       +
       +    This library 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 Library General Public
       +    License for more details.
       +
       +    You should have received a copy of the GNU Library General Public License
       +    along with this library; see the file COPYING.LIB.  If not, write to the
       +    Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
       +    02110-1301, USA.
       +*/
       +
       +#ifndef KDESCENDANTSPROXYMODEL_P_H
       +#define KDESCENDANTSPROXYMODEL_P_H
       +
       +#include <QAbstractProxyModel>
       +
       +class KDescendantsProxyModelPrivate;
       +
       +/**
       +@class KDescendantsProxyModel kdescendantsproxymodel.h KDescendantsProxyModel
       +
       +@brief Proxy Model for restructuring a Tree into a list.
       +
       +A KDescendantsProxyModel may be used to alter how the items in the tree are presented.
       +
       +Given a model which is represented as a tree:
       +
       +\image html entitytreemodel.png "A plain EntityTreeModel in a view"
       +
       +The KDescendantsProxyModel restructures the sourceModel to represent it as a flat list.
       +
       +@code
       +// ... Create an entityTreeModel
       +KDescendantsProxyModel *descProxy = new KDescendantsProxyModel(this);
       +descProxy->setSourceModel(entityTree);
       +view->setModel(descProxy);
       +@endcode
       +
       +\image html descendantentitiesproxymodel.png "A KDescendantsProxyModel."
       +
       +KDescendantEntitiesProxyModel can also display the ancestors of the index in the source model as part of its display.
       +
       +@code
       +// ... Create an entityTreeModel
       +KDescendantsProxyModel *descProxy = new KDescendantsProxyModel(this);
       +descProxy->setSourceModel(entityTree);
       +
       +// #### This is new
       +descProxy->setDisplayAncestorData(true);
       +descProxy->setAncestorSeparator(QString(" / "));
       +
       +view->setModel(descProxy);
       +
       +@endcode
       +
       +\image html descendantentitiesproxymodel-withansecnames.png "A KDescendantsProxyModel with ancestor names."
       +
       +@since 4.6
       +@author Stephen Kelly <steveire@gmail.com>
       +*/
       +class KDescendantsProxyModel : public QAbstractProxyModel
       +{
       +    Q_OBJECT
       +
       +public:
       +
       +    /**
       +     * Creates a new descendant entities proxy model.
       +     *
       +     * @param parent The parent object.
       +     */
       +    explicit KDescendantsProxyModel(QObject *parent = nullptr);
       +
       +    /**
       +     * Destroys the descendant entities proxy model.
       +     */
       +    ~KDescendantsProxyModel() override;
       +
       +    /**
       +     * Sets the source @p model of the proxy.
       +     */
       +    void setSourceModel(QAbstractItemModel *model) override;
       +
       +    /**
       +     * @deprecated
       +     *
       +     * This method does nothing.
       +     */
       +    void setRootIndex(const QModelIndex &index);
       +
       +    /**
       +     * Set whether to show ancestor data in the model. If @p display is true, then
       +     * a source model which is displayed as
       +     *
       +     * @code
       +     *  -> "Item 0-0" (this is row-depth)
       +     *  -> -> "Item 0-1"
       +     *  -> -> "Item 1-1"
       +     *  -> -> -> "Item 0-2"
       +     *  -> -> -> "Item 1-2"
       +     *  -> "Item 1-0"
       +     * @endcode
       +     *
       +     * will be displayed as
       +     *
       +     * @code
       +     *  -> *Item 0-0"
       +     *  -> "Item 0-0 / Item 0-1"
       +     *  -> "Item 0-0 / Item 1-1"
       +     *  -> "Item 0-0 / Item 1-1 / Item 0-2"
       +     *  -> "Item 0-0 / Item 1-1 / Item 1-2"
       +     *  -> "Item 1-0"
       +     * @endcode
       +     *
       +     * If @p display is false, the proxy will show
       +     *
       +     * @code
       +     *  -> *Item 0-0"
       +     *  -> "Item 0-1"
       +     *  -> "Item 1-1"
       +     *  -> "Item 0-2"
       +     *  -> "Item 1-2"
       +     *  -> "Item 1-0"
       +     * @endcode
       +     *
       +     * Default is false.
       +     */
       +    void setDisplayAncestorData(bool display);
       +
       +    /**
       +     * Whether ancestor data will be displayed.
       +     */
       +    bool displayAncestorData() const;
       +
       +    /**
       +     * Sets the ancestor @p separator used between data of ancestors.
       +     */
       +    void setAncestorSeparator(const QString &separator);
       +
       +    /**
       +     * Separator used between data of ancestors.
       +     */
       +    QString ancestorSeparator() const;
       +
       +    QModelIndex mapFromSource(const QModelIndex &sourceIndex) const override;
       +    QModelIndex mapToSource(const QModelIndex &proxyIndex) const override;
       +
       +    Qt::ItemFlags flags(const QModelIndex &index) const override;
       +    QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
       +    int rowCount(const QModelIndex &parent = QModelIndex()) const override;
       +    QVariant headerData(int section, Qt::Orientation orientation, int role) const override;
       +
       +    QMimeData *mimeData(const QModelIndexList &indexes) const override;
       +    QStringList mimeTypes() const override;
       +
       +    bool hasChildren(const QModelIndex &parent = QModelIndex()) const override;
       +    QModelIndex index(int, int, const QModelIndex &parent = QModelIndex()) const override;
       +    QModelIndex parent(const QModelIndex &) const override;
       +    int columnCount(const QModelIndex &index = QModelIndex()) const override;
       +
       +    Qt::DropActions supportedDropActions() const override;
       +
       +    /**
       +    Reimplemented to match all descendants.
       +    */
       +    virtual QModelIndexList match(const QModelIndex &start, int role, const QVariant &value,
       +                                  int hits = 1, Qt::MatchFlags flags = Qt::MatchFlags(Qt::MatchStartsWith | Qt::MatchWrap)) const override;
       +
       +private:
       +    Q_DECLARE_PRIVATE(KDescendantsProxyModel)
       +    //@cond PRIVATE
       +    KDescendantsProxyModelPrivate *d_ptr;
       +
       +    Q_PRIVATE_SLOT(d_func(), void sourceRowsAboutToBeInserted(const QModelIndex &, int, int))
       +    Q_PRIVATE_SLOT(d_func(), void sourceRowsInserted(const QModelIndex &, int, int))
       +    Q_PRIVATE_SLOT(d_func(), void sourceRowsAboutToBeRemoved(const QModelIndex &, int, int))
       +    Q_PRIVATE_SLOT(d_func(), void sourceRowsRemoved(const QModelIndex &, int, int))
       +    Q_PRIVATE_SLOT(d_func(), void sourceRowsAboutToBeMoved(const QModelIndex &, int, int, const QModelIndex &, int))
       +    Q_PRIVATE_SLOT(d_func(), void sourceRowsMoved(const QModelIndex &, int, int, const QModelIndex &, int))
       +    Q_PRIVATE_SLOT(d_func(), void sourceModelAboutToBeReset())
       +    Q_PRIVATE_SLOT(d_func(), void sourceModelReset())
       +    Q_PRIVATE_SLOT(d_func(), void sourceLayoutAboutToBeChanged())
       +    Q_PRIVATE_SLOT(d_func(), void sourceLayoutChanged())
       +    Q_PRIVATE_SLOT(d_func(), void sourceDataChanged(const QModelIndex &, const QModelIndex &))
       +    Q_PRIVATE_SLOT(d_func(), void sourceModelDestroyed())
       +
       +    Q_PRIVATE_SLOT(d_func(), void processPendingParents())
       +
       +    // Make these private, they shouldn't be called by applications
       +//   virtual bool insertRows(int , int, const QModelIndex & = QModelIndex());
       +//   virtual bool insertColumns(int, int, const QModelIndex & = QModelIndex());
       +//   virtual bool removeRows(int, int, const QModelIndex & = QModelIndex());
       +//   virtual bool removeColumns(int, int, const QModelIndex & = QModelIndex());
       +
       +    //@endcond
       +};
       +
       +#endif