added filelight

This commit is contained in:
Ivailo Monev 2014-11-30 18:15:20 +00:00
parent 1db1e29ced
commit a65a522ef5
66 changed files with 7189 additions and 0 deletions

View file

@ -24,6 +24,7 @@ macro_optional_add_subdirectory (ark)
macro_optional_add_subdirectory (bluedevil)
macro_optional_add_subdirectory (dragon)
macro_optional_add_subdirectory (ffmpegthumbs)
macro_optional_add_subdirectory (filelight)
macro_optional_add_subdirectory (gwenview)
macro_optional_add_subdirectory (kcalc)
macro_optional_add_subdirectory (kcron)

2
filelight/AUTHORS Normal file
View file

@ -0,0 +1,2 @@
Martin Sandsmark <martin.sandsmark@kde.org>
Max Howell <max.howell@methylblue.com>

38
filelight/CMakeLists.txt Normal file
View file

@ -0,0 +1,38 @@
#######################################################################
# Copyright 2008-2009 Martin Sandsmark <martin.sandsmark@kde.org>
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License as
# published by the Free Software Foundation; either version 2 of
# the License or (at your option) version 3 or any later version
# accepted by the membership of KDE e.V. (or its successor approved
# by the membership of KDE e.V.), which shall act as a proxy
# defined in Section 14 of version 3 of the license.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#######################################################################
project(Filelight)
if(${CMAKE_SOURCE_DIR} STREQUAL ${CMAKE_CURRENT_SOURCE_DIR})
find_package(KDE4)
include( KDE4Defaults )
include_directories(${KDE4_INCLUDES})
add_definitions(${QT_DEFINITIONS} ${KDE4_DEFINITIONS})
add_definitions(-DQT_USE_FAST_CONCATENATION -DQT_USE_FAST_OPERATOR_PLUS)
endif()
add_definitions( -DQT_NO_CAST_FROM_ASCII )
add_definitions( -DQT_NO_CAST_TO_ASCII )
include_directories(src/)
add_subdirectory(src)
add_subdirectory(misc)

340
filelight/COPYING Normal file
View file

@ -0,0 +1,340 @@
GNU GENERAL PUBLIC LICENSE
Version 2, June 1991
Copyright (C) 1989, 1991 Free Software Foundation, Inc.
51 Franklin Steet, Fifth Floor, Boston, MA 02111-1307 USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
License is intended to guarantee your freedom to share and change free
software--to make sure the software is free for all its users. This
General Public License applies to most of the Free Software
Foundation's software and to any other program whose authors commit to
using it. (Some other Free Software Foundation software is covered by
the GNU Library General Public License instead.) You can apply it to
your programs, too.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
this service if you wish), that you receive source code or can get it
if you want it, that you can change the software or use pieces of it
in new free programs; and that you know you can do these things.
To protect your rights, we need to make restrictions that forbid
anyone to deny you these rights or to ask you to surrender the rights.
These restrictions translate to certain responsibilities for you if you
distribute copies of the software, or if you modify it.
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must give the recipients all the rights that
you have. You must make sure that they, too, receive or can get the
source code. And you must show them these terms so they know their
rights.
We protect your rights with two steps: (1) copyright the software, and
(2) offer you this license which gives you legal permission to copy,
distribute and/or modify the software.
Also, for each author's protection and ours, we want to make certain
that everyone understands that there is no warranty for this free
software. If the software is modified by someone else and passed on, we
want its recipients to know that what they have is not the original, so
that any problems introduced by others will not reflect on the original
authors' reputations.
Finally, any free program is threatened constantly by software
patents. We wish to avoid the danger that redistributors of a free
program will individually obtain patent licenses, in effect making the
program proprietary. To prevent this, we have made it clear that any
patent must be licensed for everyone's free use or not licensed at all.
The precise terms and conditions for copying, distribution and
modification follow.
GNU GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License applies to any program or other work which contains
a notice placed by the copyright holder saying it may be distributed
under the terms of this General Public License. The "Program", below,
refers to any such program or work, and a "work based on the Program"
means either the Program or any derivative work under copyright law:
that is to say, a work containing the Program or a portion of it,
either verbatim or with modifications and/or translated into another
language. (Hereinafter, translation is included without limitation in
the term "modification".) Each licensee is addressed as "you".
Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope. The act of
running the Program is not restricted, and the output from the Program
is covered only if its contents constitute a work based on the
Program (independent of having been made by running the Program).
Whether that is true depends on what the Program does.
1. You may copy and distribute verbatim copies of the Program's
source code as you receive it, in any medium, provided that you
conspicuously and appropriately publish on each copy an appropriate
copyright notice and disclaimer of warranty; keep intact all the
notices that refer to this License and to the absence of any warranty;
and give any other recipients of the Program a copy of this License
along with the Program.
You may charge a fee for the physical act of transferring a copy, and
you may at your option offer warranty protection in exchange for a fee.
2. You may modify your copy or copies of the Program or any portion
of it, thus forming a work based on the Program, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:
a) You must cause the modified files to carry prominent notices
stating that you changed the files and the date of any change.
b) You must cause any work that you distribute or publish, that in
whole or in part contains or is derived from the Program or any
part thereof, to be licensed as a whole at no charge to all third
parties under the terms of this License.
c) If the modified program normally reads commands interactively
when run, you must cause it, when started running for such
interactive use in the most ordinary way, to print or display an
announcement including an appropriate copyright notice and a
notice that there is no warranty (or else, saying that you provide
a warranty) and that users may redistribute the program under
these conditions, and telling the user how to view a copy of this
License. (Exception: if the Program itself is interactive but
does not normally print such an announcement, your work based on
the Program is not required to print an announcement.)
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Program,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works. But when you
distribute the same sections as part of a whole which is a work based
on the Program, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote it.
Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Program.
In addition, mere aggregation of another work not based on the Program
with the Program (or with a work based on the Program) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.
3. You may copy and distribute the Program (or a work based on it,
under Section 2) in object code or executable form under the terms of
Sections 1 and 2 above provided that you also do one of the following:
a) Accompany it with the complete corresponding machine-readable
source code, which must be distributed under the terms of Sections
1 and 2 above on a medium customarily used for software interchange; or,
b) Accompany it with a written offer, valid for at least three
years, to give any third party, for a charge no more than your
cost of physically performing source distribution, a complete
machine-readable copy of the corresponding source code, to be
distributed under the terms of Sections 1 and 2 above on a medium
customarily used for software interchange; or,
c) Accompany it with the information you received as to the offer
to distribute corresponding source code. (This alternative is
allowed only for noncommercial distribution and only if you
received the program in object code or executable form with such
an offer, in accord with Subsection b above.)
The source code for a work means the preferred form of the work for
making modifications to it. For an executable work, complete source
code means all the source code for all modules it contains, plus any
associated interface definition files, plus the scripts used to
control compilation and installation of the executable. However, as a
special exception, the source code distributed need not include
anything that is normally distributed (in either source or binary
form) with the major components (compiler, kernel, and so on) of the
operating system on which the executable runs, unless that component
itself accompanies the executable.
If distribution of executable or object code is made by offering
access to copy from a designated place, then offering equivalent
access to copy the source code from the same place counts as
distribution of the source code, even though third parties are not
compelled to copy the source along with the object code.
4. You may not copy, modify, sublicense, or distribute the Program
except as expressly provided under this License. Any attempt
otherwise to copy, modify, sublicense or distribute the Program is
void, and will automatically terminate your rights under this License.
However, parties who have received copies, or rights, from you under
this License will not have their licenses terminated so long as such
parties remain in full compliance.
5. You are not required to accept this License, since you have not
signed it. However, nothing else grants you permission to modify or
distribute the Program or its derivative works. These actions are
prohibited by law if you do not accept this License. Therefore, by
modifying or distributing the Program (or any work based on the
Program), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Program or works based on it.
6. Each time you redistribute the Program (or any work based on the
Program), the recipient automatically receives a license from the
original licensor to copy, distribute or modify the Program subject to
these terms and conditions. You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties to
this License.
7. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Program at all. For example, if a patent
license would not permit royalty-free redistribution of the Program by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Program.
If any portion of this section is held invalid or unenforceable under
any particular circumstance, the balance of the section is intended to
apply and the section as a whole is intended to apply in other
circumstances.
It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system, which is
implemented by public license practices. Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.
This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.
8. If the distribution and/or use of the Program is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Program under this License
may add an explicit geographical distribution limitation excluding
those countries, so that distribution is permitted only in or among
countries not thus excluded. In such case, this License incorporates
the limitation as if written in the body of this License.
9. The Free Software Foundation may publish revised and/or new versions
of the General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the Program
specifies a version number of this License which applies to it and "any
later version", you have the option of following the terms and conditions
either of that version or of any later version published by the Free
Software Foundation. If the Program does not specify a version number of
this License, you may choose any version ever published by the Free Software
Foundation.
10. If you wish to incorporate parts of the Program into other free
programs whose distribution conditions are different, write to the author
to ask for permission. For software which is copyrighted by the Free
Software Foundation, write to the Free Software Foundation; we sometimes
make exceptions for this. Our decision will be guided by the two goals
of preserving the free status of all derivatives of our free software and
of promoting the sharing and reuse of software generally.
NO WARRANTY
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
REPAIR OR CORRECTION.
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGES.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.
To do so, attach the following notices to the program. It is safest
to attach them to the start of each source file to most effectively
convey the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
<one line to give the program's name and a brief idea of what it does.>
Copyright (C) <year> <name of author>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Steet, Fifth Floor, Boston, MA 02111-1307 USA
Also add information on how to contact you by electronic and paper mail.
If the program is interactive, make it output a short notice like this
when it starts in an interactive mode:
Gnomovision version 69, Copyright (C) year name of author
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License. Of course, the commands you use may
be called something other than `show w' and `show c'; they could even be
mouse-clicks or menu items--whatever suits your program.
You should also get your employer (if you work as a programmer) or your
school, if any, to sign a "copyright disclaimer" for the program, if
necessary. Here is a sample; alter the names:
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
`Gnomovision' (which makes passes at compilers) written by James Hacker.
<signature of Ty Coon>, 1 April 1989
Ty Coon, President of Vice
This General Public License does not permit incorporating your program into
proprietary programs. If your program is a subroutine library, you may
consider it more useful to permit linking proprietary applications with the
library. If this is what you want to do, use the GNU Library General
Public License instead of this License.

397
filelight/COPYING-DOCS Normal file
View file

@ -0,0 +1,397 @@
GNU Free Documentation License
Version 1.2, November 2002
Copyright (C) 2000,2001,2002 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.
0. PREAMBLE
The purpose of this License is to make a manual, textbook, or other
functional and useful document "free" in the sense of freedom: to
assure everyone the effective freedom to copy and redistribute it,
with or without modifying it, either commercially or noncommercially.
Secondarily, this License preserves for the author and publisher a way
to get credit for their work, while not being considered responsible
for modifications made by others.
This License is a kind of "copyleft", which means that derivative
works of the document must themselves be free in the same sense. It
complements the GNU General Public License, which is a copyleft
license designed for free software.
We have designed this License in order to use it for manuals for free
software, because free software needs free documentation: a free
program should come with manuals providing the same freedoms that the
software does. But this License is not limited to software manuals;
it can be used for any textual work, regardless of subject matter or
whether it is published as a printed book. We recommend this License
principally for works whose purpose is instruction or reference.
1. APPLICABILITY AND DEFINITIONS
This License applies to any manual or other work, in any medium, that
contains a notice placed by the copyright holder saying it can be
distributed under the terms of this License. Such a notice grants a
world-wide, royalty-free license, unlimited in duration, to use that
work under the conditions stated herein. The "Document", below,
refers to any such manual or work. Any member of the public is a
licensee, and is addressed as "you". You accept the license if you
copy, modify or distribute the work in a way requiring permission
under copyright law.
A "Modified Version" of the Document means any work containing the
Document or a portion of it, either copied verbatim, or with
modifications and/or translated into another language.
A "Secondary Section" is a named appendix or a front-matter section of
the Document that deals exclusively with the relationship of the
publishers or authors of the Document to the Document's overall subject
(or to related matters) and contains nothing that could fall directly
within that overall subject. (Thus, if the Document is in part a
textbook of mathematics, a Secondary Section may not explain any
mathematics.) The relationship could be a matter of historical
connection with the subject or with related matters, or of legal,
commercial, philosophical, ethical or political position regarding
them.
The "Invariant Sections" are certain Secondary Sections whose titles
are designated, as being those of Invariant Sections, in the notice
that says that the Document is released under this License. If a
section does not fit the above definition of Secondary then it is not
allowed to be designated as Invariant. The Document may contain zero
Invariant Sections. If the Document does not identify any Invariant
Sections then there are none.
The "Cover Texts" are certain short passages of text that are listed,
as Front-Cover Texts or Back-Cover Texts, in the notice that says that
the Document is released under this License. A Front-Cover Text may
be at most 5 words, and a Back-Cover Text may be at most 25 words.
A "Transparent" copy of the Document means a machine-readable copy,
represented in a format whose specification is available to the
general public, that is suitable for revising the document
straightforwardly with generic text editors or (for images composed of
pixels) generic paint programs or (for drawings) some widely available
drawing editor, and that is suitable for input to text formatters or
for automatic translation to a variety of formats suitable for input
to text formatters. A copy made in an otherwise Transparent file
format whose markup, or absence of markup, has been arranged to thwart
or discourage subsequent modification by readers is not Transparent.
An image format is not Transparent if used for any substantial amount
of text. A copy that is not "Transparent" is called "Opaque".
Examples of suitable formats for Transparent copies include plain
ASCII without markup, Texinfo input format, LaTeX input format, SGML
or XML using a publicly available DTD, and standard-conforming simple
HTML, PostScript or PDF designed for human modification. Examples of
transparent image formats include PNG, XCF and JPG. Opaque formats
include proprietary formats that can be read and edited only by
proprietary word processors, SGML or XML for which the DTD and/or
processing tools are not generally available, and the
machine-generated HTML, PostScript or PDF produced by some word
processors for output purposes only.
The "Title Page" means, for a printed book, the title page itself,
plus such following pages as are needed to hold, legibly, the material
this License requires to appear in the title page. For works in
formats which do not have any title page as such, "Title Page" means
the text near the most prominent appearance of the work's title,
preceding the beginning of the body of the text.
A section "Entitled XYZ" means a named subunit of the Document whose
title either is precisely XYZ or contains XYZ in parentheses following
text that translates XYZ in another language. (Here XYZ stands for a
specific section name mentioned below, such as "Acknowledgements",
"Dedications", "Endorsements", or "History".) To "Preserve the Title"
of such a section when you modify the Document means that it remains a
section "Entitled XYZ" according to this definition.
The Document may include Warranty Disclaimers next to the notice which
states that this License applies to the Document. These Warranty
Disclaimers are considered to be included by reference in this
License, but only as regards disclaiming warranties: any other
implication that these Warranty Disclaimers may have is void and has
no effect on the meaning of this License.
2. VERBATIM COPYING
You may copy and distribute the Document in any medium, either
commercially or noncommercially, provided that this License, the
copyright notices, and the license notice saying this License applies
to the Document are reproduced in all copies, and that you add no other
conditions whatsoever to those of this License. You may not use
technical measures to obstruct or control the reading or further
copying of the copies you make or distribute. However, you may accept
compensation in exchange for copies. If you distribute a large enough
number of copies you must also follow the conditions in section 3.
You may also lend copies, under the same conditions stated above, and
you may publicly display copies.
3. COPYING IN QUANTITY
If you publish printed copies (or copies in media that commonly have
printed covers) of the Document, numbering more than 100, and the
Document's license notice requires Cover Texts, you must enclose the
copies in covers that carry, clearly and legibly, all these Cover
Texts: Front-Cover Texts on the front cover, and Back-Cover Texts on
the back cover. Both covers must also clearly and legibly identify
you as the publisher of these copies. The front cover must present
the full title with all words of the title equally prominent and
visible. You may add other material on the covers in addition.
Copying with changes limited to the covers, as long as they preserve
the title of the Document and satisfy these conditions, can be treated
as verbatim copying in other respects.
If the required texts for either cover are too voluminous to fit
legibly, you should put the first ones listed (as many as fit
reasonably) on the actual cover, and continue the rest onto adjacent
pages.
If you publish or distribute Opaque copies of the Document numbering
more than 100, you must either include a machine-readable Transparent
copy along with each Opaque copy, or state in or with each Opaque copy
a computer-network location from which the general network-using
public has access to download using public-standard network protocols
a complete Transparent copy of the Document, free of added material.
If you use the latter option, you must take reasonably prudent steps,
when you begin distribution of Opaque copies in quantity, to ensure
that this Transparent copy will remain thus accessible at the stated
location until at least one year after the last time you distribute an
Opaque copy (directly or through your agents or retailers) of that
edition to the public.
It is requested, but not required, that you contact the authors of the
Document well before redistributing any large number of copies, to give
them a chance to provide you with an updated version of the Document.
4. MODIFICATIONS
You may copy and distribute a Modified Version of the Document under
the conditions of sections 2 and 3 above, provided that you release
the Modified Version under precisely this License, with the Modified
Version filling the role of the Document, thus licensing distribution
and modification of the Modified Version to whoever possesses a copy
of it. In addition, you must do these things in the Modified Version:
A. Use in the Title Page (and on the covers, if any) a title distinct
from that of the Document, and from those of previous versions
(which should, if there were any, be listed in the History section
of the Document). You may use the same title as a previous version
if the original publisher of that version gives permission.
B. List on the Title Page, as authors, one or more persons or entities
responsible for authorship of the modifications in the Modified
Version, together with at least five of the principal authors of the
Document (all of its principal authors, if it has fewer than five),
unless they release you from this requirement.
C. State on the Title page the name of the publisher of the
Modified Version, as the publisher.
D. Preserve all the copyright notices of the Document.
E. Add an appropriate copyright notice for your modifications
adjacent to the other copyright notices.
F. Include, immediately after the copyright notices, a license notice
giving the public permission to use the Modified Version under the
terms of this License, in the form shown in the Addendum below.
G. Preserve in that license notice the full lists of Invariant Sections
and required Cover Texts given in the Document's license notice.
H. Include an unaltered copy of this License.
I. Preserve the section Entitled "History", Preserve its Title, and add
to it an item stating at least the title, year, new authors, and
publisher of the Modified Version as given on the Title Page. If
there is no section Entitled "History" in the Document, create one
stating the title, year, authors, and publisher of the Document as
given on its Title Page, then add an item describing the Modified
Version as stated in the previous sentence.
J. Preserve the network location, if any, given in the Document for
public access to a Transparent copy of the Document, and likewise
the network locations given in the Document for previous versions
it was based on. These may be placed in the "History" section.
You may omit a network location for a work that was published at
least four years before the Document itself, or if the original
publisher of the version it refers to gives permission.
K. For any section Entitled "Acknowledgements" or "Dedications",
Preserve the Title of the section, and preserve in the section all
the substance and tone of each of the contributor acknowledgements
and/or dedications given therein.
L. Preserve all the Invariant Sections of the Document,
unaltered in their text and in their titles. Section numbers
or the equivalent are not considered part of the section titles.
M. Delete any section Entitled "Endorsements". Such a section
may not be included in the Modified Version.
N. Do not retitle any existing section to be Entitled "Endorsements"
or to conflict in title with any Invariant Section.
O. Preserve any Warranty Disclaimers.
If the Modified Version includes new front-matter sections or
appendices that qualify as Secondary Sections and contain no material
copied from the Document, you may at your option designate some or all
of these sections as invariant. To do this, add their titles to the
list of Invariant Sections in the Modified Version's license notice.
These titles must be distinct from any other section titles.
You may add a section Entitled "Endorsements", provided it contains
nothing but endorsements of your Modified Version by various
parties--for example, statements of peer review or that the text has
been approved by an organization as the authoritative definition of a
standard.
You may add a passage of up to five words as a Front-Cover Text, and a
passage of up to 25 words as a Back-Cover Text, to the end of the list
of Cover Texts in the Modified Version. Only one passage of
Front-Cover Text and one of Back-Cover Text may be added by (or
through arrangements made by) any one entity. If the Document already
includes a cover text for the same cover, previously added by you or
by arrangement made by the same entity you are acting on behalf of,
you may not add another; but you may replace the old one, on explicit
permission from the previous publisher that added the old one.
The author(s) and publisher(s) of the Document do not by this License
give permission to use their names for publicity for or to assert or
imply endorsement of any Modified Version.
5. COMBINING DOCUMENTS
You may combine the Document with other documents released under this
License, under the terms defined in section 4 above for modified
versions, provided that you include in the combination all of the
Invariant Sections of all of the original documents, unmodified, and
list them all as Invariant Sections of your combined work in its
license notice, and that you preserve all their Warranty Disclaimers.
The combined work need only contain one copy of this License, and
multiple identical Invariant Sections may be replaced with a single
copy. If there are multiple Invariant Sections with the same name but
different contents, make the title of each such section unique by
adding at the end of it, in parentheses, the name of the original
author or publisher of that section if known, or else a unique number.
Make the same adjustment to the section titles in the list of
Invariant Sections in the license notice of the combined work.
In the combination, you must combine any sections Entitled "History"
in the various original documents, forming one section Entitled
"History"; likewise combine any sections Entitled "Acknowledgements",
and any sections Entitled "Dedications". You must delete all sections
Entitled "Endorsements".
6. COLLECTIONS OF DOCUMENTS
You may make a collection consisting of the Document and other documents
released under this License, and replace the individual copies of this
License in the various documents with a single copy that is included in
the collection, provided that you follow the rules of this License for
verbatim copying of each of the documents in all other respects.
You may extract a single document from such a collection, and distribute
it individually under this License, provided you insert a copy of this
License into the extracted document, and follow this License in all
other respects regarding verbatim copying of that document.
7. AGGREGATION WITH INDEPENDENT WORKS
A compilation of the Document or its derivatives with other separate
and independent documents or works, in or on a volume of a storage or
distribution medium, is called an "aggregate" if the copyright
resulting from the compilation is not used to limit the legal rights
of the compilation's users beyond what the individual works permit.
When the Document is included in an aggregate, this License does not
apply to the other works in the aggregate which are not themselves
derivative works of the Document.
If the Cover Text requirement of section 3 is applicable to these
copies of the Document, then if the Document is less than one half of
the entire aggregate, the Document's Cover Texts may be placed on
covers that bracket the Document within the aggregate, or the
electronic equivalent of covers if the Document is in electronic form.
Otherwise they must appear on printed covers that bracket the whole
aggregate.
8. TRANSLATION
Translation is considered a kind of modification, so you may
distribute translations of the Document under the terms of section 4.
Replacing Invariant Sections with translations requires special
permission from their copyright holders, but you may include
translations of some or all Invariant Sections in addition to the
original versions of these Invariant Sections. You may include a
translation of this License, and all the license notices in the
Document, and any Warranty Disclaimers, provided that you also include
the original English version of this License and the original versions
of those notices and disclaimers. In case of a disagreement between
the translation and the original version of this License or a notice
or disclaimer, the original version will prevail.
If a section in the Document is Entitled "Acknowledgements",
"Dedications", or "History", the requirement (section 4) to Preserve
its Title (section 1) will typically require changing the actual
title.
9. TERMINATION
You may not copy, modify, sublicense, or distribute the Document except
as expressly provided for under this License. Any other attempt to
copy, modify, sublicense or distribute the Document 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.
10. FUTURE REVISIONS OF THIS LICENSE
The Free Software Foundation may publish new, revised versions
of the GNU Free Documentation 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. See
http://www.gnu.org/copyleft/.
Each version of the License is given a distinguishing version number.
If the Document specifies that a particular numbered version of this
License "or any later version" applies to it, you have the option of
following the terms and conditions either of that specified version or
of any later version that has been published (not as a draft) by the
Free Software Foundation. If the Document does not specify a version
number of this License, you may choose any version ever published (not
as a draft) by the Free Software Foundation.
ADDENDUM: How to use this License for your documents
To use this License in a document you have written, include a copy of
the License in the document and put the following copyright and
license notices just after the title page:
Copyright (c) YEAR YOUR NAME.
Permission is granted to copy, distribute and/or modify this document
under the terms of the GNU Free Documentation License, Version 1.2
or any later version published by the Free Software Foundation;
with no Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts.
A copy of the license is included in the section entitled "GNU
Free Documentation License".
If you have Invariant Sections, Front-Cover Texts and Back-Cover Texts,
replace the "with...Texts." line with this:
with the Invariant Sections being LIST THEIR TITLES, with the
Front-Cover Texts being LIST, and with the Back-Cover Texts being LIST.
If you have Invariant Sections without Cover Texts, or some other
combination of the three, merge those two alternatives to suit the
situation.
If your document contains nontrivial examples of program code, we
recommend releasing these examples in parallel under your choice of
free software license, such as the GNU General Public License,
to permit their use in free software.

View file

@ -0,0 +1,13 @@
## This file should be placed in the root directory of your project.
## Then modify the CMakeLists.txt file in the root directory of your
## project to incorporate the testing dashboard.
## # The following are required to uses Dart and the Cdash dashboard
## ENABLE_TESTING()
## INCLUDE(CTest)
set(CTEST_PROJECT_NAME "filelight")
set(CTEST_NIGHTLY_START_TIME "20:00:00 CET")
set(CTEST_DROP_METHOD "http")
set(CTEST_DROP_SITE "my.cdash.org")
set(CTEST_DROP_LOCATION "/submit.php?project=filelight")
set(CTEST_DROP_SITE_CDASH TRUE)

243
filelight/ChangeLog Normal file
View file

@ -0,0 +1,243 @@
1.9
Ported to Qt 4 / KDE 4
Paint directly on the widget
Remove ugly hack for checking for backingstore
1.0
Added copy to clipboard function to segment context menus
Accepts URLs from drag and drop
Click central circle to go "up"
0.6.3
Made "Scan Directory..." a KStdAction::open with setText( "Scan Directory..." );
Swaped map rendering from bitBlt to paintPixmap (again) as some users get problems with the labels being obliterated
LocationBar history is saved inbetween sessions for KDE >= 3.1.3
Rescans are forced if locationBar Go is pushed for location to current map
Fixed several bugs related to resizing the filemap
Initial map display had a long running issue which meant you had to perform a resize to ensure all detail was shown. I finally put in the hours and fixed it.
Cancelling scans clears the location bar
Option to show files not represented as segments (because they are too small) combined in large segments with relevant summaries
Directories that would normally have no child segments shown now have hidden Files segment shown
Fixed faulty show/hide of progress box when many scans done in quick succession
Session management
Saving of Window/*bar settings inbetween sessions
Fixed popup related non-updates and false action calls
Canvas code cleanup
Stopped combo activated scans being called twice
Improved map generation speed (scan speeds are still slow however)
Appropriate wait cursors are set during long operations (scans, map generation)
Fixed misrendered transparency when tooltips exceed Filelight boundries
Optimised and de-flickered the tooltips
Segments that contain unrepresented files (due to 5 level limit on maps) now show a thick border at the edge to indicate that there are unrepresented files
Commandline now accepts ../ and ./ type arguments
Add "Open Konsole here" to context-menu, also tidied it up and made it properly context relevant
Popup title is now relative to map path to reduce menu width somewhat without resorting to csqueeze()
Fixed bug with not showing unrepresented files for dirs that contained dirs
Improvement selection of units for tooltips (always prefer megabytes unless < 0.01 MB)
Improved selection of decimal places for size display (2sig.fig. please)
Label font sizes now default to the system standard
Labels have indentation relative to their level
Label selection improved (not enough yet though!)
Better looking label line diagonals
When smaller fonts are requested, Filelight maximises the font size differences
Attempted to fix crash at exit bug
Made files shades of gray, made indicator for directories that have unshown files
Removed presence of multi-file segments except in root level circumstances (unless Show Small Files is selected in Settings)
Contrast system revamped, you can now have more contrast
Segment colouring system rewritten, better distinction between different segment types
Used more KStdActions (less work for translation teams at very least)
Fixed bug where segmenttip wasn't shown for 1st pixel but labels were
Directories with unshown files have better arrow heads now thanks to some clever trig
Checked for possible cases where division by zero might occur and corrected code
Huge code rewrite in preparation for transition to KPart (must release soon, this is getting silly)
Allow clicks on the central circle to represent the map's root (eg. middle-click to open in Konqi)
0.6.2
Attempted a fix for the absurdly large file bug (eg > 1400GB!)
Linking bug fixed for Gentoo systems
Compile bug fixed for GCC < 3
Fixed crash bug when scan had been stopped and then back then forward pressed
Fixed another compile bug for systems that don't support large files (Debian apparently)
Internationalisation support thanks to patch from André Somers
Made the tooltip translucent (NOT a gimmick, this feature is essential IMO)
Started making debug messages use kdDebug so users can enable/disable the messages
Implemented XML GUI
Vast slot/signal cleanup, fixed many bugs
Fixed a few bugs with the progress box
Cancelled scans now remain stored in the back/forward histories
Fixed incorrect reporting of directory file counts
Increased minimum segment size to 3px outer diameter (any depth)
Added location_bar UI element to toolbar (much work)
The segment tip now appears below the cursor when hovering over the upper part of the map
Increased the recent scans list to 8 entries and made the combohistory work better
0.6.1
Filelight again compiles on KDE <= 3.1.3 (but with some reduced functionality)
Rewrote HistoryAction code
Improved default choice of smallest font
Lowest level segment labels show whenever mouse is not over anything
Middle click opens segment according to mime type (eg. jpgs open in kuickshow)
Implemented realtime contrast updates
Added antialiasing, font size and contrast settings to appearance tab
Renamed "colour scheme" tab "appearance"
Extruded label fontsizes reflect their segment's depth
Rescans ignore tree cache
Changing scan options clears the tree cache
Directory select dialog shows current path as selected when opened
Scans no longer have to be repeated
Implemented antialiasing for the map, very slow so only happens after resizes
Gracefully handles failures to read file attributes
Rewrote backend with templating, should have done that in first place!
Improved changelog listing methods!
Included support for GNU systems that don't support large files (>2GB)
0.6.0
Added expanded labels to give more information on segments in focus
Added settings dialogs
Added new colour schemes
Allowed scans to not cross at mount points
Added #Files info for directory tooltips
filemap is now displayed centrally
Shows percentage of files in directories
0.5.1
Added Filelight to the Utilities submenu in the K-Menu
Tooltips are now presented for file info instead of using the statusbar
Made resizing of the filemap smoother
Improved the icon and made a 48x48 and 22x22 version
Reworked the code somewhat
Scans can now be cancelled
The go history actions are more intelligent
Fixed all the bugs I could find
Attempted to improve filemap contrast some more (still not perfect, but getting there)
Added visual activation cues for various clicks
0.50
Few bug fixes
Improved performance for rendering and scanning
Improved contrast of the filemap
Added icon
Added left and right click functionality
Improved error handling
0.45
Added toolbar, implemented history functionality
Click to scan segments
Increased filesize limit to 4096 GB
Fixed <time.h> required - make bug
Various optimisations
0.4
Initial public release
1.0
Added copy to clipboard function to segment context menus
Accepts URLs from drag and drop
Click central circle to go "up"
0.6.3
Made "Scan Directory..." a KStdAction::open with setText( "Scan Directory..." );
Swaped map rendering from bitBlt to paintPixmap (again) as some users get problems with the labels being obliterated
LocationBar history is saved inbetween sessions for KDE >= 3.1.3
Rescans are forced if locationBar Go is pushed for location to current map
Fixed several bugs related to resizing the filemap
Initial map display had a long running issue which meant you had to perform a resize to ensure all detail was shown. I finally put in the hours and fixed it.
Cancelling scans clears the location bar
Option to show files not represented as segments (because they are too small) combined in large segments with relevant summaries
Directories that would normally have no child segments shown now have hidden Files segment shown
Fixed faulty show/hide of progress box when many scans done in quick succession
Session management
Saving of Window/*bar settings inbetween sessions
Fixed popup related non-updates and false action calls
Canvas code cleanup
Stopped combo activated scans being called twice
Improved map generation speed (scan speeds are still slow however)
Appropriate wait cursors are set during long operations (scans, map generation)
Fixed misrendered transparency when tooltips exceed Filelight boundries
Optimised and de-flickered the tooltips
Segments that contain unrepresented files (due to 5 level limit on maps) now show a thick border at the edge to indicate that there are unrepresented files
Commandline now accepts ../ and ./ type arguments
Add "Open Konsole here" to context-menu, also tidied it up and made it properly context relevant
Popup title is now relative to map path to reduce menu width somewhat without resorting to csqueeze()
Fixed bug with not showing unrepresented files for dirs that contained dirs
Improvement selection of units for tooltips (always prefer megabytes unless < 0.01 MB)
Improved selection of decimal places for size display (2sig.fig. please)
Label font sizes now default to the system standard
Labels have indentation relative to their level
Label selection improved (not enough yet though!)
Better looking label line diagonals
When smaller fonts are requested, Filelight maximises the font size differences
Attempted to fix crash at exit bug
Made files shades of gray, made indicator for directories that have unshown files
Removed presence of multi-file segments except in root level circumstances (unless Show Small Files is selected in Settings)
Contrast system revamped, you can now have more contrast
Segment colouring system rewritten, better distinction between different segment types
Used more KStdActions (less work for translation teams at very least)
Fixed bug where segmenttip wasn't shown for 1st pixel but labels were
Directories with unshown files have better arrow heads now thanks to some clever trig
Checked for possible cases where division by zero might occur and corrected code
Huge code rewrite in preparation for transition to KPart (must release soon, this is getting silly)
Allow clicks on the central circle to represent the map's root (eg. middle-click to open in Konqi)
0.6.2
Attempted a fix for the absurdly large file bug (eg > 1400GB!)
Linking bug fixed for Gentoo systems
Compile bug fixed for GCC < 3
Fixed crash bug when scan had been stopped and then back then forward pressed
Fixed another compile bug for systems that don't support large files (Debian apparently)
Internationalisation support thanks to patch from André Somers
Made the tooltip translucent (NOT a gimmick, this feature is essential IMO)
Started making debug messages use kdDebug so users can enable/disable the messages
Implemented XML GUI
Vast slot/signal cleanup, fixed many bugs
Fixed a few bugs with the progress box
Cancelled scans now remain stored in the back/forward histories
Fixed incorrect reporting of directory file counts
Increased minimum segment size to 3px outer diameter (any depth)
Added location_bar UI element to toolbar (much work)
The segment tip now appears below the cursor when hovering over the upper part of the map
Increased the recent scans list to 8 entries and made the combohistory work better
0.6.1
Filelight again compiles on KDE <= 3.1.3 (but with some reduced functionality)
Rewrote HistoryAction code
Improved default choice of smallest font
Lowest level segment labels show whenever mouse is not over anything
Middle click opens segment according to mime type (eg. jpgs open in kuickshow)
Implemented realtime contrast updates
Added antialiasing, font size and contrast settings to appearance tab
Renamed "colour scheme" tab "appearance"
Extruded label fontsizes reflect their segment's depth
Rescans ignore tree cache
Changing scan options clears the tree cache
Directory select dialog shows current path as selected when opened
Scans no longer have to be repeated
Implemented antialiasing for the map, very slow so only happens after resizes
Gracefully handles failures to read file attributes
Rewrote backend with templating, should have done that in first place!
Improved changelog listing methods!
Included support for GNU systems that don't support large files (>2GB)
0.6.0
Added expanded labels to give more information on segments in focus
Added settings dialogs
Added new colour schemes
Allowed scans to not cross at mount points
Added #Files info for directory tooltips
filemap is now displayed centrally
Shows percentage of files in directories
0.5.1
Added Filelight to the Utilities submenu in the K-Menu
Tooltips are now presented for file info instead of using the statusbar
Made resizing of the filemap smoother
Improved the icon and made a 48x48 and 22x22 version
Reworked the code somewhat
Scans can now be cancelled
The go history actions are more intelligent
Fixed all the bugs I could find
Attempted to improve filemap contrast some more (still not perfect, but getting there)
Added visual activation cues for various clicks
0.50
Few bug fixes
Improved performance for rendering and scanning
Improved contrast of the filemap
Added icon
Added left and right click functionality
Improved error handling
0.45
Added toolbar, implemented history functionality
Click to scan segments
Increased filesize limit to 4096 GB
Fixed <time.h> required - make bug
Various optimisations
0.4
Initial public release

32
filelight/INSTALL Normal file
View file

@ -0,0 +1,32 @@
Filelight INSTALL
===================
Simply:
$ mkdir build && cd build && cmake .. -DCMAKE_INSTALL_PREFIX=/usr \
&& make && sudo make install
Troubleshooting
=================
Check you have the kde development packages installed, they'll be named
something like:
kde-devel
This should pull in a lot of other development packages (unless they are already
installed) like:
x11-devel
qt-devel
If you get stuck, please email me with any relevant information you can
provide. I will get back to you! Compile issues suck, I know this full well.
--------------------------------------------------------------------------------
We hope you enjoy using Filelight!
Martin Sandsmark <martin.sandsmark@kde.org>
Max Howell <max.howell@methylblue.com>

8
filelight/Mainpage.dox Normal file
View file

@ -0,0 +1,8 @@
/** @mainpage Filelight
The Filelight application
*/
// DOXYGEN_REFERENCES = kdecore
// DOXYGEN_SET_PROJECT_NAME = filelight

4
filelight/Messages.sh Normal file
View file

@ -0,0 +1,4 @@
#!bin/sh
$EXTRACTRC `find . -name \*.rc -o -name \*.ui` >> rc.cpp
$XGETTEXT `find . -name \*.cpp -o -name \*.h` -o $podir/filelight.pot
rm -f rc.cpp

1
filelight/NEWS Normal file
View file

@ -0,0 +1 @@

50
filelight/README Normal file
View file

@ -0,0 +1,50 @@
Filelight README
==================
Filelight allows you to understand exactly where your diskspace is being used by
graphically representating your filesystem as a set of concentric
segmented-rings.
--------------------------------------------------------------------------------
Dependencies
==============
Filelight works on KDElibs >= 4.2 and therefore Qt >= 4.4 (lower versions may
work, but no guarantees).
Usage Tips
============
* Click on directories to center the view there
* Click on files to launch the application associated with them
* Middle click to open files/directories with Konqueror
* Right click on the central white circle to manipulate the base directory
* Increase the window size to see more detail
* Hover over segments to find out more information
* Available as a view-KPart in Konqueror
* You can specify a directory to scan on startup from the command line, eg:
$ filelight /home/mxcl
Installation
==============
See the accompanying file; INSTALL.
Bugs
======
There are less bugs everyday! Please report bugs at http://bugs.kde.org/
--------------------------------------------------------------------------------
We hope you enjoy using Filelight!
Martin Sandsmark <martin.sandsmark@kde.org>
Max Howell <max.howell@methylblue.com>

28
filelight/TODO Normal file
View file

@ -0,0 +1,28 @@
1.3
features for sysadmins, split by users etc.
1.2
split rendering engine from data-gatherer and allow data to be fed through a pipe thus allowing different data sources to be profiled.
show preview icons next to the labels
last access time colour scheme
History actions need to have menu pulldown just like konqi
show statusbar signal to say that diretories weren't scanned due to lack of permissions (allow user to enter root password, for this scan only or to keep and then scan only bits that were missed)
determine if canvas is too square and shrink map accordingly
1.1
If scanning a partition show free space
if the view is square shrink the map slightly as a slightly rectangular view is preferable
use kdirwatcher, then move rescan to scan menu, rename force rescan
clicking center goes up directory
refactor disklister.cpp
implement vectors instead of double-linked lists for file data
Trace inodes in binarytree to avoid recursive hardlinks and counting same directory tree twice
admin mode
fix that Part settings file is not same as app settings file
support other mouse actions for central circle (ie middle click, right click)
write caches for all scans, so if crash or something that root scan that took 20 mins is not lost
MAYBE
flicking mouse wheel shows different information in tooltip, and there's an off setting, show temp status message to reflect info box
ideally, eventually show which labels are children of which by grouping them with a coloured square or something
create html summary files (pics and text)

13
filelight/filelight.lsm Normal file
View file

@ -0,0 +1,13 @@
Begin3
title: Filelight
Version: 1.0
Entered-date: 5/9/2003
Description: Graphical disk usage information
Keywords: kde disk usage du filesystem diskspace
author: Max Howell <max.howell@methylblue.com>
Maintained-by: Martin Sandsmark <martin.sandsmark@kde.org>
Home-page: http://utils.kde.org/projects/filelight
Platform: unix
Copying-policy: GPL
End

View file

@ -0,0 +1,27 @@
#######################################################################
# Copyright 2008-2009 Martin Sandsmark <martin.sandsmark@kde.org>
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License as
# published by the Free Software Foundation; either version 2 of
# the License or (at your option) version 3 or any later version
# accepted by the membership of KDE e.V. (or its successor approved
# by the membership of KDE e.V.), which shall act as a proxy
# defined in Section 14 of version 3 of the license.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#######################################################################
install(FILES filelightpart.desktop DESTINATION ${SERVICES_INSTALL_DIR})
install(PROGRAMS filelight.desktop DESTINATION ${XDG_APPS_INSTALL_DIR})
install(FILES filelightrc DESTINATION ${CONFIG_INSTALL_DIR})
install(FILES filelightpartui.rc DESTINATION ${DATA_INSTALL_DIR}/filelightpart)
install(FILES filelightui.rc DESTINATION ${DATA_INSTALL_DIR}/filelight)
kde4_install_icons(${ICON_INSTALL_DIR})

160
filelight/misc/filelight.desktop Executable file
View file

@ -0,0 +1,160 @@
# KDE Config File
[Desktop Entry]
Name=Filelight
Name[bs]=Filelight
Name[ca]=Filelight
Name[ca@valencia]=Filelight
Name[cs]=Filelight
Name[da]=Filelight
Name[de]=Filelight
Name[el]=Filelight
Name[en_GB]=Filelight
Name[es]=Filelight
Name[et]=Filelight
Name[eu]=Filelight
Name[fi]=Filelight
Name[fr]=Filelight
Name[ga]=Filelight
Name[gl]=Filelight
Name[hr]=Filelight
Name[hu]=Filelight
Name[ia]=Filelight
Name[it]=Filelight
Name[kk]=Filelight
Name[km]=Filelight
Name[ko]=Filelight
Name[lt]=Filelight
Name[lv]=Filelight
Name[mr]=-
Name[nb]=Filelight
Name[nds]=Filelight
Name[nl]=Filelight
Name[pa]=
Name[pl]=Filelight
Name[pt]=Filelight
Name[pt_BR]=Filelight
Name[ro]=Filelight
Name[ru]=Filelight
Name[sk]=Filelight
Name[sl]=Filelight
Name[sr]=Фајлајт
Name[sr@ijekavian]=Фајлајт
Name[sr@ijekavianlatin]=Filelight
Name[sr@latin]=Filelight
Name[sv]=Filelight
Name[th]=Filelight
Name[tr]=Filelight
Name[ug]=Filelight
Name[uk]=Filelight
Name[wa]=Filelight
Name[x-test]=xxFilelightxx
Name[zh_CN]=Filelight
Name[zh_TW]=Filelight
GenericName=Disk Usage Statistics
GenericName[ast]=Estadístiques d'usu de discu
GenericName[bs]=Statistika upotrebe diska
GenericName[ca]=Estadístiques d'ús de disc
GenericName[ca@valencia]=Estadístiques d'ús de disc
GenericName[cs]=Statistika použití disku
GenericName[da]=Statistik over diskforbrug
GenericName[de]=Statistik über Festplattenbelegung
GenericName[el]=Στατιστικά χρήσης δίσκου
GenericName[en_GB]=Disk Usage Statistics
GenericName[es]=Estadísticas de uso de discos
GenericName[et]=Kettakasutuse statistika
GenericName[eu]=Diskoen erabilerari buruzko estatistikak
GenericName[fi]=Levynkäyttötilastot
GenericName[fr]=Statistiques d'utilisation de disques
GenericName[ga]=Staitisticí maidir le húsáid diosca
GenericName[gl]=Estatísticas de uso do disco
GenericName[hr]=Statistika o upotrebi diska
GenericName[hu]=Lemezhasználati statisztika
GenericName[ia]=Statisticas de uso de disco
GenericName[it]=Statistiche uso del disco
GenericName[kk]=Дискінің статистикасы
GenericName[km]=
GenericName[ko]=
GenericName[lt]=Disko naudojimo statistika
GenericName[lv]=Diska izlietojuma statistika
GenericName[mr]=ि
GenericName[nb]=Statistikk over diskbruk
GenericName[nds]=Fastplaatbruuk-Statistik
GenericName[nl]=Gebruiksstatistieken van schijven
GenericName[pa]=ਿ
GenericName[pl]=Statystyki wykorzystania dysku
GenericName[pt]=Estatísticas de Utilização do Disco
GenericName[pt_BR]=Estatísticas de uso do disco
GenericName[ro]=Statistici utilizare disc
GenericName[ru]=Использование дисков
GenericName[sk]=Štatistiky využitia disku
GenericName[sl]=Statistika uporabe diska
GenericName[sr]=Статистика искоришћености дискова
GenericName[sr@ijekavian]=Статистика искоришћености дискова
GenericName[sr@ijekavianlatin]=Statistika iskorišćenosti diskova
GenericName[sr@latin]=Statistika iskorišćenosti diskova
GenericName[sv]=Statistik över diskanvändning
GenericName[th]=
GenericName[tr]=Disk Kullanımı İstatistikleri
GenericName[uk]=Статистика використання диска
GenericName[x-test]=xxDisk Usage Statisticsxx
GenericName[zh_CN]=使
GenericName[zh_TW]=
Type=Application
Exec=filelight %f
Icon=filelight
Comment=View disk usage information
Comment[ast]=Ver infomación d'usu de Discu
Comment[bs]=Pogledajte podatke o upotrebi diska
Comment[ca]=Veure la informació d'ús de disc
Comment[ca@valencia]=Veure la informació d'ús de disc
Comment[cs]=Zobrazit využití disku
Comment[da]=Vis information om diskforbrug
Comment[de]=Nutzungsinformationen zu Festplatten anzeigen
Comment[el]=Εμφάνιση πληροφοριών χρήσης δίσκου
Comment[en_GB]=View disk usage information
Comment[es]=Muestra información sobre el uso de discos
Comment[et]=Kettakasutuse teabe kuvamine
Comment[eu]=Ikusi diskoen erabilerari buruzko informazioa
Comment[fi]=Näytä levynkäyttö
Comment[fr]=Afficher les informations d'utilisation de disques
Comment[ga]=Taispeáin úsáid diosca
Comment[gl]=Acceda a información de uso do disco.
Comment[hr]=Prikaži informacije o upotrebi diska
Comment[hu]=Lemezhasználati információk megjelenítése
Comment[ia]=Vide information de uso de disco
Comment[it]=Mostra l'uso del disco
Comment[ja]=使
Comment[kk]=Дискідегі орынды көрсету
Comment[km]=
Comment[ko]=
Comment[lt]=Žiūrėti disko naudojimo informaciją
Comment[lv]=Skata diska vietas izlietojumu
Comment[mr]=ि ि
Comment[nb]=Vis informasjon om bruk av diskplass
Comment[nds]=Wiest Informatschonen över den Bruuk vun de Fastplaat
Comment[nl]=Informatie over schijfgebruik bekijken
Comment[pa]=ਿ
Comment[pl]=Zobacz informacje o wykorzystaniu dysku
Comment[pt]=Ver a informação de utilização do disco
Comment[pt_BR]=Exibe as informações de utilização do disco
Comment[ro]=Vezi informații despre utilizarea discului
Comment[ru]=Наглядное представление файловой системы
Comment[sk]=Zobrazenie informácií o využití disku
Comment[sl]=Oglejte si statistiko uporabe diska
Comment[sr]=Приказ података о искоришћености дискова
Comment[sr@ijekavian]=Приказ података о искоришћености дискова
Comment[sr@ijekavianlatin]=Prikaz podataka o iskorišćenosti diskova
Comment[sr@latin]=Prikaz podataka o iskorišćenosti diskova
Comment[sv]=Visa information om hårddiskanvändning
Comment[th]=
Comment[tr]=Disk kullanımını görüntüle
Comment[ug]=دىسكىنىڭ ئىشلىتىلىش ئۇچۇرلىرىنى كۆرسىتىش پروگراممىسى
Comment[uk]=Перегляд інформації щодо використання дисків
Comment[wa]=Vey les informåcions so l' eployaedje del deure plake
Comment[x-test]=xxView disk usage informationxx
Comment[zh_CN]=使
Comment[zh_TW]=
Terminal=false
MimeType=inode/directory;
X-DocPath=filelight/index.html
Categories=Qt;KDE;Utility;

View file

@ -0,0 +1,55 @@
[Desktop Entry]
Encoding=UTF-8
Name=Radial Map
Name[bs]=Radial Map
Name[ca]=Mapa radial
Name[ca@valencia]=Mapa radial
Name[cs]=Kruhová mapa
Name[da]=Radialkort
Name[de]=Kreisförmige Darstellung
Name[el]=Ακτινωτός χάρτης
Name[en_GB]=Radial Map
Name[es]=Mapa radial
Name[et]=Radiaalkaart
Name[eu]=Mapa erradiala
Name[fi]=Säteittäinen kartta
Name[fr]=Carte radiale
Name[ga]=Mapa Gathach
Name[gl]=Mapa radial
Name[hr]=Zrakasta karta
Name[hu]=Kördiagram
Name[ia]=Mappa radial
Name[it]=Mappa radiale
Name[kk]=Дөңгелек картасы
Name[km]=
Name[ko]=
Name[lt]=Radialinis žemėlapis
Name[lv]=Radial Map
Name[mr]=ि
Name[nb]=Radielt kart
Name[nds]=Rund Koort
Name[nl]=Radiale grafiek
Name[pa]=
Name[pl]=Mapa kołowa
Name[pt]=Mapa Radial
Name[pt_BR]=Mapa radial
Name[ro]=Hartă radială
Name[ru]=Радиальная карта
Name[sk]=Radiálna mapa
Name[sl]=Krožen prikaz
Name[sr]=Кружна мапа
Name[sr@ijekavian]=Кружна мапа
Name[sr@ijekavianlatin]=Kružna mapa
Name[sr@latin]=Kružna mapa
Name[sv]=Radiell avbildning
Name[th]=Radial Map
Name[tr]=Radyal Harita
Name[uk]=Радіальна карта
Name[x-test]=xxRadial Mapxx
Name[zh_CN]=
Name[zh_TW]=
MimeType=inode/directory;
ServiceTypes=KParts/ReadOnlyPart
X-KDE-Library=filelightpart
Type=Service
Icon=view_filelight

View file

@ -0,0 +1,44 @@
<!DOCTYPE kpartgui>
<kpartgui name="filelightpart" version="2">
<MenuBar>
<Menu name="view">
<Action name="view_zoom_in" group="view_merge_group"/>
<Action name="view_zoom_out" group="view_merge_group"/>
</Menu>
<Menu name="settings">
<Action name="configure_filelight" group="settings_configure"/>
</Menu>
</MenuBar>
<ToolBar name="viewToolBar" hidden="true"><text>View Toolbar</text>
<Action name="view_zoom_in"/>
<Action name="view_zoom_out"/>
</ToolBar>
<State name="scan_started">
<disable>
<Action name="view_zoom_in"/>
<Action name="view_zoom_out"/>
<Action name="configure_filelight"/>
</disable>
</State>
<State name="scan_complete">
<enable>
<Action name="view_zoom_in"/>
<Action name="view_zoom_out"/>
<Action name="configure_filelight"/>
</enable>
</State>
<State name="scan_failed">
<!-- only for full failure situations -->
<enable>
<Action name="configure_filelight"/>
</enable>
<disable>
<Action name="view_zoom_in"/>
<Action name="view_zoom_out"/>
</disable>
</State>
</kpartgui>

View file

@ -0,0 +1,6 @@
[filelight_part]
skipList=/dev/,/proc/,/sys/,/root/
[window]
Height=400
Width=600

View file

@ -0,0 +1,96 @@
<!DOCTYPE kpartgui>
<kpartgui name="filelight" version="4">
<MenuBar>
<Menu name="file" noMerge="1"><text>&amp;Scan</text>
<Action name="scan_folder"/>
<Separator/>
<Action name="scan_home"/>
<Action name="scan_root"/>
<Separator/>
<Action name="scan_recent"/>
<Separator/>
<Action name="scan_rescan"/>
<Action name="scan_stop"/>
<Merge/>
<Separator/>
<Action name="file_quit"/>
</Menu>
<Menu name="view" noMerge="1"><text>&amp;View</text></Menu>
</MenuBar>
<ToolBar name="mainToolBar"><text>Main Toolbar</text>
<Action name="go_back"/>
<Action name="go_forward"/>
<Action name="go_up"/>
<Separator/>
<Action name="scan_rescan"/>
<Action name="scan_stop"/>
</ToolBar>
<ToolBar name="locationToolBar" fullWidth="true"><text>Location Toolbar</text>
<Action name="clear_location"/>
<Action name="location_bar"/>
<Action name="go"/>
</ToolBar>
<State name="scan_started">
<enable>
<Action name="scan_stop"/>
</enable>
<disable>
<Action name="scan_folder"/>
<Action name="scan_home"/>
<Action name="scan_root"/>
<Action name="scan_recent"/>
<Action name="scan_rescan"/>
<Action name="go_up"/>
<Action name="clear_location"/>
<Action name="location_bar"/>
<Action name="go"/>
<Action name="view_zoom_in"/>
<Action name="view_zoom_out"/>
<Action name="configure_filelight"/>
</disable>
</State>
<State name="scan_complete">
<enable>
<Action name="scan_folder"/>
<Action name="scan_home"/>
<Action name="scan_root"/>
<Action name="scan_recent"/>
<Action name="scan_rescan"/>
<Action name="go_up"/>
<Action name="clear_location"/>
<Action name="location_bar"/>
<Action name="go"/>
<Action name="view_zoom_in"/>
<Action name="view_zoom_out"/>
<Action name="configure_filelight"/>
</enable>
<disable>
<Action name="scan_stop"/>
</disable>
</State>
<State name="scan_failed">
<!-- only for full failure situations -->
<enable>
<Action name="scan_folder"/>
<Action name="scan_home"/>
<Action name="scan_root"/>
<Action name="scan_recent"/>
<Action name="scan_rescan"/>
<Action name="clear_location"/>
<Action name="location_bar"/>
<Action name="go"/>
<Action name="configure_filelight"/>
</enable>
<disable>
<Action name="scan_stop"/>
<Action name="go_up"/>
<Action name="view_zoom_in"/>
<Action name="view_zoom_out"/>
</disable>
</State>
</kpartgui>

Binary file not shown.

After

Width:  |  Height:  |  Size: 862 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.8 KiB

Binary file not shown.

View file

@ -0,0 +1,22 @@
#######################################################################
# Copyright 2008-2009 Martin Sandsmark <martin.sandsmark@kde.org>
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License as
# published by the Free Software Foundation; either version 2 of
# the License or (at your option) version 3 or any later version
# accepted by the membership of KDE e.V. (or its successor approved
# by the membership of KDE e.V.), which shall act as a proxy
# defined in Section 14 of version 3 of the license.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#######################################################################
add_subdirectory(app)
add_subdirectory(part)

View file

@ -0,0 +1,29 @@
#######################################################################
# Copyright 2008-2009 Martin Sandsmark <martin.sandsmark@kde.org>
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License as
# published by the Free Software Foundation; either version 2 of
# the License or (at your option) version 3 or any later version
# accepted by the membership of KDE e.V. (or its successor approved
# by the membership of KDE e.V.), which shall act as a proxy
# defined in Section 14 of version 3 of the license.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#######################################################################
set(filelight_SRCS historyAction.cpp mainWindow.cpp main.cpp)
kde4_add_app_icon(filelight_SRCS "../../misc/hi*-app-filelight.png")
kde4_add_executable(filelight ${filelight_SRCS})
target_link_libraries(filelight ${KDE4_KDECORE_LIBS} ${KDE4_KPARTS_LIBS} ${KDE4_KDEUI_LIBS})
install(TARGETS filelight ${INSTALL_TARGETS_DEFAULT_ARGS})

View file

@ -0,0 +1,113 @@
/***********************************************************************
* Copyright 2003-2004 Max Howell <max.howell@methylblue.com>
* Copyright 2008-2009 Martin Sandsmark <martin.sandsmark@kde.org>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of
* the License or (at your option) version 3 or any later version
* accepted by the membership of KDE e.V. (or its successor approved
* by the membership of KDE e.V.), which shall act as a proxy
* defined in Section 14 of version 3 of the license.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
***********************************************************************/
#include "historyAction.h"
#include <KAction>
#include <KActionCollection>
#include <KConfig>
#include <KConfigGroup>
#include <KLocale>
#include <KStandardShortcut>
inline HistoryAction::HistoryAction(const KIcon &icon, const QString &text, KActionCollection *ac)
: KAction(icon, text, ac)
, m_text(text)
{
// .ui files make this false, but we can't rely on UI file as it isn't compiled in :(
setEnabled(false);
}
void HistoryAction::push(const QString &path)
{
if (path.isEmpty()) return;
if (m_list.isEmpty() || (!m_list.isEmpty() && (m_list.last() != path)))
m_list.append(path);
setHelpText(path);
setEnabled(true);
}
QString HistoryAction::pop()
{
const QString s = m_list.takeLast();
if (!m_list.isEmpty())
setHelpText(m_list.last());
setEnabled();
return s;
}
HistoryCollection::HistoryCollection(KActionCollection *ac, QObject *parent)
: QObject(parent)
, m_b(new HistoryAction(KIcon(QLatin1String( "go-previous" )), i18nc("Go to the last path viewed", "Back"), ac))
, m_f(new HistoryAction(KIcon(QLatin1String( "go-next" )), i18nc("Go to forward in the history of paths viewed", "Forward"), ac))
, m_receiver(0)
{
ac->addAction(QLatin1String( "go_back" ), m_b);
ac->addAction(QLatin1String( "go_forward" ), m_f);
connect(m_b, SIGNAL(triggered(bool)), SLOT(pop()));
connect(m_f, SIGNAL(triggered(bool)), SLOT(pop()));
}
void HistoryCollection::push(const KUrl &url) //slot
{
if (!url.isEmpty())
{
if (!m_receiver)
{
m_f->clear();
m_receiver = m_b;
}
m_receiver->push(url.path(KUrl::AddTrailingSlash));
}
m_receiver = 0;
}
void HistoryCollection::pop() //slot
{
KUrl url;
const QString path = ((HistoryAction*)sender())->pop(); //FIXME here we remove the constness
url.setPath(path);
m_receiver = (sender() == m_b) ? m_f : m_b;
emit activated(url);
}
void HistoryCollection::save(KConfigGroup &configgroup)
{
configgroup.writePathEntry("backHistory", m_b->m_list);
configgroup.writePathEntry("forwardHistory", m_f->m_list);
}
void HistoryCollection::restore(const KConfigGroup &configgroup)
{
m_b->m_list = configgroup.readPathEntry("backHistory", QStringList());
m_f->m_list = configgroup.readPathEntry("forwardHistory", QStringList());
//TODO texts are not updated - no matter
}
#include "historyAction.moc"

View file

@ -0,0 +1,86 @@
/***********************************************************************
* Copyright 2003-2004 Max Howell <max.howell@methylblue.com>
* Copyright 2008-2009 Martin Sandsmark <martin.sandsmark@kde.org>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of
* the License or (at your option) version 3 or any later version
* accepted by the membership of KDE e.V. (or its successor approved
* by the membership of KDE e.V.), which shall act as a proxy
* defined in Section 14 of version 3 of the license.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
***********************************************************************/
#ifndef HISTORYACTION_H
#define HISTORYACTION_H
#include <KAction>
#include <QStringList>
#include <KUrl>
class KConfigGroup;
class KActionCollection;
class HistoryAction : KAction
{
HistoryAction(const KIcon &icon, const QString &text, KActionCollection *ac);
friend class HistoryCollection;
public:
virtual void setEnabled(bool b = true) {
KAction::setEnabled(b && !m_list.isEmpty());
}
void clear() {
m_list.clear();
setEnabled(false);
KAction::setText(m_text);
}
private:
void setText();
void push(const QString &path);
QString pop();
const QString m_text;
QStringList m_list;
};
class HistoryCollection : public QObject
{
Q_OBJECT
public:
HistoryCollection(KActionCollection *ac, QObject *parent);
void save(KConfigGroup &configgroup);
void restore(const KConfigGroup &configgroup);
public slots:
void push(const KUrl&);
void stop() {
m_receiver = 0;
}
signals:
void activated(const KUrl&);
private slots:
void pop();
private:
HistoryAction *m_b, *m_f, *m_receiver;
};
#endif

View file

@ -0,0 +1,78 @@
/***********************************************************************
* Copyright 2003-2004 Max Howell <max.howell@methylblue.com>
* Copyright 2008-2009 Martin Sandsmark <martin.sandsmark@kde.org>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of
* the License or (at your option) version 3 or any later version
* accepted by the membership of KDE e.V. (or its successor approved
* by the membership of KDE e.V.), which shall act as a proxy
* defined in Section 14 of version 3 of the license.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
***********************************************************************/
#include "define.h"
#include "mainWindow.h"
#include <KAboutData>
#include <KApplication>
#include <KCmdLineArgs>
#include <KLocale>
#include <KUrl>
static KAboutData about(
APP_NAME,
0,
ki18n(APP_PRETTYNAME),
APP_VERSION,
ki18n("Graphical disk-usage information"),
KAboutData::License_GPL,
ki18n("(C) 2006 Max Howell\n\
(C) 2008-2013 Martin Sandsmark"),
KLocalizedString(),
"http://utils.kde.org/projects/filelight");
int main(int argc, char *argv[])
{
using Filelight::MainWindow;
about.addAuthor(ki18n("Martin Sandsmark"), ki18n("Maintainer"), "martin.sandsmark@kde.org", "http://iskrembilen.com/");
about.addAuthor(ki18n("Max Howell"), ki18n("Original author"), "max.howell@methylblue.com", "http://www.methylblue.com/");
about.addCredit(ki18n("Lukas Appelhans"), ki18n("Help and support"));
about.addCredit(ki18n("Steffen Gerlach"), ki18n("Inspiration"), 0, "http://www.steffengerlach.de/");
about.addCredit(ki18n("Mike Diehl"), ki18n("Original documentation"), 0, 0);
about.addCredit(ki18n("Sune Vuorela"), ki18n("Icon"), 0, 0);
about.addCredit(ki18n("Nuno Pinheiro"), ki18n("Icon"), 0, 0);
KCmdLineArgs::init(argc, argv, &about);
KCmdLineOptions options;
KLocale *tmpLocale = new KLocale(QLatin1String(APP_NAME));
options.add(ki18nc("Path in the file system to scan", "+[path]").toString(tmpLocale).toLocal8Bit(), ki18n("Scan 'path'"));
delete tmpLocale;
KCmdLineArgs::addCmdLineOptions(options);
KApplication app;
if (!app.isSessionRestored()) {
MainWindow *mw = new MainWindow();
KCmdLineArgs* const args = KCmdLineArgs::parsedArgs();
if (args->count() > 0) mw->scan(args->url(0));
args->clear();
mw->show();
}
else RESTORE(MainWindow);
return app.exec();
}

View file

@ -0,0 +1,295 @@
/***********************************************************************
* Copyright 2003-2004 Max Howell <max.howell@methylblue.com>
* Copyright 2008-2009 Martin Sandsmark <martin.sandsmark@kde.org>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of
* the License or (at your option) version 3 or any later version
* accepted by the membership of KDE e.V. (or its successor approved
* by the membership of KDE e.V.), which shall act as a proxy
* defined in Section 14 of version 3 of the license.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
***********************************************************************/
#include "mainWindow.h"
#include "part/part.h"
#include "historyAction.h"
#include <cstdlib> //std::exit()
#include <KApplication> //setupActions()
#include <KComboBox> //locationbar
#include <KHistoryComboBox>
#include <KRecentFilesAction>
#include <KConfig>
#include <KDirSelectDialog> //slotScanFolder
#include <KEditToolBar> //for editToolbar dialog
#include <QLineEdit>
#include <KStandardShortcut>
#include <KFileDialog>
#include <KLibLoader>
#include <KLocale>
#include <KMessageBox>
#include <KShell>
#include <KStatusBar>
#include <KToolBar>
#include <KUrl>
#include <KUrlCompletion> //locationbar
#include <QObject>
#include <QToolTip>
#include <KGlobal>
#include <KConfigGroup>
#include <KShortcutsDialog>
#include <KSharedConfig>
#include <KStandardAction>
#include <KActionCollection>
namespace Filelight {
MainWindow::MainWindow() : KParts::MainWindow(), m_part(0)
{
// setXMLFile("filelightui.rc");
KPluginFactory *factory = KPluginLoader(QLatin1String( "filelightpart" )).factory();
if (!factory) {
KMessageBox::error(this, i18n("Unable to load the Filelight Part.\nPlease make sure Filelight was correctly installed."));
std::exit(1);
return;
}
m_part = static_cast<Part *>(factory->create<KParts::ReadOnlyPart>(this));
if (m_part) {
setStandardToolBarMenuEnabled(true);
setupActions();
createGUI(m_part);
setCentralWidget(m_part->widget());
stateChanged(QLatin1String( "scan_failed" )); //bah! doesn't affect the parts' actions, should I add them to the actionCollection here?
connect(m_part, SIGNAL(started(KIO::Job*)), SLOT(scanStarted()));
connect(m_part, SIGNAL(completed()), SLOT(scanCompleted()));
connect(m_part, SIGNAL(canceled(QString)), SLOT(scanFailed()));
connect(m_part, SIGNAL(canceled(QString)), m_histories, SLOT(stop()));
connect(BrowserExtension::childObject(m_part), SIGNAL(openUrlNotify()), SLOT(urlAboutToChange()));
const KConfigGroup config = KGlobal::config()->group("general");
m_combo->setHistoryItems(config.readPathEntry("comboHistory", QStringList()));
} else {
KMessageBox::error(this, i18n("Unable to create part widget."));
std::exit(1);
}
setAutoSaveSettings(QLatin1String( "window" ));
}
inline void MainWindow::setupActions() //singleton function
{
KActionCollection *const ac = actionCollection();
m_combo = new KHistoryComboBox(this);
m_combo->setCompletionObject(new KUrlCompletion(KUrlCompletion::DirCompletion));
m_combo->setAutoDeleteCompletionObject(true);
m_combo->setSizePolicy(QSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed));
m_combo->setDuplicatesEnabled(false);
KStandardAction::open(this, SLOT(slotScanFolder()), ac);
KStandardAction::quit(this, SLOT(close()), ac);
KStandardAction::up(this, SLOT(slotUp()), ac);
KStandardAction::configureToolbars(this, SLOT(configToolbars()), ac);
KStandardAction::keyBindings(this, SLOT(configKeys()), ac);
KAction* action;
action = ac->addAction(QLatin1String( "scan_home" ), this, SLOT(slotScanHomeFolder()));
action->setText(i18n("Scan &Home Folder"));
action->setIcon(KIcon(QLatin1String( "user-home" )));
action->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_Home));
action = ac->addAction(QLatin1String( "scan_root" ), this, SLOT(slotScanRootFolder()));
action->setText(i18n("Scan &Root Folder"));
action->setIcon(KIcon(QLatin1String( "folder-red" )));
action = ac->addAction(QLatin1String( "scan_rescan" ), m_part, SLOT(rescan()));
action->setText(i18n("Rescan"));
action->setIcon(KIcon(QLatin1String( "view-refresh" )));
action->setShortcut(KStandardShortcut::reload());
action = ac->addAction(QLatin1String( "scan_stop" ), this, SLOT(slotAbortScan()));
action->setText(i18n("Stop"));
action->setIcon(KIcon(QLatin1String( "process-stop" )));
action->setShortcut(Qt::Key_Escape);
action = ac->addAction(QLatin1String( "go" ), m_combo, SIGNAL(returnPressed()));
action->setText(i18n("Go"));
action->setIcon(KIcon(QLatin1String( "go-jump-locationbar" )));
action = ac->addAction(QLatin1String( "location_bar" ), 0, 0);
action->setText(i18n("Location Bar"));
action->setDefaultWidget(m_combo);
action = ac->addAction(QLatin1String( "scan_folder" ), this, SLOT(slotScanFolder()));
action->setText(i18n("Scan Folder"));
action->setIcon(KIcon(QLatin1String( "folder" )));
m_recentScans = new KRecentFilesAction(i18n("&Recent Scans"), ac);
m_recentScans->setMaxItems(8);
m_histories = new HistoryCollection(ac, this);
m_recentScans->loadEntries(KGlobal::config()->group("general"));
connect(m_recentScans, SIGNAL(urlSelected(KUrl)), SLOT(slotScanUrl(KUrl)));
connect(m_combo, SIGNAL(returnPressed()), SLOT(slotComboScan()));
connect(m_histories, SIGNAL(activated(KUrl)), SLOT(slotScanUrl(KUrl)));
}
void MainWindow::closeEvent(QCloseEvent *event)
{
KConfigGroup config = KGlobal::config()->group("general");
m_recentScans->saveEntries(config);
config.writePathEntry("comboHistory", m_combo->historyItems());
config.sync();
KParts::MainWindow::closeEvent(event);
}
inline void MainWindow::configToolbars() //slot
{
KEditToolBar dialog(factory(), this);
if (dialog.exec()) //krazy:exclude=crashy
{
createGUI(m_part);
applyMainWindowSettings(KGlobal::config()->group("window"));
}
}
inline void MainWindow::configKeys() //slot
{
KShortcutsDialog::configure(actionCollection(), KShortcutsEditor::LetterShortcutsAllowed, this, true);
}
inline void MainWindow::slotScanFolder()
{
slotScanUrl(KFileDialog::getExistingDirectoryUrl(m_part->url(), this, i18n("Select Folder to Scan")));
}
inline void MainWindow::slotScanHomeFolder() {
slotScanPath(QDir::homePath());
}
inline void MainWindow::slotScanRootFolder() {
slotScanPath(QDir::rootPath());
}
inline void MainWindow::slotUp() {
slotScanUrl(m_part->url().upUrl());
}
inline void MainWindow::slotComboScan()
{
QString path = m_combo->lineEdit()->text();
KUrl url = KUrl(path);
if (url.isRelative())
path = QLatin1String( "~/" ) + path; // KUrlCompletion completes relative to ~, not CWD
path = KShell::tildeExpand(path);
if (slotScanPath(path))
m_combo->addToHistory(path);
}
inline bool MainWindow::slotScanPath(const QString &path)
{
return slotScanUrl(KUrl(path));
}
bool MainWindow::slotScanUrl(const KUrl &url)
{
const KUrl oldUrl = m_part->url();
if (m_part->openUrl(url))
{
m_histories->push(oldUrl);
return true;
}
else
return false;
}
inline void MainWindow::slotAbortScan()
{
if (m_part->closeUrl()) action("scan_stop")->setEnabled(false);
}
inline void MainWindow::scanStarted()
{
stateChanged(QLatin1String( "scan_started" ));
m_combo->clearFocus();
}
inline void MainWindow::scanFailed()
{
stateChanged(QLatin1String( "scan_failed" ));
qobject_cast<KAction*>(action("go_up"))->setHelpText(QString());
m_combo->lineEdit()->clear();
}
void MainWindow::scanCompleted()
{
KAction *goUp = qobject_cast<KAction *>(action("go_up"));
const KUrl url = m_part->url();
stateChanged(QLatin1String( "scan_complete" ));
m_combo->lineEdit()->setText(m_part->prettyUrl());
if (url.path(KUrl::LeaveTrailingSlash) == QLatin1String( "/" )) {
goUp->setEnabled(false);
goUp->setHelpText(QString());
}
else
goUp->setHelpText(url.upUrl().path(KUrl::LeaveTrailingSlash));
m_recentScans->addUrl(url); //FIXME doesn't set the tick
}
inline void MainWindow::urlAboutToChange()
{
//called when part's URL is about to change internally
//the part will then create the Map and emit completed()
m_histories->push(m_part->url());
}
/**********************************************
SESSION MANAGEMENT
**********************************************/
void MainWindow::saveProperties(KConfigGroup &configgroup) //virtual
{
m_histories->save(configgroup);
configgroup.writeEntry("currentMap", m_part->url().path());
}
void MainWindow::readProperties(const KConfigGroup &configgroup) //virtual
{
m_histories->restore(configgroup);
slotScanPath(configgroup.group("General").readEntry("currentMap", QString()));
}
} //namespace Filelight
#include "mainWindow.moc"

View file

@ -0,0 +1,87 @@
/***********************************************************************
* Copyright 2003-2004 Max Howell <max.howell@methylblue.com>
* Copyright 2008-2009 Martin Sandsmark <martin.sandsmark@kde.org>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of
* the License or (at your option) version 3 or any later version
* accepted by the membership of KDE e.V. (or its successor approved
* by the membership of KDE e.V.), which shall act as a proxy
* defined in Section 14 of version 3 of the license.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
***********************************************************************/
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <kparts/mainwindow.h>
class KSqueezedTextLabel;
class KHistoryComboBox;
class KRecentFilesAction;
class HistoryCollection;
namespace Filelight {
class Part;
class MainWindow : public KParts::MainWindow
{
Q_OBJECT
public:
MainWindow();
void scan(const KUrl &u) {
slotScanUrl(u);
}
private slots:
void slotUp();
void slotComboScan();
void slotScanFolder();
void slotScanHomeFolder();
void slotScanRootFolder();
bool slotScanUrl(const KUrl&);
bool slotScanPath(const QString&);
void slotAbortScan();
void configToolbars();
void configKeys();
void scanStarted();
void scanFailed();
void scanCompleted();
void urlAboutToChange();
protected:
virtual void saveProperties(KConfigGroup&);
virtual void readProperties(const KConfigGroup&);
virtual void closeEvent(QCloseEvent *event);
private:
Filelight::Part *m_part;
KSqueezedTextLabel *m_status[2];
KHistoryComboBox *m_combo;
HistoryCollection *m_histories;
KRecentFilesAction *m_recentScans;
void setupStatusBar();
void setupActions();
};
} // namespace Filelight
#endif

36
filelight/src/define.h Normal file
View file

@ -0,0 +1,36 @@
/***********************************************************************
* Copyright 2003-2004 Max Howell <max.howell@methylblue.com>
* Copyright 2008-2013 Martin Sandsmark <martin.sandsmark@kde.org>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of
* the License or (at your option) version 3 or any later version
* accepted by the membership of KDE e.V. (or its successor approved
* by the membership of KDE e.V.), which shall act as a proxy
* defined in Section 14 of version 3 of the license.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
***********************************************************************/
#ifndef DEFINE_H
#define DEFINE_H
#include "part/Config.h"
#undef VERSION
#undef PACKAGE
#undef PRETTYNAME
#define APP_NAME "filelight"
#define APP_VERSION "1.20"
#define APP_PRETTYNAME "Filelight"
#endif

View file

@ -0,0 +1,47 @@
#######################################################################
# Copyright 2008-2009 Martin Sandsmark <martin.sandsmark@kde.org>
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License as
# published by the Free Software Foundation; either version 2 of
# the License or (at your option) version 3 or any later version
# accepted by the membership of KDE e.V. (or its successor approved
# by the membership of KDE e.V.), which shall act as a proxy
# defined in Section 14 of version 3 of the license.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#######################################################################
add_subdirectory(radialMap)
set(filelight_PART_SRCS
part.cpp
scan.cpp
progressBox.cpp
Config.cpp
settingsDialog.cpp
fileTree.cpp
localLister.cpp
remoteLister.cpp
summaryWidget.cpp)
kde4_add_ui_files(filelight_PART_SRCS dialog.ui)
kde4_add_plugin(filelightpart ${filelight_PART_SRCS})
target_link_libraries(filelightpart radialmap
${KDE4_KDECORE_LIBS}
${KDE4_KPARTS_LIBS}
${KDE4_KDEUI_LIBS}
${KDE4_KIO_LIBS}
${KDE4_KFILE_LIBS}
${KDE4_SOLID_LIBS})
install(TARGETS filelightpart DESTINATION ${PLUGIN_INSTALL_DIR})

View file

@ -0,0 +1,77 @@
/***********************************************************************
* Copyright 2003-2004 Max Howell <max.howell@methylblue.com>
* Copyright 2008-2009 Martin Sandsmark <martin.sandsmark@kde.org>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of
* the License or (at your option) version 3 or any later version
* accepted by the membership of KDE e.V. (or its successor approved
* by the membership of KDE e.V.), which shall act as a proxy
* defined in Section 14 of version 3 of the license.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
***********************************************************************/
#include "Config.h"
#include <KConfig>
#include <KConfigGroup>
#include <KGlobal>
#include <KSharedConfig>
#include <KSharedPtr>
bool Config::scanAcrossMounts;
bool Config::scanRemoteMounts;
bool Config::scanRemovableMedia;
bool Config::varyLabelFontSizes;
bool Config::showSmallFiles;
bool Config::antialias;
uint Config::contrast;
uint Config::minFontPitch;
uint Config::defaultRingDepth;
Filelight::MapScheme Config::scheme;
QStringList Config::skipList;
void
Filelight::Config::read()
{
const KConfigGroup config = KGlobal::config()->group("filelight_part");
scanAcrossMounts = config.readEntry("scanAcrossMounts", false);
scanRemoteMounts = config.readEntry("scanRemoteMounts", false);
scanRemovableMedia = config.readEntry("scanRemovableMedia", false);
varyLabelFontSizes = config.readEntry("varyLabelFontSizes", true);
showSmallFiles = config.readEntry("showSmallFiles", false);
contrast = config.readEntry("contrast", 75);
antialias = config.readEntry("antialias", true);
minFontPitch = config.readEntry("minFontPitch", QFont().pointSize() - 3);
scheme = (MapScheme) config.readEntry("scheme", 0);
skipList = config.readEntry("skipList", QStringList());
defaultRingDepth = 4;
}
void
Filelight::Config::write()
{
KConfigGroup config = KGlobal::config()->group("filelight_part");
config.writeEntry("scanAcrossMounts", scanAcrossMounts);
config.writeEntry("scanRemoteMounts", scanRemoteMounts);
config.writeEntry("scanRemovableMedia", scanRemovableMedia);
config.writeEntry("varyLabelFontSizes", varyLabelFontSizes);
config.writeEntry("showSmallFiles", showSmallFiles);
config.writeEntry("contrast", contrast);
config.writeEntry("antialias", antialias);
config.writeEntry("minFontPitch", minFontPitch);
config.writeEntry("scheme", (int)scheme); // TODO: make the enum belong to a qwidget,
//and use magic macros to make it save this properly
config.writePathEntry("skipList", skipList);
}

View file

@ -0,0 +1,60 @@
/***********************************************************************
* Copyright 2003-2004 Max Howell <max.howell@methylblue.com>
* Copyright 2008-2009 Martin Sandsmark <martin.sandsmark@kde.org>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of
* the License or (at your option) version 3 or any later version
* accepted by the membership of KDE e.V. (or its successor approved
* by the membership of KDE e.V.), which shall act as a proxy
* defined in Section 14 of version 3 of the license.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
***********************************************************************/
#ifndef Config_H
#define Config_H
#include <QtCore/QStringList>
class KConfig;
namespace Filelight
{
enum MapScheme { Rainbow, KDE, HighContrast, FileDensity, ModTime };
class Config
{
static KConfig& kconfig();
public:
static void read();
static void write();
//keep everything positive, avoid using DON'T, NOT or NO
static bool scanAcrossMounts;
static bool scanRemoteMounts;
static bool scanRemovableMedia;
static bool varyLabelFontSizes;
static bool showSmallFiles;
static uint contrast;
static bool antialias;
static uint minFontPitch;
static uint defaultRingDepth;
static MapScheme scheme;
static QStringList skipList;
};
}
using Filelight::Config;
#endif

View file

@ -0,0 +1,426 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>Dialog</class>
<widget class="QWidget" name="Dialog">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>556</width>
<height>405</height>
</rect>
</property>
<property name="windowTitle">
<string>Settings - Filelight</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_3">
<property name="margin">
<number>0</number>
</property>
<item>
<widget class="KTabWidget" name="tabWidget">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="acceptDrops">
<bool>false</bool>
</property>
<property name="currentIndex">
<number>0</number>
</property>
<widget class="QWidget" name="Widget2">
<attribute name="title">
<string>Scannin&amp;g</string>
</attribute>
<layout class="QVBoxLayout">
<item>
<widget class="QLabel" name="textLabel1">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Maximum">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Do &amp;not scan these folders:</string>
</property>
<property name="textFormat">
<enum>Qt::PlainText</enum>
</property>
<property name="wordWrap">
<bool>false</bool>
</property>
<property name="buddy">
<cstring>m_listBox</cstring>
</property>
</widget>
</item>
<item>
<widget class="QListWidget" name="m_listBox"/>
</item>
<item>
<layout class="QHBoxLayout">
<item>
<spacer name="m_removeAddSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Expanding</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>180</width>
<height>21</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QPushButton" name="m_removeButton">
<property name="enabled">
<bool>true</bool>
</property>
<property name="text">
<string>R&amp;emove</string>
</property>
<property name="autoDefault">
<bool>false</bool>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="m_addButton">
<property name="text">
<string>&amp;Add...</string>
</property>
<property name="autoDefault">
<bool>false</bool>
</property>
<property name="default">
<bool>false</bool>
</property>
</widget>
</item>
</layout>
</item>
<item>
<widget class="Line" name="m_scanningSeparatorLine">
<property name="minimumSize">
<size>
<width>0</width>
<height>15</height>
</size>
</property>
<property name="frameShape">
<enum>QFrame::HLine</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Sunken</enum>
</property>
<property name="lineWidth">
<number>1</number>
</property>
<property name="midLineWidth">
<number>1</number>
</property>
</widget>
</item>
<item>
<layout class="QGridLayout">
<item row="1" column="0" rowspan="2">
<spacer name="m_excludeCheckBoxSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Fixed</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>16</width>
<height>50</height>
</size>
</property>
</spacer>
</item>
<item row="1" column="1">
<widget class="QCheckBox" name="dontScanRemoteMounts">
<property name="enabled">
<bool>false</bool>
</property>
<property name="minimumSize">
<size>
<width>0</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>32767</width>
<height>32767</height>
</size>
</property>
<property name="acceptDrops">
<bool>false</bool>
</property>
<property name="toolTip">
<string/>
</property>
<property name="whatsThis">
<string>Prevents scanning of filesystems that are not on this computer, e.g. NFS or Samba mounts.</string>
</property>
<property name="text">
<string>Exclude remote files&amp;ystems</string>
</property>
</widget>
</item>
<item row="0" column="0" colspan="2">
<widget class="QCheckBox" name="scanAcrossMounts">
<property name="whatsThis">
<string>Allows scans to enter directories that are part of other filesystems. For example, when unchecked, this will usually prevent the contents of &lt;b&gt;/mnt&lt;/b&gt; from being scanned if you scan &lt;b&gt;/&lt;/b&gt;.</string>
</property>
<property name="text">
<string>Scan across filesystem &amp;boundaries</string>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QCheckBox" name="dontScanRemovableMedia">
<property name="enabled">
<bool>false</bool>
</property>
<property name="toolTip">
<string/>
</property>
<property name="whatsThis">
<string>Prevents Filelight from scanning removable media (eg. CD-ROMs).</string>
</property>
<property name="text">
<string>E&amp;xclude removable media</string>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
<widget class="QWidget" name="Widget3">
<attribute name="title">
<string>&amp;Appearance</string>
</attribute>
<layout class="QVBoxLayout" name="verticalLayout_2">
<item>
<widget class="QGroupBox" name="groupBox">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="title">
<string>Color scheme</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="KButtonGroup" name="colourSchemeGroup"/>
</item>
<item>
<layout class="QHBoxLayout">
<property name="spacing">
<number>0</number>
</property>
<property name="sizeConstraint">
<enum>QLayout::SetNoConstraint</enum>
</property>
<property name="topMargin">
<number>0</number>
</property>
<item>
<widget class="QLabel" name="textLabel3">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Co&amp;ntrast</string>
</property>
<property name="textFormat">
<enum>Qt::PlainText</enum>
</property>
<property name="wordWrap">
<bool>false</bool>
</property>
<property name="buddy">
<cstring>contrastSlider</cstring>
</property>
</widget>
</item>
<item>
<widget class="QSlider" name="contrastSlider">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="whatsThis">
<string>Here you can vary the contrast of the filemap in realtime.</string>
</property>
<property name="minimum">
<number>1</number>
</property>
<property name="maximum">
<number>100</number>
</property>
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QCheckBox" name="useAntialiasing">
<property name="whatsThis">
<string>Anti-aliasing the filemap makes it clearer and prettier, unfortunately it also makes rendering very slow.</string>
</property>
<property name="text">
<string>&amp;Use anti-aliasing</string>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="showSmallFiles">
<property name="whatsThis">
<string>Some files are too small to be rendered on the filemap. Selecting this option makes these files visible by merging them all into a single &quot;multi-segment&quot;.</string>
</property>
<property name="text">
<string>Show small files</string>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="varyLabelFontSizes">
<property name="enabled">
<bool>true</bool>
</property>
<property name="whatsThis">
<string>The font size of exploded labels can be varied relative to the depth of the directories they represent. This helps you spot the important labels more easily. Set a sensible minimum font size.</string>
</property>
<property name="text">
<string>Var&amp;y label font sizes</string>
</property>
</widget>
</item>
<item>
<layout class="QHBoxLayout">
<property name="sizeConstraint">
<enum>QLayout::SetMinimumSize</enum>
</property>
<item>
<spacer name="spacer4">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Fixed</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QLabel" name="minFontPitchLabel">
<property name="enabled">
<bool>true</bool>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="whatsThis">
<string>The smallest font size Filelight can use to render labels.</string>
</property>
<property name="text">
<string>Minimum font si&amp;ze:</string>
</property>
<property name="textFormat">
<enum>Qt::PlainText</enum>
</property>
<property name="wordWrap">
<bool>false</bool>
</property>
<property name="buddy">
<cstring>minFontPitch</cstring>
</property>
</widget>
</item>
<item>
<widget class="QSpinBox" name="minFontPitch">
<property name="maximum">
<number>20</number>
</property>
</widget>
</item>
</layout>
</item>
<item>
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
</widget>
</item>
</layout>
</widget>
<layoutdefault spacing="6" margin="11"/>
<customwidgets>
<customwidget>
<class>KButtonGroup</class>
<extends>QGroupBox</extends>
<header>kbuttongroup.h</header>
<container>1</container>
</customwidget>
<customwidget>
<class>KTabWidget</class>
<extends>QTabWidget</extends>
<header>ktabwidget.h</header>
<container>1</container>
</customwidget>
</customwidgets>
<tabstops>
<tabstop>tabWidget</tabstop>
<tabstop>varyLabelFontSizes</tabstop>
<tabstop>m_removeButton</tabstop>
<tabstop>m_addButton</tabstop>
<tabstop>scanAcrossMounts</tabstop>
<tabstop>dontScanRemoteMounts</tabstop>
<tabstop>dontScanRemovableMedia</tabstop>
</tabstops>
<resources/>
</ui>

View file

@ -0,0 +1,39 @@
/***********************************************************************
* Copyright 2003-2004 Max Howell <max.howell@methylblue.com>
* Copyright 2008-2009 Martin Sandsmark <martin.sandsmark@kde.org>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of
* the License or (at your option) version 3 or any later version
* accepted by the membership of KDE e.V. (or its successor approved
* by the membership of KDE e.V.), which shall act as a proxy
* defined in Section 14 of version 3 of the license.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
***********************************************************************/
#include "fileTree.h"
#include <KGlobal>
#include <KLocale>
QString
File::fullPath(const Folder *root /*= 0*/) const
{
QString path;
if (root == this)
root = 0; //prevent returning empty string when there is something we could return
for (const Folder *d = (Folder*)this; d != root && d; d = d->parent())
path.prepend(d->name());
return path;
}

View file

@ -0,0 +1,327 @@
/***********************************************************************
* Copyright 2003-2004 Max Howell <max.howell@methylblue.com>
* Copyright 2008-2009 Martin Sandsmark <martin.sandsmark@kde.org>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of
* the License or (at your option) version 3 or any later version
* accepted by the membership of KDE e.V. (or its successor approved
* by the membership of KDE e.V.), which shall act as a proxy
* defined in Section 14 of version 3 of the license.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
***********************************************************************/
#ifndef FILETREE_H
#define FILETREE_H
#include <QtCore/QByteArray> //qstrdup
#include <QtCore/QFile> //decodeName()
#include <QtCore/QDebug>
#include <kglobal.h>
#include <klocale.h>
#include <stdlib.h>
//TODO these are pointlessly general purpose now, make them incredibly specific
typedef quint64 FileSize;
typedef quint64 Dirsize; //**** currently unused
template <class T> class Iterator;
template <class T> class ConstIterator;
template <class T> class Chain;
template <class T>
class Link
{
public:
Link(T* const t) : prev(this), next(this), data(t) {}
Link() : prev(this), next(this), data(0) {}
//TODO unlinking is slow and you don't use it very much in this context.
// ** Perhaps you can make a faster deletion system that doesn't bother tidying up first
// ** and then you MUST call some kind of detach() function when you remove elements otherwise
~Link() {
delete data;
unlink();
}
friend class Iterator<T>;
friend class ConstIterator<T>;
friend class Chain<T>;
private:
void unlink() {
prev->next = next;
next->prev = prev;
prev = next = this;
}
Link<T>* prev;
Link<T>* next;
T* data; //ensure only iterators have access to this
};
template <class T>
class Iterator
{
public:
Iterator() : link(0) { } //**** remove this, remove this REMOVE THIS!!! dangerous as your implementation doesn't test for null links, always assumes they can be derefenced
Iterator(Link<T> *p) : link(p) { }
bool operator==(const Iterator<T>& it) const {
return link == it.link;
}
bool operator!=(const Iterator<T>& it) const {
return link != it.link;
}
bool operator!=(const Link<T> *p) const {
return p != link;
}
//here we have a choice, really I should make two classes one const the other not
const T* operator*() const {
return link->data;
}
T* operator*() {
return link->data;
}
Iterator<T>& operator++() {
link = link->next; //**** does it waste time returning in places where we don't use the retval?
return *this;
}
bool isNull() const {
return (link == 0); //REMOVE WITH ABOVE REMOVAL you don't want null iterators to be possible
}
void transferTo(Chain<T> &chain)
{
chain.append(remove());
}
T* remove() //remove from list, delete Link, data is returned NOT deleted
{
T* const d = link->data;
Link<T>* const p = link->prev;
link->data = 0;
delete link;
link = p; //make iterator point to previous element, YOU must check this points to an element
return d;
}
private:
Link<T> *link;
};
template <class T>
class ConstIterator
{
public:
ConstIterator(Link<T> *p) : link(p) { }
bool operator==(const Iterator<T>& it) const {
return link == it.link;
}
bool operator!=(const Iterator<T>& it) const {
return link != it.link;
}
bool operator!=(const Link<T> *p) const {
return p != link;
}
const T* operator*() const {
return link->data;
}
ConstIterator<T>& operator++() {
link = link->next;
return *this;
}
private:
const Link<T> *link;
};
template <class T>
class Chain
{
public:
virtual ~Chain() {
empty();
}
void append(T* const data)
{
Link<T>* const link = new Link<T>(data);
link->prev = head.prev;
link->next = &head;
head.prev->next = link;
head.prev = link;
}
void transferTo(Chain &c)
{
if (isEmpty()) return;
Link<T>* const first = head.next;
Link<T>* const last = head.prev;
head.unlink();
first->prev = c.head.prev;
c.head.prev->next = first;
last->next = &c.head;
c.head.prev = last;
}
void empty() {
while (head.next != &head) {
delete head.next;
}
}
Iterator<T> iterator() const {
return Iterator<T>(head.next);
}
ConstIterator<T> constIterator() const {
return ConstIterator<T>(head.next);
}
const Link<T> *end() const {
return &head;
}
bool isEmpty() const {
return head.next == &head;
}
private:
Link<T> head;
void operator=(const Chain&);
};
class Folder;
class QString;
class File
{
public:
friend class Folder;
public:
File(const char *name, FileSize size) : m_parent(0), m_name(qstrdup(name)), m_size(size) {}
virtual ~File() {
delete [] m_name;
}
Folder *parent() const {
return m_parent;
}
const char *name8Bit() const {
return m_name;
}
FileSize size() const {
return m_size;
}
QString name() const {
return QFile::decodeName(m_name);
}
virtual bool isFolder() const {
return false;
}
QString fullPath(const Folder* = 0) const;
QString humanReadableSize() const {
return KGlobal::locale()->formatByteSize(m_size);
}
protected:
File(const char *name, FileSize size, Folder *parent) : m_parent(parent), m_name(qstrdup(name)), m_size(size) {}
Folder *m_parent; //0 if this is treeRoot
char *m_name;
FileSize m_size; //in units of KiB
private:
File(const File&);
void operator=(const File&);
};
class Folder : public Chain<File>, public File
{
public:
Folder(const char *name) : File(name, 0), m_children(0) {} //DON'T pass the full path!
uint children() const {
return m_children;
}
virtual bool isFolder() const {
return true;
}
///appends a Folder
void append(Folder *d, const char *name=0)
{
if (name) {
delete [] d->m_name;
d->m_name = qstrdup(name);
} //directories that had a fullpath copy just their names this way
m_children += d->children(); //doesn't include the dir itself
d->m_parent = this;
append((File*)d); //will add 1 to filecount for the dir itself
}
///appends a File
void append(const char *name, FileSize size)
{
append(new File(name, size, this));
}
/// removes a file
void remove(const File *f) {
for (Iterator<File> it = iterator(); it != end(); ++it)
if (f == (*it))
it.remove();
for (Folder *d = this; d; d = d->parent())
d->m_size -= f->size();
}
private:
void append(File *p)
{
m_children++;
m_size += p->size();
Chain<File>::append(p);
}
uint m_children;
private:
Folder(const Folder&); //undefined
void operator=(const Folder&); //undefined
};
#endif

View file

@ -0,0 +1,260 @@
/***********************************************************************
* Copyright 2003-2004 Max Howell <max.howell@methylblue.com>
* Copyright 2008-2009 Martin Sandsmark <martin.sandsmark@kde.org>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of
* the License or (at your option) version 3 or any later version
* accepted by the membership of KDE e.V. (or its successor approved
* by the membership of KDE e.V.), which shall act as a proxy
* defined in Section 14 of version 3 of the license.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
***********************************************************************/
#include "localLister.h"
#include "Config.h"
#include "fileTree.h"
#include "scan.h"
#include <KDebug>
#include <Solid/StorageVolume>
#include <Solid/StorageAccess>
#include <Solid/Device>
#include <QtGui/QApplication> //postEvent()
#include <QtCore/QFile>
#include <QtCore/QByteArray>
#include <kde_file.h>
#include <dirent.h>
#ifdef Q_OS_SOLARIS
#include <sys/vfstab.h>
#elif !defined(Q_WS_WIN)
#include <fstab.h>
#endif
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
#ifdef HAVE_MNTENT_H
#include <mntent.h>
#endif
namespace Filelight
{
QStringList LocalLister::s_remoteMounts;
QStringList LocalLister::s_localMounts;
LocalLister::LocalLister(const QString &path, Chain<Folder> *cachedTrees, ScanManager *parent)
: QThread()
, m_path(path)
, m_trees(cachedTrees)
, m_parent(parent)
{
//add empty directories for any mount points that are in the path
//TODO empty directories is not ideal as adds to fileCount incorrectly
QStringList list(Config::skipList);
if (!Config::scanAcrossMounts) list += s_localMounts;
if (!Config::scanRemoteMounts) list += s_remoteMounts;
foreach(const QString &ignorePath, list) {
if (ignorePath.startsWith(path)) {
m_trees->append(new Folder(ignorePath.toLocal8Bit()));
}
}
}
void
LocalLister::run()
{
//recursively scan the requested path
const QByteArray path = QFile::encodeName(m_path);
Folder *tree = scan(path, path);
//delete the list of trees useful for this scan,
//in a sucessful scan the contents would now be transferred to 'tree'
delete m_trees;
if (m_parent->m_abort) //scan was cancelled
{
kDebug() << "Scan successfully aborted";
delete tree;
tree = 0;
}
kDebug() << "Emitting signal to cache results ...";
emit branchCompleted(tree, true);
kDebug() << "Thread terminating ...";
}
#ifndef S_BLKSIZE
#define S_BLKSIZE 512
#endif
#include <errno.h>
static void
outputError(QByteArray path)
{
///show error message that stat or opendir may give
#define out(s) kError() << s ": " << path; break
switch (errno) {
case EACCES:
out("Inadequate access permissions");
case EMFILE:
out("Too many file descriptors in use by Filelight");
case ENFILE:
out("Too many files are currently open in the system");
case ENOENT:
out("A component of the path does not exist, or the path is an empty string");
case ENOMEM:
out("Insufficient memory to complete the operation");
case ENOTDIR:
out("A component of the path is not a folder");
case EBADF:
out("Bad file descriptor");
case EFAULT:
out("Bad address");
#ifndef Q_WS_WIN
case ELOOP: //NOTE shouldn't ever happen
out("Too many symbolic links encountered while traversing the path");
#endif
case ENAMETOOLONG:
out("File name too long");
}
#undef out
}
Folder*
LocalLister::scan(const QByteArray &path, const QByteArray &dirname)
{
Folder *cwd = new Folder(dirname);
DIR *dir = opendir(path);
if (!dir) {
outputError(path);
return cwd;
}
#ifdef _MSC_VER
//use a wider struct on win for nice handling of files larger than 2 GB
#undef KDE_struct_stat
#undef KDE_lstat
#define KDE_struct_stat struct _stat64
#define KDE_lstat kdewin32_stat64
#endif
KDE_struct_stat statbuf;
dirent *ent;
while ((ent = KDE_readdir(dir)))
{
if (m_parent->m_abort)
return cwd;
if (qstrcmp(ent->d_name, ".") == 0 || qstrcmp(ent->d_name, "..") == 0)
continue;
QByteArray new_path = path;
new_path += ent->d_name;
//get file information
if (KDE_lstat(new_path, &statbuf) == -1) {
outputError(new_path);
continue;
}
if (S_ISLNK(statbuf.st_mode) ||
S_ISCHR(statbuf.st_mode) ||
S_ISBLK(statbuf.st_mode) ||
S_ISFIFO(statbuf.st_mode)||
S_ISSOCK(statbuf.st_mode))
{
continue;
}
if (S_ISREG(statbuf.st_mode)) //file
#ifndef Q_WS_WIN
cwd->append(ent->d_name, (statbuf.st_blocks * S_BLKSIZE));
#else
cwd->append(ent->d_name, statbuf.st_size);
#endif
else if (S_ISDIR(statbuf.st_mode)) //folder
{
Folder *d = 0;
QByteArray new_dirname = ent->d_name;
new_dirname += '/';
new_path += '/';
//check to see if we've scanned this section already
for (Iterator<Folder> it = m_trees->iterator(); it != m_trees->end(); ++it)
{
if (new_path == (*it)->name8Bit())
{
kDebug() << "Tree pre-completed: " << (*it)->name();
d = it.remove();
m_parent->m_files += d->children();
//**** ideally don't have this redundant extra somehow
cwd->append(d, new_dirname);
}
}
if (!d) //then scan
if ((d = scan(new_path, new_dirname))) //then scan was successful
cwd->append(d);
}
++m_parent->m_files;
}
closedir(dir);
return cwd;
}
void LocalLister::readMounts()
{
const Solid::StorageAccess *partition;
const Solid::StorageVolume *volume;
QStringList remoteFsTypes;
remoteFsTypes << QLatin1String( "smbfs" ) << QLatin1String( "nfs" ) << QLatin1String( "afs" ); //TODO: expand
foreach (const Solid::Device &device, Solid::Device::listFromType(Solid::DeviceInterface::StorageAccess))
{ // Iterate over all the partitions available.
if (!device.is<Solid::StorageAccess>()) continue; // It happens.
if (!device.is<Solid::StorageVolume>()) continue;
partition = device.as<Solid::StorageAccess>();
if (!partition->isAccessible() || partition->filePath() == QLatin1String( "/" ) || partition->filePath().isEmpty()) continue;
volume = device.as<Solid::StorageVolume>();
if (remoteFsTypes.contains(volume->fsType())) {
if (!s_remoteMounts.contains(partition->filePath())) {
s_remoteMounts.append(partition->filePath());
}
} else if (!s_localMounts.contains(partition->filePath())) {
s_localMounts.append(partition->filePath());
}
}
kDebug() << "Found the following remote filesystems: " << s_remoteMounts;
kDebug() << "Found the following local filesystems: " << s_localMounts;
}
}//namespace Filelight
#include "localLister.moc"

View file

@ -0,0 +1,61 @@
/***********************************************************************
* Copyright 2003-2004 Max Howell <max.howell@methylblue.com>
* Copyright 2008-2009 Martin Sandsmark <martin.sandsmark@kde.org>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of
* the License or (at your option) version 3 or any later version
* accepted by the membership of KDE e.V. (or its successor approved
* by the membership of KDE e.V.), which shall act as a proxy
* defined in Section 14 of version 3 of the license.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
***********************************************************************/
#ifndef LOCALLISTER_H
#define LOCALLISTER_H
#include <QtCore/QByteArray>
#include <QtCore/QThread>
class Folder;
template<class T> class Chain;
namespace Filelight
{
class ScanManager;
class LocalLister : public QThread
{
Q_OBJECT
public:
LocalLister(const QString &path, Chain<Folder> *cachedTrees, ScanManager *parent);
static void readMounts();
signals:
void branchCompleted(Folder* tree, bool finished);
private:
QString m_path;
Chain<Folder> *m_trees;
ScanManager *m_parent;
private:
virtual void run();
Folder *scan(const QByteArray&, const QByteArray&);
private:
static QStringList s_localMounts, s_remoteMounts; //TODO namespace
};
}
#endif

341
filelight/src/part/part.cpp Normal file
View file

@ -0,0 +1,341 @@
/***********************************************************************
* Copyright 2003-2004 Max Howell <max.howell@methylblue.com>
* Copyright 2008-2013 Martin Sandsmark <martin.sandsmark@kde.org>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of
* the License or (at your option) version 3 or any later version
* accepted by the membership of KDE e.V. (or its successor approved
* by the membership of KDE e.V.), which shall act as a proxy
* defined in Section 14 of version 3 of the license.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
***********************************************************************/
#include "part.h"
#include "Config.h"
#include "define.h"
#include "fileTree.h"
#include "progressBox.h"
#include "radialMap/widget.h"
#include "scan.h"
#include "settingsDialog.h"
#include "summaryWidget.h"
#include <KAboutData> //::createAboutData()
#include <KAction>
#include <KActionCollection>
#include <KLocale>
#include <KMessageBox> //::start()
#include <KStandardAction>
#include <KStatusBar>
#include <KPluginFactory>
#include <QtCore/QFile> //encodeName()
#include <QtCore/QTimer> //postInit() hack
#include <QtCore/QByteArray>
#include <QtCore/QDir>
#include <QtGui/QScrollArea>
#include <unistd.h> //access()
#include <iostream>
namespace Filelight {
K_PLUGIN_FACTORY(filelightPartFactory, registerPlugin<Part>();) // produce a factory
K_EXPORT_PLUGIN(filelightPartFactory(KAboutData(
"filelightpart",
0,
ki18n(APP_PRETTYNAME),
APP_VERSION,
ki18n("Displays file usage in an easy to understand way."),
KAboutData::License_GPL,
ki18n("(c) 2002-2004 Max Howell\n\
(c) 2008-2013 Martin T. Sandsmark"),
KLocalizedString(),
"http://utils.kde.org/projects/filelight",
"martin.sandsmark@kde.org").
setProgramIconName(QLatin1String(APP_NAME)).
setCatalogName(APP_NAME)))
BrowserExtension::BrowserExtension(Part *parent)
: KParts::BrowserExtension(parent)
{}
Part::Part(QWidget *parentWidget, QObject *parent, const QList<QVariant>&)
: ReadOnlyPart(parent)
, m_summary(0)
, m_ext(new BrowserExtension(this))
, m_statusbar(new StatusBarExtension(this))
, m_map(0)
, m_started(false)
{
Config::read();
setComponentData(filelightPartFactory::componentData());
setXMLFile(QLatin1String( "filelightpartui.rc" ));
QScrollArea *scrollArea = new QScrollArea(parentWidget);
scrollArea->setWidgetResizable(true);
setWidget(scrollArea);
QWidget *partWidget = new QWidget(scrollArea);
scrollArea->setWidget(partWidget);
partWidget->setBackgroundRole(QPalette::Base);
partWidget->setAutoFillBackground(true);
m_layout = new QGridLayout();
partWidget->setLayout(m_layout);
m_manager = new ScanManager(partWidget);
m_map = new RadialMap::Widget(partWidget);
m_layout->addWidget(m_map);
m_stateWidget = new ProgressBox(statusBar(), this, m_manager);
m_layout->addWidget(m_stateWidget);
m_stateWidget->hide();
m_numberOfFiles = new QLabel();
m_statusbar->addStatusBarItem(m_numberOfFiles, 0, true);
KStandardAction::zoomIn(m_map, SLOT(zoomIn()), actionCollection());
KStandardAction::zoomOut(m_map, SLOT(zoomOut()), actionCollection());
KAction *action = actionCollection()->addAction(QLatin1String("configure_filelight"));
action->setText(i18n("Configure Filelight..."));
action->setIcon(KIcon(QLatin1String("configure")));
connect(action, SIGNAL(triggered()), this, SLOT(configFilelight()));
connect(m_map, SIGNAL(created(const Folder*)), SIGNAL(completed()));
connect(m_map, SIGNAL(created(const Folder*)), SLOT(mapChanged(const Folder*)));
connect(m_map, SIGNAL(activated(KUrl)), SLOT(updateURL(KUrl)));
// TODO make better system
connect(m_map, SIGNAL(giveMeTreeFor(KUrl)), SLOT(updateURL(KUrl)));
connect(m_map, SIGNAL(giveMeTreeFor(KUrl)), SLOT(openUrl(KUrl)));
connect(m_manager, SIGNAL(completed(Folder*)), SLOT(scanCompleted(Folder*)));
connect(m_manager, SIGNAL(aboutToEmptyCache()), m_map, SLOT(invalidate()));
QTimer::singleShot(0, this, SLOT(postInit()));
}
void
Part::postInit()
{
if (url().isEmpty()) //if url is not empty openUrl() has been called immediately after ctor, which happens
{
m_map->hide();
showSummary();
//FIXME KXMLGUI is b0rked, it should allow us to set this
//BEFORE createGUI is called but it doesn't
stateChanged(QLatin1String( "scan_failed" ));
}
}
bool
Part::openUrl(const KUrl &u)
{
//TODO everyone hates dialogs, instead render the text in big fonts on the Map
//TODO should have an empty KUrl until scan is confirmed successful
//TODO probably should set caption to QString::null while map is unusable
#define KMSG(s) KMessageBox::information(widget(), s)
KUrl uri = u;
uri.cleanPath(KUrl::SimplifyDirSeparators);
const QString path = uri.path(KUrl::AddTrailingSlash);
const QByteArray path8bit = QFile::encodeName(path);
const bool isLocal = uri.protocol() == QLatin1String( "file" );
if (uri.isEmpty())
{
//do nothing, chances are the user accidently pressed ENTER
}
else if (!uri.isValid())
{
KMSG(i18n("The entered URL cannot be parsed; it is invalid."));
}
else if ((!isLocal && path[0] != QLatin1Char( '/' )) || (isLocal && !QDir::isAbsolutePath(path)))
{
KMSG(i18n("Filelight only accepts absolute paths, eg. /%1", path));
}
else if (isLocal && access(path8bit, F_OK) != 0) //stat(path, &statbuf) == 0
{
KMSG(i18n("Folder not found: %1", path));
}
else if (isLocal && !QDir(path).isReadable()) //access(path8bit, R_OK | X_OK) != 0 doesn't work on win32
{
KMSG(i18n("Unable to enter: %1\nYou do not have access rights to this location.", path));
}
else
{
//we don't want to be using the summary screen anymore
if (m_summary != 0)
m_summary->hide();
m_stateWidget->show();
m_layout->addWidget(m_stateWidget);
return start(uri);
}
return false;
}
bool
Part::closeUrl()
{
if (m_manager->abort())
statusBar()->showMessage(i18n("Aborting Scan..."));
m_map->hide();
m_stateWidget->hide();
showSummary();
return ReadOnlyPart::closeUrl();
}
void
Part::updateURL(const KUrl &u)
{
//the map has changed internally, update the interface to reflect this
emit m_ext->openUrlNotify(); //must be done first
emit m_ext->setLocationBarUrl(u.prettyUrl());
if (m_manager->running())
m_manager->abort();
if (u == url())
m_manager->emptyCache(); //same as rescan()
//do this last, or it breaks Konqi location bar
setUrl(u);
}
void
Part::configFilelight()
{
QWidget *dialog = new SettingsDialog(widget());
connect(dialog, SIGNAL(canvasIsDirty(int)), m_map, SLOT(refresh(int)));
connect(dialog, SIGNAL(mapIsInvalid()), m_manager, SLOT(emptyCache()));
dialog->show(); //deletes itself
}
bool
Part::start(const KUrl &url)
{
if (!m_started) {
connect(m_map, SIGNAL(mouseHover(QString)), statusBar(), SLOT(message(QString)));
connect(m_map, SIGNAL(created(const Folder*)), statusBar(), SLOT(clear()));
m_started = true;
}
if (m_manager->running())
m_manager->abort();
m_numberOfFiles->setText(QString());
if (m_manager->start(url)) {
setUrl(url);
const QString s = i18n("Scanning: %1", prettyUrl());
stateChanged(QLatin1String( "scan_started" ));
emit started(0); //as a Part, we have to do this
emit setWindowCaption(s);
statusBar()->showMessage(s);
m_map->hide();
m_map->invalidate(); //to maintain ui consistency
return true;
}
return false;
}
void
Part::rescan()
{
if (m_summary && !m_summary->isHidden()) {
delete m_summary;
m_summary = 0;
showSummary();
return;
}
//FIXME we have to empty the cache because otherwise rescan picks up the old tree..
m_manager->emptyCache(); //causes canvas to invalidate
m_map->hide();
m_stateWidget->show();
start(url());
}
void
Part::scanCompleted(Folder *tree)
{
if (tree) {
statusBar()->showMessage(i18n("Scan completed, generating map..."));
m_stateWidget->hide();
m_map->show();
m_map->create(tree);
stateChanged(QLatin1String( "scan_complete" ));
}
else {
stateChanged(QLatin1String( "scan_failed" ));
emit canceled(i18n("Scan failed: %1", prettyUrl()));
emit setWindowCaption(QString());
statusBar()->clearMessage();
setUrl(KUrl());
}
}
void
Part::mapChanged(const Folder *tree)
{
//IMPORTANT -> url() has already been set
emit setWindowCaption(prettyUrl());
const int fileCount = tree->children();
const QString text = ( fileCount == 0 ) ?
i18n("No files.") :
i18np("1 file", "%1 files",fileCount);
m_numberOfFiles->setText(text);
}
void
Part::showSummary()
{
if (m_summary == 0) {
m_summary = new SummaryWidget(widget());
m_summary->setObjectName(QLatin1String( "summaryWidget" ));
connect(m_summary, SIGNAL(activated(KUrl)), SLOT(openUrl(KUrl)));
m_summary->show();
m_layout->addWidget(m_summary);
}
else m_summary->show();
}
} //namespace Filelight
#include "part.moc"

101
filelight/src/part/part.h Normal file
View file

@ -0,0 +1,101 @@
/***********************************************************************
* Copyright 2003-2004 Max Howell <max.howell@methylblue.com>
* Copyright 2008-2009 Martin Sandsmark <martin.sandsmark@kde.org>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of
* the License or (at your option) version 3 or any later version
* accepted by the membership of KDE e.V. (or its successor approved
* by the membership of KDE e.V.), which shall act as a proxy
* defined in Section 14 of version 3 of the license.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
***********************************************************************/
#ifndef FILELIGHTPART_H
#define FILELIGHTPART_H
#include <KParts/BrowserExtension>
#include <KParts/StatusBarExtension>
#include <KParts/Part>
#include <KUrl>
#include <QtGui/QLabel>
using KParts::StatusBarExtension;
namespace RadialMap {
class Widget;
}
class Folder;
namespace Filelight
{
class Part;
class BrowserExtension : public KParts::BrowserExtension
{
public:
explicit BrowserExtension(Part*);
};
class Part : public KParts::ReadOnlyPart
{
Q_OBJECT
public:
Part(QWidget *, QObject *, const QList<QVariant>&);
virtual bool openFile() {
return false; //pure virtual in base class
}
virtual bool closeUrl();
QString prettyUrl() const {
return url().protocol() == QLatin1String( "file" ) ? url().path() : url().prettyUrl();
}
public slots:
virtual bool openUrl(const KUrl&);
void configFilelight();
void rescan();
private slots:
void postInit();
void scanCompleted(Folder*);
void mapChanged(const Folder*);
private:
KStatusBar *statusBar() {
return m_statusbar->statusBar();
}
void showSummary();
QLayout *m_layout;
QWidget *m_summary;
BrowserExtension *m_ext;
StatusBarExtension *m_statusbar;
RadialMap::Widget *m_map;
QWidget *m_stateWidget;
class ScanManager *m_manager;
QLabel *m_numberOfFiles;
bool m_started;
private:
bool start(const KUrl&);
private slots:
void updateURL(const KUrl &);
};
}
#endif

View file

@ -0,0 +1,132 @@
/***********************************************************************
* Copyright 2003-2004 Max Howell <max.howell@methylblue.com>
* Copyright 2008-2009 Martin Sandsmark <martin.sandsmark@kde.org>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of
* the License or (at your option) version 3 or any later version
* accepted by the membership of KDE e.V. (or its successor approved
* by the membership of KDE e.V.), which shall act as a proxy
* defined in Section 14 of version 3 of the license.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
***********************************************************************/
#include "progressBox.h"
#include "scan.h"
#include <KGlobal>
#include <KGlobalSettings>
#include <KColorScheme>
#include <KIO/Job>
#include <KLocale>
#include <QtGui/QLabel>
#include <QPainter>
#include <QtCore/QDebug>
#include <math.h>
ProgressBox::ProgressBox(QWidget *parent, QObject *part, Filelight::ScanManager *m)
: QWidget(parent)
, m_manager(m)
{
hide();
setObjectName(QLatin1String( "ProgressBox" ));
setFont(KGlobalSettings::fixedFont());
setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Fixed);
setText(999999);
setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
setMinimumSize(200, 200);
connect(&m_timer, SIGNAL(timeout()), SLOT(report()));
connect(part, SIGNAL(started(KIO::Job*)), SLOT(start()));
connect(part, SIGNAL(completed()), SLOT(stop()));
connect(part, SIGNAL(canceled(QString)), SLOT(halt()));
}
void
ProgressBox::start() //slot
{
m_timer.start(50); //20 times per second - very smooth
report();
show();
}
void
ProgressBox::report() //slot
{
setText(m_manager->files());
repaint();
}
void
ProgressBox::stop()
{
m_timer.stop();
}
void
ProgressBox::halt()
{
// canceled by stop button
m_timer.stop();
QTimer::singleShot(2000, this, SLOT(hide()));
}
void
ProgressBox::setText(int files)
{
m_text = i18np("%1 File", "%1 Files", files);
m_textWidth = fontMetrics().width(m_text);
m_textHeight = fontMetrics().height();
}
static const int pieces = 4;
static const float angleFactor[] = { -0.75, 0.5, 1.0, -0.3 };
static const int length[] = { 30, 40, 50, 60 };
static const int angleOffset[] = { 5760, 0, 0, -5760 };
static const int aLength[] = { 300, 2000, 200, 2000 };
void ProgressBox::paintEvent(QPaintEvent*)
{
KColorScheme view = KColorScheme(QPalette::Active, KColorScheme::Tooltip);
QPainter paint(this);
paint.setRenderHint(QPainter::Antialiasing);
static int tick = 0;
tick+=16;
for (int i=0; i<pieces; i++) {
const QRect rect(length[i]/2, length[i]/2, 200- length[i], 200-length[i]);
int angle = angleFactor[i] + tick*angleFactor[i];
QRadialGradient gradient(rect.center(), sin(angle/160.0f) * 100);
gradient.setColorAt(0, QColor::fromHsv(abs(angle/16) % 360 , 160, 255));
gradient.setColorAt(1, QColor::fromHsv(abs(angle/16) % 360 , 160, 128));
QBrush brush(gradient);
paint.setBrush(brush);
paint.drawPie(QRect(rect), angle, aLength[i]);
}
paint.setBrush(view.background(KColorScheme::ActiveBackground));
paint.setPen(view.foreground().color());
paint.translate(0.5, 0.5);
paint.drawRoundedRect(95-m_textWidth/2, 85, m_textWidth+10, m_textHeight+10, 5, 5);
paint.translate(-0.5, -0.5);
paint.drawText(100 - m_textWidth/2, 100, m_text);
}
#include "progressBox.moc"

View file

@ -0,0 +1,58 @@
/***********************************************************************
* Copyright 2003-2004 Max Howell <max.howell@methylblue.com>
* Copyright 2008-2009 Martin Sandsmark <martin.sandsmark@kde.org>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of
* the License or (at your option) version 3 or any later version
* accepted by the membership of KDE e.V. (or its successor approved
* by the membership of KDE e.V.), which shall act as a proxy
* defined in Section 14 of version 3 of the license.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
***********************************************************************/
#ifndef PROGRESSBOX_H
#define PROGRESSBOX_H
#include <QtGui/QLabel>
#include <QtCore/QTimer>
namespace Filelight {
class ScanManager;
}
class ProgressBox : public QWidget
{
Q_OBJECT
public:
ProgressBox(QWidget*, QObject*, Filelight::ScanManager*);
void setText(int);
public slots:
void start();
void report();
void stop();
void halt();
protected:
void paintEvent(QPaintEvent *event);
private:
QTimer m_timer;
Filelight::ScanManager* m_manager;
QString m_text;
int m_textWidth;
int m_textHeight;
};
#endif

View file

@ -0,0 +1,31 @@
#######################################################################
# Copyright 2008-2009 Martin Sandsmark <martin.sandsmark@kde.org>
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License as
# published by the Free Software Foundation; either version 2 of
# the License or (at your option) version 3 or any later version
# accepted by the membership of KDE e.V. (or its successor approved
# by the membership of KDE e.V.), which shall act as a proxy
# defined in Section 14 of version 3 of the license.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#######################################################################
set(radialmap_STAT_SRCS
widget.cpp
builder.cpp
map.cpp
widgetEvents.cpp
labels.cpp)
kde4_add_library(radialmap ${radialmap_STAT_SRCS} )
set_target_properties(radialmap PROPERTIES COMPILE_FLAGS -fPIC)

View file

@ -0,0 +1,161 @@
/***********************************************************************
* Copyright 2003-2004 Max Howell <max.howell@methylblue.com>
* Copyright 2008-2009 Martin Sandsmark <martin.sandsmark@kde.org>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of
* the License or (at your option) version 3 or any later version
* accepted by the membership of KDE e.V. (or its successor approved
* by the membership of KDE e.V.), which shall act as a proxy
* defined in Section 14 of version 3 of the license.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
***********************************************************************/
#include "builder.h"
#include "widget.h"
#include <part/Config.h>
#include <part/fileTree.h>
#include <KGlobal> //locale object
#include <KLocale>
//**** REMOVE NEED FOR the +1 with MAX_RING_DEPTH uses
//**** add some angle bounds checking (possibly in Segment ctor? can I delete in a ctor?)
//**** this class is a mess
RadialMap::Builder::Builder(RadialMap::Map *m, const Folder* const d, bool fast)
: m_map(m)
, m_root(d)
, m_minSize(static_cast<unsigned int>((d->size() * 3) / (PI * m->height() - m->MAP_2MARGIN)))
, m_depth(&m->m_visibleDepth)
{
m_signature = new Chain<Segment> [*m_depth + 1];
if (!fast)//|| *m_depth == 0) //depth 0 is special case usability-wise //**** WHY?!
{
//determine depth rather than use old one
findVisibleDepth(d); //sets m_depth
}
m_map->setRingBreadth();
setLimits(m_map->m_ringBreadth);
build(d);
m_map->m_signature = m_signature;
delete [] m_limits;
}
void
RadialMap::Builder::findVisibleDepth(const Folder* const dir, const unsigned int depth)
{
//**** because I don't use the same minimumSize criteria as in the visual function
// this can lead to incorrect visual representation
//**** BUT, you can't set those limits until you know m_depth!
//**** also this function doesn't check to see if anything is actually visible
// it just assumes that when it reaches a new level everything in it is visible
// automatically. This isn't right especially as there might be no files in the
// dir provided to this function!
static uint stopDepth = 0;
if (dir == m_root)
{
stopDepth = *m_depth;
*m_depth = 0;
}
if (*m_depth < depth) *m_depth = depth;
if (*m_depth >= stopDepth) return;
for (ConstIterator<File> it = dir->constIterator(); it != dir->end(); ++it)
if ((*it)->isFolder() && (*it)->size() > m_minSize)
findVisibleDepth((Folder *)*it, depth + 1); //if no files greater than min size the depth is still recorded
}
void
RadialMap::Builder::setLimits(const uint &b) //b = breadth?
{
double size3 = m_root->size() * 3;
double pi2B = PI * 2 * b;
m_limits = new uint [*m_depth + 1]; //FIXME delete!
for (unsigned int d = 0; d <= *m_depth; ++d)
m_limits[d] = (uint)(size3 / (double)(pi2B * (d + 1))); //min is angle that gives 3px outer diameter for that depth
}
//**** segments currently overlap at edges (i.e. end of first is start of next)
bool
RadialMap::Builder::build(const Folder* const dir, const unsigned int depth, unsigned int a_start, const unsigned int a_end)
{
//first iteration: dir == m_root
if (dir->children() == 0) //we do fileCount rather than size to avoid chance of divide by zero later
return false;
uint hiddenSize = 0, hiddenFileCount = 0;
for (ConstIterator<File> it = dir->constIterator(); it != dir->end(); ++it)
{
if ((*it)->size() > m_limits[depth])
{
unsigned int a_len = (unsigned int)(5760 * ((double)(*it)->size() / (double)m_root->size()));
Segment *s = new Segment(*it, a_start, a_len);
(m_signature + depth)->append(s);
if ((*it)->isFolder())
{
if (depth != *m_depth)
{
//recurse
s->m_hasHiddenChildren = build((Folder*)*it, depth + 1, a_start, a_start + a_len);
}
else s->m_hasHiddenChildren = true;
}
a_start += a_len; //**** should we add 1?
} else {
hiddenSize += (*it)->size();
if ((*it)->isFolder()) //**** considered virtual, but dir wouldn't count itself!
hiddenFileCount += static_cast<const Folder*>(*it)->children(); //need to add one to count the dir as well
++hiddenFileCount;
}
}
if (hiddenFileCount == dir->children() && !Config::showSmallFiles)
return true;
else if ((Config::showSmallFiles && hiddenSize > m_limits[depth]) || (depth == 0 && (hiddenSize > dir->size()/8)) /*|| > size() * 0.75*/)
{
//append a segment for unrepresented space - a "fake" segment
const QString s = i18np("1 file, with an average size of %2",
"%1 files, with an average size of %2",
hiddenFileCount,
KGlobal::locale()->formatByteSize(hiddenSize/hiddenFileCount));
(m_signature + depth)->append(new Segment(new File(s.toUtf8(), hiddenSize), a_start, a_end - a_start, true));
}
return false;
}

View file

@ -0,0 +1,56 @@
/***********************************************************************
* Copyright 2003-2004 Max Howell <max.howell@methylblue.com>
* Copyright 2008-2009 Martin Sandsmark <martin.sandsmark@kde.org>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of
* the License or (at your option) version 3 or any later version
* accepted by the membership of KDE e.V. (or its successor approved
* by the membership of KDE e.V.), which shall act as a proxy
* defined in Section 14 of version 3 of the license.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
***********************************************************************/
#ifndef BUILDER_H
#define BUILDER_H
#include "radialMap.h" //Segment, defines
template <class T> class Chain;
class Folder;
namespace RadialMap
{
class Map;
//temporary class that builds the Map signature
class Builder
{
public:
Builder(Map*, const Folder* const, bool fast=false);
private:
void findVisibleDepth(const Folder* const dir, const uint=0);
void setLimits(const uint&);
bool build(const Folder* const, const uint=0, uint=0, const uint=5760);
Map *m_map;
const Folder* const m_root;
const uint m_minSize;
uint *m_depth;
Chain<Segment> *m_signature;
uint *m_limits;
};
}
#endif

View file

@ -0,0 +1,340 @@
/***********************************************************************
* Copyright 2003-2004 Max Howell <max.howell@methylblue.com>
* Copyright 2008-2009 Martin Sandsmark <martin.sandsmark@kde.org>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of
* the License or (at your option) version 3 or any later version
* accepted by the membership of KDE e.V. (or its successor approved
* by the membership of KDE e.V.), which shall act as a proxy
* defined in Section 14 of version 3 of the license.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
***********************************************************************/
#include <QFont>
#include <QFontMetrics>
#include <QPainter>
#include "part/Config.h"
#include "part/fileTree.h"
#include "radialMap.h"
#include "sincos.h"
#include "widget.h"
namespace RadialMap
{
class Label
{
public:
Label(const RadialMap::Segment *s, int l) : segment(s), lvl(l), angle(segment->start() + (segment->length() / 2)) { }
bool tooClose(const int otherAngle) const {
return (angle > otherAngle - LABEL_ANGLE_MARGIN && angle < otherAngle + LABEL_ANGLE_MARGIN);
}
const RadialMap::Segment *segment;
const unsigned int lvl;
const int angle;
int x1, y1, x2, y2, x3;
int tx, ty, tw, th;
QString qs;
};
int compareAndSortLabels(Label *item1, Label *item2)
{
//you add 1440 to work round the fact that later you want the circle split vertically
//and as it is you start at 3 o' clock. It's to do with rightPrevY, stops annoying bug
int angle1 = (item1)->angle + 1440;
int angle2 = (item2)->angle + 1440;
// Also sort by level
if (angle1 == angle2)
return (item1->lvl > item2->lvl);
if (angle1 > 5760) angle1 -= 5760;
if (angle2 > 5760) angle2 -= 5760;
return (angle1 < angle2);
}
void
RadialMap::Widget::paintExplodedLabels(QPainter &paint) const
{
//we are a friend of RadialMap::Map
QList<Label*> list;
unsigned int startLevel = 0;
//1. Create list of labels sorted in the order they will be rendered
if (m_focus && m_focus->file() != m_tree) //separate behavior for selected vs unselected segments
{
//don't bother with files
if (m_focus && m_focus->file() && !m_focus->file()->isFolder())
return;
//find the range of levels we will be potentially drawing labels for
//startLevel is the level above whatever m_focus is in
for (const Folder *p = (const Folder*)m_focus->file(); p != m_tree; ++startLevel)
p = p->parent();
//range=2 means 2 levels to draw labels for
unsigned int start, end, minAngle;
start = m_focus->start();
end = m_focus->end(); //boundary angles
minAngle = int(m_focus->length() * LABEL_MIN_ANGLE_FACTOR);
#define segment (*it)
#define ring (m_map.m_signature + i)
//**** Levels should be on a scale starting with 0
//**** range is a useless parameter
//**** keep a topblock var which is the lowestLevel OR startLevel for identation purposes
for (unsigned int i = startLevel; i <= m_map.m_visibleDepth; ++i)
for (Iterator<Segment> it = ring->iterator(); it != ring->end(); ++it)
if (segment->start() >= start && segment->end() <= end)
if (segment->length() > minAngle) {
list.append(new Label(segment, i));
}
#undef ring
#undef segment
} else {
#define ring m_map.m_signature
for (Iterator<Segment> it = ring->iterator(); it != ring->end(); ++it)
if ((*it)->length() > 288) {
list.append(new Label((*it), 0));
}
#undef ring
}
qSort(list.begin(), list.end(), compareAndSortLabels);
//2. Check to see if any adjacent labels are too close together
// if so, remove it (the least significant labels, since we sort by level too).
int pos = 0;
while (pos < list.size() - 1)
{
if (list[pos]->tooClose(list[pos+1]->angle))
delete list.takeAt(pos+1);
else
++pos;
}
//used in next two steps
bool varySizes;
//**** should perhaps use doubles
int *sizes = new int [ m_map.m_visibleDepth + 1 ]; //**** make sizes an array of floats I think instead (or doubles)
// If the minimum is larger than the default it fucks up further down
if (paint.font().pointSize() < Config::minFontPitch) {
QFont font = paint.font();
font.setPointSize(Config::minFontPitch);
paint.setFont(font);
}
QList<Label*>::iterator it;
do
{
//3. Calculate font sizes
{
//determine current range of levels to draw for
uint range = 0;
for (it = list.begin(); it != list.end(); ++it)
{
uint lvl = (*it)->lvl;
if (lvl > range)
range = lvl;
//**** better way would just be to assign if nothing is range
}
range -= startLevel; //range 0 means 1 level of labels
varySizes = Config::varyLabelFontSizes && (range != 0);
if (varySizes)
{
//create an array of font sizes for various levels
//will exceed normal font pitch automatically if necessary, but not minPitch
//**** this needs to be checked lots
//**** what if this is negative (min size gtr than default size)
uint step = (paint.font().pointSize() - Config::minFontPitch) / range;
if (step == 0)
step = 1;
for (uint x = range + startLevel, y = Config::minFontPitch; x >= startLevel; y += step, --x)
sizes[x] = y;
}
}
//4. determine label co-ordinates
int x1, y1, x2, y2, x3, tx, ty; //coords
double sinra, cosra, ra; //angles
int cx = m_map.width() / 2 + m_offset.x(); //centre relative to canvas
int cy = m_map.height() / 2 + m_offset.y();
int spacer, preSpacer = int(m_map.m_ringBreadth * 0.5) + m_map.m_innerRadius;
int fullStrutLength = (m_map.width() - m_map.MAP_2MARGIN) / 2 + LABEL_MAP_SPACER; //full length of a strut from map center
int prevLeftY = 0;
int prevRightY = height();
bool rightSide;
QFont font;
for (it = list.begin(); it != list.end(); ++it)
{
//** bear in mind that text is drawn with QPoint param as BOTTOM left corner of text box
QString string = (*it)->segment->file()->name();
if (varySizes)
font.setPointSize(sizes[(*it)->lvl]);
QFontMetrics fontMetrics(font);
int fontHeight = fontMetrics.height(); //used to ensure label texts don't overlap
int lineSpacing = fontHeight / 4;
fontHeight += LABEL_TEXT_VMARGIN;
rightSide = ((*it)->angle < 1440 || (*it)->angle > 4320);
ra = M_PI/2880 * (*it)->angle; //convert to radians
sincos(ra, &sinra, &cosra);
spacer = preSpacer + m_map.m_ringBreadth * (*it)->lvl;
x1 = cx + (int)(cosra * spacer);
y1 = cy - (int)(sinra * spacer);
y2 = y1 - (int)(sinra * (fullStrutLength - spacer));
if (rightSide) { //righthand side, going upwards
if (y2 > prevRightY /*- fmh*/) //then it is too low, needs to be drawn higher
y2 = prevRightY /*- fmh*/;
}
else //lefthand side, going downwards
if (y2 < prevLeftY/* + fmh*/) //then we're too high, need to be drawn lower
y2 = prevLeftY /*+ fmh*/;
x2 = x1 - int(double(y2 - y1) / tan(ra));
ty = y2 + lineSpacing;
if (rightSide) {
if (x2 > width() || ty < fontHeight || x2 < x1) {
//skip this strut
//**** don't duplicate this code
list.erase(it); //will delete the label and set it to list.current() which _should_ be the next ptr
break;
}
prevRightY = ty - fontHeight - lineSpacing; //must be after above's "continue"
string = fontMetrics.elidedText(string, Qt::ElideMiddle, width() - x2);
x3 = width() - fontMetrics.width(string)
- LABEL_HMARGIN //outer margin
- LABEL_TEXT_HMARGIN //margin between strut and text
//- ((*it)->lvl - startLevel) * LABEL_HMARGIN; //indentation
;
if (x3 < x2) x3 = x2;
tx = x3 + LABEL_TEXT_HMARGIN;
} else {
if (x2 < 0 || ty > height() || x2 > x1)
{
//skip this strut
list.erase(it); //will delete the label and set it to list.current() which _should_ be the next ptr
break;
}
prevLeftY = ty + fontHeight - lineSpacing;
string = fontMetrics.elidedText(string, Qt::ElideMiddle, x2);
//**** needs a little tweaking:
tx = fontMetrics.width(string) + LABEL_HMARGIN/* + ((*it)->lvl - startLevel) * LABEL_HMARGIN*/;
if (tx > x2) { //text is too long
tx = LABEL_HMARGIN + x2 - tx; //some text will be lost from sight
x3 = x2; //no text margin (right side of text here)
} else {
x3 = tx + LABEL_TEXT_HMARGIN;
tx = LABEL_HMARGIN /*+ ((*it)->lvl - startLevel) * LABEL_HMARGIN*/;
}
}
(*it)->x1 = x1;
(*it)->y1 = y1;
(*it)->x2 = x2;
(*it)->y2 = y2;
(*it)->x3 = x3;
(*it)->tx = tx;
(*it)->ty = ty;
(*it)->qs = string;
}
//if an element is deleted at this stage, we need to do this whole
//iteration again, thus the following loop
//**** in rare case that deleted label was last label in top level
// and last in labelList too, this will not work as expected (not critical)
} while (it != list.end());
//5. Render labels
foreach (Label *label, list) {
if (varySizes) {
//**** how much overhead in making new QFont each time?
// (implicate sharing remember)
QFont font = paint.font();
font.setPointSize(sizes[label->lvl]);
paint.setFont(font);
}
paint.drawEllipse(label->x1 - 3, label->y1 - 3, 6, 6); //**** CPU intensive! better to use a pixmap
paint.drawLine(label->x1, label->y1, label->x2, label->y2);
paint.drawLine(label->x2, label->y2, label->x3, label->y2);
paint.drawText(label->tx, label->ty, label->qs);
}
foreach(Label *label, list) {
delete label;
}
delete [] sizes;
}
}

View file

@ -0,0 +1,381 @@
/***********************************************************************
* Copyright 2003-2004 Max Howell <max.howell@methylblue.com>
* Copyright 2008-2009 Martin Sandsmark <martin.sandsmark@kde.org>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of
* the License or (at your option) version 3 or any later version
* accepted by the membership of KDE e.V. (or its successor approved
* by the membership of KDE e.V.), which shall act as a proxy
* defined in Section 14 of version 3 of the license.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
***********************************************************************/
#include <QtGui/QApplication> //make()
#include <QtGui/QImage> //make() & paint()
#include <QtGui/QFont> //ctor
#include <QtGui/QFontMetrics> //ctor
#include <QtGui/QPainter>
#include <KCursor> //make()
#include <KDebug>
#include <KGlobalSettings> //kdeColours
#include "builder.h"
#include "part/Config.h"
#include "part/fileTree.h"
#define SINCOS_H_IMPLEMENTATION (1)
#include "sincos.h"
#include "widget.h"
RadialMap::Map::Map(bool summary)
: m_signature(NULL)
, m_visibleDepth(DEFAULT_RING_DEPTH)
, m_ringBreadth(MIN_RING_BREADTH)
, m_innerRadius(0)
, m_summary(summary)
{
//FIXME this is all broken. No longer is a maximum depth!
const int fmh = QFontMetrics(QFont()).height();
const int fmhD4 = fmh / 4;
MAP_2MARGIN = 2 * (fmh - (fmhD4 - LABEL_MAP_SPACER)); //margin is dependent on fitting in labels at top and bottom
}
RadialMap::Map::~Map()
{
delete [] m_signature;
}
void RadialMap::Map::invalidate()
{
delete [] m_signature;
m_signature = NULL;
m_visibleDepth = Config::defaultRingDepth;
}
void RadialMap::Map::make(const Folder *tree, bool refresh)
{
//slow operation so set the wait cursor
QApplication::setOverrideCursor(Qt::WaitCursor);
{
//build a signature of visible components
delete [] m_signature;
Builder builder(this, tree, refresh);
}
//colour the segments
colorise();
m_centerText = tree->humanReadableSize();
//paint the pixmap
paint();
QApplication::restoreOverrideCursor();
}
void RadialMap::Map::setRingBreadth()
{
//FIXME called too many times on creation
m_ringBreadth = (height() - MAP_2MARGIN) / (2 * m_visibleDepth + 4);
if (m_ringBreadth < MIN_RING_BREADTH)
m_ringBreadth = MIN_RING_BREADTH;
else if (m_ringBreadth > MAX_RING_BREADTH)
m_ringBreadth = MAX_RING_BREADTH;
}
bool RadialMap::Map::resize(const QRect &rect)
{
//there's a MAP_2MARGIN border
#define mw width()
#define mh height()
#define cw rect.width()
#define ch rect.height()
if (cw < mw || ch < mh || (cw > mw && ch > mh))
{
uint size = ((cw < ch) ? cw : ch) - MAP_2MARGIN;
//this also causes uneven sizes to always resize when resizing but map is small in that dimension
//size -= size % 2; //even sizes mean less staggered non-antialiased resizing
{
const uint minSize = MIN_RING_BREADTH * 2 * (m_visibleDepth + 2);
if (size < minSize)
size = minSize;
//this QRect is used by paint()
m_rect.setRect(0,0,size,size);
}
m_pixmap = QPixmap(m_rect.size());
//resize the pixmap
size += MAP_2MARGIN;
if (m_signature != NULL)
{
setRingBreadth();
paint();
}
return true;
}
#undef mw
#undef mh
#undef cw
#undef ch
return false;
}
void RadialMap::Map::colorise()
{
QColor cp, cb;
double darkness = 1;
double contrast = (double)Config::contrast / (double)100;
int h, s1, s2, v1, v2;
QColor kdeColour[2] = { KGlobalSettings::inactiveTitleColor(), KGlobalSettings::activeTitleColor() };
double deltaRed = (double)(kdeColour[0].red() - kdeColour[1].red()) / 2880; //2880 for semicircle
double deltaGreen = (double)(kdeColour[0].green() - kdeColour[1].green()) / 2880;
double deltaBlue = (double)(kdeColour[0].blue() - kdeColour[1].blue()) / 2880;
for (uint i = 0; i <= m_visibleDepth; ++i, darkness += 0.04)
{
for (Iterator<Segment> it = m_signature[i].iterator(); it != m_signature[i].end(); ++it)
{
if (m_summary){ // Summary view has its own colors, special cased.
if ((*it)->file()->name() == QLatin1String("Used")) {
cb = QApplication::palette().highlight().color();
cb.getHsv(&h, &s1, &v1);
if (s1 > 80)
s1 = 80;
v2 = v1 - int(contrast * v1);
s2 = s1 + int(contrast * (255 - s1));
cb.setHsv(h, s1, v1);
cp.setHsv(h, s2, v2);
}
else
{
cp = Qt::gray;
cb = Qt::white;
}
(*it)->setPalette(cp, cb);
}
else
{
switch (Config::scheme)
{
case Filelight::KDE:
{
//gradient will work by figuring out rgb delta values for 360 degrees
//then each component is angle*delta
int a = (*it)->start();
if (a > 2880) a = 2880 - (a - 2880);
h = (int)(deltaRed * a) + kdeColour[1].red();
s1 = (int)(deltaGreen * a) + kdeColour[1].green();
v1 = (int)(deltaBlue * a) + kdeColour[1].blue();
cb.setRgb(h, s1, v1);
cb.getHsv(&h, &s1, &v1);
break;
}
case Filelight::HighContrast:
cp.setHsv(0, 0, 0); //values of h, s and v are irrelevant
cb.setHsv(180, 0, int(255.0 * contrast));
(*it)->setPalette(cp, cb);
continue;
default:
h = int((*it)->start() / 16);
s1 = 160;
v1 = (int)(255.0 / darkness); //****doing this more often than once seems daft!
}
v2 = v1 - int(contrast * v1);
s2 = s1 + int(contrast * (255 - s1));
if (s1 < 80) s1 = 80; //can fall too low and makes contrast between the files hard to discern
if ((*it)->isFake()) //multi-file
{
cb.setHsv(h, s2, (v2 < 90) ? 90 : v2); //too dark if < 100
cp.setHsv(h, 17, v1);
}
else if (!(*it)->file()->isFolder()) //file
{
cb.setHsv(h, 17, v1);
cp.setHsv(h, 17, v2);
}
else //folder
{
cb.setHsv(h, s1, v1); //v was 225
cp.setHsv(h, s2, v2); //v was 225 - delta
}
(*it)->setPalette(cp, cb);
//TODO:
//**** may be better to store KDE colours as H and S and vary V as others
//**** perhaps make saturation difference for s2 dependent on contrast too
//**** fake segments don't work with highContrast
//**** may work better with cp = cb rather than Qt::white
//**** you have to ensure the grey of files is sufficient, currently it works only with rainbow (perhaps use contrast there too)
//**** change v1,v2 to vp, vb etc.
//**** using percentages is not strictly correct as the eye doesn't work like that
//**** darkness factor is not done for kde_colour scheme, and also value for files is incorrect really for files in this scheme as it is not set like rainbow one is
}
}
}
}
void RadialMap::Map::paint(bool antialias)
{
KColorScheme scheme(QPalette::Active, KColorScheme::View);
QPainter paint;
QRect rect = m_rect;
rect.adjust(5, 5, -5, -5);
m_pixmap.fill(scheme.background().color());
//m_rect.moveRight(1); // Uncommenting this breaks repainting when recreating map from cache
//**** best option you can think of is to make the circles slightly less perfect,
// ** i.e. slightly eliptic when resizing inbetween
if (m_pixmap.isNull())
return;
if (!paint.begin(&m_pixmap)) {
kWarning() << "Failed to initialize painting, returning...";
return;
}
if (antialias && Config::antialias) {
paint.translate(0.7, 0.7);
paint.setRenderHint(QPainter::Antialiasing);
}
int step = m_ringBreadth;
int excess = -1;
//do intelligent distribution of excess to prevent nasty resizing
if (m_ringBreadth != MAX_RING_BREADTH && m_ringBreadth != MIN_RING_BREADTH) {
excess = rect.width() % m_ringBreadth;
++step;
}
for (int x = m_visibleDepth; x >= 0; --x)
{
int width = rect.width() / 2;
//clever geometric trick to find largest angle that will give biggest arrow head
uint a_max = int(acos((double)width / double((width + 5))) * (180*16 / M_PI));
for (ConstIterator<Segment> it = m_signature[x].constIterator(); it != m_signature[x].end(); ++it)
{
//draw the pie segments, most of this code is concerned with drawing the little
//arrows on the ends of segments when they have hidden files
paint.setPen((*it)->pen());
if ((*it)->hasHiddenChildren())
{
//draw arrow head to indicate undisplayed files/directories
QPolygon pts(3);
QPoint pos, cpos = rect.center();
uint a[3] = { (*it)->start(), (*it)->length(), 0 };
a[2] = a[0] + (a[1] / 2); //assign to halfway between
if (a[1] > a_max)
{
a[1] = a_max;
a[0] = a[2] - a_max / 2;
}
a[1] += a[0];
for (int i = 0, radius = width; i < 3; ++i)
{
double ra = M_PI/(180*16) * a[i], sinra, cosra;
if (i == 2)
radius += 5;
sincos(ra, &sinra, &cosra);
pos.rx() = cpos.x() + static_cast<int>(cosra * radius);
pos.ry() = cpos.y() - static_cast<int>(sinra * radius);
pts.setPoint(i, pos);
}
paint.setBrush((*it)->pen());
paint.drawPolygon(pts);
}
paint.setBrush((*it)->brush());
paint.drawPie(rect, (*it)->start(), (*it)->length());
if ((*it)->hasHiddenChildren())
{
//**** code is bloated!
paint.save();
QPen pen = paint.pen();
int width = 2;
pen.setWidth(width);
paint.setPen(pen);
QRect rect2 = rect;
width /= 2;
rect2.adjust(width, width, -width, -width);
paint.drawArc(rect2, (*it)->start(), (*it)->length());
paint.restore();
}
}
if (excess >= 0) { //excess allows us to resize more smoothly (still crud tho)
if (excess < 2) //only decrease rect by more if even number of excesses left
--step;
excess -= 2;
}
rect.adjust(step, step, -step, -step);
}
// if(excess > 0) rect.addCoords(excess, excess, 0, 0); //ugly
paint.setPen(scheme.foreground().color());
paint.setBrush(scheme.background().color());
paint.drawEllipse(rect);
paint.drawText(rect, Qt::AlignCenter, m_centerText);
m_innerRadius = rect.width() / 2; //rect.width should be multiple of 2
paint.end();
}

View file

@ -0,0 +1,82 @@
/***********************************************************************
* Copyright 2003-2004 Max Howell <max.howell@methylblue.com>
* Copyright 2008-2009 Martin Sandsmark <martin.sandsmark@kde.org>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of
* the License or (at your option) version 3 or any later version
* accepted by the membership of KDE e.V. (or its successor approved
* by the membership of KDE e.V.), which shall act as a proxy
* defined in Section 14 of version 3 of the license.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
***********************************************************************/
#ifndef MAP_H
#define MAP_H
#include "part/fileTree.h"
#include <KColorScheme>
#include <QtGui/QPixmap>
#include <QtCore/QRect>
#include <QtCore/QString>
namespace RadialMap {
class Segment;
class Map
{
public:
explicit Map(bool summary);
~Map();
void make(const Folder *, bool = false);
bool resize(const QRect&);
bool isNull() const {
return (m_signature == 0);
}
void invalidate();
int height() const {
return m_rect.height();
}
int width() const {
return m_rect.width();
}
QPixmap pixmap() const {
return m_pixmap;
}
friend class Builder;
friend class Widget;
private:
void paint(bool antialias = true);
void colorise();
void setRingBreadth();
Chain<Segment> *m_signature;
QRect m_rect;
uint m_visibleDepth; ///visible level depth of system
QPixmap m_pixmap;
uint m_ringBreadth; ///ring breadth
uint m_innerRadius; ///radius of inner circle
QString m_centerText;
bool m_summary;
uint MAP_2MARGIN;
};
}
#endif

View file

@ -0,0 +1,110 @@
/***********************************************************************
* Copyright 2003-2004 Max Howell <max.howell@methylblue.com>
* Copyright 2008-2009 Martin Sandsmark <martin.sandsmark@kde.org>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of
* the License or (at your option) version 3 or any later version
* accepted by the membership of KDE e.V. (or its successor approved
* by the membership of KDE e.V.), which shall act as a proxy
* defined in Section 14 of version 3 of the license.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
***********************************************************************/
#ifndef RADIALMAP_H
#define RADIALMAP_H
#include <QColor>
class File;
namespace RadialMap
{
class Segment //all angles are in 16ths of degrees
{
public:
Segment(const File *f, uint s, uint l, bool isFake = false)
: m_angleStart(s)
, m_angleSegment(l)
, m_file(f)
, m_hasHiddenChildren(false)
, m_fake(isFake) {}
~Segment();
uint start() const {
return m_angleStart;
}
uint length() const {
return m_angleSegment;
}
uint end() const {
return m_angleStart + m_angleSegment;
}
const File *file() const {
return m_file;
}
const QColor& pen() const {
return m_pen;
}
const QColor& brush() const {
return m_brush;
}
bool isFake() const {
return m_fake;
}
bool hasHiddenChildren() const {
return m_hasHiddenChildren;
}
bool intersects(uint a) const {
return ((a >= start()) && (a < end()));
}
friend class Map;
friend class Builder;
private:
void setPalette(const QColor &p, const QColor &b) {
m_pen = p;
m_brush = b;
}
const uint m_angleStart, m_angleSegment;
const File* const m_file;
QColor m_pen, m_brush;
bool m_hasHiddenChildren;
const bool m_fake;
};
}
#ifndef PI
#define PI 3.141592653589793
#endif
#ifndef M_PI
#define M_PI 3.14159265358979323846264338327
#endif
#define MIN_RING_BREADTH 20
#define MAX_RING_BREADTH 60
#define DEFAULT_RING_DEPTH 4 //first level = 0
#define MIN_RING_DEPTH 0
#define LABEL_MAP_SPACER 7
#define LABEL_HMARGIN 10
#define LABEL_TEXT_HMARGIN 5
#define LABEL_TEXT_VMARGIN 0
#define LABEL_ANGLE_MARGIN 32
#define LABEL_MIN_ANGLE_FACTOR 0.05
#define LABEL_MAX_CHARS 30
#endif

View file

@ -0,0 +1,45 @@
/***********************************************************************
* Copyright 2003-2004 Max Howell <max.howell@methylblue.com>
* Copyright 2008-2009 Martin Sandsmark <martin.sandsmark@kde.org>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of
* the License or (at your option) version 3 or any later version
* accepted by the membership of KDE e.V. (or its successor approved
* by the membership of KDE e.V.), which shall act as a proxy
* defined in Section 14 of version 3 of the license.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
***********************************************************************/
#ifndef SINCOS_H
#define SINCOS_H
#include <math.h>
#if !defined(__GLIBC__) || (__GLIBC__ < 2) || (__GLIBC__ == 2 && __GLIBC_MINOR__ < 1)
#include <qmath.h>
void
sincos(double angleRadians, double *Sin, double *Cos);
#ifdef SINCOS_H_IMPLEMENTATION
void
sincos(double angleRadians, double *Sin, double *Cos)
{
*Sin = qSin(angleRadians);
*Cos = qCos(angleRadians);
}
#endif
#endif
#endif

View file

@ -0,0 +1,216 @@
/***********************************************************************
* Copyright 2003-2004 Max Howell <max.howell@methylblue.com>
* Copyright 2008-2009 Martin Sandsmark <martin.sandsmark@kde.org>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of
* the License or (at your option) version 3 or any later version
* accepted by the membership of KDE e.V. (or its successor approved
* by the membership of KDE e.V.), which shall act as a proxy
* defined in Section 14 of version 3 of the license.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
***********************************************************************/
#include "widget.h"
#include "part/Config.h"
#include "part/fileTree.h"
#include "radialMap.h" //constants
#include "map.h"
#include <KCursor> //ctor
#include <KUrl>
#include <QtGui/QApplication> //sendEvent
#include <QtGui/QBitmap> //ctor - finding cursor size
#include <QtGui/QCursor> //slotPostMouseEvent()
#include <QtCore/QTimer> //member
#include <QtGui/QWidget>
RadialMap::Widget::Widget(QWidget *parent, bool isSummary)
: QWidget(parent)
, m_tree(0)
, m_focus(0)
, m_map(isSummary)
, m_rootSegment(0) //TODO we don't delete it, *shrug*
, m_isSummary(isSummary)
, m_toBeDeleted(0)
{
setAcceptDrops(true);
setMinimumSize(350, 250);
connect(this, SIGNAL(created(const Folder*)), SLOT(sendFakeMouseEvent()));
connect(this, SIGNAL(created(const Folder*)), SLOT(update()));
connect(&m_timer, SIGNAL(timeout()), SLOT(resizeTimeout()));
}
RadialMap::Widget::~Widget()
{
delete m_rootSegment;
}
QString
RadialMap::Widget::path() const
{
return m_tree->fullPath();
}
KUrl
RadialMap::Widget::url(File const * const file) const
{
return KUrl(file ? file->fullPath() : m_tree->fullPath());
}
void
RadialMap::Widget::invalidate()
{
if (isValid())
{
//**** have to check that only way to invalidate is this function frankly
//**** otherwise you may get bugs..
//disable mouse tracking
setMouseTracking(false);
//ensure this class won't think we have a map still
m_tree = 0;
m_focus = 0;
delete m_rootSegment;
m_rootSegment = 0;
//FIXME move this disablement thing no?
// it is confusing in other areas, like the whole createFromCache() thing
m_map.invalidate();
update();
//tell rest of Filelight
emit invalidated(url());
}
}
void
RadialMap::Widget::create(const Folder *tree)
{
//it is not the responsibility of create() to invalidate first
//skip invalidation at your own risk
//FIXME make it the responsibility of create to invalidate first
if (tree)
{
m_focus = 0;
//generate the filemap image
m_map.make(tree);
//this is the inner circle in the center
m_rootSegment = new Segment(tree, 0, 16*360);
setMouseTracking(true);
}
m_tree = tree;
//tell rest of Filelight
emit created(tree);
}
void
RadialMap::Widget::createFromCache(const Folder *tree)
{
//no scan was necessary, use cached tree, however we MUST still emit invalidate
invalidate();
create(tree);
}
void
RadialMap::Widget::sendFakeMouseEvent() //slot
{
QMouseEvent me(QEvent::MouseMove, mapFromGlobal(QCursor::pos()), Qt::NoButton, Qt::NoButton, Qt::NoModifier);
QApplication::sendEvent(this, &me);
}
void
RadialMap::Widget::resizeTimeout() //slot
{
// the segments are about to erased!
// this was a horrid bug, and proves the OO programming should be obeyed always!
m_focus = 0;
if (m_tree)
m_map.make(m_tree, true);
update();
}
void
RadialMap::Widget::refresh(int filth)
{
//TODO consider a more direct connection
if (!m_map.isNull())
{
switch (filth)
{
case 1:
m_focus=0;
m_map.make(m_tree, true); //true means refresh only
break;
case 2:
m_map.paint(true); //antialiased painting
break;
case 3:
m_map.colorise(); //FALL THROUGH!
case 4:
m_map.paint();
default:
break;
}
update();
}
}
void
RadialMap::Widget::zoomIn() //slot
{
if (m_map.m_visibleDepth > MIN_RING_DEPTH)
{
--m_map.m_visibleDepth;
m_focus = 0;
m_map.make(m_tree);
Config::defaultRingDepth = m_map.m_visibleDepth;
update();
}
}
void
RadialMap::Widget::zoomOut() //slot
{
m_focus = 0;
++m_map.m_visibleDepth;
m_map.make(m_tree);
if (m_map.m_visibleDepth > Config::defaultRingDepth)
Config::defaultRingDepth = m_map.m_visibleDepth;
update();
}
RadialMap::Segment::~Segment()
{
if (isFake())
delete m_file; //created by us in Builder::build()
}
#include "widget.moc"

View file

@ -0,0 +1,123 @@
/***********************************************************************
* Copyright 2003-2004 Max Howell <max.howell@methylblue.com>
* Copyright 2008-2009 Martin Sandsmark <martin.sandsmark@kde.org>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of
* the License or (at your option) version 3 or any later version
* accepted by the membership of KDE e.V. (or its successor approved
* by the membership of KDE e.V.), which shall act as a proxy
* defined in Section 14 of version 3 of the license.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
***********************************************************************/
#ifndef WIDGET_H
#define WIDGET_H
#include <KJob>
#include <KUrl>
#include <QtGui/QDragEnterEvent>
#include <QtGui/QDropEvent>
#include <QtGui/QMouseEvent>
#include <QtGui/QPaintEvent>
#include <QtGui/QResizeEvent>
#include <QtGui/QWidget>
#include <QtCore/QTimer>
#include "map.h"
template <class T> class Chain;
class Folder;
class File;
namespace KIO {
class Job;
}
class KUrl;
namespace RadialMap
{
class Segment;
class Widget : public QWidget
{
Q_OBJECT
public:
explicit Widget(QWidget* = 0, bool = false);
virtual ~Widget();
QString path() const;
KUrl url(File const * const = 0) const;
bool isValid() const {
return m_tree != 0;
}
bool isSummary() const {
return m_isSummary;
}
friend class Label; //FIXME badness
public slots:
void zoomIn();
void zoomOut();
void create(const Folder*);
void invalidate();
void refresh(int);
private slots:
void resizeTimeout();
void sendFakeMouseEvent();
void deleteJobFinished(KJob*);
void createFromCache(const Folder*);
signals:
void activated(const KUrl&);
void invalidated(const KUrl&);
void created(const Folder*);
void mouseHover(const QString&);
void giveMeTreeFor(const KUrl&);
protected:
virtual void changeEvent(QEvent*);
virtual void dragEnterEvent(QDragEnterEvent*);
virtual void dropEvent(QDropEvent*);
virtual void mouseMoveEvent(QMouseEvent*);
virtual void mousePressEvent(QMouseEvent*);
virtual void paintEvent(QPaintEvent*);
virtual void resizeEvent(QResizeEvent*);
virtual void enterEvent(QEvent*);
protected:
const Segment *segmentAt(QPoint&) const; //FIXME const reference for a library others can use
const Segment *rootSegment() const {
return m_rootSegment; ///never == 0
}
const Segment *focusSegment() const {
return m_focus; ///0 == nothing in focus
}
private:
void paintExplodedLabels(QPainter&) const;
const Folder *m_tree;
const Segment *m_focus;
QPoint m_offset;
QTimer m_timer;
Map m_map;
Segment *m_rootSegment;
const bool m_isSummary;
const Segment *m_toBeDeleted;
};
}
#endif

View file

@ -0,0 +1,329 @@
/***********************************************************************
* Copyright 2003-2004 Max Howell <max.howell@methylblue.com>
* Copyright 2008-2009 Martin Sandsmark <martin.sandsmark@kde.org>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of
* the License or (at your option) version 3 or any later version
* accepted by the membership of KDE e.V. (or its successor approved
* by the membership of KDE e.V.), which shall act as a proxy
* defined in Section 14 of version 3 of the license.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
***********************************************************************/
#include "part/fileTree.h"
#include "part/Config.h"
#include "radialMap.h" //class Segment
#include "widget.h"
#include <KCursor> //::mouseMoveEvent()
#include <KDebug>
#include <KIconLoader> //::mousePressEvent()
#include <KJob>
#include <KIO/Job> //::mousePressEvent()
#include <KIO/DeleteJob>
#include <KIO/JobUiDelegate>
#include <KLocale>
#include <KMessageBox> //::mousePressEvent()
#include <KMenu> //::mousePressEvent()
#include <KRun> //::mousePressEvent()
#include <KToolInvocation>
#include <KUrl>
#include <QtGui/QApplication> //QApplication::setOverrideCursor()
#include <QtGui/QClipboard>
#include <QtGui/QPainter>
#include <QtCore/QTimer> //::resizeEvent()
#include <QtGui/QDropEvent>
#include <QtGui/QPaintEvent>
#include <QtGui/QResizeEvent>
#include <QtGui/QMouseEvent>
#include <QtGui/QDragEnterEvent>
#include <QtGui/QToolTip>
#include <cmath> //::segmentAt()
void RadialMap::Widget::resizeEvent(QResizeEvent*)
{
if (m_map.resize(rect()))
m_timer.setSingleShot(true);
m_timer.start(500); //will cause signature to rebuild for new size
//always do these as they need to be initialised on creation
m_offset.rx() = (width() - m_map.width()) / 2;
m_offset.ry() = (height() - m_map.height()) / 2;
}
void RadialMap::Widget::paintEvent(QPaintEvent*)
{
QPainter paint;
paint.begin(this);
if (!m_map.isNull())
paint.drawPixmap(m_offset, m_map.pixmap());
else
{
paint.drawText(rect(), 0, i18nc("We messed up, the user needs to initiate a rescan.", "Internal representation is invalid,\nplease rescan."));
return;
}
//exploded labels
if (!m_map.isNull() && !m_timer.isActive())
{
if (Config::antialias) {
paint.setRenderHint(QPainter::Antialiasing);
//make lines appear on pixel boundaries
paint.translate(0.5, 0.5);
}
paintExplodedLabels(paint);
}
}
const RadialMap::Segment* RadialMap::Widget::segmentAt(QPoint &e) const
{
//determine which segment QPoint e is above
e -= m_offset;
if (!m_map.m_signature)
return 0;
if (e.x() <= m_map.width() && e.y() <= m_map.height())
{
//transform to cartesian coords
e.rx() -= m_map.width() / 2; //should be an int
e.ry() = m_map.height() / 2 - e.y();
double length = hypot(e.x(), e.y());
if (length >= m_map.m_innerRadius) //not hovering over inner circle
{
uint depth = ((int)length - m_map.m_innerRadius) / m_map.m_ringBreadth;
if (depth <= m_map.m_visibleDepth) //**** do earlier since you can //** check not outside of range
{
//vector calculation, reduces to simple trigonometry
//cos angle = (aibi + ajbj) / albl
//ai = x, bi=1, aj=y, bj=0
//cos angle = x / (length)
uint a = (uint)(acos((double)e.x() / length) * 916.736); //916.7324722 = #radians in circle * 16
//acos only understands 0-180 degrees
if (e.y() < 0) a = 5760 - a;
#define ring (m_map.m_signature + depth)
for (ConstIterator<Segment> it = ring->constIterator(); it != ring->end(); ++it)
if ((*it)->intersects(a))
return *it;
#undef ring
}
}
else return m_rootSegment; //hovering over inner circle
}
return 0;
}
void RadialMap::Widget::mouseMoveEvent(QMouseEvent *e)
{
//set m_focus to what we hover over, update UI if it's a new segment
Segment const * const oldFocus = m_focus;
QPoint p = e->pos();
m_focus = segmentAt(p); //NOTE p is passed by non-const reference
if (m_focus)
{
if (m_focus != oldFocus) //if not same as last time
{
setCursor(Qt::PointingHandCursor);
QString string = m_focus->file()->fullPath(m_tree)
+ QLatin1Char('\n')
+ m_focus->file()->humanReadableSize()
+ QLatin1Char('\n');
if (m_focus->file()->isFolder()) {
int files = static_cast<const Folder*>(m_focus->file())->children();
const uint percent = uint((100 * files) / (double)m_tree->children());
string += i18np("File: %1", "Files: %1", files);
if (percent > 0) string += QString(QLatin1String( " (%1%)" )).arg(KGlobal::locale()->formatNumber(percent, 0));
}
const KUrl url = Widget::url(m_focus->file());
if (m_focus == m_rootSegment && url != url.upUrl()) {
string += i18n("\nClick to go up to parent directory");
}
QToolTip::showText(e->globalPos(), string, this);
emit mouseHover(m_focus->file()->fullPath());
update();
}
}
else if (oldFocus && oldFocus->file() != m_tree)
{
unsetCursor();
update();
emit mouseHover(QString());
}
}
void RadialMap::Widget::enterEvent(QEvent *)
{
if (!m_focus) return;
setCursor(Qt::PointingHandCursor);
emit mouseHover(m_focus->file()->fullPath());
update();
}
void RadialMap::Widget::mousePressEvent(QMouseEvent *e)
{
if (!isEnabled())
return;
//m_focus is set correctly (I've been strict, I assure you it is correct!)
if (m_focus && !m_focus->isFake())
{
const KUrl url = Widget::url(m_focus->file());
const bool isDir = m_focus->file()->isFolder();
// Actions in the right click menu
QAction* openFileManager = 0;
QAction* openTerminal = 0;
QAction* centerMap = 0;
QAction* openFile = 0;
QAction* copyClipboard = 0;
QAction* deleteItem = 0;
if (e->button() == Qt::RightButton)
{
KMenu popup;
popup.addTitle(m_focus->file()->fullPath(m_tree));
if (isDir) {
openFileManager = popup.addAction(KIcon(QLatin1String( "system-file-manager" )), i18n("Open &File Manager Here"));
if (url.protocol() == QLatin1String("file" ))
openTerminal = popup.addAction(KIcon(QLatin1String( "utilities-terminal" )), i18n("Open &Terminal Here"));
if (m_focus->file() != m_tree) {
popup.addSeparator();
centerMap = popup.addAction(KIcon(QLatin1String( "zoom-in" )), i18n("&Center Map Here"));
}
}
else
openFile = popup.addAction(KIcon(QLatin1String( "document-open" )), i18nc("Scan/open the path of the selected element", "&Open"));
popup.addSeparator();
copyClipboard = popup.addAction(KIcon(QLatin1String( "edit-copy" )), i18n("&Copy to clipboard"));
if (m_focus->file() != m_tree) {
popup.addSeparator();
deleteItem = popup.addAction(KIcon(QLatin1String( "edit-delete" )), i18n("&Delete"));
}
QAction* clicked = popup.exec(e->globalPos(), 0);
if (openFileManager && clicked == openFileManager) {
KRun::runUrl(url.url(),QLatin1String( "inode/directory" ), this);
} else if (openTerminal && clicked == openTerminal) {
KToolInvocation::invokeTerminal(QString(),url.path());
} else if (centerMap && clicked == centerMap) {
goto section_two;
} else if (openFile && clicked == openFile) {
goto section_two;
} else if (clicked == copyClipboard) {
QMimeData* mimedata = new QMimeData();
url.populateMimeData(mimedata);
QApplication::clipboard()->setMimeData(mimedata , QClipboard::Clipboard);
} else if (clicked == deleteItem && m_focus->file() != m_tree) {
m_toBeDeleted = m_focus;
const KUrl url = Widget::url(m_toBeDeleted->file());
const QString message = m_toBeDeleted->file()->isFolder()
? i18n("<qt>The folder at <i>'%1'</i> will be <b>recursively</b> and <b>permanently</b> deleted.</qt>", url.prettyUrl())
: i18n("<qt><i>'%1'</i> will be <b>permanently</b> deleted.</qt>", url.prettyUrl());
const int userIntention = KMessageBox::warningContinueCancel(
this, message,
QString(), KGuiItem(i18n("&Delete"), QLatin1String( "edit-delete" )));
if (userIntention == KMessageBox::Continue) {
KIO::Job *job = KIO::del(url);
job->ui()->setWindow(this);
connect(job, SIGNAL(finished(KJob*)), this, SLOT(deleteJobFinished(KJob*)));
QApplication::setOverrideCursor(Qt::BusyCursor);
setEnabled(false);
}
} else {
//ensure m_focus is set for new mouse position
sendFakeMouseEvent();
}
}
else { // not right mouse button
section_two:
const QRect rect(e->x() - 20, e->y() - 20, 40, 40);
if (!isDir || e->button() == Qt::MidButton) {
// KIconEffect::visualActivate(this, rect); // TODO: recreate this
new KRun(url, this, true); //FIXME see above
}
else if (m_focus->file() != m_tree) { // is left click
// KIconEffect::visualActivate(this, rect); // TODO: recreate this
emit activated(url); //activate first, this will cause UI to prepare itself
createFromCache((Folder *)m_focus->file());
}
else if (url.upUrl() != url)
emit giveMeTreeFor(url.upUrl());
}
}
}
void RadialMap::Widget::deleteJobFinished(KJob *job)
{
QApplication::restoreOverrideCursor();
setEnabled(true);
if (!job->error() && m_toBeDeleted) {
m_toBeDeleted->file()->parent()->remove(m_toBeDeleted->file());
delete m_toBeDeleted->file();
m_toBeDeleted = 0;
m_focus = 0;
m_map.make(m_tree, true);
repaint();
} else
KMessageBox::error(this, job->errorString(), i18n("Error while deleting"));
}
void RadialMap::Widget::dropEvent(QDropEvent *e)
{
KUrl::List uriList = KUrl::List::fromMimeData(e->mimeData());
if (!uriList.isEmpty())
emit giveMeTreeFor(uriList.first());
}
void RadialMap::Widget::dragEnterEvent(QDragEnterEvent *e)
{
KUrl::List uriList = KUrl::List::fromMimeData(e->mimeData());
e->setAccepted(!uriList.isEmpty());
}
void RadialMap::Widget::changeEvent(QEvent *e)
{
if (e->type() == QEvent::ApplicationPaletteChange ||
e->type() == QEvent::PaletteChange)
m_map.paint();
}

View file

@ -0,0 +1,171 @@
/***********************************************************************
* Copyright 2003-2004 Max Howell <max.howell@methylblue.com>
* Copyright 2008-2009 Martin Sandsmark <martin.sandsmark@kde.org>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of
* the License or (at your option) version 3 or any later version
* accepted by the membership of KDE e.V. (or its successor approved
* by the membership of KDE e.V.), which shall act as a proxy
* defined in Section 14 of version 3 of the license.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
***********************************************************************/
#include "remoteLister.h"
#include "fileTree.h"
#include "scan.h"
#include <KDebug>
#include <KDirLister>
#include <QtCore/QLinkedList>
#include <QtCore/QTimer>
#include <QtGui/QWidget>
namespace Filelight
{
//TODO: delete all this stuff!
// You need to use a single DirLister.
// One per folder breaks KIO (seemingly) and also uses un-godly amounts of memory!
struct Store {
typedef QLinkedList<Store*> List;
/// location of the folder
const KUrl url;
/// the folder on which we are operating
Folder *folder;
/// so we can reference the parent store
Store *parent;
/// directories in this folder that need to be scanned before we can propagate()
List stores;
Store() : folder(0), parent(0) {}
Store(const KUrl &u, const QString &name, Store *s)
: url(u), folder(new Folder(name.toUtf8() + '/')), parent(s) {}
Store* propagate()
{
/// returns the next store available for scanning
kDebug() << "propagate: " << url << endl;
if (parent) {
parent->folder->append(folder);
if (parent->stores.isEmpty()) {
return parent->propagate();
}
else
return parent;
}
//we reached the root, let's get our next folder scanned
return this;
}
private:
Store(Store&);
Store &operator=(const Store&);
};
RemoteLister::RemoteLister(const KUrl &url, QWidget *parent, ScanManager* manager)
: KDirLister(parent)
, m_root(new Store(url, url.url(), 0))
, m_store(m_root)
, m_manager(manager)
{
setShowingDotFiles(true); // Stupid KDirLister API function names
setMainWindow(parent);
// Use SIGNAL(result(KIO::Job*)) instead and then use Job::error()
connect(this, SIGNAL(completed()), SLOT(completed()));
connect(this, SIGNAL(canceled()), SLOT(canceled()));
}
RemoteLister::~RemoteLister()
{
Folder *tree = isFinished() ? m_store->folder : 0;
emit branchCompleted(tree, false);
delete m_root;
}
void
RemoteLister::completed()
{
kDebug() << "completed: " << url().prettyUrl() << endl;
// Delay the call to _completed since it can do a "delete this"
QTimer::singleShot(0, this, SLOT(_completed()));
}
void
RemoteLister::canceled()
{
kDebug() << "canceled: " << url().prettyUrl() << endl;
QTimer::singleShot(0, this, SLOT(_completed()));
}
void
RemoteLister::_completed()
{
//m_folder is set to the folder we should operate on
const KFileItemList items = KDirLister::items();
for (KFileItemList::ConstIterator it = items.begin(), end = items.end(); it != end; ++it)
{
if (it->isDir())
m_store->stores += new Store(it->url(), it->name(), m_store);
else
m_store->folder->append(it->name().toUtf8(), it->size());
m_manager->m_files++;
}
if (m_store->stores.isEmpty())
//no directories to scan, so we need to append ourselves to the parent folder
//propagate() will return the next ancestor that has stores left to be scanned, or root if we are done
m_store = m_store->propagate();
if (!m_store->stores.isEmpty())
{
Store::List::Iterator first = m_store->stores.begin();
const KUrl url((*first)->url);
Store *currentStore = m_store;
//we should operate with this store next time this function is called
m_store = *first;
//we don't want to handle this store again
currentStore->stores.erase(first);
//this returns _immediately_
kDebug() << "scanning: " << url << endl;
openUrl(url);
}
else {
kDebug() << "I think we're done\n";
Q_ASSERT(m_root == m_store);
delete this;
}
}
}
#include "remoteLister.moc"

View file

@ -0,0 +1,54 @@
/***********************************************************************
* Copyright 2003-2004 Max Howell <max.howell@methylblue.com>
* Copyright 2008-2009 Martin Sandsmark <martin.sandsmark@kde.org>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of
* the License or (at your option) version 3 or any later version
* accepted by the membership of KDE e.V. (or its successor approved
* by the membership of KDE e.V.), which shall act as a proxy
* defined in Section 14 of version 3 of the license.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
***********************************************************************/
#ifndef REMOTELISTER_H
#define REMOTELISTER_H
#include <KDirLister>
#include "fileTree.h"
namespace Filelight
{
class ScanManager;
class RemoteLister : public KDirLister
{
Q_OBJECT
public:
RemoteLister(const KUrl &url, QWidget *parent, ScanManager* manager);
~RemoteLister();
signals:
void branchCompleted(Folder* tree, bool finished);
private slots:
void completed();
void _completed();
void canceled();
private:
class Store *m_root, *m_store;
ScanManager* m_manager;
};
}
#endif

238
filelight/src/part/scan.cpp Normal file
View file

@ -0,0 +1,238 @@
/***********************************************************************
* Copyright 2003-2004 Max Howell <max.howell@methylblue.com>
* Copyright 2008-2009 Martin Sandsmark <martin.sandsmark@kde.org>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of
* the License or (at your option) version 3 or any later version
* accepted by the membership of KDE e.V. (or its successor approved
* by the membership of KDE e.V.), which shall act as a proxy
* defined in Section 14 of version 3 of the license.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
***********************************************************************/
#include "scan.h"
#include "remoteLister.h"
#include "fileTree.h"
#include "localLister.h"
#include <KDebug>
#include <QtGui/QApplication>
namespace Filelight
{
ScanManager::ScanManager(QObject *parent)
: QObject(parent)
, m_abort(false)
, m_files(0)
, m_mutex()
, m_thread(0)
, m_cache(new Chain<Folder>)
{
Filelight::LocalLister::readMounts();
connect(this, SIGNAL(branchCompleted(Folder*,bool)), this, SLOT(cacheTree(Folder*,bool)), Qt::QueuedConnection);
connect(this, SIGNAL(branchCacheHit(Folder*)), this, SLOT(foundCached(Folder*)), Qt::QueuedConnection);
}
ScanManager::~ScanManager()
{
if (m_thread) {
kDebug() << "Attempting to abort scan operation..." << endl;
m_abort = true;
m_thread->wait();
}
delete m_cache;
//RemoteListers are QObjects and get automatically deleted
}
bool ScanManager::running() const
{
return m_thread && m_thread->isRunning();
}
bool ScanManager::start(const KUrl &url)
{
QMutexLocker locker(&m_mutex); // The m_mutex gets released once locker is destroyed (goes out of scope).
//url is guaranteed clean and safe
kDebug() << "Scan requested for: " << url.prettyUrl() << endl;
if (running()) {
kWarning() << "Tried to launch two concurrent scans, aborting old one...";
abort();
}
m_files = 0;
m_abort = false;
if (url.protocol() == QLatin1String( "file" ))
{
const QString path = url.path(KUrl::AddTrailingSlash);
Chain<Folder> *trees = new Chain<Folder>;
/* CHECK CACHE
* user wants: /usr/local/
* cached: /usr/
*
* user wants: /usr/
* cached: /usr/local/, /usr/include/
*/
for (Iterator<Folder> it = m_cache->iterator(); it != m_cache->end(); ++it)
{
QString cachePath = (*it)->name();
if (path.startsWith(cachePath)) //then whole tree already scanned
{
//find a pointer to the requested branch
kDebug() << "Cache-(a)hit: " << cachePath << endl;
QStringList split = path.mid(cachePath.length()).split(QLatin1Char( '/' ));
Folder *d = *it;
Iterator<File> jt;
while (!split.isEmpty() && d != NULL) //if NULL we have got lost so abort!!
{
jt = d->iterator();
const Link<File> *end = d->end();
QString s = split.first();
if (s.isEmpty()) //found the dir
break;
s += QLatin1Char( '/' );
for (d = 0; jt != end; ++jt)
if (s == (*jt)->name())
{
d = (Folder*)*jt;
break;
}
split.pop_front();
}
if (d)
{
delete trees;
//we found a completed tree, thus no need to scan
kDebug() << "Found cache-handle, generating map.." << endl;
emit branchCacheHit(d);
return true;
}
else
{
//something went wrong, we couldn't find the folder we were expecting
kError() << "Didn't find " << path << " in the cache!\n";
delete it.remove(); //safest to get rid of it
break; //do a full scan
}
}
else if (cachePath.startsWith(path)) //then part of the requested tree is already scanned
{
kDebug() << "Cache-(b)hit: " << cachePath << endl;
it.transferTo(*trees);
}
}
m_url.setPath(path); //FIXME stop switching between paths and KURLs all the time
QApplication::setOverrideCursor(Qt::BusyCursor);
//starts listing by itself
m_thread = new Filelight::LocalLister(path, trees, this);
connect(m_thread, SIGNAL(branchCompleted(Folder*,bool)), this, SLOT(cacheTree(Folder*,bool)), Qt::QueuedConnection);
m_thread->start();
return true;
}
m_url = url;
QApplication::setOverrideCursor(Qt::BusyCursor);
//will start listing straight away
Filelight::RemoteLister *remoteLister = new Filelight::RemoteLister(url, (QWidget*)parent(), this);
connect(remoteLister, SIGNAL(branchCompleted(Folder*,bool)), this, SLOT(cacheTree(Folder*,bool)), Qt::QueuedConnection);
remoteLister->setParent(this);
remoteLister->setObjectName(QLatin1String( "remote_lister" ));
remoteLister->openUrl(url);
return true;
}
bool
ScanManager::abort()
{
m_abort = true;
delete findChild<RemoteLister *>(QLatin1String( "remote_lister" ));
return m_thread && m_thread->wait();
}
void
ScanManager::emptyCache()
{
m_abort = true;
if (m_thread && m_thread->isRunning())
m_thread->wait();
emit aboutToEmptyCache();
m_cache->empty();
}
void
ScanManager::cacheTree(Folder *tree, bool finished)
{
QMutexLocker locker(&m_mutex); // This gets released once it is destroyed.
if (m_thread) {
kDebug() << "Waiting for thread to terminate ...";
m_thread->wait();
kDebug() << "Thread terminated!";
delete m_thread; //note the lister deletes itself
m_thread = 0;
}
emit completed(tree);
if (tree) {
//we don't cache foreign stuff
//we don't recache stuff (thus only type 1000 events)
if (m_url.protocol() == QLatin1String( "file" ) && finished)
//TODO sanity check the cache
m_cache->append(tree);
}
else //scan failed
m_cache->empty(); //FIXME this is safe but annoying
QApplication::restoreOverrideCursor();
}
void
ScanManager::foundCached(Folder *tree)
{
emit completed(tree);
QApplication::restoreOverrideCursor();
}
}
#include "scan.moc"

77
filelight/src/part/scan.h Normal file
View file

@ -0,0 +1,77 @@
/***********************************************************************
* Copyright 2003-2004 Max Howell <max.howell@methylblue.com>
* Copyright 2008-2009 Martin Sandsmark <martin.sandsmark@kde.org>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of
* the License or (at your option) version 3 or any later version
* accepted by the membership of KDE e.V. (or its successor approved
* by the membership of KDE e.V.), which shall act as a proxy
* defined in Section 14 of version 3 of the license.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
***********************************************************************/
#ifndef SCAN_H
#define SCAN_H
#include <KUrl>
#include <QtCore/QObject>
#include <QtCore/QMutex>
class QThread;
class Folder;
template<class T> class Chain;
namespace Filelight
{
class ScanManager : public QObject
{
Q_OBJECT
friend class LocalLister;
friend class RemoteLister;
public:
explicit ScanManager(QObject *parent);
virtual ~ScanManager();
bool start(const KUrl&);
bool running() const;
uint files() const {
return m_files;
}
public slots:
bool abort();
void emptyCache();
void cacheTree(Folder*, bool);
void foundCached(Folder*);
signals:
void completed(Folder*);
void aboutToEmptyCache();
void branchCompleted(Folder* tree, bool finished);
void branchCacheHit(Folder* tree);
private:
bool m_abort;
uint m_files;
KUrl m_url;
QMutex m_mutex;
QThread *m_thread;
Chain<Folder> *m_cache;
};
}
#endif

View file

@ -0,0 +1,242 @@
/***********************************************************************
* Copyright 2003-2004 Max Howell <max.howell@methylblue.com>
* Copyright 2008-2009 Martin Sandsmark <martin.sandsmark@kde.org>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of
* the License or (at your option) version 3 or any later version
* accepted by the membership of KDE e.V. (or its successor approved
* by the membership of KDE e.V.), which shall act as a proxy
* defined in Section 14 of version 3 of the license.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
***********************************************************************/
#include "settingsDialog.h"
#include "Config.h"
#include <KDirSelectDialog>
#include <KLocale>
#include <KMessageBox>
#include <QtGui/QRadioButton>
#include <QtGui/QCloseEvent>
#include <QtCore/QDir>
SettingsDialog::SettingsDialog(QWidget *parent) : KDialog(parent)
{
setButtons(KDialog::Reset | KDialog::Close);
setupUi(this->mainWidget());
QVBoxLayout *vbox = new QVBoxLayout;
//colourSchemeGroup->setFrameShape(QFrame::NoFrame);
vbox->addWidget(new QRadioButton(i18n("Rainbow"), this), Filelight::Rainbow);
vbox->addWidget(new QRadioButton(i18n("System Colors"), this), Filelight::KDE);
vbox->addWidget(new QRadioButton(i18n("High Contrast"), this), Filelight::HighContrast);
colourSchemeGroup->setLayout(vbox);
//read in settings before you make all those nasty connections!
reset(); //makes dialog reflect global settings
connect(&m_timer, SIGNAL(timeout()), SIGNAL(mapIsInvalid()));
connect(m_addButton, SIGNAL(clicked()), SLOT(addFolder()));
connect(m_removeButton, SIGNAL(clicked()), SLOT(removeFolder()));
connect(this, SIGNAL(resetClicked()), SLOT(reset()));
connect(this, SIGNAL(closeClicked()), SLOT(close()));
connect(colourSchemeGroup, SIGNAL(clicked(int)), SLOT(changeScheme(int)));
connect(contrastSlider, SIGNAL(valueChanged(int)), SLOT(changeContrast(int)));
connect(contrastSlider, SIGNAL(sliderReleased()), SLOT(slotSliderReleased()));
connect(scanAcrossMounts, SIGNAL(toggled(bool)), SLOT(startTimer()));
connect(dontScanRemoteMounts, SIGNAL(toggled(bool)), SLOT(startTimer()));
connect(dontScanRemovableMedia, SIGNAL(toggled(bool)), SLOT(startTimer()));
connect(scanAcrossMounts, SIGNAL(toggled(bool)),
SLOT(toggleScanAcrossMounts(bool)));
connect(dontScanRemoteMounts, SIGNAL(toggled(bool)),
SLOT(toggleDontScanRemoteMounts(bool)));
connect(dontScanRemovableMedia, SIGNAL(toggled(bool)),
SLOT(toggleDontScanRemovableMedia(bool)));
connect(useAntialiasing, SIGNAL(toggled(bool)), SLOT(toggleUseAntialiasing(bool)));
connect(varyLabelFontSizes, SIGNAL(toggled(bool)), SLOT(toggleVaryLabelFontSizes(bool)));
connect(showSmallFiles, SIGNAL(toggled(bool)), SLOT(toggleShowSmallFiles(bool)));
connect(minFontPitch, SIGNAL (valueChanged(int)), SLOT(changeMinFontPitch(int)));
m_addButton->setIcon(KIcon(QLatin1String( "folder-open" )));
m_removeButton->setIcon(KIcon(QLatin1String( "list-remove" )));
}
void SettingsDialog::closeEvent(QCloseEvent*)
{
//if an invalidation is pending, force it now!
if (m_timer.isActive()) m_timer.setInterval(0);
Config::write();
deleteLater();
}
void SettingsDialog::reset()
{
Config::read();
//tab 1
scanAcrossMounts->setChecked(Config::scanAcrossMounts);
dontScanRemoteMounts->setChecked(!Config::scanRemoteMounts);
dontScanRemovableMedia->setChecked(!Config::scanRemovableMedia);
dontScanRemoteMounts->setEnabled(Config::scanAcrossMounts);
// dontScanRemovableMedia.setEnabled(Config::scanAcrossMounts);
m_listBox->clear();
m_listBox->addItems(Config::skipList);
m_listBox->setCurrentRow(0);
m_removeButton->setEnabled(m_listBox->count() > 0);
//tab 2
if (colourSchemeGroup->selected() != Config::scheme) //TODO: This is probably wrong
{
qobject_cast<QRadioButton*>(colourSchemeGroup->layout()->itemAt(Config::scheme)->widget())->setChecked(true);
//colourSchemeGroup->setSelected(Config::scheme);
//setButton doesn't call a single QButtonGroup signal!
//so we need to call this ourselves (and hence the detection above)
changeScheme(Config::scheme);
}
contrastSlider->setValue(Config::contrast);
useAntialiasing->setChecked(Config::antialias);
varyLabelFontSizes->setChecked(Config::varyLabelFontSizes);
minFontPitchLabel->setEnabled(Config::varyLabelFontSizes);
minFontPitch->setEnabled(Config::varyLabelFontSizes);
minFontPitch->setValue(Config::minFontPitch);
showSmallFiles->setChecked(Config::showSmallFiles);
}
void SettingsDialog::toggleScanAcrossMounts(bool b)
{
Config::scanAcrossMounts = b;
dontScanRemoteMounts->setEnabled(b);
//dontScanRemovableMedia.setEnabled(b);
}
void SettingsDialog::toggleDontScanRemoteMounts(bool b)
{
Config::scanRemoteMounts = !b;
}
void SettingsDialog::toggleDontScanRemovableMedia(bool b)
{
Config::scanRemovableMedia = !b;
}
void SettingsDialog::addFolder()
{
const KUrl url = KDirSelectDialog::selectDirectory(KUrl(QDir::rootPath()), false, this, i18n( "Select Folder to Scan" ));
//TODO error handling!
//TODO wrong protocol handling!
if (!url.isEmpty())
{
const QString path = url.path(KUrl::AddTrailingSlash);
if (!Config::skipList.contains(path))
{
Config::skipList.append(path);
m_listBox->addItem(path);
if (m_listBox->currentItem() == 0) m_listBox->setCurrentRow(0);
m_removeButton->setEnabled(true);
}
else KMessageBox::sorry(this, i18n("That folder is already set to be excluded from scans"));
}
}
void SettingsDialog::removeFolder()
{
Config::skipList.removeAll(m_listBox->currentItem()->text()); //removes all entries that match
//safest method to ensure consistency
m_listBox->clear();
m_listBox->addItems(Config::skipList);
m_removeButton->setEnabled(m_listBox->count() > 0);
if (m_listBox->count() > 0) m_listBox->setCurrentRow(0);
}
void SettingsDialog::startTimer()
{
m_timer.setSingleShot(true);
m_timer.start(TIMEOUT);
}
void SettingsDialog::changeScheme(int s)
{
Config::scheme = (Filelight::MapScheme)s;
emit canvasIsDirty(1);
}
void SettingsDialog::changeContrast(int c)
{
Config::contrast = c;
emit canvasIsDirty(3);
}
void SettingsDialog::toggleUseAntialiasing(bool b)
{
Config::antialias = b;
emit canvasIsDirty(2);
}
void SettingsDialog::toggleVaryLabelFontSizes(bool b)
{
Config::varyLabelFontSizes = b;
minFontPitchLabel->setEnabled(b);
minFontPitch->setEnabled(b);
emit canvasIsDirty(0);
}
void SettingsDialog::changeMinFontPitch(int p)
{
Config::minFontPitch = p;
emit canvasIsDirty(0);
}
void SettingsDialog::toggleShowSmallFiles(bool b)
{
Config::showSmallFiles = b;
emit canvasIsDirty(1);
}
void SettingsDialog::slotSliderReleased()
{
emit canvasIsDirty(2);
}
void SettingsDialog::reject()
{
//called when escape is pressed
reset();
KDialog::reject(); //**** doesn't change back scheme so far
}
#include "settingsDialog.moc"

View file

@ -0,0 +1,68 @@
/***********************************************************************
* Copyright 2003-2004 Max Howell <max.howell@methylblue.com>
* Copyright 2008-2009 Martin Sandsmark <martin.sandsmark@kde.org>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of
* the License or (at your option) version 3 or any later version
* accepted by the membership of KDE e.V. (or its successor approved
* by the membership of KDE e.V.), which shall act as a proxy
* defined in Section 14 of version 3 of the license.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
***********************************************************************/
#ifndef SETTINGSDIALOG_H
#define SETTINGSDIALOG_H
#include "ui_dialog.h" //generated by uic
#include <QtCore/QTimer>
#include <QtGui/QCloseEvent>
class SettingsDialog : public KDialog, public Ui::Dialog
{
Q_OBJECT
public:
explicit SettingsDialog(QWidget* = 0);
protected:
virtual void closeEvent(QCloseEvent *);
virtual void reject();
public slots:
void addFolder();
void removeFolder();
void toggleScanAcrossMounts(bool);
void toggleDontScanRemoteMounts(bool);
void toggleDontScanRemovableMedia(bool);
void reset();
void startTimer();
void toggleUseAntialiasing(bool = true);
void toggleVaryLabelFontSizes(bool);
void changeContrast(int);
void changeScheme(int);
void changeMinFontPitch(int);
void toggleShowSmallFiles(bool);
void slotSliderReleased();
signals:
void mapIsInvalid();
void canvasIsDirty(int);
private:
QTimer m_timer;
static const uint TIMEOUT=1000;
};
#endif

View file

@ -0,0 +1,189 @@
/***********************************************************************
* Copyright 2003-2004 Max Howell <max.howell@methylblue.com>
* Copyright 2008-2009 Martin Sandsmark <martin.sandsmark@kde.org>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of
* the License or (at your option) version 3 or any later version
* accepted by the membership of KDE e.V. (or its successor approved
* by the membership of KDE e.V.), which shall act as a proxy
* defined in Section 14 of version 3 of the license.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
***********************************************************************/
#include "summaryWidget.h"
#include "Config.h"
#include "fileTree.h"
#include "radialMap/radialMap.h"
#include "radialMap/widget.h"
#include "summaryWidget.moc"
#include <KDebug>
#include <KIconEffect> //MyRadialMap::mousePressEvent()
#include <KIconLoader>
#include <KIcon>
#include <KLocale>
#include <Solid/Device>
#include <Solid/StorageAccess>
#include <KDiskFreeSpaceInfo>
#include <QtGui/QLabel>
#include <QtGui/QApplication>
#include <QtCore/QByteArray>
#include <QtCore/QList>
#include <QtGui/QMouseEvent>
#include <QtGui/QLayout>
struct Disk
{
QString mount;
QString icon;
qint64 size;
qint64 used;
qint64 free; //NOTE used+avail != size (clustersize!)
};
struct DiskList : QList<Disk>
{
DiskList();
};
class MyRadialMap : public RadialMap::Widget
{
public:
MyRadialMap(QWidget *parent)
: RadialMap::Widget(parent, true)
{
}
virtual void setCursor(const QCursor &c)
{
if (focusSegment() && focusSegment()->file()->name() == QLatin1String( "Used" ))
RadialMap::Widget::setCursor(c);
else
unsetCursor();
}
virtual void mousePressEvent(QMouseEvent *e)
{
const RadialMap::Segment *segment = focusSegment();
//we will allow right clicks to the center circle
if (segment == rootSegment() && e->button() == Qt::RightButton)
RadialMap::Widget::mousePressEvent(e);
//and clicks to the used segment
else if (e->button() == Qt::LeftButton ) {
const QRect rect(e->x() - 20, e->y() - 20, 40, 40);
// KIconEffect::visualActivate(this, rect); TODO: Re-enable
emit activated(url());
}
}
};
SummaryWidget::SummaryWidget(QWidget *parent)
: QWidget(parent)
{
qApp->setOverrideCursor(Qt::WaitCursor);
setLayout(new QGridLayout(this));
createDiskMaps();
qApp->restoreOverrideCursor();
}
void SummaryWidget::createDiskMaps()
{
DiskList disks;
const QByteArray free = i18nc("Free space on the disks/partitions", "Free").toUtf8();
const QByteArray used = i18nc("Used space on the disks/partitions", "Used").toUtf8();
KIconLoader loader;
QString text;
for (DiskList::ConstIterator it = disks.constBegin(), end = disks.constEnd(); it != end; ++it)
{
Disk const &disk = *it;
if (disk.free == 0 && disk.used == 0)
continue;
QWidget *volume = new QWidget(this);
QVBoxLayout *volumeLayout = new QVBoxLayout(volume);
RadialMap::Widget *map = new MyRadialMap(this);
QWidget *info = new QWidget(this);
info->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed);
QHBoxLayout* horizontalLayout = new QHBoxLayout(info);
// Create the text and icon under the radialMap.
text = QLatin1String( "<b>" ) + disk.mount + i18nc("Percent used disk space on the partition", "</b> (%1% Used)", disk.used*100/disk.size);
QLabel *label = new QLabel(text, this);
horizontalLayout->addWidget(label);
QLabel *icon = new QLabel(this);
icon->setPixmap(KIcon(disk.icon).pixmap(16,16));
horizontalLayout->addWidget(icon);
horizontalLayout->setAlignment(Qt::AlignCenter);
volumeLayout->addWidget(map);
volumeLayout->addWidget(info);
// row (=n/2) column (0 or 1)
qobject_cast<QGridLayout*>(layout())->addWidget(volume, layout()->count()/2, layout()->count() % 2);
Folder *tree = new Folder(disk.mount.toUtf8());
tree->append(free, disk.free);
tree->append(used, disk.used);
map->create(tree); //must be done when visible
connect(map, SIGNAL(activated(KUrl)), SIGNAL(activated(KUrl)));
}
}
DiskList::DiskList()
{
const Solid::StorageAccess *partition;
QStringList partitions;
foreach (const Solid::Device &device, Solid::Device::listFromType(Solid::DeviceInterface::StorageAccess))
{ // Iterate over all the partitions available.
if (!device.is<Solid::StorageAccess>()) continue; // It happens.
partition = device.as<Solid::StorageAccess>();
if (!partition->isAccessible()) continue;
if (partitions.contains(partition->filePath())) // check for duplicate partitions from Solid
continue;
partitions.append(partition->filePath());
KDiskFreeSpaceInfo info = KDiskFreeSpaceInfo::freeSpaceInfo(partition->filePath());
if (!info.isValid()) continue;
Disk disk;
disk.mount = partition->filePath();
disk.icon = device.icon();
disk.size = info.size();
disk.free = info.available();
disk.used = info.used();
*this += disk;
}
}

View file

@ -0,0 +1,43 @@
/***********************************************************************
* Copyright 2003-2004 Max Howell <max.howell@methylblue.com>
* Copyright 2008-2009 Martin Sandsmark <martin.sandsmark@kde.org>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of
* the License or (at your option) version 3 or any later version
* accepted by the membership of KDE e.V. (or its successor approved
* by the membership of KDE e.V.), which shall act as a proxy
* defined in Section 14 of version 3 of the license.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
***********************************************************************/
#ifndef SUMMARYWIDGET_H
#define SUMMARYWIDGET_H
#include <KUrl>
#include <QtGui/QWidget>
class SummaryWidget : public QWidget
{
Q_OBJECT
public:
explicit SummaryWidget(QWidget *parent);
signals:
void activated(const KUrl&);
private:
void createDiskMaps();
};
#endif