mirror of
https://bitbucket.org/smil3y/kde-workspace.git
synced 2025-02-23 18:32:50 +00:00
plasma: remove homerun applet
Signed-off-by: Ivailo Monev <xakepa10@laimg.moc>
This commit is contained in:
parent
86873898d3
commit
4b1f94af9a
230 changed files with 0 additions and 28029 deletions
|
@ -22,7 +22,6 @@ add_subdirectory(systemtray)
|
|||
add_subdirectory(kickoff)
|
||||
add_subdirectory(trash)
|
||||
if(LIBKONQ_FOUND)
|
||||
add_subdirectory(homerun)
|
||||
add_subdirectory(folderview)
|
||||
endif()
|
||||
|
||||
|
|
|
@ -1,28 +0,0 @@
|
|||
project(homerun)
|
||||
|
||||
# Packaging
|
||||
set(HOMERUN_VERSION "1.2.5")
|
||||
|
||||
# Compile options
|
||||
add_definitions(${QT_DEFINITIONS} ${KDE4_DEFINITIONS})
|
||||
add_definitions(-DQT_USE_FAST_CONCATENATION -DQT_USE_FAST_OPERATOR_PLUS)
|
||||
add_definitions(-std=c++0x)
|
||||
include_directories(${CMAKE_SOURCE_DIR} ${CMAKE_BINARY_DIR} ${KDE4_INCLUDES})
|
||||
|
||||
# configuration file
|
||||
configure_file(homerun_config.h.in ${CMAKE_BINARY_DIR}/homerun_config.h @ONLY)
|
||||
|
||||
# config/
|
||||
install(FILES config/homerunrc DESTINATION ${CONFIG_INSTALL_DIR})
|
||||
install(FILES config/homerunkickerrc DESTINATION ${CONFIG_INSTALL_DIR})
|
||||
|
||||
install(FILES data/favoriteapps.xml DESTINATION ${DATA_INSTALL_DIR}/homerun/)
|
||||
|
||||
add_subdirectory(lib)
|
||||
add_subdirectory(components)
|
||||
add_subdirectory(fullscreen)
|
||||
add_subdirectory(fixes)
|
||||
#add_subdirectory(tests)
|
||||
add_subdirectory(icons)
|
||||
add_subdirectory(kicker)
|
||||
add_subdirectory(plugins)
|
|
@ -1,14 +0,0 @@
|
|||
Individual files should have appropriate license headers.
|
||||
|
||||
libhomerun is licensed under LGPL v2.1 or v3 or later versions approved by the
|
||||
membership of KDE e.V.
|
||||
|
||||
homerunviewer and the homerun plasma applet are licensed uder GPL v2 or later.
|
||||
|
||||
cmake checks and libhomerun examples are licensed under BSD 2-clause.
|
||||
|
||||
The rest of the code is licensed under either:
|
||||
- LGPL v2.1 or later
|
||||
- LGPL v2.1 or v3 or later versions approved by the membership of KDE e.V
|
||||
- GPL v2 or later
|
||||
- GPL v2.1 or v3 or later versions approved by the membership of KDE e.V
|
|
@ -1,20 +0,0 @@
|
|||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
1. Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
2. Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
SUCH DAMAGE.
|
|
@ -1,339 +0,0 @@
|
|||
GNU GENERAL PUBLIC LICENSE
|
||||
Version 2, June 1991
|
||||
|
||||
Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
Preamble
|
||||
|
||||
The licenses for most software are designed to take away your
|
||||
freedom to share and change it. By contrast, the GNU General Public
|
||||
License is intended to guarantee your freedom to share and change free
|
||||
software--to make sure the software is free for all its users. This
|
||||
General Public License applies to most of the Free Software
|
||||
Foundation's software and to any other program whose authors commit to
|
||||
using it. (Some other Free Software Foundation software is covered by
|
||||
the GNU Lesser General Public License instead.) You can apply it to
|
||||
your programs, too.
|
||||
|
||||
When we speak of free software, we are referring to freedom, not
|
||||
price. Our General Public Licenses are designed to make sure that you
|
||||
have the freedom to distribute copies of free software (and charge for
|
||||
this service if you wish), that you receive source code or can get it
|
||||
if you want it, that you can change the software or use pieces of it
|
||||
in new free programs; and that you know you can do these things.
|
||||
|
||||
To protect your rights, we need to make restrictions that forbid
|
||||
anyone to deny you these rights or to ask you to surrender the rights.
|
||||
These restrictions translate to certain responsibilities for you if you
|
||||
distribute copies of the software, or if you modify it.
|
||||
|
||||
For example, if you distribute copies of such a program, whether
|
||||
gratis or for a fee, you must give the recipients all the rights that
|
||||
you have. You must make sure that they, too, receive or can get the
|
||||
source code. And you must show them these terms so they know their
|
||||
rights.
|
||||
|
||||
We protect your rights with two steps: (1) copyright the software, and
|
||||
(2) offer you this license which gives you legal permission to copy,
|
||||
distribute and/or modify the software.
|
||||
|
||||
Also, for each author's protection and ours, we want to make certain
|
||||
that everyone understands that there is no warranty for this free
|
||||
software. If the software is modified by someone else and passed on, we
|
||||
want its recipients to know that what they have is not the original, so
|
||||
that any problems introduced by others will not reflect on the original
|
||||
authors' reputations.
|
||||
|
||||
Finally, any free program is threatened constantly by software
|
||||
patents. We wish to avoid the danger that redistributors of a free
|
||||
program will individually obtain patent licenses, in effect making the
|
||||
program proprietary. To prevent this, we have made it clear that any
|
||||
patent must be licensed for everyone's free use or not licensed at all.
|
||||
|
||||
The precise terms and conditions for copying, distribution and
|
||||
modification follow.
|
||||
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||
|
||||
0. This License applies to any program or other work which contains
|
||||
a notice placed by the copyright holder saying it may be distributed
|
||||
under the terms of this General Public License. The "Program", below,
|
||||
refers to any such program or work, and a "work based on the Program"
|
||||
means either the Program or any derivative work under copyright law:
|
||||
that is to say, a work containing the Program or a portion of it,
|
||||
either verbatim or with modifications and/or translated into another
|
||||
language. (Hereinafter, translation is included without limitation in
|
||||
the term "modification".) Each licensee is addressed as "you".
|
||||
|
||||
Activities other than copying, distribution and modification are not
|
||||
covered by this License; they are outside its scope. The act of
|
||||
running the Program is not restricted, and the output from the Program
|
||||
is covered only if its contents constitute a work based on the
|
||||
Program (independent of having been made by running the Program).
|
||||
Whether that is true depends on what the Program does.
|
||||
|
||||
1. You may copy and distribute verbatim copies of the Program's
|
||||
source code as you receive it, in any medium, provided that you
|
||||
conspicuously and appropriately publish on each copy an appropriate
|
||||
copyright notice and disclaimer of warranty; keep intact all the
|
||||
notices that refer to this License and to the absence of any warranty;
|
||||
and give any other recipients of the Program a copy of this License
|
||||
along with the Program.
|
||||
|
||||
You may charge a fee for the physical act of transferring a copy, and
|
||||
you may at your option offer warranty protection in exchange for a fee.
|
||||
|
||||
2. You may modify your copy or copies of the Program or any portion
|
||||
of it, thus forming a work based on the Program, and copy and
|
||||
distribute such modifications or work under the terms of Section 1
|
||||
above, provided that you also meet all of these conditions:
|
||||
|
||||
a) You must cause the modified files to carry prominent notices
|
||||
stating that you changed the files and the date of any change.
|
||||
|
||||
b) You must cause any work that you distribute or publish, that in
|
||||
whole or in part contains or is derived from the Program or any
|
||||
part thereof, to be licensed as a whole at no charge to all third
|
||||
parties under the terms of this License.
|
||||
|
||||
c) If the modified program normally reads commands interactively
|
||||
when run, you must cause it, when started running for such
|
||||
interactive use in the most ordinary way, to print or display an
|
||||
announcement including an appropriate copyright notice and a
|
||||
notice that there is no warranty (or else, saying that you provide
|
||||
a warranty) and that users may redistribute the program under
|
||||
these conditions, and telling the user how to view a copy of this
|
||||
License. (Exception: if the Program itself is interactive but
|
||||
does not normally print such an announcement, your work based on
|
||||
the Program is not required to print an announcement.)
|
||||
|
||||
These requirements apply to the modified work as a whole. If
|
||||
identifiable sections of that work are not derived from the Program,
|
||||
and can be reasonably considered independent and separate works in
|
||||
themselves, then this License, and its terms, do not apply to those
|
||||
sections when you distribute them as separate works. But when you
|
||||
distribute the same sections as part of a whole which is a work based
|
||||
on the Program, the distribution of the whole must be on the terms of
|
||||
this License, whose permissions for other licensees extend to the
|
||||
entire whole, and thus to each and every part regardless of who wrote it.
|
||||
|
||||
Thus, it is not the intent of this section to claim rights or contest
|
||||
your rights to work written entirely by you; rather, the intent is to
|
||||
exercise the right to control the distribution of derivative or
|
||||
collective works based on the Program.
|
||||
|
||||
In addition, mere aggregation of another work not based on the Program
|
||||
with the Program (or with a work based on the Program) on a volume of
|
||||
a storage or distribution medium does not bring the other work under
|
||||
the scope of this License.
|
||||
|
||||
3. You may copy and distribute the Program (or a work based on it,
|
||||
under Section 2) in object code or executable form under the terms of
|
||||
Sections 1 and 2 above provided that you also do one of the following:
|
||||
|
||||
a) Accompany it with the complete corresponding machine-readable
|
||||
source code, which must be distributed under the terms of Sections
|
||||
1 and 2 above on a medium customarily used for software interchange; or,
|
||||
|
||||
b) Accompany it with a written offer, valid for at least three
|
||||
years, to give any third party, for a charge no more than your
|
||||
cost of physically performing source distribution, a complete
|
||||
machine-readable copy of the corresponding source code, to be
|
||||
distributed under the terms of Sections 1 and 2 above on a medium
|
||||
customarily used for software interchange; or,
|
||||
|
||||
c) Accompany it with the information you received as to the offer
|
||||
to distribute corresponding source code. (This alternative is
|
||||
allowed only for noncommercial distribution and only if you
|
||||
received the program in object code or executable form with such
|
||||
an offer, in accord with Subsection b above.)
|
||||
|
||||
The source code for a work means the preferred form of the work for
|
||||
making modifications to it. For an executable work, complete source
|
||||
code means all the source code for all modules it contains, plus any
|
||||
associated interface definition files, plus the scripts used to
|
||||
control compilation and installation of the executable. However, as a
|
||||
special exception, the source code distributed need not include
|
||||
anything that is normally distributed (in either source or binary
|
||||
form) with the major components (compiler, kernel, and so on) of the
|
||||
operating system on which the executable runs, unless that component
|
||||
itself accompanies the executable.
|
||||
|
||||
If distribution of executable or object code is made by offering
|
||||
access to copy from a designated place, then offering equivalent
|
||||
access to copy the source code from the same place counts as
|
||||
distribution of the source code, even though third parties are not
|
||||
compelled to copy the source along with the object code.
|
||||
|
||||
4. You may not copy, modify, sublicense, or distribute the Program
|
||||
except as expressly provided under this License. Any attempt
|
||||
otherwise to copy, modify, sublicense or distribute the Program is
|
||||
void, and will automatically terminate your rights under this License.
|
||||
However, parties who have received copies, or rights, from you under
|
||||
this License will not have their licenses terminated so long as such
|
||||
parties remain in full compliance.
|
||||
|
||||
5. You are not required to accept this License, since you have not
|
||||
signed it. However, nothing else grants you permission to modify or
|
||||
distribute the Program or its derivative works. These actions are
|
||||
prohibited by law if you do not accept this License. Therefore, by
|
||||
modifying or distributing the Program (or any work based on the
|
||||
Program), you indicate your acceptance of this License to do so, and
|
||||
all its terms and conditions for copying, distributing or modifying
|
||||
the Program or works based on it.
|
||||
|
||||
6. Each time you redistribute the Program (or any work based on the
|
||||
Program), the recipient automatically receives a license from the
|
||||
original licensor to copy, distribute or modify the Program subject to
|
||||
these terms and conditions. You may not impose any further
|
||||
restrictions on the recipients' exercise of the rights granted herein.
|
||||
You are not responsible for enforcing compliance by third parties to
|
||||
this License.
|
||||
|
||||
7. If, as a consequence of a court judgment or allegation of patent
|
||||
infringement or for any other reason (not limited to patent issues),
|
||||
conditions are imposed on you (whether by court order, agreement or
|
||||
otherwise) that contradict the conditions of this License, they do not
|
||||
excuse you from the conditions of this License. If you cannot
|
||||
distribute so as to satisfy simultaneously your obligations under this
|
||||
License and any other pertinent obligations, then as a consequence you
|
||||
may not distribute the Program at all. For example, if a patent
|
||||
license would not permit royalty-free redistribution of the Program by
|
||||
all those who receive copies directly or indirectly through you, then
|
||||
the only way you could satisfy both it and this License would be to
|
||||
refrain entirely from distribution of the Program.
|
||||
|
||||
If any portion of this section is held invalid or unenforceable under
|
||||
any particular circumstance, the balance of the section is intended to
|
||||
apply and the section as a whole is intended to apply in other
|
||||
circumstances.
|
||||
|
||||
It is not the purpose of this section to induce you to infringe any
|
||||
patents or other property right claims or to contest validity of any
|
||||
such claims; this section has the sole purpose of protecting the
|
||||
integrity of the free software distribution system, which is
|
||||
implemented by public license practices. Many people have made
|
||||
generous contributions to the wide range of software distributed
|
||||
through that system in reliance on consistent application of that
|
||||
system; it is up to the author/donor to decide if he or she is willing
|
||||
to distribute software through any other system and a licensee cannot
|
||||
impose that choice.
|
||||
|
||||
This section is intended to make thoroughly clear what is believed to
|
||||
be a consequence of the rest of this License.
|
||||
|
||||
8. If the distribution and/or use of the Program is restricted in
|
||||
certain countries either by patents or by copyrighted interfaces, the
|
||||
original copyright holder who places the Program under this License
|
||||
may add an explicit geographical distribution limitation excluding
|
||||
those countries, so that distribution is permitted only in or among
|
||||
countries not thus excluded. In such case, this License incorporates
|
||||
the limitation as if written in the body of this License.
|
||||
|
||||
9. The Free Software Foundation may publish revised and/or new versions
|
||||
of the General Public License from time to time. Such new versions will
|
||||
be similar in spirit to the present version, but may differ in detail to
|
||||
address new problems or concerns.
|
||||
|
||||
Each version is given a distinguishing version number. If the Program
|
||||
specifies a version number of this License which applies to it and "any
|
||||
later version", you have the option of following the terms and conditions
|
||||
either of that version or of any later version published by the Free
|
||||
Software Foundation. If the Program does not specify a version number of
|
||||
this License, you may choose any version ever published by the Free Software
|
||||
Foundation.
|
||||
|
||||
10. If you wish to incorporate parts of the Program into other free
|
||||
programs whose distribution conditions are different, write to the author
|
||||
to ask for permission. For software which is copyrighted by the Free
|
||||
Software Foundation, write to the Free Software Foundation; we sometimes
|
||||
make exceptions for this. Our decision will be guided by the two goals
|
||||
of preserving the free status of all derivatives of our free software and
|
||||
of promoting the sharing and reuse of software generally.
|
||||
|
||||
NO WARRANTY
|
||||
|
||||
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
|
||||
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
|
||||
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
|
||||
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
|
||||
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
|
||||
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
|
||||
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
|
||||
REPAIR OR CORRECTION.
|
||||
|
||||
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
||||
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
|
||||
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
|
||||
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
|
||||
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
|
||||
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
|
||||
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
|
||||
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGES.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
How to Apply These Terms to Your New Programs
|
||||
|
||||
If you develop a new program, and you want it to be of the greatest
|
||||
possible use to the public, the best way to achieve this is to make it
|
||||
free software which everyone can redistribute and change under these terms.
|
||||
|
||||
To do so, attach the following notices to the program. It is safest
|
||||
to attach them to the start of each source file to most effectively
|
||||
convey the exclusion of warranty; and each file should have at least
|
||||
the "copyright" line and a pointer to where the full notice is found.
|
||||
|
||||
<one line to give the program's name and a brief idea of what it does.>
|
||||
Copyright (C) <year> <name of author>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
|
||||
Also add information on how to contact you by electronic and paper mail.
|
||||
|
||||
If the program is interactive, make it output a short notice like this
|
||||
when it starts in an interactive mode:
|
||||
|
||||
Gnomovision version 69, Copyright (C) year name of author
|
||||
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
|
||||
This is free software, and you are welcome to redistribute it
|
||||
under certain conditions; type `show c' for details.
|
||||
|
||||
The hypothetical commands `show w' and `show c' should show the appropriate
|
||||
parts of the General Public License. Of course, the commands you use may
|
||||
be called something other than `show w' and `show c'; they could even be
|
||||
mouse-clicks or menu items--whatever suits your program.
|
||||
|
||||
You should also get your employer (if you work as a programmer) or your
|
||||
school, if any, to sign a "copyright disclaimer" for the program, if
|
||||
necessary. Here is a sample; alter the names:
|
||||
|
||||
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
|
||||
`Gnomovision' (which makes passes at compilers) written by James Hacker.
|
||||
|
||||
<signature of Ty Coon>, 1 April 1989
|
||||
Ty Coon, President of Vice
|
||||
|
||||
This General Public License does not permit incorporating your program into
|
||||
proprietary programs. If your program is a subroutine library, you may
|
||||
consider it more useful to permit linking proprietary applications with the
|
||||
library. If this is what you want to do, use the GNU Lesser General
|
||||
Public License instead of this License.
|
|
@ -1,502 +0,0 @@
|
|||
GNU LESSER GENERAL PUBLIC LICENSE
|
||||
Version 2.1, February 1999
|
||||
|
||||
Copyright (C) 1991, 1999 Free Software Foundation, Inc.
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
[This is the first released version of the Lesser GPL. It also counts
|
||||
as the successor of the GNU Library Public License, version 2, hence
|
||||
the version number 2.1.]
|
||||
|
||||
Preamble
|
||||
|
||||
The licenses for most software are designed to take away your
|
||||
freedom to share and change it. By contrast, the GNU General Public
|
||||
Licenses are intended to guarantee your freedom to share and change
|
||||
free software--to make sure the software is free for all its users.
|
||||
|
||||
This license, the Lesser General Public License, applies to some
|
||||
specially designated software packages--typically libraries--of the
|
||||
Free Software Foundation and other authors who decide to use it. You
|
||||
can use it too, but we suggest you first think carefully about whether
|
||||
this license or the ordinary General Public License is the better
|
||||
strategy to use in any particular case, based on the explanations below.
|
||||
|
||||
When we speak of free software, we are referring to freedom of use,
|
||||
not price. Our General Public Licenses are designed to make sure that
|
||||
you have the freedom to distribute copies of free software (and charge
|
||||
for this service if you wish); that you receive source code or can get
|
||||
it if you want it; that you can change the software and use pieces of
|
||||
it in new free programs; and that you are informed that you can do
|
||||
these things.
|
||||
|
||||
To protect your rights, we need to make restrictions that forbid
|
||||
distributors to deny you these rights or to ask you to surrender these
|
||||
rights. These restrictions translate to certain responsibilities for
|
||||
you if you distribute copies of the library or if you modify it.
|
||||
|
||||
For example, if you distribute copies of the library, whether gratis
|
||||
or for a fee, you must give the recipients all the rights that we gave
|
||||
you. You must make sure that they, too, receive or can get the source
|
||||
code. If you link other code with the library, you must provide
|
||||
complete object files to the recipients, so that they can relink them
|
||||
with the library after making changes to the library and recompiling
|
||||
it. And you must show them these terms so they know their rights.
|
||||
|
||||
We protect your rights with a two-step method: (1) we copyright the
|
||||
library, and (2) we offer you this license, which gives you legal
|
||||
permission to copy, distribute and/or modify the library.
|
||||
|
||||
To protect each distributor, we want to make it very clear that
|
||||
there is no warranty for the free library. Also, if the library is
|
||||
modified by someone else and passed on, the recipients should know
|
||||
that what they have is not the original version, so that the original
|
||||
author's reputation will not be affected by problems that might be
|
||||
introduced by others.
|
||||
|
||||
Finally, software patents pose a constant threat to the existence of
|
||||
any free program. We wish to make sure that a company cannot
|
||||
effectively restrict the users of a free program by obtaining a
|
||||
restrictive license from a patent holder. Therefore, we insist that
|
||||
any patent license obtained for a version of the library must be
|
||||
consistent with the full freedom of use specified in this license.
|
||||
|
||||
Most GNU software, including some libraries, is covered by the
|
||||
ordinary GNU General Public License. This license, the GNU Lesser
|
||||
General Public License, applies to certain designated libraries, and
|
||||
is quite different from the ordinary General Public License. We use
|
||||
this license for certain libraries in order to permit linking those
|
||||
libraries into non-free programs.
|
||||
|
||||
When a program is linked with a library, whether statically or using
|
||||
a shared library, the combination of the two is legally speaking a
|
||||
combined work, a derivative of the original library. The ordinary
|
||||
General Public License therefore permits such linking only if the
|
||||
entire combination fits its criteria of freedom. The Lesser General
|
||||
Public License permits more lax criteria for linking other code with
|
||||
the library.
|
||||
|
||||
We call this license the "Lesser" General Public License because it
|
||||
does Less to protect the user's freedom than the ordinary General
|
||||
Public License. It also provides other free software developers Less
|
||||
of an advantage over competing non-free programs. These disadvantages
|
||||
are the reason we use the ordinary General Public License for many
|
||||
libraries. However, the Lesser license provides advantages in certain
|
||||
special circumstances.
|
||||
|
||||
For example, on rare occasions, there may be a special need to
|
||||
encourage the widest possible use of a certain library, so that it becomes
|
||||
a de-facto standard. To achieve this, non-free programs must be
|
||||
allowed to use the library. A more frequent case is that a free
|
||||
library does the same job as widely used non-free libraries. In this
|
||||
case, there is little to gain by limiting the free library to free
|
||||
software only, so we use the Lesser General Public License.
|
||||
|
||||
In other cases, permission to use a particular library in non-free
|
||||
programs enables a greater number of people to use a large body of
|
||||
free software. For example, permission to use the GNU C Library in
|
||||
non-free programs enables many more people to use the whole GNU
|
||||
operating system, as well as its variant, the GNU/Linux operating
|
||||
system.
|
||||
|
||||
Although the Lesser General Public License is Less protective of the
|
||||
users' freedom, it does ensure that the user of a program that is
|
||||
linked with the Library has the freedom and the wherewithal to run
|
||||
that program using a modified version of the Library.
|
||||
|
||||
The precise terms and conditions for copying, distribution and
|
||||
modification follow. Pay close attention to the difference between a
|
||||
"work based on the library" and a "work that uses the library". The
|
||||
former contains code derived from the library, whereas the latter must
|
||||
be combined with the library in order to run.
|
||||
|
||||
GNU LESSER GENERAL PUBLIC LICENSE
|
||||
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||
|
||||
0. This License Agreement applies to any software library or other
|
||||
program which contains a notice placed by the copyright holder or
|
||||
other authorized party saying it may be distributed under the terms of
|
||||
this Lesser General Public License (also called "this License").
|
||||
Each licensee is addressed as "you".
|
||||
|
||||
A "library" means a collection of software functions and/or data
|
||||
prepared so as to be conveniently linked with application programs
|
||||
(which use some of those functions and data) to form executables.
|
||||
|
||||
The "Library", below, refers to any such software library or work
|
||||
which has been distributed under these terms. A "work based on the
|
||||
Library" means either the Library or any derivative work under
|
||||
copyright law: that is to say, a work containing the Library or a
|
||||
portion of it, either verbatim or with modifications and/or translated
|
||||
straightforwardly into another language. (Hereinafter, translation is
|
||||
included without limitation in the term "modification".)
|
||||
|
||||
"Source code" for a work means the preferred form of the work for
|
||||
making modifications to it. For a library, complete source code means
|
||||
all the source code for all modules it contains, plus any associated
|
||||
interface definition files, plus the scripts used to control compilation
|
||||
and installation of the library.
|
||||
|
||||
Activities other than copying, distribution and modification are not
|
||||
covered by this License; they are outside its scope. The act of
|
||||
running a program using the Library is not restricted, and output from
|
||||
such a program is covered only if its contents constitute a work based
|
||||
on the Library (independent of the use of the Library in a tool for
|
||||
writing it). Whether that is true depends on what the Library does
|
||||
and what the program that uses the Library does.
|
||||
|
||||
1. You may copy and distribute verbatim copies of the Library's
|
||||
complete source code as you receive it, in any medium, provided that
|
||||
you conspicuously and appropriately publish on each copy an
|
||||
appropriate copyright notice and disclaimer of warranty; keep intact
|
||||
all the notices that refer to this License and to the absence of any
|
||||
warranty; and distribute a copy of this License along with the
|
||||
Library.
|
||||
|
||||
You may charge a fee for the physical act of transferring a copy,
|
||||
and you may at your option offer warranty protection in exchange for a
|
||||
fee.
|
||||
|
||||
2. You may modify your copy or copies of the Library or any portion
|
||||
of it, thus forming a work based on the Library, and copy and
|
||||
distribute such modifications or work under the terms of Section 1
|
||||
above, provided that you also meet all of these conditions:
|
||||
|
||||
a) The modified work must itself be a software library.
|
||||
|
||||
b) You must cause the files modified to carry prominent notices
|
||||
stating that you changed the files and the date of any change.
|
||||
|
||||
c) You must cause the whole of the work to be licensed at no
|
||||
charge to all third parties under the terms of this License.
|
||||
|
||||
d) If a facility in the modified Library refers to a function or a
|
||||
table of data to be supplied by an application program that uses
|
||||
the facility, other than as an argument passed when the facility
|
||||
is invoked, then you must make a good faith effort to ensure that,
|
||||
in the event an application does not supply such function or
|
||||
table, the facility still operates, and performs whatever part of
|
||||
its purpose remains meaningful.
|
||||
|
||||
(For example, a function in a library to compute square roots has
|
||||
a purpose that is entirely well-defined independent of the
|
||||
application. Therefore, Subsection 2d requires that any
|
||||
application-supplied function or table used by this function must
|
||||
be optional: if the application does not supply it, the square
|
||||
root function must still compute square roots.)
|
||||
|
||||
These requirements apply to the modified work as a whole. If
|
||||
identifiable sections of that work are not derived from the Library,
|
||||
and can be reasonably considered independent and separate works in
|
||||
themselves, then this License, and its terms, do not apply to those
|
||||
sections when you distribute them as separate works. But when you
|
||||
distribute the same sections as part of a whole which is a work based
|
||||
on the Library, the distribution of the whole must be on the terms of
|
||||
this License, whose permissions for other licensees extend to the
|
||||
entire whole, and thus to each and every part regardless of who wrote
|
||||
it.
|
||||
|
||||
Thus, it is not the intent of this section to claim rights or contest
|
||||
your rights to work written entirely by you; rather, the intent is to
|
||||
exercise the right to control the distribution of derivative or
|
||||
collective works based on the Library.
|
||||
|
||||
In addition, mere aggregation of another work not based on the Library
|
||||
with the Library (or with a work based on the Library) on a volume of
|
||||
a storage or distribution medium does not bring the other work under
|
||||
the scope of this License.
|
||||
|
||||
3. You may opt to apply the terms of the ordinary GNU General Public
|
||||
License instead of this License to a given copy of the Library. To do
|
||||
this, you must alter all the notices that refer to this License, so
|
||||
that they refer to the ordinary GNU General Public License, version 2,
|
||||
instead of to this License. (If a newer version than version 2 of the
|
||||
ordinary GNU General Public License has appeared, then you can specify
|
||||
that version instead if you wish.) Do not make any other change in
|
||||
these notices.
|
||||
|
||||
Once this change is made in a given copy, it is irreversible for
|
||||
that copy, so the ordinary GNU General Public License applies to all
|
||||
subsequent copies and derivative works made from that copy.
|
||||
|
||||
This option is useful when you wish to copy part of the code of
|
||||
the Library into a program that is not a library.
|
||||
|
||||
4. You may copy and distribute the Library (or a portion or
|
||||
derivative of it, under Section 2) in object code or executable form
|
||||
under the terms of Sections 1 and 2 above provided that you accompany
|
||||
it with the complete corresponding machine-readable source code, which
|
||||
must be distributed under the terms of Sections 1 and 2 above on a
|
||||
medium customarily used for software interchange.
|
||||
|
||||
If distribution of object code is made by offering access to copy
|
||||
from a designated place, then offering equivalent access to copy the
|
||||
source code from the same place satisfies the requirement to
|
||||
distribute the source code, even though third parties are not
|
||||
compelled to copy the source along with the object code.
|
||||
|
||||
5. A program that contains no derivative of any portion of the
|
||||
Library, but is designed to work with the Library by being compiled or
|
||||
linked with it, is called a "work that uses the Library". Such a
|
||||
work, in isolation, is not a derivative work of the Library, and
|
||||
therefore falls outside the scope of this License.
|
||||
|
||||
However, linking a "work that uses the Library" with the Library
|
||||
creates an executable that is a derivative of the Library (because it
|
||||
contains portions of the Library), rather than a "work that uses the
|
||||
library". The executable is therefore covered by this License.
|
||||
Section 6 states terms for distribution of such executables.
|
||||
|
||||
When a "work that uses the Library" uses material from a header file
|
||||
that is part of the Library, the object code for the work may be a
|
||||
derivative work of the Library even though the source code is not.
|
||||
Whether this is true is especially significant if the work can be
|
||||
linked without the Library, or if the work is itself a library. The
|
||||
threshold for this to be true is not precisely defined by law.
|
||||
|
||||
If such an object file uses only numerical parameters, data
|
||||
structure layouts and accessors, and small macros and small inline
|
||||
functions (ten lines or less in length), then the use of the object
|
||||
file is unrestricted, regardless of whether it is legally a derivative
|
||||
work. (Executables containing this object code plus portions of the
|
||||
Library will still fall under Section 6.)
|
||||
|
||||
Otherwise, if the work is a derivative of the Library, you may
|
||||
distribute the object code for the work under the terms of Section 6.
|
||||
Any executables containing that work also fall under Section 6,
|
||||
whether or not they are linked directly with the Library itself.
|
||||
|
||||
6. As an exception to the Sections above, you may also combine or
|
||||
link a "work that uses the Library" with the Library to produce a
|
||||
work containing portions of the Library, and distribute that work
|
||||
under terms of your choice, provided that the terms permit
|
||||
modification of the work for the customer's own use and reverse
|
||||
engineering for debugging such modifications.
|
||||
|
||||
You must give prominent notice with each copy of the work that the
|
||||
Library is used in it and that the Library and its use are covered by
|
||||
this License. You must supply a copy of this License. If the work
|
||||
during execution displays copyright notices, you must include the
|
||||
copyright notice for the Library among them, as well as a reference
|
||||
directing the user to the copy of this License. Also, you must do one
|
||||
of these things:
|
||||
|
||||
a) Accompany the work with the complete corresponding
|
||||
machine-readable source code for the Library including whatever
|
||||
changes were used in the work (which must be distributed under
|
||||
Sections 1 and 2 above); and, if the work is an executable linked
|
||||
with the Library, with the complete machine-readable "work that
|
||||
uses the Library", as object code and/or source code, so that the
|
||||
user can modify the Library and then relink to produce a modified
|
||||
executable containing the modified Library. (It is understood
|
||||
that the user who changes the contents of definitions files in the
|
||||
Library will not necessarily be able to recompile the application
|
||||
to use the modified definitions.)
|
||||
|
||||
b) Use a suitable shared library mechanism for linking with the
|
||||
Library. A suitable mechanism is one that (1) uses at run time a
|
||||
copy of the library already present on the user's computer system,
|
||||
rather than copying library functions into the executable, and (2)
|
||||
will operate properly with a modified version of the library, if
|
||||
the user installs one, as long as the modified version is
|
||||
interface-compatible with the version that the work was made with.
|
||||
|
||||
c) Accompany the work with a written offer, valid for at
|
||||
least three years, to give the same user the materials
|
||||
specified in Subsection 6a, above, for a charge no more
|
||||
than the cost of performing this distribution.
|
||||
|
||||
d) If distribution of the work is made by offering access to copy
|
||||
from a designated place, offer equivalent access to copy the above
|
||||
specified materials from the same place.
|
||||
|
||||
e) Verify that the user has already received a copy of these
|
||||
materials or that you have already sent this user a copy.
|
||||
|
||||
For an executable, the required form of the "work that uses the
|
||||
Library" must include any data and utility programs needed for
|
||||
reproducing the executable from it. However, as a special exception,
|
||||
the materials to be distributed need not include anything that is
|
||||
normally distributed (in either source or binary form) with the major
|
||||
components (compiler, kernel, and so on) of the operating system on
|
||||
which the executable runs, unless that component itself accompanies
|
||||
the executable.
|
||||
|
||||
It may happen that this requirement contradicts the license
|
||||
restrictions of other proprietary libraries that do not normally
|
||||
accompany the operating system. Such a contradiction means you cannot
|
||||
use both them and the Library together in an executable that you
|
||||
distribute.
|
||||
|
||||
7. You may place library facilities that are a work based on the
|
||||
Library side-by-side in a single library together with other library
|
||||
facilities not covered by this License, and distribute such a combined
|
||||
library, provided that the separate distribution of the work based on
|
||||
the Library and of the other library facilities is otherwise
|
||||
permitted, and provided that you do these two things:
|
||||
|
||||
a) Accompany the combined library with a copy of the same work
|
||||
based on the Library, uncombined with any other library
|
||||
facilities. This must be distributed under the terms of the
|
||||
Sections above.
|
||||
|
||||
b) Give prominent notice with the combined library of the fact
|
||||
that part of it is a work based on the Library, and explaining
|
||||
where to find the accompanying uncombined form of the same work.
|
||||
|
||||
8. You may not copy, modify, sublicense, link with, or distribute
|
||||
the Library except as expressly provided under this License. Any
|
||||
attempt otherwise to copy, modify, sublicense, link with, or
|
||||
distribute the Library is void, and will automatically terminate your
|
||||
rights under this License. However, parties who have received copies,
|
||||
or rights, from you under this License will not have their licenses
|
||||
terminated so long as such parties remain in full compliance.
|
||||
|
||||
9. You are not required to accept this License, since you have not
|
||||
signed it. However, nothing else grants you permission to modify or
|
||||
distribute the Library or its derivative works. These actions are
|
||||
prohibited by law if you do not accept this License. Therefore, by
|
||||
modifying or distributing the Library (or any work based on the
|
||||
Library), you indicate your acceptance of this License to do so, and
|
||||
all its terms and conditions for copying, distributing or modifying
|
||||
the Library or works based on it.
|
||||
|
||||
10. Each time you redistribute the Library (or any work based on the
|
||||
Library), the recipient automatically receives a license from the
|
||||
original licensor to copy, distribute, link with or modify the Library
|
||||
subject to these terms and conditions. You may not impose any further
|
||||
restrictions on the recipients' exercise of the rights granted herein.
|
||||
You are not responsible for enforcing compliance by third parties with
|
||||
this License.
|
||||
|
||||
11. If, as a consequence of a court judgment or allegation of patent
|
||||
infringement or for any other reason (not limited to patent issues),
|
||||
conditions are imposed on you (whether by court order, agreement or
|
||||
otherwise) that contradict the conditions of this License, they do not
|
||||
excuse you from the conditions of this License. If you cannot
|
||||
distribute so as to satisfy simultaneously your obligations under this
|
||||
License and any other pertinent obligations, then as a consequence you
|
||||
may not distribute the Library at all. For example, if a patent
|
||||
license would not permit royalty-free redistribution of the Library by
|
||||
all those who receive copies directly or indirectly through you, then
|
||||
the only way you could satisfy both it and this License would be to
|
||||
refrain entirely from distribution of the Library.
|
||||
|
||||
If any portion of this section is held invalid or unenforceable under any
|
||||
particular circumstance, the balance of the section is intended to apply,
|
||||
and the section as a whole is intended to apply in other circumstances.
|
||||
|
||||
It is not the purpose of this section to induce you to infringe any
|
||||
patents or other property right claims or to contest validity of any
|
||||
such claims; this section has the sole purpose of protecting the
|
||||
integrity of the free software distribution system which is
|
||||
implemented by public license practices. Many people have made
|
||||
generous contributions to the wide range of software distributed
|
||||
through that system in reliance on consistent application of that
|
||||
system; it is up to the author/donor to decide if he or she is willing
|
||||
to distribute software through any other system and a licensee cannot
|
||||
impose that choice.
|
||||
|
||||
This section is intended to make thoroughly clear what is believed to
|
||||
be a consequence of the rest of this License.
|
||||
|
||||
12. If the distribution and/or use of the Library is restricted in
|
||||
certain countries either by patents or by copyrighted interfaces, the
|
||||
original copyright holder who places the Library under this License may add
|
||||
an explicit geographical distribution limitation excluding those countries,
|
||||
so that distribution is permitted only in or among countries not thus
|
||||
excluded. In such case, this License incorporates the limitation as if
|
||||
written in the body of this License.
|
||||
|
||||
13. The Free Software Foundation may publish revised and/or new
|
||||
versions of the Lesser General Public License from time to time.
|
||||
Such new versions will be similar in spirit to the present version,
|
||||
but may differ in detail to address new problems or concerns.
|
||||
|
||||
Each version is given a distinguishing version number. If the Library
|
||||
specifies a version number of this License which applies to it and
|
||||
"any later version", you have the option of following the terms and
|
||||
conditions either of that version or of any later version published by
|
||||
the Free Software Foundation. If the Library does not specify a
|
||||
license version number, you may choose any version ever published by
|
||||
the Free Software Foundation.
|
||||
|
||||
14. If you wish to incorporate parts of the Library into other free
|
||||
programs whose distribution conditions are incompatible with these,
|
||||
write to the author to ask for permission. For software which is
|
||||
copyrighted by the Free Software Foundation, write to the Free
|
||||
Software Foundation; we sometimes make exceptions for this. Our
|
||||
decision will be guided by the two goals of preserving the free status
|
||||
of all derivatives of our free software and of promoting the sharing
|
||||
and reuse of software generally.
|
||||
|
||||
NO WARRANTY
|
||||
|
||||
15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
|
||||
WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
|
||||
EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
|
||||
OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
|
||||
KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
|
||||
LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
|
||||
THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
|
||||
|
||||
16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
|
||||
WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
|
||||
AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
|
||||
FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
|
||||
CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
|
||||
LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
|
||||
RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
|
||||
FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
|
||||
SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
|
||||
DAMAGES.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
How to Apply These Terms to Your New Libraries
|
||||
|
||||
If you develop a new library, and you want it to be of the greatest
|
||||
possible use to the public, we recommend making it free software that
|
||||
everyone can redistribute and change. You can do so by permitting
|
||||
redistribution under these terms (or, alternatively, under the terms of the
|
||||
ordinary General Public License).
|
||||
|
||||
To apply these terms, attach the following notices to the library. It is
|
||||
safest to attach them to the start of each source file to most effectively
|
||||
convey the exclusion of warranty; and each file should have at least the
|
||||
"copyright" line and a pointer to where the full notice is found.
|
||||
|
||||
<one line to give the library's name and a brief idea of what it does.>
|
||||
Copyright (C) <year> <name of author>
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
Also add information on how to contact you by electronic and paper mail.
|
||||
|
||||
You should also get your employer (if you work as a programmer) or your
|
||||
school, if any, to sign a "copyright disclaimer" for the library, if
|
||||
necessary. Here is a sample; alter the names:
|
||||
|
||||
Yoyodyne, Inc., hereby disclaims all copyright interest in the
|
||||
library `Frob' (a library for tweaking knobs) written by James Random Hacker.
|
||||
|
||||
<signature of Ty Coon>, 1 April 1990
|
||||
Ty Coon, President of Vice
|
||||
|
||||
That's all there is to it!
|
|
@ -1,4 +0,0 @@
|
|||
#! /usr/bin/env bash
|
||||
$EXTRACTRC `find . -name \*.rc -o -name \*.ui -o -name \*.kcfg` >> rc.cpp
|
||||
$XGETTEXT `find . -name \*.cpp -o -name \*.qml` -o $podir/plasma_applet_org.kde.homerun.pot
|
||||
rm -f rc.cpp
|
|
@ -1,87 +0,0 @@
|
|||
# Homerun
|
||||
|
||||
## What is it?
|
||||
|
||||
Homerun is a KDE application launcher and document opener.
|
||||
|
||||
It is a fullscreen launcher with content organized in tabs. A tab is made of
|
||||
several "sources". A source can provide one or more sections to a tab. Homerun
|
||||
comes with a few built-in sources, but custom sources can be written using
|
||||
libhomerun.
|
||||
|
||||
Homerun allows you to start applications, but also to browse hierarchies: for
|
||||
example clicking on an item of the "Favorite Places" section won't start
|
||||
Dolphin in this folder: it will list the folder content in Homerun itself,
|
||||
making it possible to explore the filesystem and directly open the file you are
|
||||
looking for. In this aspect it can be seen as an alternative to the Folder View
|
||||
applet.
|
||||
|
||||
Homerun can either be used from a launcher button in a panel, like Kickoff, or
|
||||
as a containment, like the Search and Launch containment.
|
||||
|
||||
## Dependencies
|
||||
|
||||
kdelibs 4.10
|
||||
|
||||
## Build instructions
|
||||
|
||||
Homerun currently requires kdelibs and kde-runtime 4.10.
|
||||
|
||||
To build it, do the following:
|
||||
|
||||
mkdir build
|
||||
cd build
|
||||
cmake -DCMAKE_INSTALL_PREFIX=`kde4-config --prefix` ..
|
||||
|
||||
Assuming cmake did not complain about missing dependencies, run:
|
||||
|
||||
make
|
||||
|
||||
Then to install it, run as root:
|
||||
|
||||
make install
|
||||
|
||||
## For packagers: Package manager integration
|
||||
|
||||
You can integrate your package manager with Homerun.
|
||||
|
||||
When browsing installed applications by category, Homerun can provide an item to
|
||||
install more applications from this category. To do so you need to:
|
||||
|
||||
First, create a .desktop file whose Exec= line contains a "@category" placeholder.
|
||||
This placeholder will be replaced by the category Homerun is browsing.
|
||||
|
||||
For example, here is muon-discover-category.desktop:
|
||||
|
||||
[Desktop Entry]
|
||||
Name=Install More...
|
||||
Exec=muon-discover --category @category
|
||||
Icon=muondiscover
|
||||
Type=Application
|
||||
NoDisplay=true
|
||||
|
||||
Then in "homerunrc", "PackageManagement" group, set the value of the
|
||||
"categoryInstaller" entry to the name of your .desktop file (without the
|
||||
.desktop extension)
|
||||
|
||||
## Creating your own sources
|
||||
|
||||
It is possible to create your own sources using libhomerun.
|
||||
|
||||
To learn more about libhomerun, run `make dox` to generate the API
|
||||
documentation. The generated documentation will be in "$BUILDDIR/lib/html".
|
||||
|
||||
You should also have a look at the code of the "helloworld" example source in
|
||||
"devdoc/helloworld".
|
||||
|
||||
## Getting involved
|
||||
|
||||
You can get in touch with us on IRC: #kde-homerun on Freenode.
|
||||
|
||||
You can report bugs on <https://bugs.kde.org>, product "homerun".
|
||||
|
||||
Clone the git repository with:
|
||||
|
||||
git clone git://anongit.kde.org/homerun
|
||||
|
||||
File review requests on <http://git.reviewboard.kde.org>, repository "homerun".
|
|
@ -1,79 +0,0 @@
|
|||
set(components_SRCS
|
||||
${PROJECT_SOURCE_DIR}/internal/aboutdata.cpp
|
||||
abstractsourceregistry.cpp
|
||||
action.cpp
|
||||
actionmanager.cpp
|
||||
componentsplugin.cpp
|
||||
globalsettings.cpp
|
||||
helpmenuactions.cpp
|
||||
icondialog.cpp
|
||||
image.cpp
|
||||
messagebox.cpp
|
||||
shadoweffect.cpp
|
||||
sourceconfigurationdialog.cpp
|
||||
sourcemodel.cpp
|
||||
sourceregistry.cpp
|
||||
sources/dir/dirconfigurationwidget.cpp
|
||||
sources/dir/dirmodel.cpp
|
||||
sources/favorites/favoriteappsmodel.cpp
|
||||
sources/favorites/favoriteplacesmodel.cpp
|
||||
sources/favorites/favoriteutils.cpp
|
||||
sources/favorites/fileplacesmodel.cpp
|
||||
sources/favorites/kfileplacesitem.cpp
|
||||
sources/favorites/kfileplacessharedbookmarks.cpp
|
||||
sources/installedapps/changenotifier.cpp
|
||||
sources/installedapps/filterableinstalledappsmodel.cpp
|
||||
sources/installedapps/groupedinstalledappsmodel.cpp
|
||||
sources/installedapps/installedappsconfigurationwidget.cpp
|
||||
sources/installedapps/installedappsmodel.cpp
|
||||
sources/power/powermodel.cpp
|
||||
sources/power/combinedpowersessionmodel.cpp
|
||||
sources/recentapps/recentappsmodel.cpp
|
||||
sources/runners/querymatchmodel.cpp
|
||||
sources/runners/singlerunnermodel.cpp
|
||||
sources/runners/runnerconfigurationwidget.cpp
|
||||
sources/runners/runnermodel.cpp
|
||||
sources/session/openedsessionsmodel.cpp
|
||||
sources/session/sessionmodel.cpp
|
||||
sources/session/sessionswatcher.cpp
|
||||
standarditemmodel.cpp
|
||||
tabmodel.cpp
|
||||
|
||||
sources/dir/dirconfigurationwidget.ui
|
||||
sources/installedapps/installedappsconfigurationwidget.ui
|
||||
sources/runners/runnerconfigurationwidget.ui
|
||||
)
|
||||
|
||||
include_directories(
|
||||
${lib_BINARY_DIR}
|
||||
${lib_SOURCE_DIR}
|
||||
${PROJECT_SOURCE_DIR}/internal
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/sources/dir
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/sources/favorites
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/sources/installedapps
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/sources/power
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/sources/recentapps
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/sources/runners
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/sources/session
|
||||
)
|
||||
|
||||
add_library(componentsplugin SHARED ${components_SRCS})
|
||||
|
||||
target_link_libraries(componentsplugin
|
||||
${QT_QTCORE_LIBRARY}
|
||||
${QT_QTDECLARATIVE_LIBRARY}
|
||||
${KDE4_PLASMA_LIBS}
|
||||
${KDE4_KIO_LIBS}
|
||||
${KDE4_KFILE_LIBS}
|
||||
${KDE4_SOLID_LIBS}
|
||||
kworkspace
|
||||
homerun
|
||||
)
|
||||
|
||||
install(TARGETS componentsplugin DESTINATION ${IMPORTS_INSTALL_DIR}/org/kde/homerun/components)
|
||||
install(DIRECTORY qml/
|
||||
DESTINATION ${IMPORTS_INSTALL_DIR}/org/kde/homerun/components
|
||||
PATTERN "*.qml"
|
||||
PATTERN "qmldir"
|
||||
PATTERN "*.js"
|
||||
)
|
|
@ -1,47 +0,0 @@
|
|||
/*
|
||||
Copyright 2012 Aurélien Gâteau <agateau@kde.org>
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) 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 6 of version 3 of the license.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
// Self
|
||||
#include <abstractsourceregistry.h>
|
||||
|
||||
// Local
|
||||
|
||||
// KDE
|
||||
|
||||
// Qt
|
||||
|
||||
namespace Homerun
|
||||
{
|
||||
|
||||
AbstractSourceRegistry::AbstractSourceRegistry(QObject *parent)
|
||||
: QObject(parent)
|
||||
{}
|
||||
|
||||
AbstractSourceRegistry::~AbstractSourceRegistry()
|
||||
{
|
||||
}
|
||||
|
||||
QObject *AbstractSourceRegistry::createModelFromConfigGroup(const QString &/*sourceId*/, const KConfigGroup &/*configGroup*/, QObject * /*parent*/)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
} // namespace Homerun
|
||||
|
||||
#include "moc_abstractsourceregistry.cpp"
|
|
@ -1,54 +0,0 @@
|
|||
/*
|
||||
Copyright 2012 Aurélien Gâteau <agateau@kde.org>
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) 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 6 of version 3 of the license.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#ifndef ABSTRACTSOURCEREGISTRY_H
|
||||
#define ABSTRACTSOURCEREGISTRY_H
|
||||
|
||||
// Local
|
||||
|
||||
// Qt
|
||||
#include <QObject>
|
||||
|
||||
// KDE
|
||||
|
||||
class KConfigGroup;
|
||||
|
||||
namespace Homerun
|
||||
{
|
||||
|
||||
/**
|
||||
* Defines the API of the SourceRegistry. Make it possible to mock the
|
||||
* SourceRegistry in unit-tests.
|
||||
*
|
||||
* Methods of this class cannot be pure virtual because AbstractSourceRegistry
|
||||
* needs to be declared as a QML component to be usable in TabModel.
|
||||
*/
|
||||
class AbstractSourceRegistry : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
AbstractSourceRegistry(QObject *parent = 0);
|
||||
~AbstractSourceRegistry();
|
||||
|
||||
virtual QObject *createModelFromConfigGroup(const QString &sourceId, const KConfigGroup &configGroup, QObject *parent);
|
||||
};
|
||||
|
||||
} // namespace Homerun
|
||||
|
||||
#endif /* ABSTRACTSOURCEREGISTRY_H */
|
|
@ -1,74 +0,0 @@
|
|||
/*
|
||||
Copyright 2013 Aurélien Gâteau <agateau@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/>.
|
||||
*/
|
||||
// Self
|
||||
#include <action.h>
|
||||
|
||||
// Local
|
||||
|
||||
// KDE
|
||||
#include <KDebug>
|
||||
|
||||
// Qt
|
||||
#include <QApplication>
|
||||
#include <QKeySequence>
|
||||
#include <QList>
|
||||
#include <QWidget>
|
||||
|
||||
Action::Action(QObject *parent)
|
||||
: KAction(parent)
|
||||
{
|
||||
connect(qApp, SIGNAL(focusChanged(QWidget*,QWidget*)), SLOT(finishInit()));
|
||||
finishInit();
|
||||
}
|
||||
|
||||
void Action::finishInit()
|
||||
{
|
||||
QWidget *widget = QApplication::activeWindow();
|
||||
if (!widget) {
|
||||
return;
|
||||
}
|
||||
widget->addAction(this);
|
||||
disconnect(qApp, SIGNAL(focusChanged(QWidget*,QWidget*)), this, SLOT(finishInit()));
|
||||
}
|
||||
|
||||
Action::~Action()
|
||||
{
|
||||
}
|
||||
|
||||
QStringList Action::keys() const
|
||||
{
|
||||
return m_keys;
|
||||
}
|
||||
|
||||
void Action::setKeys(const QStringList &list)
|
||||
{
|
||||
if (m_keys == list) {
|
||||
return;
|
||||
}
|
||||
QList<QKeySequence> sequenceList;
|
||||
Q_FOREACH(const QString &txt, list) {
|
||||
sequenceList.append(QKeySequence::fromString(txt));
|
||||
}
|
||||
setShortcuts(sequenceList);
|
||||
m_keys = list;
|
||||
keysChanged();
|
||||
}
|
||||
|
||||
#include "moc_action.cpp"
|
|
@ -1,69 +0,0 @@
|
|||
/*
|
||||
Copyright 2013 Aurélien Gâteau <agateau@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 ACTION_H
|
||||
#define ACTION_H
|
||||
|
||||
// Local
|
||||
|
||||
// Qt
|
||||
|
||||
// KDE
|
||||
#include <KAction>
|
||||
|
||||
/**
|
||||
* Thin QML wrapper around KAction
|
||||
*
|
||||
* To be used with ActionManager
|
||||
* Be sure to define the action objectName(), otherwise ActionManager
|
||||
* integration will fail!
|
||||
*/
|
||||
class Action : public KAction
|
||||
{
|
||||
Q_OBJECT
|
||||
/**
|
||||
* Define shortcut keys. Each element of the list is one shortcut.
|
||||
* Each element is a string using the same format as
|
||||
* QKeySequence::fromString()
|
||||
*
|
||||
* Examples:
|
||||
* - "Ctrl+PgUp"
|
||||
* - "Ctrl+PgDown"
|
||||
* - "Alt+S"
|
||||
* - "Ctrl+Alt+Left"
|
||||
*/
|
||||
Q_PROPERTY(QStringList keys READ keys WRITE setKeys NOTIFY keysChanged)
|
||||
public:
|
||||
explicit Action(QObject *parent = 0);
|
||||
~Action();
|
||||
|
||||
QStringList keys() const;
|
||||
void setKeys(const QStringList &keys);
|
||||
|
||||
Q_SIGNALS:
|
||||
void keysChanged();
|
||||
|
||||
private Q_SLOTS:
|
||||
void finishInit();
|
||||
|
||||
private:
|
||||
QStringList m_keys;
|
||||
};
|
||||
|
||||
#endif /* ACTION_H */
|
|
@ -1,104 +0,0 @@
|
|||
/*
|
||||
Copyright 2013 Aurélien Gâteau <agateau@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/>.
|
||||
*/
|
||||
// Self
|
||||
#include <actionmanager.h>
|
||||
|
||||
// Local
|
||||
|
||||
// KDE
|
||||
#include <KDebug>
|
||||
#include <KSharedConfig>
|
||||
#include <KShortcutsDialog>
|
||||
|
||||
// Qt
|
||||
#include <QApplication>
|
||||
#include <QTimer>
|
||||
|
||||
ActionManager::ActionManager(QObject *parent)
|
||||
: QObject(parent)
|
||||
, m_readSettingsTimer(new QTimer(this))
|
||||
, m_collection(new KActionCollection(this))
|
||||
, m_list(this, 0, append)
|
||||
{
|
||||
m_readSettingsTimer->setSingleShot(true);
|
||||
m_readSettingsTimer->setInterval(0);
|
||||
connect(m_readSettingsTimer, SIGNAL(timeout()),
|
||||
SLOT(readSettings()));
|
||||
}
|
||||
|
||||
ActionManager::~ActionManager()
|
||||
{
|
||||
}
|
||||
|
||||
QDeclarativeListProperty<Action> ActionManager::actions()
|
||||
{
|
||||
return m_list;
|
||||
}
|
||||
|
||||
void ActionManager::append(QDeclarativeListProperty<Action> *property, Action *action)
|
||||
{
|
||||
static_cast<ActionManager *>(property->object)->addAction(action);
|
||||
}
|
||||
|
||||
void ActionManager::addAction(Action *action)
|
||||
{
|
||||
if (action->objectName().isEmpty()) {
|
||||
kWarning() << "Cannot add action" << action << "to collection: action.objectName has not been defined";
|
||||
return;
|
||||
}
|
||||
m_collection->addAction(action->objectName(), action);
|
||||
m_readSettingsTimer->start();
|
||||
}
|
||||
|
||||
void ActionManager::configure()
|
||||
{
|
||||
KShortcutsDialog::configure(m_collection,
|
||||
KShortcutsEditor::LetterShortcutsAllowed,
|
||||
QApplication::activeWindow(),
|
||||
false /* bSaveSettings */);
|
||||
|
||||
m_collection->writeSettings(&m_configGroup);
|
||||
}
|
||||
|
||||
void ActionManager::readSettings()
|
||||
{
|
||||
if (!m_configGroup.isValid()) {
|
||||
return;
|
||||
}
|
||||
m_collection->readSettings(&m_configGroup);
|
||||
}
|
||||
|
||||
QString ActionManager::configFileName() const
|
||||
{
|
||||
return m_configFileName;
|
||||
}
|
||||
|
||||
void ActionManager::setConfigFileName(const QString &name)
|
||||
{
|
||||
if (m_configFileName == name) {
|
||||
return;
|
||||
}
|
||||
m_configFileName = name;
|
||||
m_configGroup = KSharedConfig::openConfig(m_configFileName)->group("Shortcuts");
|
||||
m_readSettingsTimer->start();
|
||||
emit configFileNameChanged();
|
||||
}
|
||||
|
||||
#include "moc_actionmanager.cpp"
|
|
@ -1,92 +0,0 @@
|
|||
/*
|
||||
Copyright 2013 Aurélien Gâteau <agateau@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 ACTIONMANAGER_H
|
||||
#define ACTIONMANAGER_H
|
||||
|
||||
// Local
|
||||
#include <action.h>
|
||||
|
||||
// Qt
|
||||
#include <QtDeclarative/qdeclarativelist.h>
|
||||
|
||||
// KDE
|
||||
#include <KActionCollection>
|
||||
#include <KConfigGroup>
|
||||
|
||||
class QTimer;
|
||||
|
||||
/**
|
||||
* Handles a list of Action items, make it possible to configure their shortcuts.
|
||||
*
|
||||
* Quite similar to KActionCollection, but does not directly expose a
|
||||
* KActionCollection.
|
||||
*
|
||||
* Usage:
|
||||
* ActionManager {
|
||||
* id: actionManager
|
||||
* configFileName: "myapprc"
|
||||
* Action {
|
||||
* ...
|
||||
* }
|
||||
* Action {
|
||||
* ...
|
||||
* }
|
||||
* ...
|
||||
* }
|
||||
*
|
||||
* To configure action shortcuts:
|
||||
*
|
||||
* actionManager.configure()
|
||||
*/
|
||||
class ActionManager : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_PROPERTY(QDeclarativeListProperty<Action> actions READ actions)
|
||||
Q_PROPERTY(QString configFileName READ configFileName WRITE setConfigFileName NOTIFY configFileNameChanged)
|
||||
Q_CLASSINFO("DefaultProperty", "actions")
|
||||
public:
|
||||
explicit ActionManager(QObject *parent = 0);
|
||||
~ActionManager();
|
||||
|
||||
QDeclarativeListProperty<Action> actions();
|
||||
|
||||
Q_INVOKABLE void configure();
|
||||
|
||||
QString configFileName() const;
|
||||
void setConfigFileName(const QString &name);
|
||||
|
||||
Q_SIGNALS:
|
||||
void configFileNameChanged();
|
||||
|
||||
private Q_SLOTS:
|
||||
void readSettings();
|
||||
|
||||
private:
|
||||
QTimer *m_readSettingsTimer;
|
||||
KActionCollection *m_collection;
|
||||
QDeclarativeListProperty<Action> m_list;
|
||||
QString m_configFileName;
|
||||
KConfigGroup m_configGroup;
|
||||
|
||||
void addAction(Action *action);
|
||||
static void append(QDeclarativeListProperty<Action> *property, Action *action);
|
||||
};
|
||||
|
||||
#endif /* ACTIONMANAGER_H */
|
|
@ -1,52 +0,0 @@
|
|||
/*
|
||||
* Copyright 2012 Shaun Reich <shaun.reich@blue-systems.com>
|
||||
* Copyright 2012 by Aurélien Gâteau <agateau@kde.org>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Library General Public License as
|
||||
* published by the Free Software Foundation; either version 2, 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 Library General Public License for more details
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this program; if not, write to the
|
||||
* Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#include "componentsplugin.h"
|
||||
|
||||
#include <QtDeclarative/qdeclarative.h>
|
||||
|
||||
#include <action.h>
|
||||
#include <actionmanager.h>
|
||||
#include <globalsettings.h>
|
||||
#include <helpmenuactions.h>
|
||||
#include <icondialog.h>
|
||||
#include <image.h>
|
||||
#include <messagebox.h>
|
||||
#include <shadoweffect.h>
|
||||
#include <sourceregistry.h>
|
||||
#include <tabmodel.h>
|
||||
|
||||
void ComponentsPlugin::registerTypes(const char *uri)
|
||||
{
|
||||
Q_ASSERT(uri == QLatin1String("org.kde.homerun.components"));
|
||||
qmlRegisterType<Action>(uri, 0, 1, "Action");
|
||||
qmlRegisterType<ActionManager>(uri, 0, 1, "ActionManager");
|
||||
qmlRegisterType<ShadowEffect>(uri, 0, 1, "ShadowEffect");
|
||||
qmlRegisterType<GlobalSettings>(uri, 0, 1, "GlobalSettings");
|
||||
qmlRegisterType<HelpMenuActions>(uri, 0, 1, "HelpMenuActions");
|
||||
qmlRegisterType<IconDialog>(uri, 0, 1, "IconDialog");
|
||||
qmlRegisterType<Image>(uri, 0, 1, "Image");
|
||||
qmlRegisterType<MessageBox>(uri, 0, 1, "MessageBox");
|
||||
qmlRegisterType<Homerun::AbstractSourceRegistry>(uri, 0, 1, "AbstractSourceRegistry");
|
||||
qmlRegisterType<Homerun::SourceRegistry>(uri, 0, 1, "SourceRegistry");
|
||||
qmlRegisterType<TabModel>(uri, 0, 1, "TabModel");
|
||||
}
|
||||
|
||||
#include "moc_componentsplugin.cpp"
|
|
@ -1,36 +0,0 @@
|
|||
/*
|
||||
* Copyright 2011 by Marco Martin <mart@kde.org>
|
||||
* Copyright 2011 by Aaron Seigo <aseigo@kde.org>
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Library General Public License as
|
||||
* published by the Free Software Foundation; either version 2, 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 Library General Public License for more details
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this program; if not, write to the
|
||||
* Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#ifndef COMPONENTSPLUGIN_H
|
||||
#define COMPONENTSPLUGIN_H
|
||||
|
||||
#include <QDeclarativeExtensionPlugin>
|
||||
|
||||
|
||||
class ComponentsPlugin : public QDeclarativeExtensionPlugin
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
void registerTypes(const char *uri);
|
||||
};
|
||||
|
||||
Q_EXPORT_PLUGIN2(componentsplugin, ComponentsPlugin)
|
||||
|
||||
#endif
|
|
@ -1,30 +0,0 @@
|
|||
/*
|
||||
Copyright 2012 Aurélien Gâteau <agateau@kde.org>
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) 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 6 of version 3 of the license.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#ifndef CUSTOMTYPES_H
|
||||
#define CUSTOMTYPES_H
|
||||
|
||||
// KDE
|
||||
#include <KConfigGroup>
|
||||
|
||||
// We use KConfigGroup* and not KConfigGroup because if using the later, one
|
||||
// gets an invalid group from the QVariant
|
||||
Q_DECLARE_METATYPE(KConfigGroup*)
|
||||
|
||||
#endif /* CUSTOMTYPES_H */
|
|
@ -1,97 +0,0 @@
|
|||
/*
|
||||
Copyright 2013 Eike Hein <hein@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/>.
|
||||
*/
|
||||
// Self
|
||||
#include <globalsettings.h>
|
||||
|
||||
// Local
|
||||
|
||||
// KDE
|
||||
#include <KConfigGroup>
|
||||
#include <KSharedConfig>
|
||||
|
||||
GlobalSettings::GlobalSettings(QObject *parent) : QObject(parent)
|
||||
{
|
||||
}
|
||||
|
||||
GlobalSettings::~GlobalSettings()
|
||||
{
|
||||
}
|
||||
|
||||
QString GlobalSettings::configFileName() const
|
||||
{
|
||||
return m_configFileName;
|
||||
}
|
||||
|
||||
void GlobalSettings::setConfigFileName(const QString &name)
|
||||
{
|
||||
if (m_configFileName == name) {
|
||||
return;
|
||||
}
|
||||
|
||||
m_configFileName = name;
|
||||
m_configGroup = KSharedConfig::openConfig(m_configFileName)->group("Global");
|
||||
emit configFileNameChanged();
|
||||
emit showActionListOverlayChanged();
|
||||
emit showDesktopToolBoxChanged();
|
||||
}
|
||||
|
||||
bool GlobalSettings::showActionListOverlay() const
|
||||
{
|
||||
if (!m_configGroup.isValid()) {
|
||||
return false;
|
||||
}
|
||||
return m_configGroup.readEntry<bool>("ShowActionListOverlay", false);
|
||||
}
|
||||
|
||||
void GlobalSettings::setShowActionListOverlay(bool show)
|
||||
{
|
||||
if (show == showActionListOverlay()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (m_configGroup.isValid()) {
|
||||
m_configGroup.writeEntry("ShowActionListOverlay", show);
|
||||
m_configGroup.sync();
|
||||
emit showActionListOverlayChanged();
|
||||
}
|
||||
}
|
||||
|
||||
bool GlobalSettings::showDesktopToolBox() const
|
||||
{
|
||||
if (!m_configGroup.isValid()) {
|
||||
return false;
|
||||
}
|
||||
return m_configGroup.readEntry<bool>("ShowDesktopToolBox", false);
|
||||
}
|
||||
|
||||
void GlobalSettings::setShowDesktopToolBox(bool show)
|
||||
{
|
||||
if (show == showDesktopToolBox()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (m_configGroup.isValid()) {
|
||||
m_configGroup.writeEntry("ShowDesktopToolBox", show);
|
||||
m_configGroup.sync();
|
||||
emit showDesktopToolBoxChanged();
|
||||
}
|
||||
}
|
||||
|
||||
#include "moc_globalsettings.cpp"
|
|
@ -1,58 +0,0 @@
|
|||
/*
|
||||
Copyright 2013 Eike Hein <hein@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 GLOBALSETTINGS_H
|
||||
#define GLOBALSETTINGS_H
|
||||
|
||||
// Qt
|
||||
#include <QObject>
|
||||
|
||||
// KDE
|
||||
#include <KConfigGroup>
|
||||
|
||||
class GlobalSettings : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_PROPERTY(QString configFileName READ configFileName WRITE setConfigFileName NOTIFY configFileNameChanged)
|
||||
Q_PROPERTY(bool showActionListOverlay READ showActionListOverlay WRITE setShowActionListOverlay NOTIFY showActionListOverlayChanged)
|
||||
Q_PROPERTY(bool showDesktopToolBox READ showDesktopToolBox WRITE setShowDesktopToolBox NOTIFY showDesktopToolBoxChanged)
|
||||
public:
|
||||
explicit GlobalSettings(QObject *parent = 0);
|
||||
~GlobalSettings();
|
||||
|
||||
QString configFileName() const;
|
||||
void setConfigFileName(const QString &name);
|
||||
|
||||
bool showActionListOverlay() const;
|
||||
void setShowActionListOverlay(bool show);
|
||||
|
||||
bool showDesktopToolBox() const;
|
||||
void setShowDesktopToolBox(bool show);
|
||||
|
||||
Q_SIGNALS:
|
||||
void configFileNameChanged();
|
||||
void showActionListOverlayChanged();
|
||||
void showDesktopToolBoxChanged();
|
||||
|
||||
private:
|
||||
QString m_configFileName;
|
||||
KConfigGroup m_configGroup;
|
||||
};
|
||||
|
||||
#endif /* GLOBALSETTINGS_H */
|
|
@ -1,73 +0,0 @@
|
|||
/*
|
||||
Copyright 2012 Aurélien Gâteau <agateau@kde.org>
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) 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 6 of version 3 of the license.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
// Self
|
||||
#include <helpmenuactions.h>
|
||||
|
||||
// Local
|
||||
|
||||
// KDE
|
||||
#include <KAboutData>
|
||||
|
||||
// Qt
|
||||
#include <QAction>
|
||||
#include <QApplication>
|
||||
|
||||
// Local
|
||||
#include <aboutdata.h>
|
||||
|
||||
HelpMenuActions::HelpMenuActions(QObject *parent)
|
||||
: QObject(parent)
|
||||
, m_menu(0)
|
||||
, m_aboutData(0)
|
||||
{
|
||||
}
|
||||
|
||||
HelpMenuActions::~HelpMenuActions()
|
||||
{
|
||||
delete m_menu;
|
||||
delete m_aboutData;
|
||||
}
|
||||
|
||||
QString HelpMenuActions::text(HelpMenuActions::ActionId actionId)
|
||||
{
|
||||
QAction *act = action(actionId);
|
||||
Q_ASSERT(act);
|
||||
return act->text();
|
||||
}
|
||||
|
||||
void HelpMenuActions::trigger(HelpMenuActions::ActionId actionId)
|
||||
{
|
||||
QAction *act = action(actionId);
|
||||
Q_ASSERT(act);
|
||||
act->trigger();
|
||||
}
|
||||
|
||||
QAction *HelpMenuActions::action(HelpMenuActions::ActionId actionId)
|
||||
{
|
||||
if (!m_menu) {
|
||||
m_aboutData = HomerunInternal::createAboutData();
|
||||
m_menu = new KHelpMenu(QApplication::activeWindow(), m_aboutData);
|
||||
// Call menu() to cause the actions to be created
|
||||
m_menu->menu();
|
||||
}
|
||||
return m_menu->action(static_cast<KHelpMenu::MenuId>(actionId));
|
||||
}
|
||||
|
||||
#include "moc_helpmenuactions.cpp"
|
|
@ -1,58 +0,0 @@
|
|||
/*
|
||||
Copyright 2012 Aurélien Gâteau <agateau@kde.org>
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) 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 6 of version 3 of the license.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#ifndef HELPMENUACTIONS_H
|
||||
#define HELPMENUACTIONS_H
|
||||
|
||||
// Local
|
||||
|
||||
// Qt
|
||||
|
||||
// KDE
|
||||
#include <KHelpMenu>
|
||||
|
||||
/**
|
||||
* Wrapper exposing KHelpMenu actions
|
||||
*/
|
||||
class HelpMenuActions : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_ENUMS(ActionId)
|
||||
public:
|
||||
explicit HelpMenuActions(QObject *parent = 0);
|
||||
~HelpMenuActions();
|
||||
|
||||
enum ActionId {
|
||||
AboutApplication = KHelpMenu::menuAboutApp,
|
||||
AboutKDE = KHelpMenu::menuAboutKDE,
|
||||
ReportBug = KHelpMenu::menuReportBug,
|
||||
SwitchLanguage = KHelpMenu::menuSwitchLanguage,
|
||||
};
|
||||
|
||||
Q_INVOKABLE QString text(ActionId);
|
||||
Q_INVOKABLE void trigger(ActionId);
|
||||
|
||||
private:
|
||||
KHelpMenu *m_menu;
|
||||
KAboutData *m_aboutData;
|
||||
|
||||
QAction *action(ActionId);
|
||||
};
|
||||
|
||||
#endif /* HELPMENUACTIONS_H */
|
|
@ -1,47 +0,0 @@
|
|||
/*
|
||||
Copyright 2012 Aurélien Gâteau <agateau@kde.org>
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) 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 6 of version 3 of the license.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
// Self
|
||||
#include <icondialog.h>
|
||||
|
||||
// Local
|
||||
|
||||
// KDE
|
||||
#include <KIconDialog>
|
||||
|
||||
// Qt
|
||||
#include <QApplication>
|
||||
|
||||
IconDialog::IconDialog(QObject *parent)
|
||||
: QObject(parent)
|
||||
{
|
||||
}
|
||||
|
||||
QString IconDialog::getIcon()
|
||||
{
|
||||
KIconDialog dialog(QApplication::activeWindow());
|
||||
dialog.setup(
|
||||
KIconLoader::Small /* group */,
|
||||
KIconLoader::Category /* context */,
|
||||
true /* strictIconSize */
|
||||
);
|
||||
return dialog.openDialog();
|
||||
}
|
||||
|
||||
#include "moc_icondialog.cpp"
|
|
@ -1,42 +0,0 @@
|
|||
/*
|
||||
Copyright 2012 Aurélien Gâteau <agateau@kde.org>
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) 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 6 of version 3 of the license.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#ifndef ICONDIALOG_H
|
||||
#define ICONDIALOG_H
|
||||
|
||||
// Local
|
||||
|
||||
// Qt
|
||||
#include <QObject>
|
||||
|
||||
// KDE
|
||||
|
||||
/**
|
||||
* A simplistic QML wrapper for KIconDialog
|
||||
*/
|
||||
class IconDialog : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit IconDialog(QObject *parent = 0);
|
||||
|
||||
Q_INVOKABLE QString getIcon();
|
||||
};
|
||||
|
||||
#endif /* ICONDIALOG_H */
|
|
@ -1,98 +0,0 @@
|
|||
/*
|
||||
Copyright 2013 Aurélien Gâteau <agateau@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/>.
|
||||
*/
|
||||
// Self
|
||||
#include <image.h>
|
||||
|
||||
// Local
|
||||
|
||||
// KDE
|
||||
#include <KDebug>
|
||||
#include <KIcon>
|
||||
|
||||
// Qt
|
||||
#include <QPainter>
|
||||
#include <QtGui/qstyleoption.h>
|
||||
|
||||
Image::Image(QDeclarativeItem *parent)
|
||||
: QDeclarativeItem(parent)
|
||||
{
|
||||
setFlag(QGraphicsItem::ItemHasNoContents, false);
|
||||
}
|
||||
|
||||
Image::~Image()
|
||||
{
|
||||
}
|
||||
|
||||
QVariant Image::source() const
|
||||
{
|
||||
return m_source;
|
||||
}
|
||||
|
||||
void Image::setSource(const QVariant &source)
|
||||
{
|
||||
if (source == m_source) {
|
||||
return;
|
||||
}
|
||||
m_source = source;
|
||||
reload();
|
||||
sourceChanged();
|
||||
}
|
||||
|
||||
void Image::reload()
|
||||
{
|
||||
const int extent = qMin(width(), height());
|
||||
if (m_source.canConvert<QString>()) {
|
||||
KIcon icon(m_source.toString());
|
||||
m_pixmap = icon.pixmap(extent);
|
||||
} else if (m_source.canConvert<QIcon>()) {
|
||||
QIcon icon = m_source.value<QIcon>();
|
||||
m_pixmap = icon.pixmap(extent);
|
||||
} else {
|
||||
if (m_source.isValid()) {
|
||||
kWarning() << "Don't know how to handle source" << m_source;
|
||||
}
|
||||
m_pixmap = QPixmap();
|
||||
}
|
||||
// Always update, even if we do not have valid content. If we had content
|
||||
// before, we need to erase it.
|
||||
update();
|
||||
}
|
||||
|
||||
void Image::geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry)
|
||||
{
|
||||
if (newGeometry.size() != oldGeometry.size()) {
|
||||
reload();
|
||||
}
|
||||
}
|
||||
|
||||
void Image::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *)
|
||||
{
|
||||
if (m_pixmap.isNull()) {
|
||||
return;
|
||||
}
|
||||
const QRect &rect = option->rect;
|
||||
painter->drawPixmap(
|
||||
rect.x() + (rect.width() - m_pixmap.width())/ 2,
|
||||
rect.y() + (rect.height() - m_pixmap.height()) / 2,
|
||||
m_pixmap);
|
||||
}
|
||||
|
||||
|
||||
#include "moc_image.cpp"
|
|
@ -1,61 +0,0 @@
|
|||
/*
|
||||
Copyright 2013 Aurélien Gâteau <agateau@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 IMAGE_H
|
||||
#define IMAGE_H
|
||||
|
||||
// Local
|
||||
|
||||
// Qt
|
||||
#include <QDeclarativeItem>
|
||||
|
||||
// KDE
|
||||
|
||||
/**
|
||||
* An item which shows images whose sources can be either the name of an icon
|
||||
* or a QIcon.
|
||||
*/
|
||||
class Image : public QDeclarativeItem
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
Q_PROPERTY(QVariant source READ source WRITE setSource NOTIFY sourceChanged)
|
||||
public:
|
||||
explicit Image(QDeclarativeItem *parent = 0);
|
||||
~Image();
|
||||
|
||||
QVariant source() const;
|
||||
void setSource(const QVariant &value);
|
||||
|
||||
void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) override;
|
||||
|
||||
Q_SIGNALS:
|
||||
void sourceChanged();
|
||||
|
||||
protected:
|
||||
void geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry) override;
|
||||
|
||||
private:
|
||||
QVariant m_source;
|
||||
QPixmap m_pixmap;
|
||||
|
||||
void reload();
|
||||
};
|
||||
|
||||
#endif /* IMAGE_H */
|
|
@ -1,45 +0,0 @@
|
|||
/*
|
||||
Copyright 2013 Aurélien Gâteau <agateau@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/>.
|
||||
*/
|
||||
// Self
|
||||
#include <messagebox.h>
|
||||
|
||||
// Local
|
||||
|
||||
// KDE
|
||||
|
||||
// Qt
|
||||
#include <QApplication>
|
||||
|
||||
MessageBox::MessageBox(QObject *parent)
|
||||
: QObject(parent)
|
||||
{
|
||||
}
|
||||
|
||||
int MessageBox::warningContinueCancel(const QString& text, const QString& caption, const QString& continueText, const QString& cancelText)
|
||||
{
|
||||
KGuiItem cont = continueText.isEmpty() ? KStandardGuiItem::cont() : KGuiItem(continueText);
|
||||
KGuiItem cancel = cancelText.isEmpty() ? KStandardGuiItem::cancel() : KGuiItem(cancelText);
|
||||
int ret = KMessageBox::warningContinueCancel(QApplication::activeWindow(),
|
||||
text, caption, cont, cancel);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
#include "moc_messagebox.cpp"
|
|
@ -1,60 +0,0 @@
|
|||
/*
|
||||
Copyright 2013 Aurélien Gâteau <agateau@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 MESSAGEBOX_H
|
||||
#define MESSAGEBOX_H
|
||||
|
||||
// Local
|
||||
|
||||
// Qt
|
||||
#include <QObject>
|
||||
|
||||
// KDE
|
||||
#include <KMessageBox>
|
||||
|
||||
/**
|
||||
* Wrapper around KMessageBox
|
||||
*/
|
||||
class MessageBox : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_ENUMS(ButtonCode)
|
||||
public:
|
||||
explicit MessageBox(QObject *parent = 0);
|
||||
|
||||
enum ButtonCode {
|
||||
Ok = KMessageBox::Ok,
|
||||
Cancel = KMessageBox::Cancel,
|
||||
Yes = KMessageBox::Yes,
|
||||
No = KMessageBox::No,
|
||||
Continue = KMessageBox::Continue,
|
||||
};
|
||||
|
||||
/**
|
||||
* Return value is a MessageBox::ButtonCode
|
||||
*/
|
||||
Q_INVOKABLE int warningContinueCancel(
|
||||
const QString &text,
|
||||
const QString &caption = QString(),
|
||||
const QString &continueText = QString(),
|
||||
const QString &cancelText = QString()
|
||||
);
|
||||
};
|
||||
|
||||
#endif /* MESSAGEBOX_H */
|
|
@ -1,103 +0,0 @@
|
|||
/*
|
||||
Copyright 2013 Aurélien Gâteau <agateau@kde.org>
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) 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 6 of version 3 of the license.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
import QtQuick 1.1
|
||||
|
||||
import org.kde.plasma.components 0.1 as PlasmaComponents
|
||||
|
||||
Item {
|
||||
id: main
|
||||
/// Public
|
||||
|
||||
/// type:list<map<string,variant>> list of actions
|
||||
property variant actionList
|
||||
|
||||
property Item visualParent
|
||||
|
||||
property bool opened: menu ? (menu.status != PlasmaComponents.DialogStatus.Closed) : false
|
||||
|
||||
signal actionClicked(string actionId, variant actionArgument)
|
||||
|
||||
function open(x, y) {
|
||||
if (x && y) {
|
||||
menu.open(x, y);
|
||||
} else {
|
||||
menu.open();
|
||||
}
|
||||
}
|
||||
|
||||
/// Internal
|
||||
property QtObject menu
|
||||
|
||||
Component {
|
||||
id: contextMenuComponent
|
||||
PlasmaComponents.ContextMenu {
|
||||
visualParent: main.visualParent
|
||||
}
|
||||
}
|
||||
|
||||
Component {
|
||||
id: contextMenuItemComponent
|
||||
|
||||
PlasmaComponents.MenuItem {
|
||||
property variant actionItem
|
||||
|
||||
text: actionItem.text ? actionItem.text : ""
|
||||
enabled: actionItem.type != "title" && ("enabled" in actionItem ? actionItem.enabled : true)
|
||||
separator: actionItem.type == "separator"
|
||||
icon: actionItem.icon ? actionItem.icon : null
|
||||
|
||||
onClicked: {
|
||||
actionClicked(actionItem.actionId, actionItem.actionArgument);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Component {
|
||||
id: emptyMenuItemComponent
|
||||
PlasmaComponents.MenuItem {
|
||||
text: i18n("(Empty)")
|
||||
enabled: false
|
||||
}
|
||||
}
|
||||
|
||||
// Code
|
||||
onActionListChanged: refreshMenu();
|
||||
|
||||
function refreshMenu() {
|
||||
if (menu) {
|
||||
menu.destroy();
|
||||
}
|
||||
|
||||
menu = contextMenuComponent.createObject(main);
|
||||
|
||||
if (!actionList || actionList.length == 0) {
|
||||
var item = emptyMenuItemComponent.createObject(menu);
|
||||
menu.addMenuItem(item);
|
||||
return;
|
||||
}
|
||||
|
||||
actionList.forEach(function(actionItem) {
|
||||
var item = contextMenuItemComponent.createObject(menu, {
|
||||
"actionItem": actionItem,
|
||||
});
|
||||
menu.addMenuItem(item);
|
||||
});
|
||||
}
|
||||
}
|
|
@ -1,170 +0,0 @@
|
|||
/*
|
||||
Copyright 2013 Aurélien Gâteau <agateau@kde.org>
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) 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 6 of version 3 of the license.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
import QtQuick 1.1
|
||||
|
||||
Item {
|
||||
id: main
|
||||
property Item dragContainer
|
||||
property Item draggedItem: parent
|
||||
property int itemIndex: -1
|
||||
|
||||
property alias hoverEnabled: mouseArea.hoverEnabled
|
||||
property bool dragEnabled: true
|
||||
|
||||
// Read only info
|
||||
property bool isHoldDown: mouseArea.holdX > -1
|
||||
property bool isDragged: dragContainer.draggedIndex != -1 && itemIndex == dragContainer.draggedIndex
|
||||
|
||||
property alias mouseX: mouseArea.mouseX
|
||||
property alias mouseY: mouseArea.mouseY
|
||||
property alias containsMouse: mouseArea.containsMouse
|
||||
|
||||
/**
|
||||
* type:Qt::MouseButtons accepted buttons
|
||||
*
|
||||
* MiddleButton is already used for dragging, so you can't react to middle button
|
||||
*/
|
||||
property int acceptedButtons
|
||||
|
||||
/**
|
||||
* @param type:MouseEvent mouse Mouse event for the click
|
||||
*/
|
||||
signal clicked(variant mouse)
|
||||
|
||||
signal longPressTimeReached()
|
||||
|
||||
/**
|
||||
* Emitted when user pressed the item for a long time and released it.
|
||||
* This is a good opportunity to show a context menu.
|
||||
*/
|
||||
signal longPressReleased()
|
||||
|
||||
// Internal
|
||||
property Item oldParent
|
||||
|
||||
MouseArea {
|
||||
id: mouseArea
|
||||
acceptedButtons: main.acceptedButtons | Qt.MiddleButton
|
||||
anchors.fill: parent
|
||||
|
||||
property real holdX: -1
|
||||
property real holdY: -1
|
||||
|
||||
onPressAndHold: {
|
||||
holdX = mouseX;
|
||||
holdY = mouseY;
|
||||
longPressTimeReached();
|
||||
}
|
||||
|
||||
onPressed: {
|
||||
if (main.dragEnabled && mouse.button == Qt.MiddleButton) {
|
||||
main.startDrag();
|
||||
mouse.accepted = true;
|
||||
}
|
||||
}
|
||||
|
||||
onPositionChanged: {
|
||||
function moved(a, b) {
|
||||
return Math.abs(a, b) > 16;
|
||||
}
|
||||
if (!main.dragEnabled) {
|
||||
if (isHoldDown) {
|
||||
resetHold();
|
||||
}
|
||||
return;
|
||||
}
|
||||
// We only reach this point when drag is enabled
|
||||
if (main.isHoldDown && (moved(mouseX, holdX) || moved(mouseY, holdY))) {
|
||||
resetHold();
|
||||
main.startDrag();
|
||||
return;
|
||||
}
|
||||
if (main.isDragged) {
|
||||
main.updateDrag();
|
||||
}
|
||||
}
|
||||
|
||||
onReleased: {
|
||||
if (main.isHoldDown) {
|
||||
resetHold();
|
||||
longPressReleased();
|
||||
return;
|
||||
}
|
||||
if (isDragged) {
|
||||
stopDrag();
|
||||
}
|
||||
}
|
||||
|
||||
onClicked: {
|
||||
main.clicked(mouse);
|
||||
}
|
||||
|
||||
function resetHold() {
|
||||
holdX = -1;
|
||||
holdY = -1;
|
||||
}
|
||||
}
|
||||
|
||||
function startDrag() {
|
||||
if (isDragged) {
|
||||
return;
|
||||
}
|
||||
dragContainer.draggedIndex = itemIndex;
|
||||
oldParent = draggedItem.parent;
|
||||
|
||||
// Move draggedItem to dragContainer, keeping its position unchanged
|
||||
var coord = dragContainer.mapFromItem(main, 0, 0);
|
||||
draggedItem.parent = dragContainer;
|
||||
draggedItem.x = coord.x;
|
||||
draggedItem.y = coord.y;
|
||||
|
||||
mouseArea.drag.target = draggedItem;
|
||||
}
|
||||
|
||||
function updateDrag() {
|
||||
var coord = dragContainer.mapFromItem(draggedItem, draggedItem.width / 2, draggedItem.height / 2);
|
||||
var newIndex = dragContainer.indexAt(coord.x, coord.y);
|
||||
|
||||
if (dragContainer.draggedIndex != -1 && newIndex != -1 && newIndex != dragContainer.draggedIndex) {
|
||||
if ("move" in dragContainer.model) {
|
||||
dragContainer.model.move(dragContainer.draggedIndex, newIndex, 1);
|
||||
} else if ("moveRow" in dragContainer.model) {
|
||||
dragContainer.model.moveRow(dragContainer.draggedIndex, newIndex);
|
||||
} else {
|
||||
console.log("DragArea.updateDrag(): ERROR: Don't know how to move rows for model " + dragContainer.model);
|
||||
stopDrag();
|
||||
return;
|
||||
}
|
||||
dragContainer.draggedIndex = newIndex;
|
||||
}
|
||||
}
|
||||
|
||||
function stopDrag() {
|
||||
dragContainer.draggedIndex = -1;
|
||||
|
||||
// Move draggedItem back to its old parent
|
||||
draggedItem.parent = oldParent;
|
||||
draggedItem.x = 0;
|
||||
draggedItem.y = 0;
|
||||
oldParent = null;
|
||||
|
||||
mouseArea.drag.target = null;
|
||||
}
|
||||
}
|
|
@ -1,30 +0,0 @@
|
|||
/*
|
||||
Copyright 2013 Aurélien Gâteau <agateau@kde.org>
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) 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 6 of version 3 of the license.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
import QtQuick 1.1
|
||||
|
||||
Item {
|
||||
property QtObject model
|
||||
|
||||
property int draggedIndex: -1
|
||||
|
||||
function indexAt(viewX, viewY) {
|
||||
return parent.indexAt(parent.contentX + viewX, parent.contentY + viewY);
|
||||
}
|
||||
}
|
|
@ -1,68 +0,0 @@
|
|||
/*
|
||||
Copyright 2013 Aurélien Gâteau <agateau@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/>.
|
||||
*/
|
||||
import QtQuick 1.1
|
||||
import org.kde.homerun.components 0.1 as HomerunComponents
|
||||
import org.kde.plasma.components 0.1 as PlasmaComponents
|
||||
|
||||
/**
|
||||
* A label which uses Plasma colors by default, but appears differently when
|
||||
* run as a containment: it shows a shadow behind itself and both shadow and
|
||||
* text colors can be customized.
|
||||
*/
|
||||
PlasmaComponents.Label {
|
||||
id: main
|
||||
|
||||
Component {
|
||||
id: shadowComponent
|
||||
HomerunComponents.ShadowEffect {
|
||||
xOffset: 0
|
||||
yOffset: 1
|
||||
blurRadius: 2
|
||||
}
|
||||
}
|
||||
|
||||
Component.onCompleted: {
|
||||
var isContainment = "plasmoid" in this;
|
||||
if (isContainment) {
|
||||
readConfig();
|
||||
plasmoid.addEventListener("ConfigChanged", readConfig);
|
||||
} else {
|
||||
main.color = theme.textColor;
|
||||
}
|
||||
}
|
||||
|
||||
function readConfig() {
|
||||
main.color = plasmoid.readConfig("textColor");
|
||||
if (plasmoid.readConfig("shadowModeNone") == true) {
|
||||
if (main.effect) {
|
||||
main.effect.destroy();
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (!main.effect) {
|
||||
main.effect = shadowComponent.createObject(main);
|
||||
}
|
||||
if (plasmoid.readConfig("shadowModeCustom") == true) {
|
||||
main.effect.color = plasmoid.readConfig("shadowColor");
|
||||
} else {
|
||||
main.effect.resetColor();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,120 +0,0 @@
|
|||
/*
|
||||
* Copyright 2012 Aurélien Gâteau <agateau@kde.org>
|
||||
*
|
||||
* Based on TabBar.qml from KDE Plasma Components.
|
||||
*
|
||||
*- Start of KDE Plasma Components TabBar.qml copyright header ---------
|
||||
*
|
||||
* Copyright 2011 Marco Martin <mart@kde.org>
|
||||
*
|
||||
* Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
|
||||
* All rights reserved.
|
||||
* Contact: Nokia Corporation (qt-info@nokia.com)
|
||||
*
|
||||
* This file is part of the Qt Components project.
|
||||
*
|
||||
* $QT_BEGIN_LICENSE:BSD$
|
||||
* You may use this file under the terms of the BSD license as follows:
|
||||
*
|
||||
* "Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met:
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor
|
||||
* the names of its contributors may be used to endorse or promote
|
||||
* products derived from this software without specific prior written
|
||||
* permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
|
||||
*
|
||||
*- End of KDE Plasma Components TabBar.qml copyright header ------------
|
||||
*/
|
||||
|
||||
import QtQuick 1.1
|
||||
import org.kde.plasma.core 0.1 as PlasmaCore
|
||||
import org.kde.plasma.components 0.1
|
||||
|
||||
Item {
|
||||
id: root
|
||||
|
||||
height: frame.margins.top
|
||||
+ buttonFrame.margins.top
|
||||
+ theme.smallIconSize
|
||||
+ buttonFrame.margins.bottom
|
||||
+ frame.margins.bottom
|
||||
|
||||
property alias model: listView.model
|
||||
property alias delegate: listView.delegate
|
||||
property alias currentIndex: listView.currentIndex
|
||||
property alias currentItem: listView.currentItem
|
||||
property alias count: listView.count
|
||||
|
||||
function incrementCurrentIndex() {
|
||||
listView.incrementCurrentIndex();
|
||||
}
|
||||
|
||||
function decrementCurrentIndex() {
|
||||
listView.decrementCurrentIndex();
|
||||
}
|
||||
|
||||
property alias buttonFrame: listView.buttonFrame
|
||||
|
||||
PlasmaCore.FrameSvgItem {
|
||||
id: frame
|
||||
|
||||
anchors.fill: parent
|
||||
imagePath: "widgets/frame"
|
||||
prefix: "sunken"
|
||||
|
||||
ListView {
|
||||
id: listView
|
||||
|
||||
// Hack: make it possible for other elements to know the margins
|
||||
// of the highlight item before it is created
|
||||
property Item buttonFrame: PlasmaCore.FrameSvgItem {
|
||||
imagePath: "widgets/button"
|
||||
prefix: "normal"
|
||||
visible: false
|
||||
}
|
||||
|
||||
anchors {
|
||||
left: parent.left
|
||||
top: parent.top
|
||||
right: parent.right
|
||||
bottom: parent.bottom
|
||||
leftMargin: frame.margins.left
|
||||
topMargin: frame.margins.top
|
||||
rightMargin: frame.margins.right
|
||||
bottomMargin: frame.margins.bottom
|
||||
}
|
||||
|
||||
orientation: ListView.Horizontal
|
||||
|
||||
highlightMoveDuration: 250
|
||||
highlightResizeDuration: 250
|
||||
|
||||
highlight: PlasmaCore.FrameSvgItem {
|
||||
imagePath: "widgets/button"
|
||||
prefix: "normal"
|
||||
height: parent ? parent.height : 0
|
||||
}
|
||||
|
||||
currentIndex: 0
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,199 +0,0 @@
|
|||
/*
|
||||
* Copyright 2012 Aurélien Gâteau <agateau@kde.org>
|
||||
*
|
||||
* Based on TabBar.qml from KDE Plasma Components.
|
||||
*
|
||||
*- Start of KDE Plasma Components TabBar.qml copyright header ---------
|
||||
*
|
||||
* Copyright 2011 Marco Martin <mart@kde.org>
|
||||
*
|
||||
* Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
|
||||
* All rights reserved.
|
||||
* Contact: Nokia Corporation (qt-info@nokia.com)
|
||||
*
|
||||
* This file is part of the Qt Components project.
|
||||
*
|
||||
* $QT_BEGIN_LICENSE:BSD$
|
||||
* You may use this file under the terms of the BSD license as follows:
|
||||
*
|
||||
* "Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met:
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor
|
||||
* the names of its contributors may be used to endorse or promote
|
||||
* products derived from this software without specific prior written
|
||||
* permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
|
||||
* $QT_END_LICENSE$
|
||||
*
|
||||
*- End of KDE Plasma Components TabBar.qml copyright header ------------
|
||||
*/
|
||||
|
||||
/**Documented API
|
||||
Inherits:
|
||||
Item
|
||||
|
||||
Imports:
|
||||
QtQuick 1.1
|
||||
AppManager.js
|
||||
|
||||
Description:
|
||||
A simple tab button which is using the plasma theme.
|
||||
|
||||
Properties:
|
||||
Item tab:
|
||||
The reference to the tab content (one of the children of a TabGroup,
|
||||
usually a Page) that is activated when this TabButton is clicked.
|
||||
|
||||
bool checked:
|
||||
True if the button is checked,otherwise false.
|
||||
|
||||
bool pressed:
|
||||
True if the button is being pressed,otherwise false.
|
||||
|
||||
string text:
|
||||
Sets the text for the button.
|
||||
|
||||
string iconSource:
|
||||
Icon for the button. It can be a Freedesktop icon name, a full path to a ong/svg file,
|
||||
or any name for which the application has an image handler registered.
|
||||
|
||||
Signals:
|
||||
onClicked:
|
||||
The signal is emmited when the button is clicked.
|
||||
**/
|
||||
|
||||
import QtQuick 1.1
|
||||
import org.kde.plasma.components 0.1 as PlasmaComponents
|
||||
import "private" as Private
|
||||
|
||||
Item {
|
||||
id: root
|
||||
|
||||
// Common Public API
|
||||
property Item tab
|
||||
property int index
|
||||
|
||||
property bool pressed: mouseArea.pressed == true && mouseArea.containsMouse
|
||||
property alias text: label.text
|
||||
property alias iconSource: imageLoader.source
|
||||
|
||||
property alias rightSide: rightSideItems.data
|
||||
|
||||
property int iconSpacing: 4
|
||||
|
||||
property int topMargin: ListView.view.buttonFrame.margins.top
|
||||
property int bottomMargin: ListView.view.buttonFrame.margins.bottom
|
||||
property int leftMargin: ListView.view.buttonFrame.margins.left
|
||||
property int rightMargin: ListView.view.buttonFrame.margins.right
|
||||
|
||||
width: ListView.view.width / ListView.view.count
|
||||
|
||||
implicitWidth: label.implicitWidth + (iconSource != null ? imageLoader.implicitWidth + iconSpacing : 0)
|
||||
implicitHeight: (iconSource === null
|
||||
? label.implicitHeight
|
||||
: Math.max(label.implicitHeight, imageLoader.implicitHeight)
|
||||
) + topMargin + bottomMargin
|
||||
|
||||
opacity: enabled ? 1 : 0.6
|
||||
|
||||
Private.IconLoader {
|
||||
id: imageLoader
|
||||
|
||||
implicitWidth: theme.smallIconSize
|
||||
implicitHeight: implicitWidth
|
||||
|
||||
anchors {
|
||||
left: parent.left
|
||||
leftMargin: leftMargin
|
||||
verticalCenter: parent.verticalCenter
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
HACK: We use a HomerunComponents.Label for the normal text and
|
||||
a PlasmaComponents.Label for the current text.
|
||||
|
||||
This is necessary for containment mode:
|
||||
It makes it possible to have custom color + shadow for normal text (to
|
||||
ensure it remains readable) and buttonTextColor + no-shadow for button text
|
||||
(because it is drawn on top of a button frame)
|
||||
*/
|
||||
Label {
|
||||
id: label
|
||||
|
||||
objectName: "label"
|
||||
|
||||
anchors {
|
||||
top: parent.top
|
||||
left: iconSource == null ? parent.left : imageLoader.right
|
||||
leftMargin: iconSource == null ? leftMargin : iconSpacing
|
||||
right: rightSideItems.left
|
||||
bottom: parent.bottom
|
||||
}
|
||||
|
||||
elide: Text.ElideRight
|
||||
horizontalAlignment: Text.AlignLeft
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
|
||||
color: theme.textColor
|
||||
opacity: root.ListView.isCurrentItem ? 0 : 1
|
||||
Behavior on opacity { NumberAnimation { duration: 250 }}
|
||||
}
|
||||
|
||||
PlasmaComponents.Label {
|
||||
id: currentLabel
|
||||
text: label.text
|
||||
|
||||
anchors.fill: label
|
||||
|
||||
elide: label.elide
|
||||
horizontalAlignment: label.horizontalAlignment
|
||||
verticalAlignment: label.verticalAlignment
|
||||
|
||||
color: theme.buttonTextColor
|
||||
opacity: root.ListView.isCurrentItem ? 1 : 0
|
||||
Behavior on opacity { NumberAnimation { duration: 250 }}
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
id: mouseArea
|
||||
|
||||
onClicked: {
|
||||
root.ListView.view.currentIndex = root.index;
|
||||
}
|
||||
|
||||
anchors {
|
||||
top: parent.top
|
||||
left: parent.left
|
||||
right: label.right
|
||||
bottom: parent.bottom
|
||||
}
|
||||
}
|
||||
|
||||
Row {
|
||||
id: rightSideItems
|
||||
anchors {
|
||||
top: parent.top
|
||||
right: parent.right
|
||||
bottom: parent.bottom
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,274 +0,0 @@
|
|||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
|
||||
** All rights reserved.
|
||||
** Contact: Nokia Corporation (qt-info@nokia.com)
|
||||
**
|
||||
** This file is part of the Qt Components project.
|
||||
**
|
||||
** $QT_BEGIN_LICENSE:BSD$
|
||||
** You may use this file under the terms of the BSD license as follows:
|
||||
**
|
||||
** "Redistribution and use in source and binary forms, with or without
|
||||
** modification, are permitted provided that the following conditions are
|
||||
** met:
|
||||
** * Redistributions of source code must retain the above copyright
|
||||
** notice, this list of conditions and the following disclaimer.
|
||||
** * Redistributions in binary form must reproduce the above copyright
|
||||
** notice, this list of conditions and the following disclaimer in
|
||||
** the documentation and/or other materials provided with the
|
||||
** distribution.
|
||||
** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor
|
||||
** the names of its contributors may be used to endorse or promote
|
||||
** products derived from this software without specific prior written
|
||||
** permission.
|
||||
**
|
||||
** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
|
||||
** $QT_END_LICENSE$
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
/**Documented API
|
||||
Inherits:
|
||||
Item
|
||||
|
||||
Imports:
|
||||
QtQuick 1.1
|
||||
|
||||
Description:
|
||||
Provides a set of pages for a tab-based interface.
|
||||
A tabbed interface is made up of tab buttons plus content for each button. A TabGroup component has, as its children, each page of content in the interface. These pages can be any QML items but are typically Page components for a single page of content or PageStack components when a hierarchical navigation system is required for the tab content.
|
||||
If you use Page components for your tab content, the status property of each page is updated appropriately when the current tab is changed: the current page has status PageStatus.Active and other pages have the status PageStatus.Inactive. During page transitions, PageStatus.Activating (for the page that is becoming the current page) and PageStatus.Deactivating (for the page that was the current page) statuses are also set.
|
||||
|
||||
Properties:
|
||||
Item currentTab:
|
||||
The tab that is currently active and visible to the user.
|
||||
The currentTab property is initialized to null and is automatically set to point to the first tab when content is added. You can set the currentTab at any time to activate a particular tab.
|
||||
|
||||
**/
|
||||
|
||||
import QtQuick 1.1
|
||||
import "private/TabGroup.js" as Engine
|
||||
|
||||
import "." 0.1
|
||||
|
||||
Item {
|
||||
id: root
|
||||
property Item currentTab
|
||||
|
||||
property list<Item> privateContents
|
||||
// Qt defect: cannot have list as default property
|
||||
default property alias privateContentsDefault: root.privateContents
|
||||
|
||||
onChildrenChanged: {
|
||||
// [0] is containerHost
|
||||
if (children.length > 1)
|
||||
Engine.addTab(children[1])
|
||||
}
|
||||
|
||||
onPrivateContentsChanged: {
|
||||
Engine.ensureContainers()
|
||||
}
|
||||
|
||||
Component.onCompleted: {
|
||||
// Set first tabs as current if currentTab is not set by application
|
||||
if (currentTab == null && containerHost.children[0] && containerHost.children[0].children[0])
|
||||
currentTab = containerHost.children[0].children[0]
|
||||
priv.complete = true;
|
||||
}
|
||||
|
||||
Item {
|
||||
id: containerHost
|
||||
objectName: "containerHost"
|
||||
anchors.fill: parent
|
||||
}
|
||||
|
||||
Component {
|
||||
id: tabContainerComponent
|
||||
Item {
|
||||
id: tabContainerItem
|
||||
|
||||
onChildrenChanged: {
|
||||
if (children.length == 0)
|
||||
Engine.removeContainer(tabContainerItem)
|
||||
|
||||
else if (children.length == 1) {
|
||||
children[0].width = width
|
||||
children[0].height = height
|
||||
// tab content created. set the first tab as current (if not set before, and if
|
||||
// child is added after TabGroup has completed)
|
||||
if (priv.complete && root.currentTab == null)
|
||||
root.currentTab = children[0]
|
||||
}
|
||||
}
|
||||
|
||||
onWidthChanged: {
|
||||
if (children.length > 0)
|
||||
children[0].width = width
|
||||
}
|
||||
|
||||
onHeightChanged: {
|
||||
if (children.length > 0)
|
||||
children[0].height = height
|
||||
}
|
||||
|
||||
Component.onDestruction: {
|
||||
if (typeof(root) != "undefined" && !root.currentTab) {
|
||||
// selected one deleted. try to activate the neighbour
|
||||
var removedIndex = -1
|
||||
for (var i = 0; i < containerHost.children.length; i++) {
|
||||
if (containerHost.children[i] == tabContainerItem) {
|
||||
removedIndex = i
|
||||
break
|
||||
}
|
||||
}
|
||||
var newIndex = -1
|
||||
if (removedIndex != -1) {
|
||||
if (removedIndex != containerHost.children.length - 1)
|
||||
newIndex = removedIndex + 1
|
||||
else if (removedIndex != 0)
|
||||
newIndex = removedIndex - 1
|
||||
}
|
||||
|
||||
if (newIndex != -1)
|
||||
root.currentTab = containerHost.children[newIndex].children[0]
|
||||
else
|
||||
root.currentTab = null
|
||||
}
|
||||
}
|
||||
|
||||
function incomingDone() {
|
||||
state = ""
|
||||
if (priv.incomingPage) {
|
||||
if (priv.incomingPage.status != undefined) {
|
||||
priv.incomingPage.status = PageStatus.Active
|
||||
}
|
||||
priv.incomingPage = null
|
||||
}
|
||||
}
|
||||
|
||||
function outgoingDone() {
|
||||
if (priv.outgoingPage) {
|
||||
if (priv.outgoingPage.status != undefined) {
|
||||
priv.outgoingPage.status = PageStatus.Active
|
||||
}
|
||||
priv.outgoingPage.visible = false
|
||||
priv.outgoingPage = null
|
||||
}
|
||||
state = "HiddenLeft"
|
||||
}
|
||||
|
||||
width: parent ? parent.width : 0
|
||||
height: parent ? parent.height : 0
|
||||
state: "HiddenLeft"
|
||||
|
||||
states: [
|
||||
State { name: ""; PropertyChanges { target: tabContainerItem; opacity: 1.0; x: 0 } },
|
||||
State { name: "Incoming"; PropertyChanges { target: tabContainerItem; opacity: 1.0; x: 0 } },
|
||||
|
||||
State {
|
||||
name: "OutgoingLeft"
|
||||
PropertyChanges {
|
||||
target: tabContainerItem
|
||||
opacity: 0.0
|
||||
x: -root.width
|
||||
}
|
||||
},
|
||||
State {
|
||||
name: "OutgoingRight"
|
||||
PropertyChanges {
|
||||
target: tabContainerItem
|
||||
opacity: 0.0
|
||||
x: root.width
|
||||
}
|
||||
},
|
||||
|
||||
State { name: "HiddenLeft"; PropertyChanges { target: tabContainerItem; opacity: 0.0; x: root.width } },
|
||||
State { name: "HiddenRight"; PropertyChanges { target: tabContainerItem; opacity: 0.0; x: -root.width } }
|
||||
]
|
||||
|
||||
transitions: [
|
||||
Transition {
|
||||
to: "Incoming"
|
||||
SequentialAnimation {
|
||||
ScriptAction { script: root.clip = true }
|
||||
PropertyAnimation { properties: "opacity,x"; easing.type: Easing.InQuad; duration: 250 }
|
||||
ScriptAction { script: {incomingDone(); root.clip = false} }
|
||||
}
|
||||
},
|
||||
Transition {
|
||||
to: "OutgoingLeft,OutgoingRight"
|
||||
SequentialAnimation {
|
||||
PropertyAnimation { properties: "opacity,x"; easing.type: Easing.InQuad; duration: 250 }
|
||||
ScriptAction { script: outgoingDone() }
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
QtObject {
|
||||
id: priv
|
||||
property bool reparenting: false
|
||||
property bool complete: false
|
||||
property Item currentTabContainer: root.currentTab ? root.currentTab.parent : null
|
||||
property int currentIndex: 0
|
||||
property Item incomingPage
|
||||
property Item outgoingPage
|
||||
property bool animate: true
|
||||
|
||||
onCurrentTabContainerChanged: {
|
||||
var newCurrentIndex = 0
|
||||
for (var i = 0; i < containerHost.children.length; i++) {
|
||||
if (containerHost.children[i] == currentTabContainer) {
|
||||
newCurrentIndex = i
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
currentTabContainer.visible = true
|
||||
incomingPage = currentTabContainer.children[0]
|
||||
incomingPage.visible = true
|
||||
if (incomingPage.status != undefined) {
|
||||
incomingPage.status = PageStatus.Activating
|
||||
}
|
||||
if (currentIndex < newCurrentIndex) {
|
||||
currentTabContainer.state = "HiddenLeft"
|
||||
} else {
|
||||
currentTabContainer.state = "HiddenRight"
|
||||
}
|
||||
if (animate) {
|
||||
currentTabContainer.state = "Incoming"
|
||||
} else {
|
||||
currentTabContainer.incomingDone()
|
||||
}
|
||||
|
||||
if (newCurrentIndex == currentIndex) {
|
||||
return
|
||||
}
|
||||
|
||||
var oldPage = containerHost.children[currentIndex]
|
||||
outgoingPage = oldPage.children[0]
|
||||
if (animate) {
|
||||
if (currentIndex < newCurrentIndex) {
|
||||
oldPage.state = "OutgoingLeft"
|
||||
} else {
|
||||
oldPage.state = "OutgoingRight"
|
||||
}
|
||||
} else {
|
||||
oldPage.outgoingDone()
|
||||
}
|
||||
currentIndex = newCurrentIndex
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,140 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2011 by Marco MArtin <mart@kde.org>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Library General Public License as
|
||||
* published by the Free Software Foundation; either version 2, 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 Library General Public License for more details
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this program; if not, write to the
|
||||
* Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
/**Documented API
|
||||
Inherits:
|
||||
Item
|
||||
|
||||
Imports:
|
||||
QtQuick 1.1
|
||||
org.kde.plasma.core
|
||||
org.kde.qtextracomponents
|
||||
|
||||
Description:
|
||||
TODO i need more info here
|
||||
|
||||
Properties:
|
||||
bool valid:
|
||||
Returns if the icon is valid or not.
|
||||
|
||||
string source:
|
||||
Returns the dir,in which the icon exists.
|
||||
**/
|
||||
|
||||
import QtQuick 1.1
|
||||
import org.kde.plasma.core 0.1 as PlasmaCore
|
||||
import org.kde.qtextracomponents 0.1
|
||||
|
||||
Item {
|
||||
id: root
|
||||
|
||||
property bool valid: false
|
||||
|
||||
property variant source
|
||||
|
||||
onSourceChanged: {
|
||||
//is it a qicon?
|
||||
if (typeof source != "string") {
|
||||
imageLoader.sourceComponent = iconComponent
|
||||
valid = true
|
||||
return
|
||||
} else if (source == "") {
|
||||
imageLoader.sourceComponent = null
|
||||
valid = false
|
||||
return
|
||||
}
|
||||
|
||||
svgIcon.imagePath = "toolbar-icons/"+root.source.split("-")[0]
|
||||
if (!svgIcon.isValid() || !svgIcon.hasElement(root.source)) {
|
||||
svgIcon.imagePath = "icons/"+root.source.split("-")[0]
|
||||
}
|
||||
|
||||
if (svgIcon.isValid() && svgIcon.hasElement(root.source)) {
|
||||
imageLoader.sourceComponent = svgComponent
|
||||
} else if ((root.source.indexOf(".") == -1 && root.source.indexOf(":") == -1)) {
|
||||
imageLoader.sourceComponent = iconComponent
|
||||
} else {
|
||||
imageLoader.sourceComponent = imageComponent
|
||||
}
|
||||
valid = true
|
||||
}
|
||||
|
||||
implicitWidth: theme.smallIconSize
|
||||
implicitHeight: theme.smallIconSize
|
||||
|
||||
PlasmaCore.Svg {
|
||||
id: svgIcon
|
||||
}
|
||||
|
||||
function roundToStandardSize(size)
|
||||
{
|
||||
if (size >= theme.enormousIconSize) {
|
||||
return theme.enormousIconSize
|
||||
} else if (size >= theme.hugeIconSize) {
|
||||
return theme.hugeIconSize
|
||||
} else if (size >= theme.largeIconSize) {
|
||||
return theme.largeIconSize
|
||||
} else if (size >= theme.mediumIconSize) {
|
||||
return theme.mediumIconSize
|
||||
} else if (size >= theme.smallMediumIconSize) {
|
||||
return theme.smallMediumIconSize
|
||||
} else {
|
||||
return theme.smallIconSize
|
||||
}
|
||||
}
|
||||
|
||||
Loader {
|
||||
id: imageLoader
|
||||
anchors.fill: parent
|
||||
|
||||
Component {
|
||||
id: svgComponent
|
||||
|
||||
PlasmaCore.SvgItem {
|
||||
svg: svgIcon
|
||||
elementId: root.source
|
||||
anchors.fill: parent
|
||||
smooth: true
|
||||
}
|
||||
}
|
||||
|
||||
Component {
|
||||
id: iconComponent
|
||||
|
||||
QIconItem {
|
||||
icon: (typeof source == "string") ? QIcon(root.source) : root.source
|
||||
smooth: true
|
||||
anchors.fill: parent
|
||||
}
|
||||
}
|
||||
|
||||
Component {
|
||||
id: imageComponent
|
||||
|
||||
Image {
|
||||
source: root.source
|
||||
sourceSize.width: width
|
||||
sourceSize.height: height
|
||||
fillMode: Image.PreserveAspectFit
|
||||
smooth: true
|
||||
anchors.fill: parent
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,114 +0,0 @@
|
|||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
|
||||
** All rights reserved.
|
||||
** Contact: Nokia Corporation (qt-info@nokia.com)
|
||||
**
|
||||
** This file is part of the Qt Components project.
|
||||
**
|
||||
** $QT_BEGIN_LICENSE:BSD$
|
||||
** You may use this file under the terms of the BSD license as follows:
|
||||
**
|
||||
** "Redistribution and use in source and binary forms, with or without
|
||||
** modification, are permitted provided that the following conditions are
|
||||
** met:
|
||||
** * Redistributions of source code must retain the above copyright
|
||||
** notice, this list of conditions and the following disclaimer.
|
||||
** * Redistributions in binary form must reproduce the above copyright
|
||||
** notice, this list of conditions and the following disclaimer in
|
||||
** the documentation and/or other materials provided with the
|
||||
** distribution.
|
||||
** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor
|
||||
** the names of its contributors may be used to endorse or promote
|
||||
** products derived from this software without specific prior written
|
||||
** permission.
|
||||
**
|
||||
** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
|
||||
** $QT_END_LICENSE$
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
var allContainers = []
|
||||
var allContents = []
|
||||
|
||||
function hasContainer(content) {
|
||||
for (var i = 0; i < allContainers.length; ++i) {
|
||||
if (allContainers[i].children[0] == content)
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
function addContent(content) {
|
||||
for (var i = 0; i < allContents.length; ++i) {
|
||||
if (allContents[i] == content)
|
||||
return false
|
||||
}
|
||||
allContents.push(content)
|
||||
return true
|
||||
}
|
||||
|
||||
function ensureContainers() {
|
||||
var somethingChanged = false
|
||||
|
||||
// check if we need to create a container
|
||||
for (var i = 0; i < root.privateContents.length; ++i) {
|
||||
var content = root.privateContents[i]
|
||||
addContent(content)
|
||||
if (!hasContainer(content)) {
|
||||
var newContainer = tabContainerComponent.createObject(containerHost)
|
||||
content.parent = newContainer
|
||||
allContainers.push(newContainer)
|
||||
somethingChanged = true
|
||||
}
|
||||
}
|
||||
return somethingChanged
|
||||
}
|
||||
|
||||
function addTab(content) {
|
||||
if (addContent(content)) {
|
||||
var newContainer = tabContainerComponent.createObject(containerHost)
|
||||
content.parent = newContainer
|
||||
allContainers.push(newContainer)
|
||||
}
|
||||
}
|
||||
|
||||
function removeTab(content) {
|
||||
var foundIndex = -1
|
||||
for (var i = 0; i < allContents.length && foundIndex == -1; ++i) {
|
||||
if (allContents[i] == content)
|
||||
foundIndex = i
|
||||
}
|
||||
|
||||
if (foundIndex != -1)
|
||||
allContents.splice(foundIndex, 1)
|
||||
|
||||
if (hasContainer(content))
|
||||
content.parent = null // this causes deletion of container
|
||||
}
|
||||
|
||||
function removeContainer(container) {
|
||||
var foundIndex = -1
|
||||
for (var i = 0; i < allContainers.length && foundIndex == -1; ++i) {
|
||||
if (allContainers[i] == container)
|
||||
foundIndex = i
|
||||
}
|
||||
|
||||
if (foundIndex != -1) {
|
||||
var deletedContainer = allContainers[foundIndex]
|
||||
if (deletedContainer.children.length > 0)
|
||||
removeTab(deletedContainer.children[0])
|
||||
allContainers.splice(foundIndex, 1)
|
||||
deletedContainer.destroy()
|
||||
}
|
||||
}
|
|
@ -1,9 +0,0 @@
|
|||
plugin componentsplugin
|
||||
|
||||
ActionMenu 0.1 ActionMenu.qml
|
||||
DragArea 0.1 DragArea.qml
|
||||
DragContainer 0.1 DragContainer.qml
|
||||
TabBar 0.1 TabBar.qml
|
||||
TabButton 0.1 TabButton.qml
|
||||
TabGroup 0.1 TabGroup.qml
|
||||
Label 0.1 Label.qml
|
|
@ -1,240 +0,0 @@
|
|||
/*
|
||||
* Copyright 2013 Aurélien Gâteau <agateau@kde.org>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Library General Public License as
|
||||
* published by the Free Software Foundation; either version 2, 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 Library General Public License for more details
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this program; if not, write to the
|
||||
* Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
// Self
|
||||
#include <shadoweffect.h>
|
||||
|
||||
// Local
|
||||
|
||||
// KDE
|
||||
#include <KDebug>
|
||||
#include <Plasma/PaintUtils>
|
||||
|
||||
// Qt
|
||||
#include <QPainter>
|
||||
#include <QPaintEngine>
|
||||
|
||||
ShadowEffect::ShadowEffect(QObject *parent)
|
||||
: QGraphicsEffect(parent)
|
||||
, m_xOffset(0)
|
||||
, m_yOffset(1)
|
||||
, m_blurRadius(3)
|
||||
{
|
||||
}
|
||||
|
||||
ShadowEffect::~ShadowEffect()
|
||||
{
|
||||
}
|
||||
|
||||
qreal ShadowEffect::xOffset() const
|
||||
{
|
||||
return m_xOffset;
|
||||
}
|
||||
|
||||
qreal ShadowEffect::yOffset() const
|
||||
{
|
||||
return m_yOffset;
|
||||
}
|
||||
|
||||
qreal ShadowEffect::blurRadius() const
|
||||
{
|
||||
return m_blurRadius;
|
||||
}
|
||||
|
||||
QColor ShadowEffect::color() const
|
||||
{
|
||||
return m_color;
|
||||
}
|
||||
|
||||
void ShadowEffect::setXOffset(qreal value)
|
||||
{
|
||||
if (qFuzzyCompare(m_xOffset, value)) {
|
||||
return;
|
||||
}
|
||||
m_xOffset = value;
|
||||
m_shadow = QImage();
|
||||
updateBoundingRect();
|
||||
xOffsetChanged(m_xOffset);
|
||||
}
|
||||
|
||||
void ShadowEffect::setYOffset(qreal value)
|
||||
{
|
||||
if (qFuzzyCompare(m_yOffset, value)) {
|
||||
return;
|
||||
}
|
||||
m_yOffset = value;
|
||||
m_shadow = QImage();
|
||||
updateBoundingRect();
|
||||
yOffsetChanged(m_yOffset);
|
||||
}
|
||||
|
||||
void ShadowEffect::setBlurRadius(qreal value)
|
||||
{
|
||||
if (qFuzzyCompare(m_blurRadius, value)) {
|
||||
return;
|
||||
}
|
||||
m_blurRadius = value;
|
||||
m_shadow = QImage();
|
||||
updateBoundingRect();
|
||||
blurRadiusChanged(m_blurRadius);
|
||||
}
|
||||
|
||||
void ShadowEffect::setColor(const QColor &value)
|
||||
{
|
||||
if (m_color == value) {
|
||||
return;
|
||||
}
|
||||
m_color = value;
|
||||
m_shadow = QImage();
|
||||
update();
|
||||
colorChanged(m_color);
|
||||
}
|
||||
|
||||
void ShadowEffect::resetColor()
|
||||
{
|
||||
setColor(QColor());
|
||||
}
|
||||
|
||||
QRectF ShadowEffect::boundingRectFor(const QRectF &rect) const
|
||||
{
|
||||
qreal padding = m_blurRadius * 2;
|
||||
return rect.united(
|
||||
rect.translated(m_xOffset, m_yOffset)
|
||||
.adjusted(-padding, -padding, padding, padding)
|
||||
);
|
||||
}
|
||||
|
||||
QImage ShadowEffect::generateShadow(const QPixmap &px) const
|
||||
{
|
||||
if (px.isNull()) {
|
||||
return QImage();
|
||||
}
|
||||
|
||||
QColor color = m_color.isValid() ? m_color : computeColorFromSource();
|
||||
|
||||
QImage tmp(px.size(), QImage::Format_ARGB32_Premultiplied);
|
||||
tmp.fill(0);
|
||||
if (m_blurRadius > 0) {
|
||||
QPainter painter(&tmp);
|
||||
painter.setCompositionMode(QPainter::CompositionMode_Source);
|
||||
painter.drawPixmap(m_xOffset, m_yOffset, px);
|
||||
painter.end();
|
||||
Plasma::PaintUtils::shadowBlur(tmp, m_blurRadius, color);
|
||||
} else {
|
||||
QPainter painter(&tmp);
|
||||
painter.setCompositionMode(QPainter::CompositionMode_Source);
|
||||
painter.fillRect(m_xOffset, m_yOffset, px.width(), px.height(), color);
|
||||
painter.setCompositionMode(QPainter::CompositionMode_DestinationIn);
|
||||
painter.drawPixmap(m_xOffset, m_yOffset, px);
|
||||
}
|
||||
return tmp;
|
||||
}
|
||||
|
||||
void ShadowEffect::draw(QPainter *painter)
|
||||
{
|
||||
if (m_blurRadius < 0 && qFuzzyIsNull(m_xOffset) && qFuzzyIsNull(m_yOffset)) {
|
||||
drawSource(painter);
|
||||
return;
|
||||
}
|
||||
|
||||
PixmapPadMode mode = PadToEffectiveBoundingRect;
|
||||
if (painter->paintEngine()->type() == QPaintEngine::OpenGL2) {
|
||||
mode = NoPad;
|
||||
}
|
||||
|
||||
// Draw pixmap in device coordinates to avoid pixmap scaling.
|
||||
QPoint offset;
|
||||
const QPixmap pixmap = sourcePixmap(Qt::DeviceCoordinates, &offset, mode);
|
||||
if (pixmap.isNull()) {
|
||||
return;
|
||||
}
|
||||
|
||||
QTransform restoreTransform = painter->worldTransform();
|
||||
painter->setWorldTransform(QTransform());
|
||||
if (m_shadow.isNull()) {
|
||||
m_shadow = generateShadow(pixmap);
|
||||
}
|
||||
// Draw shadow (draw it twice to darken it)
|
||||
painter->drawImage(offset, m_shadow);
|
||||
painter->drawImage(offset, m_shadow);
|
||||
// Draw the actual pixmap
|
||||
painter->drawPixmap(offset, pixmap);
|
||||
painter->setWorldTransform(restoreTransform);
|
||||
}
|
||||
|
||||
void ShadowEffect::sourceChanged(ChangeFlags flags)
|
||||
{
|
||||
switch (flags) {
|
||||
case SourceAttached:
|
||||
case SourceBoundingRectChanged:
|
||||
case SourceInvalidated:
|
||||
m_shadow = QImage();
|
||||
break;
|
||||
case SourceDetached:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*****************************************************************************
|
||||
* UGLYNESS
|
||||
*
|
||||
* If the shadow color is not defined, we want to compute it from the color of
|
||||
* the item on which the effect is applied.
|
||||
*
|
||||
* To do so we need to reach the item from the effect.
|
||||
*
|
||||
* QGraphicsEffect has an internal, but public, "source()" method, which
|
||||
* returns a pointer to a QGraphicsEffectSource, which has a "graphicsItem()"
|
||||
* public method.
|
||||
*
|
||||
* QGraphicsEffectSource is not in any installed header, so we need to declare
|
||||
* it. Since "graphicsItem()" is not virtual we can escape with declaring a
|
||||
* fake QGraphicsEffectSource class, containing only the graphicsItem() method.
|
||||
*
|
||||
* The original class is defined in Qt4 in src/gui/effects/qgraphicseffect_p.h
|
||||
*****************************************************************************/
|
||||
class QGraphicsEffectSource
|
||||
{
|
||||
public:
|
||||
const QGraphicsItem *graphicsItem() const;
|
||||
};
|
||||
|
||||
|
||||
QColor ShadowEffect::computeColorFromSource() const
|
||||
{
|
||||
const QGraphicsItem *item = source()->graphicsItem();
|
||||
if (!item) {
|
||||
kWarning() << "No source item!";
|
||||
return Qt::black;
|
||||
}
|
||||
const QGraphicsObject *obj = item->toGraphicsObject();
|
||||
if (!obj) {
|
||||
kWarning() << "Source is not a QGraphicsObject";
|
||||
return Qt::black;
|
||||
}
|
||||
QVariant variant = obj->property("color");
|
||||
if (!variant.canConvert<QColor>()) {
|
||||
kWarning() << "Source has no 'color' property, or its 'color' property is not a QColor!";
|
||||
return Qt::black;
|
||||
}
|
||||
int value = variant.value<QColor>().value();
|
||||
return value >= 128 ? Qt::black : Qt::white;
|
||||
}
|
||||
|
||||
#include "moc_shadoweffect.cpp"
|
|
@ -1,88 +0,0 @@
|
|||
/*
|
||||
* Copyright 2013 Aurélien Gâteau <agateau@kde.org>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Library General Public License as
|
||||
* published by the Free Software Foundation; either version 2, 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 Library General Public License for more details
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this program; if not, write to the
|
||||
* Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
#ifndef SHADOWEFFECT_H
|
||||
#define SHADOWEFFECT_H
|
||||
|
||||
// Qt
|
||||
#include <QGraphicsEffect>
|
||||
|
||||
/**
|
||||
* An effect which draws a shadow behind an item, using
|
||||
* Plasma::PaintUtils::shadowBlur()
|
||||
*
|
||||
* If the color is not specified, it will attempt to compute the best
|
||||
* appropriate color, based on the item "color" property (if it has any).
|
||||
*/
|
||||
class ShadowEffect : public QGraphicsEffect
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_PROPERTY(qreal xOffset READ xOffset WRITE setXOffset NOTIFY xOffsetChanged)
|
||||
Q_PROPERTY(qreal yOffset READ yOffset WRITE setYOffset NOTIFY yOffsetChanged)
|
||||
Q_PROPERTY(qreal blurRadius READ blurRadius WRITE setBlurRadius NOTIFY blurRadiusChanged)
|
||||
Q_PROPERTY(QColor color READ color WRITE setColor NOTIFY colorChanged)
|
||||
public:
|
||||
explicit ShadowEffect(QObject *parent = 0);
|
||||
~ShadowEffect();
|
||||
|
||||
QRectF boundingRectFor(const QRectF &rect) const; // reimp
|
||||
|
||||
qreal xOffset() const;
|
||||
|
||||
qreal yOffset() const;
|
||||
|
||||
qreal blurRadius() const;
|
||||
QColor color() const;
|
||||
|
||||
/**
|
||||
* Use this method if you set the color manually and now want ShadowEffect
|
||||
* to pick the color automatically, based on the color of the item on which
|
||||
* the effect is applied.
|
||||
*/
|
||||
Q_INVOKABLE void resetColor();
|
||||
|
||||
public Q_SLOTS:
|
||||
void setXOffset(qreal dx);
|
||||
void setYOffset(qreal dy);
|
||||
void setBlurRadius(qreal blurRadius);
|
||||
void setColor(const QColor &color);
|
||||
|
||||
Q_SIGNALS:
|
||||
void xOffsetChanged(qreal);
|
||||
void yOffsetChanged(qreal);
|
||||
void blurRadiusChanged(qreal blurRadius);
|
||||
void colorChanged(const QColor &color);
|
||||
|
||||
protected:
|
||||
void draw(QPainter *painter); // reimp
|
||||
void sourceChanged(ChangeFlags flags); // reimp
|
||||
|
||||
private:
|
||||
qreal m_xOffset;
|
||||
qreal m_yOffset;
|
||||
qreal m_blurRadius;
|
||||
QColor m_color;
|
||||
|
||||
QImage m_shadow;
|
||||
|
||||
QImage generateShadow(const QPixmap &px) const;
|
||||
|
||||
QColor computeColorFromSource() const;
|
||||
};
|
||||
|
||||
#endif /* SHADOWEFFECT_H */
|
|
@ -1,53 +0,0 @@
|
|||
/*
|
||||
Copyright 2012 Aurélien Gâteau <agateau@kde.org>
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) 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 6 of version 3 of the license.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
// Self
|
||||
#include <sourceconfigurationdialog.h>
|
||||
|
||||
// Local
|
||||
#include <abstractsource.h>
|
||||
#include <sourceconfigurationwidget.h>
|
||||
|
||||
// KDE
|
||||
|
||||
// Qt
|
||||
|
||||
namespace Homerun
|
||||
{
|
||||
|
||||
SourceConfigurationDialog::SourceConfigurationDialog(AbstractSource *source, const KConfigGroup &group, QWidget *parent)
|
||||
: KDialog(parent)
|
||||
, m_sourceWidget(source->createConfigurationWidget(group))
|
||||
{
|
||||
setMainWidget(m_sourceWidget);
|
||||
}
|
||||
|
||||
SourceConfigurationDialog::~SourceConfigurationDialog()
|
||||
{
|
||||
}
|
||||
|
||||
void SourceConfigurationDialog::save()
|
||||
{
|
||||
m_sourceWidget->save();
|
||||
m_sourceWidget->configGroup().sync();
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
#include "moc_sourceconfigurationdialog.cpp"
|
|
@ -1,56 +0,0 @@
|
|||
/*
|
||||
Copyright 2012 Aurélien Gâteau <agateau@kde.org>
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) 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 6 of version 3 of the license.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#ifndef SOURCECONFIGURATIONDIALOG_H
|
||||
#define SOURCECONFIGURATIONDIALOG_H
|
||||
|
||||
// Local
|
||||
|
||||
// Qt
|
||||
|
||||
// KDE
|
||||
#include <KDialog>
|
||||
|
||||
class KConfigGroup;
|
||||
|
||||
namespace Homerun
|
||||
{
|
||||
|
||||
class AbstractSource;
|
||||
class SourceConfigurationWidget;
|
||||
|
||||
/**
|
||||
* A dialog to configure a source
|
||||
*/
|
||||
class SourceConfigurationDialog : public KDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit SourceConfigurationDialog(AbstractSource *source, const KConfigGroup &group, QWidget *parent);
|
||||
~SourceConfigurationDialog();
|
||||
|
||||
Q_INVOKABLE void save();
|
||||
|
||||
private:
|
||||
SourceConfigurationWidget *m_sourceWidget;
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
#endif /* SOURCECONFIGURATIONDIALOG_H */
|
|
@ -1,215 +0,0 @@
|
|||
/*
|
||||
Copyright 2012 Aurélien Gâteau <agateau@kde.org>
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) 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 6 of version 3 of the license.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
// Self
|
||||
#include <sourcemodel.h>
|
||||
|
||||
// Local
|
||||
#include <abstractsourceregistry.h>
|
||||
#include <customtypes.h>
|
||||
|
||||
// KDE
|
||||
#include <KDebug>
|
||||
|
||||
// Qt
|
||||
|
||||
using namespace Homerun;
|
||||
|
||||
static const char *TAB_SOURCES_KEY = "sources";
|
||||
|
||||
static const char *SOURCE_GROUP_PREFIX = "Source";
|
||||
static const char *SOURCE_SOURCEID_KEY = "sourceId";
|
||||
|
||||
class SourceModelItem
|
||||
{
|
||||
public:
|
||||
SourceModelItem(AbstractSourceRegistry *registry, const QString &sourceId, const KConfigGroup &group, QObject *parent)
|
||||
: m_sourceId(sourceId)
|
||||
, m_group(group)
|
||||
, m_sourceRegistry(registry)
|
||||
, m_model(0)
|
||||
, m_parent(parent)
|
||||
{}
|
||||
|
||||
QObject *model() const
|
||||
{
|
||||
if (!m_model) {
|
||||
m_model = m_sourceRegistry->createModelFromConfigGroup(m_sourceId, m_group, m_parent);
|
||||
}
|
||||
return m_model;
|
||||
}
|
||||
|
||||
void deleteModel()
|
||||
{
|
||||
delete m_model;
|
||||
m_model = 0;
|
||||
}
|
||||
|
||||
QString m_sourceId;
|
||||
KConfigGroup m_group;
|
||||
|
||||
private:
|
||||
AbstractSourceRegistry *m_sourceRegistry;
|
||||
mutable QObject *m_model;
|
||||
QObject *m_parent;
|
||||
};
|
||||
|
||||
|
||||
SourceModel::SourceModel(AbstractSourceRegistry *registry, const KConfigGroup &tabGroup, QObject *parent)
|
||||
: QAbstractListModel(parent)
|
||||
, m_sourceRegistry(registry)
|
||||
, m_tabGroup(tabGroup)
|
||||
{
|
||||
Q_ASSERT(registry);
|
||||
QHash<int, QByteArray> roles;
|
||||
roles.insert(SourceIdRole, "sourceId");
|
||||
roles.insert(ModelRole, "model");
|
||||
roles.insert(ConfigGroupRole, "configGroup");
|
||||
setRoleNames(roles);
|
||||
reload();
|
||||
}
|
||||
|
||||
SourceModel::~SourceModel()
|
||||
{
|
||||
qDeleteAll(m_list);
|
||||
}
|
||||
|
||||
int SourceModel::rowCount(const QModelIndex &parent) const
|
||||
{
|
||||
if (parent.isValid()) {
|
||||
return 0;
|
||||
}
|
||||
return m_list.count();
|
||||
}
|
||||
|
||||
QVariant SourceModel::data(const QModelIndex &index, int role) const
|
||||
{
|
||||
SourceModelItem *item = m_list.value(index.row());
|
||||
if (!item) {
|
||||
kWarning() << "Invalid row" << index.row();
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
switch (role) {
|
||||
case SourceIdRole:
|
||||
return item->m_sourceId;
|
||||
case ModelRole:
|
||||
return QVariant::fromValue(item->model());
|
||||
case ConfigGroupRole:
|
||||
return QVariant::fromValue(&item->m_group);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
void SourceModel::reload()
|
||||
{
|
||||
qDeleteAll(m_list);
|
||||
m_list.clear();
|
||||
|
||||
QString tabGroupName = m_tabGroup.name();
|
||||
|
||||
QStringList names = m_tabGroup.readEntry(TAB_SOURCES_KEY, QStringList());
|
||||
Q_FOREACH(const QString &name, names) {
|
||||
KConfigGroup sourceGroup(&m_tabGroup, name);
|
||||
QString sourceId = sourceGroup.readEntry(SOURCE_SOURCEID_KEY);
|
||||
SourceModelItem *item = new SourceModelItem(m_sourceRegistry, sourceId, sourceGroup, this);
|
||||
m_list << item;
|
||||
}
|
||||
}
|
||||
|
||||
void SourceModel::appendSource(const QString &sourceId)
|
||||
{
|
||||
KConfigGroup sourceGroup;
|
||||
for (int idx = 0; ; ++idx) {
|
||||
sourceGroup = KConfigGroup(&m_tabGroup, SOURCE_GROUP_PREFIX + QString::number(idx));
|
||||
if (!sourceGroup.exists()) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
beginInsertRows(QModelIndex(), m_list.count(), m_list.count());
|
||||
SourceModelItem *item = new SourceModelItem(m_sourceRegistry, sourceId, sourceGroup, this);
|
||||
m_list << item;
|
||||
item->m_group.writeEntry(SOURCE_SOURCEID_KEY, sourceId);
|
||||
item->m_group.sync();
|
||||
writeSourcesEntry();
|
||||
endInsertRows();
|
||||
}
|
||||
|
||||
void SourceModel::writeSourcesEntry()
|
||||
{
|
||||
QStringList lst;
|
||||
Q_FOREACH(const SourceModelItem *item, m_list) {
|
||||
lst << item->m_group.name();
|
||||
}
|
||||
m_tabGroup.writeEntry(TAB_SOURCES_KEY, lst);
|
||||
m_tabGroup.sync();
|
||||
}
|
||||
|
||||
void SourceModel::recreateModel(int row)
|
||||
{
|
||||
SourceModelItem *item = m_list.value(row);
|
||||
if (!item) {
|
||||
kWarning() << "Invalid row" << row;
|
||||
return;
|
||||
}
|
||||
// Just delete the model: next time the model property is accessed, the
|
||||
// model will be recreated
|
||||
item->deleteModel();
|
||||
|
||||
QModelIndex idx = index(row, 0);
|
||||
dataChanged(idx, idx);
|
||||
}
|
||||
|
||||
#define CHECK_ROW(row) \
|
||||
if (row < 0 || row >= m_list.count()) { \
|
||||
kWarning() << "Invalid row number" << row; \
|
||||
return; \
|
||||
}
|
||||
|
||||
void SourceModel::remove(int row)
|
||||
{
|
||||
CHECK_ROW(row)
|
||||
beginRemoveRows(QModelIndex(), row, row);
|
||||
SourceModelItem *item = m_list.takeAt(row);
|
||||
item->m_group.deleteGroup();
|
||||
delete item;
|
||||
writeSourcesEntry();
|
||||
endRemoveRows();
|
||||
}
|
||||
|
||||
void SourceModel::move(int from, int to)
|
||||
{
|
||||
CHECK_ROW(from)
|
||||
CHECK_ROW(to)
|
||||
if (from == to) {
|
||||
kWarning() << "Cannot move row to itself";
|
||||
return;
|
||||
}
|
||||
// See beginMoveRows() doc for an explanation on modelTo
|
||||
int modelTo = to + (to > from ? 1 : 0);
|
||||
beginMoveRows(QModelIndex(), from, from, QModelIndex(), modelTo);
|
||||
m_list.move(from, to);
|
||||
writeSourcesEntry();
|
||||
endMoveRows();
|
||||
}
|
||||
|
||||
#include "moc_sourcemodel.cpp"
|
|
@ -1,73 +0,0 @@
|
|||
/*
|
||||
Copyright 2012 Aurélien Gâteau <agateau@kde.org>
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) 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 6 of version 3 of the license.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#ifndef SOURCEMODEL_H
|
||||
#define SOURCEMODEL_H
|
||||
|
||||
// Local
|
||||
|
||||
// Qt
|
||||
#include <QtCore/qabstractitemmodel.h>
|
||||
|
||||
// KDE
|
||||
#include <KConfigGroup>
|
||||
|
||||
namespace Homerun
|
||||
{
|
||||
class AbstractSourceRegistry;
|
||||
}
|
||||
|
||||
class SourceModelItem;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
class SourceModel : public QAbstractListModel
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit SourceModel(Homerun::AbstractSourceRegistry *registry, const KConfigGroup &tabGroup, QObject *parent);
|
||||
~SourceModel();
|
||||
|
||||
enum {
|
||||
SourceIdRole = Qt::UserRole + 1,
|
||||
ModelRole,
|
||||
ConfigGroupRole,
|
||||
};
|
||||
|
||||
int rowCount(const QModelIndex &parent = QModelIndex()) const; // reimp
|
||||
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const; // reimp
|
||||
|
||||
void reload();
|
||||
|
||||
Q_INVOKABLE void appendSource(const QString &sourceId);
|
||||
Q_INVOKABLE void recreateModel(int row);
|
||||
Q_INVOKABLE void remove(int row);
|
||||
Q_INVOKABLE void move(int from, int to);
|
||||
|
||||
private:
|
||||
Homerun::AbstractSourceRegistry *m_sourceRegistry;
|
||||
KConfigGroup m_tabGroup;
|
||||
QList<SourceModelItem *> m_list;
|
||||
|
||||
void writeSourcesEntry();
|
||||
};
|
||||
|
||||
#endif /* SOURCEMODEL_H */
|
|
@ -1,449 +0,0 @@
|
|||
/*
|
||||
Copyright 2012 Aurélien Gâteau <agateau@kde.org>
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) 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 6 of version 3 of the license.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
// Self
|
||||
#include <sourceregistry.h>
|
||||
|
||||
// Local
|
||||
#include <abstractsource.h>
|
||||
#include <customtypes.h>
|
||||
#include <libhomerun_config.h>
|
||||
#include <sourceconfigurationdialog.h>
|
||||
|
||||
#include <sources/dir/dirmodel.h>
|
||||
#include <sources/favorites/favoriteappsmodel.h>
|
||||
#include <sources/favorites/favoriteplacesmodel.h>
|
||||
#include <sources/installedapps/installedappsmodel.h>
|
||||
#include <sources/installedapps/groupedinstalledappsmodel.h>
|
||||
#include <sources/installedapps/filterableinstalledappsmodel.h>
|
||||
#include <sources/recentapps/recentappsmodel.h>
|
||||
#include <sources/power/powermodel.h>
|
||||
#include <sources/power/combinedpowersessionmodel.h>
|
||||
#include <sources/runners/singlerunnermodel.h>
|
||||
#include <sources/runners/runnermodel.h>
|
||||
#include <sources/session/openedsessionsmodel.h>
|
||||
#include <sources/session/sessionmodel.h>
|
||||
|
||||
// KDE
|
||||
#include <KConfigGroup>
|
||||
#include <KDebug>
|
||||
#include <KPluginFactory>
|
||||
#include <KPluginInfo>
|
||||
#include <KPluginLoader>
|
||||
#include <KServiceTypeTrader>
|
||||
#include <Plasma/PluginLoader>
|
||||
|
||||
// Qt
|
||||
#include <QApplication>
|
||||
|
||||
namespace Homerun {
|
||||
|
||||
//- SingletonSource -------------------------------------------
|
||||
class SingletonSource : public AbstractSource
|
||||
{
|
||||
public:
|
||||
SingletonSource(QAbstractItemModel *model, SourceRegistry *registry)
|
||||
: AbstractSource(registry)
|
||||
, m_model(model)
|
||||
{}
|
||||
|
||||
QAbstractItemModel *createModelFromConfigGroup(const KConfigGroup &/* group */)
|
||||
{
|
||||
return m_model;
|
||||
}
|
||||
|
||||
private:
|
||||
QAbstractItemModel *m_model;
|
||||
};
|
||||
|
||||
//- SourceInfo ------------------------------------------------
|
||||
struct SourceInfo
|
||||
{
|
||||
QString id;
|
||||
QString visibleName;
|
||||
QString comment;
|
||||
AbstractSource *source;
|
||||
KService::Ptr service;
|
||||
|
||||
SourceInfo()
|
||||
: source(0)
|
||||
{}
|
||||
};
|
||||
|
||||
//- AvailableSourcesModel -------------------------------------
|
||||
class AvailableSourcesModel : public QAbstractListModel
|
||||
{
|
||||
public:
|
||||
enum {
|
||||
SourceIdRole = Qt::UserRole + 1,
|
||||
CommentRole
|
||||
};
|
||||
|
||||
AvailableSourcesModel(const QList<SourceInfo *> &sources, QObject *parent)
|
||||
: QAbstractListModel(parent)
|
||||
, m_sourceInfos(sources)
|
||||
{
|
||||
QHash<int, QByteArray> roles;
|
||||
roles.insert(Qt::DisplayRole, "display");
|
||||
roles.insert(SourceIdRole, "sourceId");
|
||||
roles.insert(CommentRole, "comment");
|
||||
setRoleNames(roles);
|
||||
}
|
||||
|
||||
int rowCount(const QModelIndex &parent) const
|
||||
{
|
||||
return parent.isValid() ? 0 : m_sourceInfos.size();
|
||||
}
|
||||
|
||||
QVariant data(const QModelIndex &index, int role) const
|
||||
{
|
||||
int row = index.row();
|
||||
if (row < 0 || row >= m_sourceInfos.size()) {
|
||||
return QVariant();
|
||||
}
|
||||
SourceInfo *sourceInfo = m_sourceInfos.at(row);
|
||||
switch (role) {
|
||||
case Qt::DisplayRole:
|
||||
return sourceInfo->visibleName;
|
||||
case SourceIdRole:
|
||||
return sourceInfo->id;
|
||||
case CommentRole:
|
||||
return sourceInfo->comment;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
private:
|
||||
const QList<SourceInfo *> &m_sourceInfos;
|
||||
};
|
||||
|
||||
//- SourceRegistryPrivate -------------------------------------
|
||||
struct SourceRegistryPrivate
|
||||
{
|
||||
SourceRegistry *q;
|
||||
QHash<QString, QAbstractItemModel*> m_favoriteModels;
|
||||
|
||||
QList<SourceInfo *> m_sourceInfos;
|
||||
QHash<QString, SourceInfo *> m_sourceInfoById;
|
||||
|
||||
AvailableSourcesModel *m_availableSourcesModel;
|
||||
KSharedConfig::Ptr m_config;
|
||||
|
||||
void listSourcePlugins()
|
||||
{
|
||||
KService::List offers = KServiceTypeTrader::self()->query(
|
||||
"Homerun/Source",
|
||||
QString("[X-KDE-Homerun-APIVersion] == %1").arg(HOMERUN_API_VERSION)
|
||||
);
|
||||
|
||||
Q_FOREACH(KService::Ptr ptr, offers) {
|
||||
KPluginInfo pluginInfo(ptr);
|
||||
if (pluginInfo.pluginName().isEmpty()) {
|
||||
kWarning() << "Missing X-KDE-PluginInfo-Name key in" << ptr->entryPath();
|
||||
continue;
|
||||
}
|
||||
SourceInfo *sourceInfo = new SourceInfo;
|
||||
sourceInfo->service = ptr;
|
||||
sourceInfo->id = pluginInfo.pluginName();
|
||||
sourceInfo->visibleName = pluginInfo.name();
|
||||
sourceInfo->comment = pluginInfo.comment();
|
||||
registerSourceInfo(sourceInfo);
|
||||
}
|
||||
}
|
||||
|
||||
void loadPluginForSourceInfo(SourceInfo *sourceInfo)
|
||||
{
|
||||
Q_ASSERT(sourceInfo->service);
|
||||
// Create the plugin factory
|
||||
KPluginLoader loader(*sourceInfo->service);
|
||||
KPluginFactory *factory = loader.factory();
|
||||
if (!factory) {
|
||||
kWarning() << "Failed to load plugin (desktop file: " << sourceInfo->service->entryPath() << ", source:" << sourceInfo->id << ")";
|
||||
kWarning() << loader.errorString();
|
||||
return;
|
||||
}
|
||||
|
||||
// Create the source
|
||||
AbstractSource *source = factory->create<AbstractSource>();
|
||||
if (!source) {
|
||||
kWarning() << "Failed to create source from plugin (desktop file: " << sourceInfo->service->entryPath() << ", source:" << sourceInfo->id << ")";
|
||||
return;
|
||||
}
|
||||
source->setConfig(m_config);
|
||||
sourceInfo->source = source;
|
||||
}
|
||||
|
||||
void registerSource(const QString &id, AbstractSource *source, const QString &visibleName, const QString &comment)
|
||||
{
|
||||
SourceInfo *info = new SourceInfo;
|
||||
info->id = id;
|
||||
info->visibleName = visibleName;
|
||||
info->source = source;
|
||||
info->comment = comment;
|
||||
registerSourceInfo(info);
|
||||
}
|
||||
|
||||
void registerSourceInfo(SourceInfo *info)
|
||||
{
|
||||
m_sourceInfos << info;
|
||||
m_sourceInfoById.insert(info->id, info);
|
||||
}
|
||||
|
||||
AbstractSource *sourceById(const QString &id)
|
||||
{
|
||||
SourceInfo *sourceInfo = m_sourceInfoById.value(id);
|
||||
if (!sourceInfo) {
|
||||
kWarning() << "No source named" << id;
|
||||
return 0;
|
||||
}
|
||||
if (sourceInfo->source) {
|
||||
return sourceInfo->source;
|
||||
}
|
||||
loadPluginForSourceInfo(sourceInfo);
|
||||
if (!sourceInfo->source) {
|
||||
kWarning() << "Failed to load source for" << id;
|
||||
return 0;
|
||||
}
|
||||
return sourceInfo->source;
|
||||
}
|
||||
|
||||
void registerSingleRunnerSources()
|
||||
{
|
||||
KPluginInfo::List list = Plasma::PluginLoader::pluginLoader()->listRunnerInfo();
|
||||
|
||||
Q_FOREACH(const KPluginInfo &info, list) {
|
||||
if (!info.property("X-Plasma-AdvertiseSingleRunnerQueryMode").toBool()) {
|
||||
continue;
|
||||
}
|
||||
QString runnerId = info.pluginName();
|
||||
SingleRunnerSource *source = new SingleRunnerSource(runnerId, q);
|
||||
QString name = i18n("Runner: %1", info.name());
|
||||
registerSource("SingleRunner/" + runnerId, source, name, info.comment());
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
//- SourceRegistry --------------------------------------------
|
||||
SourceRegistry::SourceRegistry(QObject *parent)
|
||||
: AbstractSourceRegistry(parent)
|
||||
, d(new SourceRegistryPrivate)
|
||||
{
|
||||
d->q = this;
|
||||
d->m_availableSourcesModel = new AvailableSourcesModel(d->m_sourceInfos, this);
|
||||
|
||||
d->m_favoriteModels.insert("app", new FavoriteAppsModel(this));
|
||||
d->m_favoriteModels.insert("place", new FavoritePlacesModel(this));
|
||||
|
||||
d->registerSource("InstalledApps", new InstalledAppsSource(this),
|
||||
i18n("Installed Applications"),
|
||||
i18n("Browse installed applications by categories")
|
||||
);
|
||||
d->registerSource("GroupedInstalledApps", new GroupedInstalledAppsSource(this),
|
||||
i18n("All Installed Applications"),
|
||||
i18n("List all installed applications in a flat list, grouped by categories")
|
||||
);
|
||||
d->registerSource("FilterableInstalledApps", new FilterableInstalledAppsSource(this),
|
||||
i18n("All Installed Applications With Filters"),
|
||||
i18n("List all installed applications and filter via the sidebar")
|
||||
);
|
||||
d->registerSource("RecentApps", new RecentAppsSource(this),
|
||||
i18n("Recent Applications"),
|
||||
i18n("List the most recently launched applications")
|
||||
);
|
||||
d->registerSource("Dir", new DirSource(this),
|
||||
i18n("Folder"),
|
||||
i18n("List the content of a folder and let you browse into sub-folders")
|
||||
);
|
||||
d->registerSource("FavoritePlaces", new SingletonSource(d->m_favoriteModels.value("place"), this),
|
||||
i18n("Favorite Places"),
|
||||
i18n("Browse the content of your favorite places")
|
||||
);
|
||||
d->registerSource("FavoriteApps", new SingletonSource(d->m_favoriteModels.value("app"), this),
|
||||
i18n("Favorite Applications"),
|
||||
i18n("List applications marked as favorite")
|
||||
);
|
||||
d->registerSource("Power", new SimpleSource<PowerModel>(this),
|
||||
i18n("Power Management"),
|
||||
i18n("Provide buttons to suspend, hibernate, reboot or halt your computer")
|
||||
);
|
||||
d->registerSource("Session", new SimpleSource<SessionModel>(this),
|
||||
i18n("Session"),
|
||||
i18n("Provide buttons to lock the screen, log out, or switch to another user")
|
||||
);
|
||||
d->registerSource("OpenedSessions", new SimpleSource<OpenedSessionsModel>(this),
|
||||
i18n("Opened Sessions"),
|
||||
i18n("Provide buttons to switch to opened sessions")
|
||||
);
|
||||
d->registerSource("CombinedPowerSession", new CombinedPowerSessionSource(this),
|
||||
i18n("Power / Session"),
|
||||
i18n("Provide buttons to manage your workspace session and the power state of your computer")
|
||||
);
|
||||
d->registerSource("Runner", new RunnerSource(this),
|
||||
i18n("KRunner"),
|
||||
i18n("Perform searchs using a selection of runners")
|
||||
);
|
||||
|
||||
d->registerSingleRunnerSources();
|
||||
|
||||
d->listSourcePlugins();
|
||||
}
|
||||
|
||||
SourceRegistry::~SourceRegistry()
|
||||
{
|
||||
qDeleteAll(d->m_sourceInfos);
|
||||
delete d;
|
||||
}
|
||||
|
||||
QObject *SourceRegistry::createModelFromArguments(const QString &sourceId, const QVariantMap &sourceArguments, QObject *parent)
|
||||
{
|
||||
// Get source
|
||||
AbstractSource *source = d->sourceById(sourceId);
|
||||
if (!source) {
|
||||
kWarning() << "Invalid sourceId in group (sourceId=" << sourceId << ")";
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Create model
|
||||
QAbstractItemModel *model = source->createModelFromArguments(sourceArguments);
|
||||
if (!model) {
|
||||
kWarning() << "Failed to create model";
|
||||
return 0;
|
||||
}
|
||||
model->setObjectName(sourceId);
|
||||
|
||||
// If the model already has a parent, then don't change it.
|
||||
// This is used by singleton sources to keep their model alive.
|
||||
if (!model->parent()) {
|
||||
model->setParent(parent);
|
||||
}
|
||||
|
||||
return model;
|
||||
}
|
||||
|
||||
QObject *SourceRegistry::createModelFromConfigGroup(const QString &sourceId, const KConfigGroup &group, QObject *parent)
|
||||
{
|
||||
// Get source
|
||||
AbstractSource *source = d->sourceById(sourceId);
|
||||
if (!source) {
|
||||
kWarning() << "Invalid sourceId in group (sourceId=" << sourceId << ")";
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Create model
|
||||
QAbstractItemModel *model = source->createModelFromConfigGroup(group);
|
||||
if (!model) {
|
||||
kWarning() << "Failed to create model from group" << group.name();
|
||||
return 0;
|
||||
}
|
||||
model->setObjectName(sourceId);
|
||||
|
||||
// If the model already has a parent, then don't change it.
|
||||
// This is used by singleton sources to keep their model alive.
|
||||
if (!model->parent()) {
|
||||
model->setParent(parent);
|
||||
}
|
||||
|
||||
return model;
|
||||
}
|
||||
|
||||
QVariantMap SourceRegistry::favoriteModels() const
|
||||
{
|
||||
QVariantMap map;
|
||||
auto it = d->m_favoriteModels.constBegin(), end = d->m_favoriteModels.constEnd();
|
||||
for (; it != end; ++it) {
|
||||
map.insert(it.key(), QVariant::fromValue<QObject *>(it.value()));
|
||||
}
|
||||
return map;
|
||||
}
|
||||
|
||||
QAbstractItemModel *SourceRegistry::favoriteModel(const QString &name) const
|
||||
{
|
||||
return d->m_favoriteModels.value(name);
|
||||
}
|
||||
|
||||
KSharedConfig::Ptr SourceRegistry::config() const
|
||||
{
|
||||
return d->m_config;
|
||||
}
|
||||
|
||||
QString SourceRegistry::configFileName() const
|
||||
{
|
||||
return d->m_config ? d->m_config->name() : QString();
|
||||
}
|
||||
|
||||
void SourceRegistry::setConfigFileName(const QString &name)
|
||||
{
|
||||
if (d->m_config && d->m_config->name() == name) {
|
||||
return;
|
||||
}
|
||||
d->m_config = KSharedConfig::openConfig(name);
|
||||
Q_FOREACH(SourceInfo *sourceInfo, d->m_sourceInfos) {
|
||||
AbstractSource *source = sourceInfo->source;
|
||||
if (source) {
|
||||
source->setConfig(d->m_config);
|
||||
}
|
||||
}
|
||||
configFileNameChanged(name);
|
||||
}
|
||||
|
||||
QObject *SourceRegistry::availableSourcesModel() const
|
||||
{
|
||||
return d->m_availableSourcesModel;
|
||||
}
|
||||
|
||||
QString SourceRegistry::visibleNameForSource(const QString &sourceId) const
|
||||
{
|
||||
SourceInfo *info = d->m_sourceInfoById.value(sourceId);
|
||||
if (!info) {
|
||||
kWarning() << "No source for" << sourceId;
|
||||
return QString();
|
||||
}
|
||||
return info->visibleName;
|
||||
}
|
||||
|
||||
bool SourceRegistry::isSourceConfigurable(const QString &sourceId) const
|
||||
{
|
||||
AbstractSource *source = d->sourceById(sourceId);
|
||||
if (!source) {
|
||||
kWarning() << "No source for" << sourceId;
|
||||
return false;
|
||||
}
|
||||
return source->isConfigurable();
|
||||
}
|
||||
|
||||
QObject *SourceRegistry::createConfigurationDialog(const QString &sourceId, const QVariant &configGroupVariant) const
|
||||
{
|
||||
AbstractSource *source = d->sourceById(sourceId);
|
||||
if (!source) {
|
||||
kWarning() << "No source for" << sourceId;
|
||||
return 0;
|
||||
}
|
||||
|
||||
KConfigGroup *sourceGroup = configGroupVariant.value<KConfigGroup*>();
|
||||
Q_ASSERT(sourceGroup);
|
||||
Q_ASSERT(sourceGroup->isValid());
|
||||
|
||||
return new SourceConfigurationDialog(source, *sourceGroup, QApplication::activeWindow());
|
||||
}
|
||||
|
||||
} // namespace Homerun
|
||||
|
||||
#include "moc_sourceregistry.cpp"
|
|
@ -1,81 +0,0 @@
|
|||
/*
|
||||
Copyright 2012 Aurélien Gâteau <agateau@kde.org>
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) 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 6 of version 3 of the license.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#ifndef SOURCEREGISTRY_H
|
||||
#define SOURCEREGISTRY_H
|
||||
|
||||
// Local
|
||||
#include <abstractsourceregistry.h>
|
||||
|
||||
// Qt
|
||||
|
||||
// KDE
|
||||
#include <KSharedConfig>
|
||||
|
||||
class QAbstractItemModel;
|
||||
|
||||
namespace Homerun {
|
||||
|
||||
class AbstractSource;
|
||||
class SourceRegistryPrivate;
|
||||
|
||||
/**
|
||||
* The source registry. This class is responsible for loading source plugins
|
||||
* and instantiating source models.
|
||||
*/
|
||||
class SourceRegistry : public AbstractSourceRegistry
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_PROPERTY(QVariantMap favoriteModels READ favoriteModels CONSTANT)
|
||||
Q_PROPERTY(QString configFileName READ configFileName WRITE setConfigFileName NOTIFY configFileNameChanged)
|
||||
public:
|
||||
explicit SourceRegistry(QObject *parent = 0);
|
||||
~SourceRegistry();
|
||||
|
||||
Q_INVOKABLE QObject *createModelFromArguments(const QString &sourceId, const QVariantMap &sourceArguments, QObject *parent);
|
||||
|
||||
QObject *createModelFromConfigGroup(const QString &sourceId, const KConfigGroup &configGroup, QObject *parent); // reimp
|
||||
KSharedConfig::Ptr config() const;
|
||||
|
||||
QVariantMap favoriteModels() const;
|
||||
|
||||
QAbstractItemModel *favoriteModel(const QString &name) const;
|
||||
|
||||
QString configFileName() const;
|
||||
void setConfigFileName(const QString &name);
|
||||
|
||||
//// Config API
|
||||
Q_INVOKABLE QObject *availableSourcesModel() const;
|
||||
|
||||
Q_INVOKABLE QString visibleNameForSource(const QString &sourceId) const;
|
||||
|
||||
Q_INVOKABLE bool isSourceConfigurable(const QString &sourceId) const;
|
||||
|
||||
Q_INVOKABLE QObject *createConfigurationDialog(const QString &sourceId, const QVariant &groupVariant) const;
|
||||
|
||||
Q_SIGNALS:
|
||||
void configFileNameChanged(const QString &);
|
||||
|
||||
private:
|
||||
SourceRegistryPrivate * const d;
|
||||
};
|
||||
|
||||
} // namespace Homerun
|
||||
|
||||
#endif /* SOURCEREGISTRY_H */
|
|
@ -1,68 +0,0 @@
|
|||
/*
|
||||
Copyright 2012 Aurélien Gâteau <agateau@kde.org>
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) 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 6 of version 3 of the license.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
// Self
|
||||
#include <dirconfigurationwidget.h>
|
||||
|
||||
// Local
|
||||
#include <ui_dirconfigurationwidget.h>
|
||||
|
||||
// KDE
|
||||
#include <KGlobalSettings>
|
||||
#include <KUrlRequester>
|
||||
#include <KConfigGroup>
|
||||
|
||||
// Qt
|
||||
#include <QDir>
|
||||
#include <QVBoxLayout>
|
||||
|
||||
using namespace Homerun;
|
||||
|
||||
DirConfigurationWidget::DirConfigurationWidget(const KConfigGroup &group)
|
||||
: SourceConfigurationWidget(group)
|
||||
, m_ui(new Ui_DirConfigurationWidget)
|
||||
{
|
||||
m_ui->setupUi(this);
|
||||
|
||||
QFont helpFont = KGlobalSettings::smallestReadableFont();
|
||||
m_ui->titleHelpLabel->setFont(helpFont);
|
||||
|
||||
KUrl url = group.readPathEntry("rootUrl", QDir::homePath());
|
||||
if (url.isValid()) {
|
||||
m_ui->urlRequester->setUrl(url);
|
||||
}
|
||||
|
||||
m_ui->titleLineEdit->setText(group.readEntry("rootName", QString()));
|
||||
}
|
||||
|
||||
DirConfigurationWidget::~DirConfigurationWidget()
|
||||
{
|
||||
delete m_ui;
|
||||
}
|
||||
|
||||
void DirConfigurationWidget::save()
|
||||
{
|
||||
KUrl url = m_ui->urlRequester->url().url();
|
||||
QString title = m_ui->titleLineEdit->text();
|
||||
|
||||
configGroup().writePathEntry("rootUrl", url.url());
|
||||
configGroup().writeEntry("rootName", title);
|
||||
}
|
||||
|
||||
#include "moc_dirconfigurationwidget.cpp"
|
|
@ -1,48 +0,0 @@
|
|||
/*
|
||||
Copyright 2012 Aurélien Gâteau <agateau@kde.org>
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) 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 6 of version 3 of the license.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#ifndef DIRCONFIGURATIONWIDGET_H
|
||||
#define DIRCONFIGURATIONWIDGET_H
|
||||
|
||||
// Local
|
||||
#include <sourceconfigurationwidget.h>
|
||||
|
||||
// Qt
|
||||
|
||||
// KDE
|
||||
|
||||
class Ui_DirConfigurationWidget;
|
||||
|
||||
/**
|
||||
* Configuration widget for the Dir source
|
||||
*/
|
||||
class DirConfigurationWidget : public Homerun::SourceConfigurationWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
DirConfigurationWidget(const KConfigGroup &group);
|
||||
~DirConfigurationWidget();
|
||||
|
||||
void save(); // reimp
|
||||
|
||||
private:
|
||||
Ui_DirConfigurationWidget *m_ui;
|
||||
};
|
||||
|
||||
#endif /* DIRCONFIGURATIONWIDGET_H */
|
|
@ -1,83 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>DirConfigurationWidget</class>
|
||||
<widget class="QWidget" name="DirConfigurationWidget">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>400</width>
|
||||
<height>85</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Minimum" vsizetype="Minimum">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>400</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string/>
|
||||
</property>
|
||||
<layout class="QFormLayout" name="formLayout">
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="label_2">
|
||||
<property name="text">
|
||||
<string>Folder to show:</string>
|
||||
</property>
|
||||
<property name="buddy">
|
||||
<cstring>urlRequester</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="KUrlRequester" name="urlRequester">
|
||||
<property name="mode">
|
||||
<set>KFile::Directory|KFile::ExistingOnly</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QLineEdit" name="titleLineEdit"/>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="text">
|
||||
<string>Title:</string>
|
||||
</property>
|
||||
<property name="buddy">
|
||||
<cstring>titleLineEdit</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="1">
|
||||
<widget class="QLabel" name="titleHelpLabel">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Minimum" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>If title is left empty, the folder name will be used</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<customwidgets>
|
||||
<customwidget>
|
||||
<class>KUrlRequester</class>
|
||||
<extends>QFrame</extends>
|
||||
<header>kurlrequester.h</header>
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
|
@ -1,262 +0,0 @@
|
|||
/*
|
||||
Copyright 2012 Aurélien Gâteau <agateau@kde.org>
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) 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 6 of version 3 of the license.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
// Self
|
||||
#include <dirmodel.h>
|
||||
|
||||
// Local
|
||||
#include <dirconfigurationwidget.h>
|
||||
#include <favoriteutils.h>
|
||||
|
||||
// libhomerun
|
||||
#include <actionlist.h>
|
||||
#include <pathmodel.h>
|
||||
|
||||
// KDE
|
||||
#include <KConfigGroup>
|
||||
#include <KDebug>
|
||||
#include <KDirModel>
|
||||
#include <KDirLister>
|
||||
|
||||
// Qt
|
||||
#include <QDir>
|
||||
|
||||
namespace Homerun
|
||||
{
|
||||
|
||||
static const char *SOURCE_ID = "Dir";
|
||||
|
||||
static inline KFileItem itemForIndex(const QModelIndex &index)
|
||||
{
|
||||
return index.data(KDirModel::FileItemRole).value<KFileItem>();
|
||||
}
|
||||
|
||||
//- DirModel ------------------------------------------------------
|
||||
QVariantMap DirModel::sourceArguments(const KUrl &rootUrl, const QString &rootName, const KUrl &url)
|
||||
{
|
||||
QVariantMap args;
|
||||
args.insert("rootUrl", rootUrl.url());
|
||||
args.insert("rootName", rootName);
|
||||
args.insert("url", url.url());
|
||||
return args;
|
||||
}
|
||||
|
||||
|
||||
DirModel::DirModel(QObject *parent)
|
||||
: KDirSortFilterProxyModel(parent)
|
||||
, m_pathModel(new PathModel(this))
|
||||
{
|
||||
setSourceModel(new KDirModel(this));
|
||||
setSortFoldersFirst(true);
|
||||
|
||||
QHash<int, QByteArray> roles;
|
||||
roles.insert(Qt::DisplayRole, "display");
|
||||
roles.insert(Qt::DecorationRole, "decoration");
|
||||
roles.insert(DirModel::FavoriteIdRole, "favoriteId");
|
||||
roles.insert(DirModel::HasActionListRole, "hasActionList");
|
||||
roles.insert(DirModel::ActionListRole, "actionList");
|
||||
setRoleNames(roles);
|
||||
|
||||
dirLister()->setDelayedMimeTypes(true);
|
||||
connect(dirLister(), SIGNAL(started(KUrl)), SLOT(emitRunningChanged()));
|
||||
connect(dirLister(), SIGNAL(completed()), SLOT(emitRunningChanged()));
|
||||
}
|
||||
|
||||
void DirModel::init(const KUrl &rootUrl, const QString &rootName, const KUrl &url)
|
||||
{
|
||||
m_rootUrl = rootUrl;
|
||||
m_rootName = rootName;
|
||||
initPathModel(url);
|
||||
dirLister()->openUrl(url);
|
||||
}
|
||||
|
||||
void DirModel::initPathModel(const KUrl &openedUrl)
|
||||
{
|
||||
QVariantMap args = sourceArguments(m_rootUrl, m_rootName, m_rootUrl);
|
||||
m_pathModel->addPath(m_rootName, SOURCE_ID, args);
|
||||
|
||||
KUrl rootUrl = m_rootUrl;
|
||||
// Needed for KUrl::relativeUrl
|
||||
rootUrl.adjustPath(KUrl::AddTrailingSlash);
|
||||
QString relativePath = KUrl::relativeUrl(rootUrl, openedUrl);
|
||||
if (relativePath == "./") {
|
||||
return;
|
||||
}
|
||||
KUrl url = m_rootUrl;
|
||||
Q_FOREACH(const QString &token, relativePath.split('/')) {
|
||||
if (token.isEmpty()) {
|
||||
// Just in case relativePath ends with '/'
|
||||
continue;
|
||||
}
|
||||
url.addPath(token);
|
||||
args["url"] = url.url();
|
||||
m_pathModel->addPath(token, SOURCE_ID, args);
|
||||
}
|
||||
}
|
||||
|
||||
KDirLister *DirModel::dirLister() const
|
||||
{
|
||||
return static_cast<KDirModel *>(sourceModel())->dirLister();
|
||||
}
|
||||
|
||||
QVariant DirModel::data(const QModelIndex &index, int role) const
|
||||
{
|
||||
KFileItem item = qvariant_cast<KFileItem>(QSortFilterProxyModel::data(index, KDirModel::FileItemRole));
|
||||
|
||||
if (role == Qt::DecorationRole && !item.isFinalIconKnown()) {
|
||||
item.determineMimeType();
|
||||
}
|
||||
|
||||
if (role != FavoriteIdRole && role != HasActionListRole && role != ActionListRole) {
|
||||
return QSortFilterProxyModel::data(index, role);
|
||||
}
|
||||
if (index.row() < 0 || index.row() >= rowCount()) {
|
||||
return QVariant();
|
||||
}
|
||||
if (role == HasActionListRole) {
|
||||
return true;
|
||||
}
|
||||
if (role == FavoriteIdRole) {
|
||||
if (item.isDir()) {
|
||||
return FavoriteUtils::favoriteIdFromUrl(item.url());
|
||||
} else {
|
||||
return QString();
|
||||
}
|
||||
} else if (role == ActionListRole) {
|
||||
return ActionList::createListForFileItem(item);
|
||||
}
|
||||
// Never reached
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
int DirModel::count() const
|
||||
{
|
||||
return rowCount(QModelIndex());
|
||||
}
|
||||
|
||||
QString DirModel::name() const
|
||||
{
|
||||
return m_rootName;
|
||||
}
|
||||
|
||||
bool DirModel::running() const
|
||||
{
|
||||
return !dirLister()->isFinished();
|
||||
}
|
||||
|
||||
PathModel *DirModel::pathModel() const
|
||||
{
|
||||
return m_pathModel;
|
||||
}
|
||||
|
||||
QString DirModel::query() const
|
||||
{
|
||||
return filterRegExp().pattern();
|
||||
}
|
||||
|
||||
void DirModel::setQuery(const QString &value)
|
||||
{
|
||||
if (value == query()) {
|
||||
return;
|
||||
}
|
||||
setFilterRegExp(QRegExp(value, Qt::CaseInsensitive));
|
||||
queryChanged(value);
|
||||
}
|
||||
|
||||
void DirModel::emitRunningChanged()
|
||||
{
|
||||
runningChanged(running());
|
||||
}
|
||||
|
||||
bool DirModel::trigger(int row, const QString &actionId, const QVariant &actionArg)
|
||||
{
|
||||
QModelIndex idx = index(row, 0);
|
||||
KFileItem item = itemForIndex(idx);
|
||||
|
||||
if (actionId.isEmpty()) {
|
||||
if (item.isDir()) {
|
||||
openSourceRequested(SOURCE_ID, sourceArguments(m_rootUrl, m_rootName, item.url()));
|
||||
} else {
|
||||
item.run();
|
||||
}
|
||||
}
|
||||
|
||||
bool close;
|
||||
ActionList::handleFileItemAction(item, actionId, actionArg, &close);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
//- DirSource -------------------------------------------------------
|
||||
DirSource::DirSource(QObject *parent)
|
||||
: AbstractSource(parent)
|
||||
{}
|
||||
|
||||
QAbstractItemModel *DirSource::createModelFromArguments(const QVariantMap &args)
|
||||
{
|
||||
KUrl rootUrl = args.value("rootUrl").toString();
|
||||
QString rootName = args.value("rootName").toString();
|
||||
KUrl url = args.value("url").toString();
|
||||
return createModel(rootUrl, rootName, url);
|
||||
}
|
||||
|
||||
QAbstractItemModel *DirSource::createModelFromConfigGroup(const KConfigGroup &group)
|
||||
{
|
||||
KUrl rootUrl = group.readPathEntry("rootUrl", QDir::homePath());
|
||||
QString rootName = group.readEntry("rootName", QString());
|
||||
return createModel(rootUrl, rootName, KUrl());
|
||||
}
|
||||
|
||||
QAbstractItemModel *DirSource::createModel(const KUrl &rootUrl_, const QString &rootName_, const KUrl &url_)
|
||||
{
|
||||
KUrl rootUrl = rootUrl_;
|
||||
QString rootName = rootName_;
|
||||
KUrl url = url_;
|
||||
if (!rootUrl.isValid()) {
|
||||
rootUrl = KUrl::fromPath(QDir::homePath());
|
||||
}
|
||||
|
||||
if (rootName.isEmpty()) {
|
||||
rootName = rootUrl.fileName();
|
||||
if (rootName.isEmpty()) {
|
||||
rootName = rootUrl.prettyUrl();
|
||||
}
|
||||
}
|
||||
if (!url.isValid()) {
|
||||
url = rootUrl;
|
||||
}
|
||||
|
||||
DirModel *model = new DirModel;
|
||||
model->init(rootUrl, rootName, url);
|
||||
return model;
|
||||
}
|
||||
|
||||
bool DirSource::isConfigurable() const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
SourceConfigurationWidget *DirSource::createConfigurationWidget(const KConfigGroup &group)
|
||||
{
|
||||
return new DirConfigurationWidget(group);
|
||||
}
|
||||
|
||||
} // namespace Homerun
|
||||
|
||||
#include "moc_dirmodel.cpp"
|
|
@ -1,113 +0,0 @@
|
|||
/*
|
||||
Copyright 2012 Aurélien Gâteau <agateau@kde.org>
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) 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 6 of version 3 of the license.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#ifndef DIRMODEL_H
|
||||
#define DIRMODEL_H
|
||||
|
||||
// Local
|
||||
#include <abstractsource.h>
|
||||
|
||||
// Qt
|
||||
|
||||
// KDE
|
||||
#include <KDirSortFilterProxyModel>
|
||||
#include <KUrl>
|
||||
|
||||
class KDirLister;
|
||||
|
||||
namespace Homerun {
|
||||
|
||||
class PathModel;
|
||||
|
||||
/**
|
||||
* Internal
|
||||
*/
|
||||
class DirModel : public KDirSortFilterProxyModel
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_PROPERTY(int count READ count NOTIFY countChanged)
|
||||
Q_PROPERTY(QString name READ name CONSTANT)
|
||||
|
||||
Q_PROPERTY(bool running READ running NOTIFY runningChanged)
|
||||
Q_PROPERTY(QObject *pathModel READ pathModel CONSTANT)
|
||||
Q_PROPERTY(QString query READ query WRITE setQuery NOTIFY queryChanged)
|
||||
public:
|
||||
explicit DirModel(QObject *parent = 0);
|
||||
|
||||
void init(const KUrl &rootUrl, const QString &rootName, const KUrl &url);
|
||||
|
||||
enum {
|
||||
FavoriteIdRole = Qt::UserRole + 1,
|
||||
HasActionListRole,
|
||||
ActionListRole,
|
||||
};
|
||||
|
||||
Q_INVOKABLE bool trigger(int row, const QString &actionId = QString(), const QVariant &actionArgument = QVariant());
|
||||
|
||||
KDirLister *dirLister() const;
|
||||
|
||||
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const; // reimp
|
||||
|
||||
PathModel *pathModel() const;
|
||||
|
||||
int count() const;
|
||||
|
||||
QString name() const;
|
||||
|
||||
bool running() const;
|
||||
|
||||
QString query() const;
|
||||
|
||||
void setQuery(const QString &query);
|
||||
|
||||
static QVariantMap sourceArguments(const KUrl &rootUrl, const QString &rootName, const KUrl &url);
|
||||
|
||||
Q_SIGNALS:
|
||||
void countChanged();
|
||||
void runningChanged(bool);
|
||||
void openSourceRequested(const QString &sourceId, const QVariantMap &sourceArguments);
|
||||
void queryChanged(const QString &);
|
||||
|
||||
private Q_SLOTS:
|
||||
void emitRunningChanged();
|
||||
|
||||
private:
|
||||
PathModel *m_pathModel;
|
||||
KUrl m_rootUrl;
|
||||
QString m_rootName;
|
||||
|
||||
void initPathModel(const KUrl &url);
|
||||
};
|
||||
|
||||
class DirSource : public AbstractSource
|
||||
{
|
||||
public:
|
||||
DirSource(QObject *parent);
|
||||
QAbstractItemModel *createModelFromConfigGroup(const KConfigGroup &group);
|
||||
QAbstractItemModel *createModelFromArguments(const QVariantMap &args);
|
||||
bool isConfigurable() const;
|
||||
SourceConfigurationWidget *createConfigurationWidget(const KConfigGroup &group);
|
||||
|
||||
private:
|
||||
QAbstractItemModel *createModel(const KUrl &rootUrl, const QString &rootName, const KUrl &url);
|
||||
};
|
||||
|
||||
} // namespace Homerun
|
||||
|
||||
#endif /* DIRMODEL_H */
|
|
@ -1,354 +0,0 @@
|
|||
/*
|
||||
Copyright 2009 Ivan Cukic <ivan.cukic+kde@gmail.com>
|
||||
Copyright 2010 Marco Martin <notmart@gmail.com>
|
||||
Copyright 2012 Aurélien Gâteau <agateau@kde.org>
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Library General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Library General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Library General Public License
|
||||
along with this library; see the file COPYING.LIB. If not, write to
|
||||
the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
||||
Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
// Own
|
||||
#include "favoriteappsmodel.h"
|
||||
|
||||
// Qt
|
||||
#include <QtXml/qdom.h>
|
||||
#include <QFile>
|
||||
|
||||
// KDE
|
||||
#include <KDebug>
|
||||
#include <KIcon>
|
||||
#include <KConfigGroup>
|
||||
#include <KLocale>
|
||||
#include <KRun>
|
||||
#include <KService>
|
||||
#include <KStandardDirs>
|
||||
|
||||
namespace Homerun {
|
||||
|
||||
static QString localXmlFileName()
|
||||
{
|
||||
return KStandardDirs::locateLocal("data", "homerun/favoriteapps.xml");
|
||||
}
|
||||
|
||||
static QString systemXmlFileName()
|
||||
{
|
||||
return KStandardDirs::locate("data", "homerun/favoriteapps.xml");
|
||||
}
|
||||
|
||||
static QString serviceIdFromFavoriteId(const QString &favoriteId)
|
||||
{
|
||||
if (!favoriteId.startsWith("app:")) {
|
||||
kWarning() << "Wrong favoriteId" << favoriteId;
|
||||
return QString();
|
||||
}
|
||||
return favoriteId.mid(4);
|
||||
}
|
||||
|
||||
FavoriteAppsModel::FavoriteAppsModel(QObject *parent)
|
||||
: QAbstractListModel(parent)
|
||||
{
|
||||
QHash<int, QByteArray> roles;
|
||||
roles.insert(Qt::DisplayRole, "display");
|
||||
roles.insert(Qt::DecorationRole, "decoration");
|
||||
roles.insert(FavoriteIdRole, "favoriteId");
|
||||
setRoleNames(roles);
|
||||
load();
|
||||
}
|
||||
|
||||
FavoriteAppsModel::~FavoriteAppsModel()
|
||||
{
|
||||
}
|
||||
|
||||
void FavoriteAppsModel::load()
|
||||
{
|
||||
bool ok;
|
||||
QString name = localXmlFileName();
|
||||
if (QFile::exists(name)) {
|
||||
ok = loadFromXml(name);
|
||||
if (ok) {
|
||||
return;
|
||||
} else {
|
||||
kWarning() << "Failed to load from" << name;
|
||||
}
|
||||
}
|
||||
importFromConfigFile();
|
||||
if (m_favoriteList.isEmpty()) {
|
||||
// Nothing to import, load system xml file
|
||||
ok = loadFromXml(systemXmlFileName());
|
||||
if (!ok) {
|
||||
kWarning() << "Failed to load any favoriteapps file. No apps will be listed as favorite.";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool FavoriteAppsModel::loadFromXml(const QString &fileName)
|
||||
{
|
||||
QDomDocument doc;
|
||||
bool ok;
|
||||
{
|
||||
QFile file(fileName);
|
||||
ok = file.open(QIODevice::ReadOnly);
|
||||
if (!ok) {
|
||||
kWarning() << "Failed to open" << fileName << ". Error " << file.error();
|
||||
return false;
|
||||
}
|
||||
QString msg;
|
||||
int line, column;
|
||||
ok = doc.setContent(&file, &msg, &line, &column);
|
||||
if (!ok) {
|
||||
kWarning() << "Failed to parse" << fileName << ". Error line" << line << "column" << column << ":" << msg;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
beginResetModel();
|
||||
m_favoriteList.clear();
|
||||
QDomElement root = doc.documentElement();
|
||||
for(QDomNode node = root.firstChild(); !node.isNull(); node = node.nextSibling()) {
|
||||
const QDomElement element = node.toElement();
|
||||
if (element.isNull()) {
|
||||
kWarning() << "Ignoring invalid node";
|
||||
continue;
|
||||
}
|
||||
const QString serviceId = element.attribute("serviceId");
|
||||
if (serviceId.isEmpty()) {
|
||||
kWarning() << "Ignoring element with empty serviceId attribute";
|
||||
continue;
|
||||
}
|
||||
KService::Ptr service = KService::serviceByStorageId(serviceId);
|
||||
if (service.isNull()) {
|
||||
kWarning() << "Ignoring element with invalid serviceId" << serviceId;
|
||||
continue;
|
||||
}
|
||||
FavoriteInfo info = { service };
|
||||
m_favoriteList << info;
|
||||
}
|
||||
endResetModel();
|
||||
countChanged();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void FavoriteAppsModel::saveToXml()
|
||||
{
|
||||
bool ok;
|
||||
|
||||
QDomDocument doc;
|
||||
QDomElement root = doc.createElement("apps");
|
||||
root.setAttribute("version", "1");
|
||||
doc.appendChild(root);
|
||||
|
||||
Q_FOREACH(const FavoriteInfo &info, m_favoriteList) {
|
||||
QString serviceId = info.service->storageId();
|
||||
QDomElement element = doc.createElement("app");
|
||||
element.setAttribute("serviceId", serviceId);
|
||||
root.appendChild(element);
|
||||
}
|
||||
|
||||
QFile file(localXmlFileName());
|
||||
ok = file.open(QIODevice::WriteOnly);
|
||||
if (!ok) {
|
||||
kWarning() << "Failed to open" << localXmlFileName() << "for writing. Error" << file.error();
|
||||
return;
|
||||
}
|
||||
file.write(doc.toByteArray(4));
|
||||
}
|
||||
|
||||
void FavoriteAppsModel::addFavorite(const QString &favoriteId)
|
||||
{
|
||||
QString serviceId = serviceIdFromFavoriteId(favoriteId);
|
||||
if (serviceId.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
KService::Ptr service = KService::serviceByStorageId(serviceId);
|
||||
if (service.isNull()) {
|
||||
kWarning() << "Could not find a service for" << serviceId;
|
||||
return;
|
||||
}
|
||||
FavoriteInfo info = { service };
|
||||
|
||||
int row = m_favoriteList.count();
|
||||
beginInsertRows(QModelIndex(), row, row);
|
||||
m_favoriteList << info;
|
||||
endInsertRows();
|
||||
countChanged();
|
||||
|
||||
saveToXml();
|
||||
}
|
||||
|
||||
void FavoriteAppsModel::removeFavorite(const QString &favoriteId)
|
||||
{
|
||||
int row = rowForFavoriteId(favoriteId);
|
||||
if (row == -1) {
|
||||
kWarning() << "Could not find favorite" << favoriteId;
|
||||
return;
|
||||
}
|
||||
beginRemoveRows(QModelIndex(), row, row);
|
||||
FavoriteInfo info = m_favoriteList.takeAt(row);
|
||||
endRemoveRows();
|
||||
countChanged();
|
||||
|
||||
saveToXml();
|
||||
}
|
||||
|
||||
bool FavoriteAppsModel::isFavorite(const QString &favoriteId) const
|
||||
{
|
||||
return rowForFavoriteId(favoriteId) != -1;
|
||||
}
|
||||
|
||||
int FavoriteAppsModel::rowForFavoriteId(const QString& favoriteId) const
|
||||
{
|
||||
QString serviceId = serviceIdFromFavoriteId(favoriteId);
|
||||
if (serviceId.isEmpty()) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
for (int row = m_favoriteList.count() - 1; row >= 0; --row) {
|
||||
const FavoriteInfo& info = m_favoriteList.at(row);
|
||||
if (info.service->storageId() == serviceId) {
|
||||
return row;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
int FavoriteAppsModel::count() const
|
||||
{
|
||||
return m_favoriteList.count();
|
||||
}
|
||||
|
||||
QString FavoriteAppsModel::name() const
|
||||
{
|
||||
return i18n("Favorite Applications");
|
||||
}
|
||||
|
||||
QString FavoriteAppsModel::favoritePrefix() const
|
||||
{
|
||||
return "app";
|
||||
}
|
||||
|
||||
bool FavoriteAppsModel::canMoveRow() const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
int FavoriteAppsModel::rowCount(const QModelIndex &index) const
|
||||
{
|
||||
if (index.isValid()) {
|
||||
return 0;
|
||||
}
|
||||
return m_favoriteList.count();
|
||||
}
|
||||
|
||||
QVariant FavoriteAppsModel::data(const QModelIndex &index, int role) const
|
||||
{
|
||||
KService::Ptr service = m_favoriteList.value(index.row()).service;
|
||||
if (service.isNull()) {
|
||||
return QVariant();
|
||||
}
|
||||
if (role == Qt::DisplayRole) {
|
||||
return service->name();
|
||||
} else if (role == Qt::DecorationRole) {
|
||||
return service->icon();
|
||||
} else if (role == FavoriteIdRole) {
|
||||
return QVariant("app:" + service->storageId());
|
||||
} else {
|
||||
kWarning() << "Unhandled role" << role;
|
||||
return QVariant();
|
||||
}
|
||||
}
|
||||
|
||||
bool FavoriteAppsModel::trigger(int row)
|
||||
{
|
||||
KService::Ptr service = m_favoriteList.value(row).service;
|
||||
if (service.isNull()) {
|
||||
kWarning() << "Invalid row";
|
||||
return false;
|
||||
}
|
||||
return KRun::run(*service, KUrl::List(), 0);
|
||||
}
|
||||
|
||||
#define CHECK_ROW(row) \
|
||||
if (row < 0 || row >= m_favoriteList.count()) { \
|
||||
kWarning() << "Invalid row number" << row; \
|
||||
return; \
|
||||
}
|
||||
|
||||
void FavoriteAppsModel::moveRow(int from, int to)
|
||||
{
|
||||
CHECK_ROW(from)
|
||||
CHECK_ROW(to)
|
||||
if (from == to) {
|
||||
kWarning() << "Cannot move row to itself";
|
||||
return;
|
||||
}
|
||||
// See beginMoveRows() doc for an explanation on modelTo
|
||||
int modelTo = to + (to > from ? 1 : 0);
|
||||
bool ok = beginMoveRows(QModelIndex(), from, from, QModelIndex(), modelTo);
|
||||
if (!ok) {
|
||||
kWarning() << "beginMoveRows failed";
|
||||
Q_ASSERT(!"beginMoveRows failed");
|
||||
}
|
||||
m_favoriteList.move(from, to);
|
||||
endMoveRows();
|
||||
|
||||
saveToXml();
|
||||
}
|
||||
|
||||
void FavoriteAppsModel::importFromConfigFile()
|
||||
{
|
||||
KSharedConfig::Ptr config = KSharedConfig::openConfig("homerunrc", KConfig::SimpleConfig);
|
||||
KConfigGroup baseGroup(config, "favorites");
|
||||
if (!baseGroup.exists()) {
|
||||
// No favorite to import. Leave now, we do not want to write an empty
|
||||
// xml file
|
||||
return;
|
||||
}
|
||||
|
||||
// Get favorites in a map to order them correctly
|
||||
QMap<int, KService::Ptr> favoriteMap;
|
||||
Q_FOREACH(const QString &favoriteGroup, baseGroup.groupList()) {
|
||||
if (favoriteGroup.startsWith("favorite-")) {
|
||||
KConfigGroup favoriteConfig(&baseGroup, favoriteGroup);
|
||||
int rank = favoriteGroup.split("-").last().toInt();
|
||||
QString id = favoriteConfig.readEntry("serviceId");
|
||||
KService::Ptr service = KService::serviceByStorageId(id);
|
||||
if (!service.isNull()) {
|
||||
favoriteMap.insert(rank, service);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Load favorites following map order
|
||||
beginResetModel();
|
||||
auto it = favoriteMap.constBegin(), end = favoriteMap.constEnd();
|
||||
for (; it != end; ++it) {
|
||||
FavoriteInfo info = { it.value() };
|
||||
m_favoriteList << info;
|
||||
}
|
||||
|
||||
// Finish migration
|
||||
saveToXml();
|
||||
config->deleteGroup("favorites");
|
||||
config->sync();
|
||||
|
||||
// Notify outside
|
||||
endResetModel();
|
||||
countChanged();
|
||||
}
|
||||
|
||||
} // namespace Homerun
|
||||
|
||||
#include "moc_favoriteappsmodel.cpp"
|
|
@ -1,90 +0,0 @@
|
|||
/*
|
||||
Copyright 2009 Ivan Cukic <ivan.cukic+kde@gmail.com>
|
||||
Copyright 2010 Marco Martin <notmart@gmail.com>
|
||||
Copyright 2012 Aurélien Gâteau <agateau@kde.org>
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Library General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Library General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Library General Public License
|
||||
along with this library; see the file COPYING.LIB. If not, write to
|
||||
the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
||||
Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#ifndef FAVORITEAPPSMODEL_H
|
||||
#define FAVORITEAPPSMODEL_H
|
||||
|
||||
#include <QtCore/qabstractitemmodel.h>
|
||||
|
||||
#include <KService>
|
||||
#include <KSharedConfig>
|
||||
|
||||
class QDomDocument;
|
||||
|
||||
namespace Homerun {
|
||||
|
||||
struct FavoriteInfo
|
||||
{
|
||||
KService::Ptr service;
|
||||
};
|
||||
|
||||
class FavoriteAppsModel : public QAbstractListModel
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_PROPERTY(QString name READ name CONSTANT)
|
||||
Q_PROPERTY(bool canMoveRow READ canMoveRow CONSTANT)
|
||||
Q_PROPERTY(int count READ count NOTIFY countChanged)
|
||||
|
||||
Q_PROPERTY(QString favoritePrefix READ favoritePrefix CONSTANT)
|
||||
|
||||
public:
|
||||
FavoriteAppsModel(QObject *parent = 0);
|
||||
~FavoriteAppsModel();
|
||||
|
||||
enum {
|
||||
FavoriteIdRole = Qt::UserRole + 1
|
||||
};
|
||||
|
||||
int count() const;
|
||||
QString name() const;
|
||||
bool canMoveRow() const;
|
||||
QString favoritePrefix() const;
|
||||
|
||||
int rowCount(const QModelIndex & = QModelIndex()) const;
|
||||
QVariant data(const QModelIndex &, int role = Qt::DisplayRole) const;
|
||||
|
||||
Q_INVOKABLE bool isFavorite(const QString &favoriteId) const;
|
||||
Q_INVOKABLE void addFavorite(const QString &favoriteId);
|
||||
Q_INVOKABLE void removeFavorite(const QString &favoriteId);
|
||||
|
||||
Q_INVOKABLE bool trigger(int row);
|
||||
|
||||
Q_INVOKABLE void moveRow(int from, int to);
|
||||
|
||||
Q_SIGNALS:
|
||||
void countChanged();
|
||||
void itemsMoved(int from, int to, int n);
|
||||
|
||||
private:
|
||||
KSharedConfig::Ptr m_config;
|
||||
QList<FavoriteInfo> m_favoriteList;
|
||||
|
||||
int rowForFavoriteId(const QString &favoriteId) const;
|
||||
|
||||
void load();
|
||||
void importFromConfigFile();
|
||||
bool loadFromXml(const QString &fileName);
|
||||
void saveToXml();
|
||||
};
|
||||
|
||||
} // namespace Homerun
|
||||
|
||||
#endif // FAVORITEAPPSMODEL_H
|
|
@ -1,166 +0,0 @@
|
|||
/*
|
||||
Copyright 2012 Aurélien Gâteau <agateau@kde.org>
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) 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 6 of version 3 of the license.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#include "favoriteplacesmodel.h"
|
||||
|
||||
// Local
|
||||
#include <dirmodel.h>
|
||||
#include <favoriteutils.h>
|
||||
|
||||
// libhomerun
|
||||
#include <actionlist.h>
|
||||
|
||||
// KDE
|
||||
#include <KDebug>
|
||||
#include <KFileItem>
|
||||
#include <KLocale>
|
||||
|
||||
// Qt
|
||||
|
||||
namespace Homerun {
|
||||
|
||||
//- FavoritePlacesModel ------------------------------------------------
|
||||
FavoritePlacesModel::FavoritePlacesModel(QObject *parent)
|
||||
: Fixes::KFilePlacesModel(parent)
|
||||
{
|
||||
QHash<int, QByteArray> roles;
|
||||
roles.insert(Qt::DisplayRole, "display");
|
||||
roles.insert(Qt::DecorationRole, "decoration");
|
||||
roles.insert(FavoriteIdRole, "favoriteId");
|
||||
roles.insert(HasActionListRole, "hasActionList");
|
||||
roles.insert(ActionListRole, "actionList");
|
||||
setRoleNames(roles);
|
||||
}
|
||||
|
||||
QString FavoritePlacesModel::favoritePrefix() const
|
||||
{
|
||||
return "place";
|
||||
}
|
||||
|
||||
bool FavoritePlacesModel::isFavorite(const QString &favoriteId) const
|
||||
{
|
||||
return indexForFavoriteId(favoriteId).isValid();
|
||||
}
|
||||
|
||||
void FavoritePlacesModel::addFavorite(const QString &favoriteId)
|
||||
{
|
||||
KUrl favoriteUrl = FavoriteUtils::urlFromFavoriteId(favoriteId);
|
||||
if (favoriteUrl.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
addPlace(favoriteUrl.fileName(), favoriteUrl);
|
||||
}
|
||||
|
||||
void FavoritePlacesModel::removeFavorite(const QString &favoriteId)
|
||||
{
|
||||
QModelIndex index = indexForFavoriteId(favoriteId);
|
||||
if (!index.isValid()) {
|
||||
kWarning() << "No favorite place for" << favoriteId;
|
||||
return;
|
||||
}
|
||||
removePlace(index);
|
||||
}
|
||||
|
||||
QModelIndex FavoritePlacesModel::indexForFavoriteId(const QString &favoriteId) const
|
||||
{
|
||||
KUrl favoriteUrl = FavoriteUtils::urlFromFavoriteId(favoriteId);
|
||||
if (favoriteUrl.isEmpty()) {
|
||||
return QModelIndex();
|
||||
}
|
||||
for (int row = rowCount() - 1; row >= 0; --row) {
|
||||
QModelIndex idx = index(row, 0);
|
||||
if (url(idx).equals(favoriteUrl, KUrl::CompareWithoutTrailingSlash)) {
|
||||
return idx;
|
||||
}
|
||||
}
|
||||
return QModelIndex();
|
||||
}
|
||||
|
||||
QVariant FavoritePlacesModel::data(const QModelIndex &index, int role) const
|
||||
{
|
||||
if (role != FavoriteIdRole && role != HasActionListRole && role != ActionListRole) {
|
||||
return Fixes::KFilePlacesModel::data(index, role);
|
||||
}
|
||||
|
||||
if (index.row() < 0 || index.row() >= rowCount()) {
|
||||
return QVariant();
|
||||
}
|
||||
if (role == FavoriteIdRole) {
|
||||
return QVariant(FavoriteUtils::favoriteIdFromUrl(url(index)));
|
||||
}
|
||||
if (role == HasActionListRole) {
|
||||
return true;
|
||||
}
|
||||
if (role == ActionListRole) {
|
||||
KFileItem item(KFileItem::Unknown, KFileItem::Unknown, url(index));
|
||||
return ActionList::createListForFileItem(item);
|
||||
}
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
bool FavoritePlacesModel::trigger(int row, const QString &actionId, const QVariant &actionArgument)
|
||||
{
|
||||
QModelIndex idx = index(row, 0);
|
||||
KUrl theUrl = idx.data(Fixes::KFilePlacesModel::UrlRole).value<QUrl>();
|
||||
if (actionId.isEmpty()) {
|
||||
theUrl.adjustPath(KUrl::AddTrailingSlash);
|
||||
QString rootName = idx.data(Qt::DisplayRole).toString();
|
||||
openSourceRequested("Dir", DirModel::sourceArguments(theUrl, rootName, theUrl));
|
||||
return false;
|
||||
}
|
||||
|
||||
bool close;
|
||||
KFileItem item(KFileItem::Unknown, KFileItem::Unknown, theUrl);
|
||||
if (ActionList::handleFileItemAction(item, actionId, actionArgument, &close)) {
|
||||
return close;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
QString FavoritePlacesModel::name() const
|
||||
{
|
||||
return i18n("Favorite Places");
|
||||
}
|
||||
|
||||
int FavoritePlacesModel::count() const
|
||||
{
|
||||
return rowCount(QModelIndex());
|
||||
}
|
||||
|
||||
void FavoritePlacesModel::moveRow(int from, int to)
|
||||
{
|
||||
// Simulate a move by drag'n'drop because moving the row this way
|
||||
// is the only way to get rowsMoved() signals instead of remove+insert
|
||||
QMimeData *data = mimeData(QModelIndexList() << index(from, 0));
|
||||
Q_ASSERT(data);
|
||||
if (from < to) {
|
||||
++to;
|
||||
}
|
||||
dropMimeData(data, Qt::MoveAction, to, 0, QModelIndex());
|
||||
}
|
||||
|
||||
bool FavoritePlacesModel::canMoveRow() const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace Homerun
|
||||
|
||||
#include "moc_favoriteplacesmodel.cpp"
|
|
@ -1,78 +0,0 @@
|
|||
/*
|
||||
Copyright 2012 Aurélien Gâteau <agateau@kde.org>
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) 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 6 of version 3 of the license.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#ifndef PLACESMODEL_H
|
||||
#define PLACESMODEL_H
|
||||
|
||||
// Local
|
||||
#include <fileplacesmodel.h>
|
||||
|
||||
// Qt
|
||||
|
||||
// KDE
|
||||
|
||||
namespace Homerun {
|
||||
|
||||
/**
|
||||
* Adapts KFilePlacesModel to make it usable as a Homerun favorite model
|
||||
*/
|
||||
class FavoritePlacesModel : public Fixes::KFilePlacesModel
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_PROPERTY(QString favoritePrefix READ favoritePrefix CONSTANT)
|
||||
Q_PROPERTY(int count READ count NOTIFY countChanged)
|
||||
Q_PROPERTY(QString name READ name CONSTANT)
|
||||
Q_PROPERTY(bool canMoveRow READ canMoveRow CONSTANT)
|
||||
|
||||
public:
|
||||
enum {
|
||||
FavoriteIdRole = Qt::UserRole + 1,
|
||||
HasActionListRole,
|
||||
ActionListRole,
|
||||
};
|
||||
|
||||
FavoritePlacesModel(QObject *parent = 0);
|
||||
|
||||
Q_INVOKABLE bool isFavorite(const QString &favoriteId) const;
|
||||
Q_INVOKABLE void addFavorite(const QString &favoriteId);
|
||||
Q_INVOKABLE void removeFavorite(const QString &favoriteId);
|
||||
Q_INVOKABLE bool trigger(int row, const QString &actionId, const QVariant &actionArg);
|
||||
Q_INVOKABLE void moveRow(int from, int to);
|
||||
|
||||
QString favoritePrefix() const;
|
||||
|
||||
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const; // reimp
|
||||
|
||||
QString name() const;
|
||||
|
||||
int count() const;
|
||||
|
||||
bool canMoveRow() const;
|
||||
|
||||
Q_SIGNALS:
|
||||
void openSourceRequested(const QString &sourceId, const QVariantMap &sourceArguments);
|
||||
void countChanged();
|
||||
|
||||
private:
|
||||
QModelIndex indexForFavoriteId(const QString &favoriteId) const;
|
||||
};
|
||||
|
||||
} // namespace Homerun
|
||||
|
||||
#endif /* PLACESMODEL_H */
|
|
@ -1,48 +0,0 @@
|
|||
/*
|
||||
Copyright 2013 Aurélien Gâteau <agateau@kde.org>
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) 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 6 of version 3 of the license.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#include <favoriteutils.h>
|
||||
|
||||
// KDE
|
||||
#include <KDebug>
|
||||
#include <KUrl>
|
||||
|
||||
namespace Homerun
|
||||
{
|
||||
|
||||
namespace FavoriteUtils
|
||||
{
|
||||
|
||||
KUrl urlFromFavoriteId(const QString &favoriteId)
|
||||
{
|
||||
if (!favoriteId.startsWith("place:")) {
|
||||
kWarning() << "Wrong favoriteId" << favoriteId;
|
||||
return QString();
|
||||
}
|
||||
return KUrl(favoriteId.mid(6));
|
||||
}
|
||||
|
||||
QString favoriteIdFromUrl(const KUrl &url)
|
||||
{
|
||||
return "place:" + url.url();
|
||||
}
|
||||
|
||||
} // namespace FavoriteUtils
|
||||
|
||||
} // namespace Homerun
|
|
@ -1,39 +0,0 @@
|
|||
/*
|
||||
Copyright 2013 Aurélien Gâteau <agateau@kde.org>
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) 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 6 of version 3 of the license.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#ifndef FAVORITEUTILS_H
|
||||
#define FAVORITEUTILS_H
|
||||
|
||||
class QString;
|
||||
class KUrl;
|
||||
|
||||
namespace Homerun
|
||||
{
|
||||
|
||||
namespace FavoriteUtils
|
||||
{
|
||||
|
||||
KUrl urlFromFavoriteId(const QString &favoriteId);
|
||||
QString favoriteIdFromUrl(const KUrl &url);
|
||||
|
||||
} // namespace FavoriteUtils
|
||||
|
||||
} // namespace Homerun
|
||||
|
||||
#endif /* FAVORITEUTILS_H */
|
|
@ -1,876 +0,0 @@
|
|||
/* This file is part of the KDE project
|
||||
Copyright (C) 2007 Kevin Ottens <ervin@kde.org>
|
||||
Copyright (C) 2007 David Faure <faure@kde.org>
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Library General Public
|
||||
License version 2 as published by the Free Software Foundation.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Library General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Library General Public License
|
||||
along with this library; see the file COPYING.LIB. If not, write to
|
||||
the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
||||
Boston, MA 02110-1301, USA.
|
||||
|
||||
*/
|
||||
#include "fileplacesmodel.h"
|
||||
#include "kfileplacesitem_p.h"
|
||||
#include "kfileplacessharedbookmarks_p.h"
|
||||
|
||||
#ifdef _WIN32_WCE
|
||||
#include "Windows.h"
|
||||
#include "WinBase.h"
|
||||
#include <QtCore/QDir>
|
||||
#endif
|
||||
|
||||
#include <QtCore/QMimeData>
|
||||
#include <QtCore/QTimer>
|
||||
#include <QtCore/QFile>
|
||||
#include <QtGui/QColor>
|
||||
#include <QtGui/QAction>
|
||||
|
||||
#include <kfileitem.h>
|
||||
#include <kglobal.h>
|
||||
#include <klocale.h>
|
||||
#include <kuser.h>
|
||||
#include <kstandarddirs.h>
|
||||
#include <kcomponentdata.h>
|
||||
#include <kicon.h>
|
||||
#include <kmimetype.h>
|
||||
#include <kdebug.h>
|
||||
|
||||
#include <kbookmarkmanager.h>
|
||||
#include <kbookmark.h>
|
||||
|
||||
#include <kio/netaccess.h>
|
||||
#include <kprotocolinfo.h>
|
||||
|
||||
#include <solid/devicenotifier.h>
|
||||
#include <solid/storageaccess.h>
|
||||
#include <solid/storagedrive.h>
|
||||
#include <solid/storagevolume.h>
|
||||
#include <solid/opticaldrive.h>
|
||||
#include <solid/opticaldisc.h>
|
||||
#include <solid/portablemediaplayer.h>
|
||||
#include <solid/predicate.h>
|
||||
|
||||
namespace Homerun
|
||||
{
|
||||
namespace Fixes
|
||||
{
|
||||
|
||||
class KFilePlacesModel::Private
|
||||
{
|
||||
public:
|
||||
Private(KFilePlacesModel *self) : q(self), bookmarkManager(0), sharedBookmarks(0) {}
|
||||
~Private()
|
||||
{
|
||||
delete sharedBookmarks;
|
||||
qDeleteAll(items);
|
||||
}
|
||||
|
||||
KFilePlacesModel *q;
|
||||
|
||||
QList<KFilePlacesItem*> items;
|
||||
QSet<QString> availableDevices;
|
||||
QMap<QObject*, QPersistentModelIndex> setupInProgress;
|
||||
|
||||
Solid::Predicate predicate;
|
||||
KBookmarkManager *bookmarkManager;
|
||||
KFilePlacesSharedBookmarks * sharedBookmarks;
|
||||
|
||||
void reloadAndSignal();
|
||||
QList<KFilePlacesItem *> loadBookmarkList();
|
||||
|
||||
void _k_initDeviceList();
|
||||
void _k_deviceAdded(const QString &udi);
|
||||
void _k_deviceRemoved(const QString &udi);
|
||||
void _k_itemChanged(const QString &udi);
|
||||
void _k_reloadBookmarks();
|
||||
void _k_storageSetupDone(Solid::ErrorType error, QVariant errorData);
|
||||
void _k_storageTeardownDone(Solid::ErrorType error, QVariant errorData);
|
||||
};
|
||||
|
||||
KFilePlacesModel::KFilePlacesModel(QObject *parent)
|
||||
: QAbstractItemModel(parent), d(new Private(this))
|
||||
{
|
||||
const QString file = KStandardDirs::locateLocal("data", "kfileplaces/bookmarks.xml");
|
||||
d->bookmarkManager = KBookmarkManager::managerForFile(file, "kfilePlaces");
|
||||
|
||||
// Let's put some places in there if it's empty. We have a corner case here:
|
||||
// Given you have bookmarked some folders (which have been saved on
|
||||
// ~/.local/share/user-places.xbel (according to freedesktop bookmarks spec), and
|
||||
// deleted the home directory ~/.kde, the call managerForFile() will return the
|
||||
// bookmark manager for the fallback "kfilePlaces", making root.first().isNull() being
|
||||
// false (you have your own items bookmarked), resulting on only being added your own
|
||||
// bookmarks, and not the default ones too. So, we also check if kfileplaces/bookmarks.xml
|
||||
// file exists, and if it doesn't, we also add the default places. (ereslibre)
|
||||
KBookmarkGroup root = d->bookmarkManager->root();
|
||||
if (root.first().isNull() || !QFile::exists(file)) {
|
||||
|
||||
// NOTE: The context for these I18N_NOOP2 calls has to be "KFile System Bookmarks".
|
||||
// The real i18nc call is made later, with this context, so the two must match.
|
||||
//
|
||||
// createSystemBookmark actually does nothing with its third argument,
|
||||
// but we have to give it something so the I18N_NOOP2 calls stay here for now.
|
||||
//
|
||||
// (coles, 13th May 2009)
|
||||
|
||||
KFilePlacesItem::createSystemBookmark(d->bookmarkManager,
|
||||
"Home", I18N_NOOP2("KFile System Bookmarks", "Home"),
|
||||
KUrl(KUser().homeDir()), "user-home");
|
||||
KFilePlacesItem::createSystemBookmark(d->bookmarkManager,
|
||||
"Network", I18N_NOOP2("KFile System Bookmarks", "Network"),
|
||||
KUrl("remote:/"), "network-workgroup");
|
||||
#if defined(_WIN32_WCE)
|
||||
// adding drives
|
||||
foreach ( const QFileInfo& info, QDir::drives() ) {
|
||||
QString driveIcon = "drive-harddisk";
|
||||
KFilePlacesItem::createSystemBookmark(d->bookmarkManager,
|
||||
info.absoluteFilePath(), info.absoluteFilePath(),
|
||||
KUrl(info.absoluteFilePath()), driveIcon);
|
||||
}
|
||||
#elif !defined(Q_OS_WIN)
|
||||
KFilePlacesItem::createSystemBookmark(d->bookmarkManager,
|
||||
"Root", I18N_NOOP2("KFile System Bookmarks", "Root"),
|
||||
KUrl("/"), "folder-red");
|
||||
#endif
|
||||
KFilePlacesItem::createSystemBookmark(d->bookmarkManager,
|
||||
"Trash", I18N_NOOP2("KFile System Bookmarks", "Trash"),
|
||||
KUrl("trash:/"), "user-trash");
|
||||
|
||||
// Force bookmarks to be saved. If on open/save dialog and the bookmarks are not saved, QFile::exists
|
||||
// will always return false, which opening/closing all the time the open/save dialog would case the
|
||||
// bookmarks to be added once each time, having lots of times each bookmark. This forces the defaults
|
||||
// to be saved on the bookmarks.xml file. Of course, the complete list of bookmarks (those that come from
|
||||
// user-places.xbel will be filled later). (ereslibre)
|
||||
d->bookmarkManager->saveAs(file);
|
||||
}
|
||||
|
||||
// create after, so if we have own places, they are added afterwards, in case of equal priorities
|
||||
d->sharedBookmarks = new KFilePlacesSharedBookmarks(d->bookmarkManager);
|
||||
|
||||
QString predicate("[[[[ StorageVolume.ignored == false AND [ StorageVolume.usage == 'FileSystem' OR StorageVolume.usage == 'Encrypted' ]]"
|
||||
" OR "
|
||||
"[ IS StorageAccess AND StorageDrive.driveType == 'Floppy' ]]"
|
||||
" OR "
|
||||
"OpticalDisc.availableContent & 'Audio' ]"
|
||||
" OR "
|
||||
"StorageAccess.ignored == false ]");
|
||||
|
||||
if (KProtocolInfo::isKnownProtocol("mtp")) {
|
||||
predicate.prepend("[");
|
||||
predicate.append(" OR PortableMediaPlayer.supportedProtocols == 'mtp']");
|
||||
}
|
||||
|
||||
d->predicate = Solid::Predicate::fromString(predicate);
|
||||
|
||||
Q_ASSERT(d->predicate.isValid());
|
||||
|
||||
connect(d->bookmarkManager, SIGNAL(changed(QString,QString)),
|
||||
this, SLOT(_k_reloadBookmarks()));
|
||||
connect(d->bookmarkManager, SIGNAL(bookmarksChanged(QString)),
|
||||
this, SLOT(_k_reloadBookmarks()));
|
||||
|
||||
d->_k_reloadBookmarks();
|
||||
QTimer::singleShot(0, this, SLOT(_k_initDeviceList()));
|
||||
}
|
||||
|
||||
KFilePlacesModel::~KFilePlacesModel()
|
||||
{
|
||||
delete d;
|
||||
}
|
||||
|
||||
KUrl KFilePlacesModel::url(const QModelIndex &index) const
|
||||
{
|
||||
return KUrl(data(index, UrlRole).toUrl());
|
||||
}
|
||||
|
||||
bool KFilePlacesModel::setupNeeded(const QModelIndex &index) const
|
||||
{
|
||||
return data(index, SetupNeededRole).toBool();
|
||||
}
|
||||
|
||||
KIcon KFilePlacesModel::icon(const QModelIndex &index) const
|
||||
{
|
||||
return KIcon(data(index, Qt::DecorationRole).value<QIcon>());
|
||||
}
|
||||
|
||||
QString KFilePlacesModel::text(const QModelIndex &index) const
|
||||
{
|
||||
return data(index, Qt::DisplayRole).toString();
|
||||
}
|
||||
|
||||
bool KFilePlacesModel::isHidden(const QModelIndex &index) const
|
||||
{
|
||||
return data(index, HiddenRole).toBool();
|
||||
}
|
||||
|
||||
bool KFilePlacesModel::isDevice(const QModelIndex &index) const
|
||||
{
|
||||
if (!index.isValid())
|
||||
return false;
|
||||
|
||||
KFilePlacesItem *item = static_cast<KFilePlacesItem*>(index.internalPointer());
|
||||
|
||||
return item->isDevice();
|
||||
}
|
||||
|
||||
Solid::Device KFilePlacesModel::deviceForIndex(const QModelIndex &index) const
|
||||
{
|
||||
if (!index.isValid())
|
||||
return Solid::Device();
|
||||
|
||||
KFilePlacesItem *item = static_cast<KFilePlacesItem*>(index.internalPointer());
|
||||
|
||||
if (item->isDevice()) {
|
||||
return item->device();
|
||||
} else {
|
||||
return Solid::Device();
|
||||
}
|
||||
}
|
||||
|
||||
KBookmark KFilePlacesModel::bookmarkForIndex(const QModelIndex &index) const
|
||||
{
|
||||
if (!index.isValid())
|
||||
return KBookmark();
|
||||
|
||||
KFilePlacesItem *item = static_cast<KFilePlacesItem*>(index.internalPointer());
|
||||
|
||||
if (!item->isDevice()) {
|
||||
return item->bookmark();
|
||||
} else {
|
||||
return KBookmark();
|
||||
}
|
||||
}
|
||||
|
||||
QVariant KFilePlacesModel::data(const QModelIndex &index, int role) const
|
||||
{
|
||||
if (!index.isValid())
|
||||
return QVariant();
|
||||
|
||||
KFilePlacesItem *item = static_cast<KFilePlacesItem*>(index.internalPointer());
|
||||
return item->data(role);
|
||||
}
|
||||
|
||||
QModelIndex KFilePlacesModel::index(int row, int column, const QModelIndex &parent) const
|
||||
{
|
||||
if (row<0 || column!=0 || row>=d->items.size())
|
||||
return QModelIndex();
|
||||
|
||||
if (parent.isValid())
|
||||
return QModelIndex();
|
||||
|
||||
return createIndex(row, column, d->items.at(row));
|
||||
}
|
||||
|
||||
QModelIndex KFilePlacesModel::parent(const QModelIndex &child) const
|
||||
{
|
||||
Q_UNUSED(child);
|
||||
return QModelIndex();
|
||||
}
|
||||
|
||||
int KFilePlacesModel::rowCount(const QModelIndex &parent) const
|
||||
{
|
||||
if (parent.isValid())
|
||||
return 0;
|
||||
else
|
||||
return d->items.size();
|
||||
}
|
||||
|
||||
int KFilePlacesModel::columnCount(const QModelIndex &parent) const
|
||||
{
|
||||
Q_UNUSED(parent)
|
||||
// We only know 1 piece of information for a particular entry
|
||||
return 1;
|
||||
}
|
||||
|
||||
QModelIndex KFilePlacesModel::closestItem(const KUrl &url) const
|
||||
{
|
||||
int foundRow = -1;
|
||||
int maxLength = 0;
|
||||
|
||||
// Search the item which is equal to the URL or at least is a parent URL.
|
||||
// If there are more than one possible item URL candidates, choose the item
|
||||
// which covers the bigger range of the URL.
|
||||
for (int row = 0; row<d->items.size(); ++row) {
|
||||
KFilePlacesItem *item = d->items[row];
|
||||
KUrl itemUrl = KUrl(item->data(UrlRole).toUrl());
|
||||
|
||||
if (itemUrl.isParentOf(url)) {
|
||||
const int length = itemUrl.prettyUrl().length();
|
||||
if (length > maxLength) {
|
||||
foundRow = row;
|
||||
maxLength = length;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (foundRow==-1)
|
||||
return QModelIndex();
|
||||
else
|
||||
return createIndex(foundRow, 0, d->items[foundRow]);
|
||||
}
|
||||
|
||||
void KFilePlacesModel::Private::_k_initDeviceList()
|
||||
{
|
||||
Solid::DeviceNotifier *notifier = Solid::DeviceNotifier::instance();
|
||||
|
||||
connect(notifier, SIGNAL(deviceAdded(QString)),
|
||||
q, SLOT(_k_deviceAdded(QString)));
|
||||
connect(notifier, SIGNAL(deviceRemoved(QString)),
|
||||
q, SLOT(_k_deviceRemoved(QString)));
|
||||
|
||||
const QList<Solid::Device> &deviceList = Solid::Device::listFromQuery(predicate);
|
||||
|
||||
foreach(const Solid::Device &device, deviceList) {
|
||||
availableDevices << device.udi();
|
||||
}
|
||||
|
||||
_k_reloadBookmarks();
|
||||
}
|
||||
|
||||
void KFilePlacesModel::Private::_k_deviceAdded(const QString &udi)
|
||||
{
|
||||
Solid::Device d(udi);
|
||||
|
||||
if (predicate.matches(d)) {
|
||||
availableDevices << udi;
|
||||
_k_reloadBookmarks();
|
||||
}
|
||||
}
|
||||
|
||||
void KFilePlacesModel::Private::_k_deviceRemoved(const QString &udi)
|
||||
{
|
||||
if (availableDevices.contains(udi)) {
|
||||
availableDevices.remove(udi);
|
||||
_k_reloadBookmarks();
|
||||
}
|
||||
}
|
||||
|
||||
void KFilePlacesModel::Private::_k_itemChanged(const QString &id)
|
||||
{
|
||||
for (int row = 0; row<items.size(); ++row) {
|
||||
if (items.at(row)->id()==id) {
|
||||
QModelIndex index = q->index(row, 0);
|
||||
emit q->dataChanged(index, index);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void KFilePlacesModel::Private::_k_reloadBookmarks()
|
||||
{
|
||||
QList<KFilePlacesItem*> currentItems = loadBookmarkList();
|
||||
|
||||
QList<KFilePlacesItem*>::Iterator it_i = items.begin();
|
||||
QList<KFilePlacesItem*>::Iterator it_c = currentItems.begin();
|
||||
|
||||
QList<KFilePlacesItem*>::Iterator end_i = items.end();
|
||||
QList<KFilePlacesItem*>::Iterator end_c = currentItems.end();
|
||||
|
||||
while (it_i!=end_i || it_c!=end_c) {
|
||||
if (it_i==end_i && it_c!=end_c) {
|
||||
int row = items.count();
|
||||
|
||||
q->beginInsertRows(QModelIndex(), row, row);
|
||||
it_i = items.insert(it_i, *it_c);
|
||||
++it_i;
|
||||
it_c = currentItems.erase(it_c);
|
||||
|
||||
end_i = items.end();
|
||||
end_c = currentItems.end();
|
||||
q->endInsertRows();
|
||||
|
||||
} else if (it_i!=end_i && it_c==end_c) {
|
||||
int row = items.indexOf(*it_i);
|
||||
|
||||
q->beginRemoveRows(QModelIndex(), row, row);
|
||||
delete *it_i;
|
||||
it_i = items.erase(it_i);
|
||||
|
||||
end_i = items.end();
|
||||
end_c = currentItems.end();
|
||||
q->endRemoveRows();
|
||||
|
||||
} else if ((*it_i)->id()==(*it_c)->id()) {
|
||||
bool shouldEmit = !((*it_i)->bookmark()==(*it_c)->bookmark());
|
||||
(*it_i)->setBookmark((*it_c)->bookmark());
|
||||
if (shouldEmit) {
|
||||
int row = items.indexOf(*it_i);
|
||||
QModelIndex idx = q->index(row, 0);
|
||||
emit q->dataChanged(idx, idx);
|
||||
}
|
||||
++it_i;
|
||||
++it_c;
|
||||
} else if ((*it_i)->id()!=(*it_c)->id()) {
|
||||
int row = items.indexOf(*it_i);
|
||||
|
||||
if (it_i+1!=end_i && (*(it_i+1))->id()==(*it_c)->id()) { // if the next one matches, it's a remove
|
||||
q->beginRemoveRows(QModelIndex(), row, row);
|
||||
delete *it_i;
|
||||
it_i = items.erase(it_i);
|
||||
|
||||
end_i = items.end();
|
||||
end_c = currentItems.end();
|
||||
q->endRemoveRows();
|
||||
} else {
|
||||
q->beginInsertRows(QModelIndex(), row, row);
|
||||
it_i = items.insert(it_i, *it_c);
|
||||
++it_i;
|
||||
it_c = currentItems.erase(it_c);
|
||||
|
||||
end_i = items.end();
|
||||
end_c = currentItems.end();
|
||||
q->endInsertRows();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
qDeleteAll(currentItems);
|
||||
currentItems.clear();
|
||||
}
|
||||
|
||||
QList<KFilePlacesItem *> KFilePlacesModel::Private::loadBookmarkList()
|
||||
{
|
||||
QList<KFilePlacesItem*> items;
|
||||
|
||||
KBookmarkGroup root = bookmarkManager->root();
|
||||
KBookmark bookmark = root.first();
|
||||
QSet<QString> devices = availableDevices;
|
||||
|
||||
while (!bookmark.isNull()) {
|
||||
QString udi = bookmark.metaDataItem("UDI");
|
||||
QString appName = bookmark.metaDataItem("OnlyInApp");
|
||||
bool deviceAvailable = devices.remove(udi);
|
||||
|
||||
bool allowedHere = appName.isEmpty() || (appName==KGlobal::mainComponent().componentName());
|
||||
|
||||
if ((udi.isEmpty() && allowedHere) || deviceAvailable) {
|
||||
KFilePlacesItem *item;
|
||||
if (deviceAvailable) {
|
||||
item = new KFilePlacesItem(bookmarkManager, bookmark.address(), udi);
|
||||
// TODO: Update bookmark internal element
|
||||
} else {
|
||||
item = new KFilePlacesItem(bookmarkManager, bookmark.address());
|
||||
}
|
||||
connect(item, SIGNAL(itemChanged(QString)),
|
||||
q, SLOT(_k_itemChanged(QString)));
|
||||
items << item;
|
||||
}
|
||||
|
||||
bookmark = root.next(bookmark);
|
||||
}
|
||||
|
||||
// Add bookmarks for the remaining devices, they were previously unknown
|
||||
foreach (const QString &udi, devices) {
|
||||
bookmark = KFilePlacesItem::createDeviceBookmark(bookmarkManager, udi);
|
||||
if (!bookmark.isNull()) {
|
||||
KFilePlacesItem *item = new KFilePlacesItem(bookmarkManager,
|
||||
bookmark.address(), udi);
|
||||
connect(item, SIGNAL(itemChanged(QString)),
|
||||
q, SLOT(_k_itemChanged(QString)));
|
||||
// TODO: Update bookmark internal element
|
||||
items << item;
|
||||
}
|
||||
}
|
||||
|
||||
return items;
|
||||
}
|
||||
|
||||
void KFilePlacesModel::Private::reloadAndSignal()
|
||||
{
|
||||
bookmarkManager->emitChanged(bookmarkManager->root()); // ... we'll get relisted anyway
|
||||
}
|
||||
|
||||
Qt::DropActions KFilePlacesModel::supportedDropActions() const
|
||||
{
|
||||
return Qt::ActionMask;
|
||||
}
|
||||
|
||||
Qt::ItemFlags KFilePlacesModel::flags(const QModelIndex &index) const
|
||||
{
|
||||
Qt::ItemFlags res = Qt::ItemIsSelectable|Qt::ItemIsEnabled;
|
||||
|
||||
if (index.isValid())
|
||||
res|= Qt::ItemIsDragEnabled;
|
||||
|
||||
if (!index.isValid())
|
||||
res|= Qt::ItemIsDropEnabled;
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
static QString _k_internalMimetype(const KFilePlacesModel * const self)
|
||||
{
|
||||
return QString("application/x-fileplacesmodel-")+QString::number((qptrdiff)self);
|
||||
}
|
||||
|
||||
QStringList KFilePlacesModel::mimeTypes() const
|
||||
{
|
||||
QStringList types;
|
||||
|
||||
types << _k_internalMimetype(this) << "text/uri-list";
|
||||
|
||||
return types;
|
||||
}
|
||||
|
||||
QMimeData *KFilePlacesModel::mimeData(const QModelIndexList &indexes) const
|
||||
{
|
||||
KUrl::List urls;
|
||||
QByteArray itemData;
|
||||
|
||||
QDataStream stream(&itemData, QIODevice::WriteOnly);
|
||||
|
||||
foreach (const QModelIndex &index, indexes) {
|
||||
KUrl itemUrl = url(index);
|
||||
if (itemUrl.isValid())
|
||||
urls << itemUrl;
|
||||
stream << index.row();
|
||||
}
|
||||
|
||||
QMimeData *mimeData = new QMimeData();
|
||||
|
||||
if (!urls.isEmpty())
|
||||
urls.populateMimeData(mimeData);
|
||||
|
||||
mimeData->setData(_k_internalMimetype(this), itemData);
|
||||
|
||||
return mimeData;
|
||||
}
|
||||
|
||||
bool KFilePlacesModel::dropMimeData(const QMimeData *data, Qt::DropAction action,
|
||||
int row, int column, const QModelIndex &parent)
|
||||
{
|
||||
if (action == Qt::IgnoreAction)
|
||||
return true;
|
||||
|
||||
if (column > 0)
|
||||
return false;
|
||||
|
||||
if (row==-1 && parent.isValid()) {
|
||||
return false; // Don't allow to move an item onto another one,
|
||||
// too easy for the user to mess something up
|
||||
// If we really really want to allow copying files this way,
|
||||
// let's do it in the views to get the good old drop menu
|
||||
}
|
||||
|
||||
|
||||
KBookmark afterBookmark;
|
||||
|
||||
if (row==-1) {
|
||||
// The dropped item is moved or added to the last position
|
||||
|
||||
KFilePlacesItem *lastItem = d->items.last();
|
||||
afterBookmark = lastItem->bookmark();
|
||||
|
||||
} else {
|
||||
// The dropped item is moved or added before position 'row', ie after position 'row-1'
|
||||
|
||||
if (row>0) {
|
||||
KFilePlacesItem *afterItem = d->items[row-1];
|
||||
afterBookmark = afterItem->bookmark();
|
||||
}
|
||||
}
|
||||
|
||||
if (data->hasFormat(_k_internalMimetype(this))) {
|
||||
// The operation is an internal move
|
||||
QByteArray itemData = data->data(_k_internalMimetype(this));
|
||||
QDataStream stream(&itemData, QIODevice::ReadOnly);
|
||||
int itemRow;
|
||||
|
||||
stream >> itemRow;
|
||||
|
||||
KFilePlacesItem *item = d->items[itemRow];
|
||||
KBookmark bookmark = item->bookmark();
|
||||
|
||||
int destRow = row == -1 ? d->items.count() : row;
|
||||
beginMoveRows(QModelIndex(), itemRow, itemRow, QModelIndex(), destRow);
|
||||
d->bookmarkManager->root().moveBookmark(bookmark, afterBookmark);
|
||||
// Move item ourselves so that _k_reloadBookmarks() does not consider
|
||||
// the move as a remove + insert.
|
||||
//
|
||||
// 2nd argument of QList::move() expects the final destination index,
|
||||
// but 'row' is the value of the destination index before the moved
|
||||
// item has been removed from its original position. That is why we
|
||||
// adjust if necessary.
|
||||
d->items.move(itemRow, itemRow < destRow ? (destRow - 1) : destRow);
|
||||
endMoveRows();
|
||||
} else if (data->hasFormat("text/uri-list")) {
|
||||
// The operation is an add
|
||||
KUrl::List urls = KUrl::List::fromMimeData(data);
|
||||
|
||||
KBookmarkGroup group = d->bookmarkManager->root();
|
||||
|
||||
foreach (const KUrl &url, urls) {
|
||||
// TODO: use KIO::stat in order to get the UDS_DISPLAY_NAME too
|
||||
KMimeType::Ptr mimetype = KMimeType::mimeType(KIO::NetAccess::mimetype(url, 0));
|
||||
|
||||
if (!mimetype) {
|
||||
kWarning() << "URL not added to Places as mimetype could not be determined!";
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!mimetype->is("inode/directory")) {
|
||||
// Only directories are allowed
|
||||
continue;
|
||||
}
|
||||
|
||||
KBookmark bookmark = KFilePlacesItem::createBookmark(d->bookmarkManager,
|
||||
url.fileName(), url,
|
||||
mimetype->iconName(url));
|
||||
group.moveBookmark(bookmark, afterBookmark);
|
||||
afterBookmark = bookmark;
|
||||
}
|
||||
|
||||
} else {
|
||||
// Oops, shouldn't happen thanks to mimeTypes()
|
||||
kWarning() << ": received wrong mimedata, " << data->formats();
|
||||
return false;
|
||||
}
|
||||
|
||||
d->reloadAndSignal();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void KFilePlacesModel::addPlace(const QString &text, const KUrl &url,
|
||||
const QString &iconName, const QString &appName)
|
||||
{
|
||||
addPlace(text, url, iconName, appName, QModelIndex());
|
||||
}
|
||||
|
||||
void KFilePlacesModel::addPlace(const QString &text, const KUrl &url,
|
||||
const QString &iconName, const QString &appName,
|
||||
const QModelIndex &after)
|
||||
{
|
||||
KBookmark bookmark = KFilePlacesItem::createBookmark(d->bookmarkManager,
|
||||
text, url, iconName);
|
||||
|
||||
if (!appName.isEmpty()) {
|
||||
bookmark.setMetaDataItem("OnlyInApp", appName);
|
||||
}
|
||||
|
||||
if (after.isValid()) {
|
||||
KFilePlacesItem *item = static_cast<KFilePlacesItem*>(after.internalPointer());
|
||||
d->bookmarkManager->root().moveBookmark(bookmark, item->bookmark());
|
||||
}
|
||||
|
||||
d->reloadAndSignal();
|
||||
}
|
||||
|
||||
void KFilePlacesModel::editPlace(const QModelIndex &index, const QString &text, const KUrl &url,
|
||||
const QString &iconName, const QString &appName)
|
||||
{
|
||||
if (!index.isValid()) return;
|
||||
|
||||
KFilePlacesItem *item = static_cast<KFilePlacesItem*>(index.internalPointer());
|
||||
|
||||
if (item->isDevice()) return;
|
||||
|
||||
KBookmark bookmark = item->bookmark();
|
||||
|
||||
if (bookmark.isNull()) return;
|
||||
|
||||
bookmark.setFullText(text);
|
||||
bookmark.setUrl(url);
|
||||
bookmark.setIcon(iconName);
|
||||
bookmark.setMetaDataItem("OnlyInApp", appName);
|
||||
|
||||
d->reloadAndSignal();
|
||||
emit dataChanged(index, index);
|
||||
}
|
||||
|
||||
void KFilePlacesModel::removePlace(const QModelIndex &index) const
|
||||
{
|
||||
if (!index.isValid()) return;
|
||||
|
||||
KFilePlacesItem *item = static_cast<KFilePlacesItem*>(index.internalPointer());
|
||||
|
||||
if (item->isDevice()) return;
|
||||
|
||||
KBookmark bookmark = item->bookmark();
|
||||
|
||||
if (bookmark.isNull()) return;
|
||||
|
||||
d->bookmarkManager->root().deleteBookmark(bookmark);
|
||||
d->reloadAndSignal();
|
||||
}
|
||||
|
||||
void KFilePlacesModel::setPlaceHidden(const QModelIndex &index, bool hidden)
|
||||
{
|
||||
if (!index.isValid()) return;
|
||||
|
||||
KFilePlacesItem *item = static_cast<KFilePlacesItem*>(index.internalPointer());
|
||||
|
||||
KBookmark bookmark = item->bookmark();
|
||||
|
||||
if (bookmark.isNull()) return;
|
||||
|
||||
bookmark.setMetaDataItem("IsHidden", (hidden ? "true" : "false"));
|
||||
|
||||
d->reloadAndSignal();
|
||||
emit dataChanged(index, index);
|
||||
}
|
||||
|
||||
int KFilePlacesModel::hiddenCount() const
|
||||
{
|
||||
int rows = rowCount();
|
||||
int hidden = 0;
|
||||
|
||||
for (int i=0; i<rows; ++i) {
|
||||
if (isHidden(index(i, 0))) {
|
||||
hidden++;
|
||||
}
|
||||
}
|
||||
|
||||
return hidden;
|
||||
}
|
||||
|
||||
QAction *KFilePlacesModel::teardownActionForIndex(const QModelIndex &index) const
|
||||
{
|
||||
Solid::Device device = deviceForIndex(index);
|
||||
|
||||
if (device.is<Solid::StorageAccess>() && device.as<Solid::StorageAccess>()->isAccessible()) {
|
||||
|
||||
Solid::StorageDrive *drive = device.as<Solid::StorageDrive>();
|
||||
|
||||
if (drive==0) {
|
||||
drive = device.parent().as<Solid::StorageDrive>();
|
||||
}
|
||||
|
||||
bool hotpluggable = false;
|
||||
bool removable = false;
|
||||
|
||||
if (drive!=0) {
|
||||
hotpluggable = drive->isHotpluggable();
|
||||
removable = drive->isRemovable();
|
||||
}
|
||||
|
||||
QString iconName;
|
||||
QString text;
|
||||
QString label = data(index, Qt::DisplayRole).toString().replace('&',"&&");
|
||||
|
||||
if (device.is<Solid::OpticalDisc>()) {
|
||||
text = i18n("&Release '%1'", label);
|
||||
} else if (removable || hotpluggable) {
|
||||
text = i18n("&Safely Remove '%1'", label);
|
||||
iconName = "media-eject";
|
||||
} else {
|
||||
text = i18n("&Unmount '%1'", label);
|
||||
iconName = "media-eject";
|
||||
}
|
||||
|
||||
if (!iconName.isEmpty()) {
|
||||
return new QAction(KIcon(iconName), text, 0);
|
||||
} else {
|
||||
return new QAction(text, 0);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
QAction *KFilePlacesModel::ejectActionForIndex(const QModelIndex &index) const
|
||||
{
|
||||
Solid::Device device = deviceForIndex(index);
|
||||
|
||||
if (device.is<Solid::OpticalDisc>()) {
|
||||
|
||||
QString label = data(index, Qt::DisplayRole).toString().replace('&',"&&");
|
||||
QString text = i18n("&Eject '%1'", label);
|
||||
|
||||
return new QAction(KIcon("media-eject"), text, 0);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void KFilePlacesModel::requestTeardown(const QModelIndex &index)
|
||||
{
|
||||
Solid::Device device = deviceForIndex(index);
|
||||
Solid::StorageAccess *access = device.as<Solid::StorageAccess>();
|
||||
|
||||
if (access!=0) {
|
||||
connect(access, SIGNAL(teardownDone(Solid::ErrorType,QVariant,QString)),
|
||||
this, SLOT(_k_storageTeardownDone(Solid::ErrorType,QVariant)));
|
||||
|
||||
access->teardown();
|
||||
}
|
||||
}
|
||||
|
||||
void KFilePlacesModel::requestEject(const QModelIndex &index)
|
||||
{
|
||||
Solid::Device device = deviceForIndex(index);
|
||||
|
||||
Solid::OpticalDrive *drive = device.parent().as<Solid::OpticalDrive>();
|
||||
|
||||
if (drive!=0) {
|
||||
connect(drive, SIGNAL(ejectDone(Solid::ErrorType,QVariant,QString)),
|
||||
this, SLOT(_k_storageTeardownDone(Solid::ErrorType,QVariant)));
|
||||
|
||||
drive->eject();
|
||||
} else {
|
||||
QString label = data(index, Qt::DisplayRole).toString().replace('&',"&&");
|
||||
QString message = i18n("The device '%1' is not a disk and cannot be ejected.", label);
|
||||
emit errorMessage(message);
|
||||
}
|
||||
}
|
||||
|
||||
void KFilePlacesModel::requestSetup(const QModelIndex &index)
|
||||
{
|
||||
Solid::Device device = deviceForIndex(index);
|
||||
|
||||
if (device.is<Solid::StorageAccess>()
|
||||
&& !d->setupInProgress.contains(device.as<Solid::StorageAccess>())
|
||||
&& !device.as<Solid::StorageAccess>()->isAccessible()) {
|
||||
|
||||
Solid::StorageAccess *access = device.as<Solid::StorageAccess>();
|
||||
|
||||
d->setupInProgress[access] = index;
|
||||
|
||||
connect(access, SIGNAL(setupDone(Solid::ErrorType,QVariant,QString)),
|
||||
this, SLOT(_k_storageSetupDone(Solid::ErrorType,QVariant)));
|
||||
|
||||
access->setup();
|
||||
}
|
||||
}
|
||||
|
||||
void KFilePlacesModel::Private::_k_storageSetupDone(Solid::ErrorType error, QVariant errorData)
|
||||
{
|
||||
QPersistentModelIndex index = setupInProgress.take(q->sender());
|
||||
|
||||
if (!index.isValid()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!error) {
|
||||
emit q->setupDone(index, true);
|
||||
} else {
|
||||
if (errorData.isValid()) {
|
||||
emit q->errorMessage(i18n("An error occurred while accessing '%1', the system responded: %2",
|
||||
q->text(index),
|
||||
errorData.toString()));
|
||||
} else {
|
||||
emit q->errorMessage(i18n("An error occurred while accessing '%1'",
|
||||
q->text(index)));
|
||||
}
|
||||
emit q->setupDone(index, false);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void KFilePlacesModel::Private::_k_storageTeardownDone(Solid::ErrorType error, QVariant errorData)
|
||||
{
|
||||
if (error && errorData.isValid()) {
|
||||
emit q->errorMessage(errorData.toString());
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace
|
||||
} // namespace
|
||||
|
||||
#include "moc_fileplacesmodel.cpp"
|
|
@ -1,159 +0,0 @@
|
|||
/* This file is part of the KDE project
|
||||
Copyright (C) 2007 Kevin Ottens <ervin@kde.org>
|
||||
Copyright (C) 2007 David Faure <faure@kde.org>
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Library General Public
|
||||
License version 2 as published by the Free Software Foundation.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Library General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Library General Public License
|
||||
along with this library; see the file COPYING.LIB. If not, write to
|
||||
the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
||||
Boston, MA 02110-1301, USA.
|
||||
|
||||
*/
|
||||
#ifndef KFILEPLACESMODEL_H
|
||||
#define KFILEPLACESMODEL_H
|
||||
|
||||
#include <kfile_export.h>
|
||||
|
||||
#include <QtCore/QAbstractItemModel>
|
||||
#include <kurl.h>
|
||||
#include <kbookmark.h>
|
||||
#include <kicon.h>
|
||||
|
||||
#include <solid/device.h>
|
||||
|
||||
class QMimeData;
|
||||
class QAction;
|
||||
|
||||
namespace Homerun
|
||||
{
|
||||
namespace Fixes
|
||||
{
|
||||
|
||||
/**
|
||||
* This class is a list view model. Each entry represents a "place"
|
||||
* where user can access files. Only revelant when
|
||||
* used with QListView or QTableView.
|
||||
*/
|
||||
class KFILE_EXPORT KFilePlacesModel : public QAbstractItemModel
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
enum AdditionalRoles {
|
||||
UrlRole = 0x069CD12B,
|
||||
HiddenRole = 0x0741CAAC,
|
||||
SetupNeededRole = 0x059A935D,
|
||||
FixedDeviceRole = 0x332896C1,
|
||||
CapacityBarRecommendedRole = 0x1548C5C4
|
||||
};
|
||||
|
||||
KFilePlacesModel(QObject *parent=0);
|
||||
~KFilePlacesModel();
|
||||
|
||||
KUrl url(const QModelIndex &index) const;
|
||||
bool setupNeeded(const QModelIndex &index) const;
|
||||
KIcon icon(const QModelIndex &index) const;
|
||||
QString text(const QModelIndex &index) const;
|
||||
bool isHidden(const QModelIndex &index) const;
|
||||
bool isDevice(const QModelIndex &index) const;
|
||||
Solid::Device deviceForIndex(const QModelIndex &index) const;
|
||||
KBookmark bookmarkForIndex(const QModelIndex &index) const;
|
||||
|
||||
QAction *teardownActionForIndex(const QModelIndex &index) const;
|
||||
QAction *ejectActionForIndex(const QModelIndex &index) const;
|
||||
void requestTeardown(const QModelIndex &index);
|
||||
void requestEject(const QModelIndex &index);
|
||||
void requestSetup(const QModelIndex &index);
|
||||
|
||||
void addPlace(const QString &text, const KUrl &url, const QString &iconName = QString(), const QString &appName = QString());
|
||||
void addPlace(const QString &text, const KUrl &url, const QString &iconName, const QString &appName, const QModelIndex &after);
|
||||
void editPlace(const QModelIndex &index, const QString &text, const KUrl &url, const QString &iconName = QString(), const QString &appName = QString());
|
||||
void removePlace(const QModelIndex &index) const;
|
||||
void setPlaceHidden(const QModelIndex &index, bool hidden);
|
||||
|
||||
int hiddenCount() const;
|
||||
|
||||
/**
|
||||
* @brief Get a visible data based on Qt role for the given index.
|
||||
* Return the device information for the give index.
|
||||
*
|
||||
* @param index The QModelIndex which contains the row, column to fetch the data.
|
||||
* @param role The Interview data role(ex: Qt::DisplayRole).
|
||||
*
|
||||
* @return the data for the given index and role.
|
||||
*/
|
||||
QVariant data(const QModelIndex &index, int role) const;
|
||||
|
||||
/**
|
||||
* @brief Get the children model index for the given row and column.
|
||||
*/
|
||||
QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const;
|
||||
|
||||
/**
|
||||
* @brief Get the parent QModelIndex for the given model child.
|
||||
*/
|
||||
QModelIndex parent(const QModelIndex &child) const;
|
||||
|
||||
/**
|
||||
* @brief Get the number of rows for a model index.
|
||||
*/
|
||||
int rowCount(const QModelIndex &parent = QModelIndex()) const;
|
||||
|
||||
/**
|
||||
* @brief Get the number of columns for a model index.
|
||||
*/
|
||||
int columnCount(const QModelIndex &parent = QModelIndex()) const;
|
||||
|
||||
/**
|
||||
* Returns the closest item for the URL \a url.
|
||||
* The closest item is defined as item which is equal to
|
||||
* the URL or at least is a parent URL. If there are more than
|
||||
* one possible parent URL candidates, the item which covers
|
||||
* the bigger range of the URL is returned.
|
||||
*
|
||||
* Example: the url is '/home/peter/Documents/Music'.
|
||||
* Available items are:
|
||||
* - /home/peter
|
||||
* - /home/peter/Documents
|
||||
*
|
||||
* The returned item will the one for '/home/peter/Documents'.
|
||||
*/
|
||||
QModelIndex closestItem(const KUrl &url) const;
|
||||
|
||||
|
||||
Qt::DropActions supportedDropActions() const;
|
||||
Qt::ItemFlags flags(const QModelIndex &index) const;
|
||||
QStringList mimeTypes() const;
|
||||
QMimeData *mimeData(const QModelIndexList &indexes) const;
|
||||
bool dropMimeData(const QMimeData *data, Qt::DropAction action,
|
||||
int row, int column, const QModelIndex &parent);
|
||||
|
||||
Q_SIGNALS:
|
||||
void errorMessage(const QString &message);
|
||||
void setupDone(const QModelIndex &index, bool success);
|
||||
|
||||
private:
|
||||
Q_PRIVATE_SLOT(d, void _k_initDeviceList())
|
||||
Q_PRIVATE_SLOT(d, void _k_deviceAdded(const QString&))
|
||||
Q_PRIVATE_SLOT(d, void _k_deviceRemoved(const QString&))
|
||||
Q_PRIVATE_SLOT(d, void _k_itemChanged(const QString&))
|
||||
Q_PRIVATE_SLOT(d, void _k_reloadBookmarks())
|
||||
Q_PRIVATE_SLOT(d, void _k_storageSetupDone(Solid::ErrorType, QVariant))
|
||||
Q_PRIVATE_SLOT(d, void _k_storageTeardownDone(Solid::ErrorType, QVariant))
|
||||
|
||||
class Private;
|
||||
Private * const d;
|
||||
friend class Private;
|
||||
};
|
||||
|
||||
} // namespace
|
||||
} // namespace
|
||||
|
||||
#endif
|
|
@ -1,325 +0,0 @@
|
|||
/* This file is part of the KDE project
|
||||
Copyright (C) 2007 Kevin Ottens <ervin@kde.org>
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Library General Public
|
||||
License version 2 as published by the Free Software Foundation.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Library General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Library General Public License
|
||||
along with this library; see the file COPYING.LIB. If not, write to
|
||||
the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
||||
Boston, MA 02110-1301, USA.
|
||||
|
||||
*/
|
||||
|
||||
#include "kfileplacesitem_p.h"
|
||||
#include "kfileplacesmodel.h"
|
||||
|
||||
#include <QtCore/QDateTime>
|
||||
|
||||
#include <kbookmarkmanager.h>
|
||||
#include <kiconloader.h>
|
||||
#include <kdirlister.h>
|
||||
#include <klocale.h>
|
||||
#include <solid/block.h>
|
||||
#include <solid/opticaldisc.h>
|
||||
#include <solid/opticaldrive.h>
|
||||
#include <solid/storageaccess.h>
|
||||
#include <solid/storagevolume.h>
|
||||
#include <solid/storagedrive.h>
|
||||
#include <solid/portablemediaplayer.h>
|
||||
|
||||
|
||||
KFilePlacesItem::KFilePlacesItem(KBookmarkManager *manager,
|
||||
const QString &address,
|
||||
const QString &udi)
|
||||
: m_manager(manager), m_lister(0), m_folderIsEmpty(true), m_isCdrom(false),
|
||||
m_isAccessible(false), m_device(udi)
|
||||
{
|
||||
setBookmark(m_manager->findByAddress(address));
|
||||
|
||||
if (udi.isEmpty() && m_bookmark.metaDataItem("ID").isEmpty()) {
|
||||
m_bookmark.setMetaDataItem("ID", generateNewId());
|
||||
} else if (udi.isEmpty()) {
|
||||
if (hasFullIcon(m_bookmark)) {
|
||||
// TODO if this is only for the trash, it would be much faster to just read trashrc
|
||||
m_lister = new KDirLister(this);
|
||||
m_lister->setAutoErrorHandlingEnabled(false, 0); // don't bother the user if trash:/ doesn't exist
|
||||
m_lister->setDelayedMimeTypes(true); // we don't need the mimetypes, so don't penalize other KDirLister users
|
||||
connect(m_lister, SIGNAL(completed()),
|
||||
this, SLOT(onListerCompleted()));
|
||||
m_lister->openUrl(m_bookmark.url());
|
||||
}
|
||||
} else if (!udi.isEmpty() && m_device.isValid()) {
|
||||
m_access = m_device.as<Solid::StorageAccess>();
|
||||
m_volume = m_device.as<Solid::StorageVolume>();
|
||||
m_disc = m_device.as<Solid::OpticalDisc>();
|
||||
m_mtp = m_device.as<Solid::PortableMediaPlayer>();
|
||||
if (m_access) {
|
||||
connect(m_access, SIGNAL(accessibilityChanged(bool,QString)),
|
||||
this, SLOT(onAccessibilityChanged(bool)));
|
||||
onAccessibilityChanged(m_access->isAccessible());
|
||||
}
|
||||
m_iconPath = m_device.icon();
|
||||
m_emblems = m_device.emblems();
|
||||
}
|
||||
}
|
||||
|
||||
KFilePlacesItem::~KFilePlacesItem()
|
||||
{
|
||||
}
|
||||
|
||||
QString KFilePlacesItem::id() const
|
||||
{
|
||||
if (isDevice()) {
|
||||
return bookmark().metaDataItem("UDI");
|
||||
} else {
|
||||
return bookmark().metaDataItem("ID");
|
||||
}
|
||||
}
|
||||
|
||||
bool KFilePlacesItem::isDevice() const
|
||||
{
|
||||
return !bookmark().metaDataItem("UDI").isEmpty();
|
||||
}
|
||||
|
||||
KBookmark KFilePlacesItem::bookmark() const
|
||||
{
|
||||
return m_bookmark;
|
||||
}
|
||||
|
||||
void KFilePlacesItem::setBookmark(const KBookmark &bookmark)
|
||||
{
|
||||
m_bookmark = bookmark;
|
||||
|
||||
if (bookmark.metaDataItem("isSystemItem") == "true") {
|
||||
// This context must stay as it is - the translated system bookmark names
|
||||
// are created with 'KFile System Bookmarks' as their context, so this
|
||||
// ensures the right string is picked from the catalog.
|
||||
// (coles, 13th May 2009)
|
||||
|
||||
m_text = i18nc("KFile System Bookmarks", bookmark.text().toUtf8().data());
|
||||
} else {
|
||||
m_text = bookmark.text();
|
||||
}
|
||||
}
|
||||
|
||||
Solid::Device KFilePlacesItem::device() const
|
||||
{
|
||||
if (m_device.udi().isEmpty()) {
|
||||
m_device = Solid::Device(bookmark().metaDataItem("UDI"));
|
||||
if (m_device.isValid()) {
|
||||
m_access = m_device.as<Solid::StorageAccess>();
|
||||
m_volume = m_device.as<Solid::StorageVolume>();
|
||||
m_disc = m_device.as<Solid::OpticalDisc>();
|
||||
m_mtp = m_device.as<Solid::PortableMediaPlayer>();
|
||||
} else {
|
||||
m_access = 0;
|
||||
m_volume = 0;
|
||||
m_disc = 0;
|
||||
m_mtp = 0;
|
||||
}
|
||||
}
|
||||
return m_device;
|
||||
}
|
||||
|
||||
QVariant KFilePlacesItem::data(int role) const
|
||||
{
|
||||
QVariant returnData;
|
||||
|
||||
if (role!=KFilePlacesModel::HiddenRole && role!=Qt::BackgroundRole && isDevice()) {
|
||||
returnData = deviceData(role);
|
||||
} else {
|
||||
returnData = bookmarkData(role);
|
||||
}
|
||||
|
||||
return returnData;
|
||||
}
|
||||
|
||||
QVariant KFilePlacesItem::bookmarkData(int role) const
|
||||
{
|
||||
KBookmark b = bookmark();
|
||||
|
||||
if (b.isNull()) return QVariant();
|
||||
|
||||
switch (role)
|
||||
{
|
||||
case Qt::DisplayRole:
|
||||
return m_text;
|
||||
case Qt::DecorationRole:
|
||||
return KIcon(iconNameForBookmark(b));
|
||||
case Qt::BackgroundRole:
|
||||
if (b.metaDataItem("IsHidden")=="true") {
|
||||
return Qt::lightGray;
|
||||
} else {
|
||||
return QVariant();
|
||||
}
|
||||
case KFilePlacesModel::UrlRole:
|
||||
return QUrl(b.url());
|
||||
case KFilePlacesModel::SetupNeededRole:
|
||||
return false;
|
||||
case KFilePlacesModel::HiddenRole:
|
||||
return b.metaDataItem("IsHidden")=="true";
|
||||
default:
|
||||
return QVariant();
|
||||
}
|
||||
}
|
||||
|
||||
QVariant KFilePlacesItem::deviceData(int role) const
|
||||
{
|
||||
Solid::Device d = device();
|
||||
|
||||
if (d.isValid()) {
|
||||
switch (role)
|
||||
{
|
||||
case Qt::DisplayRole:
|
||||
return d.description();
|
||||
case Qt::DecorationRole:
|
||||
return KIcon(m_iconPath, 0, m_emblems);
|
||||
case KFilePlacesModel::UrlRole:
|
||||
if (m_access) {
|
||||
return QUrl(KUrl(m_access->filePath()));
|
||||
} else if (m_disc && (m_disc->availableContent() & Solid::OpticalDisc::Audio)!=0) {
|
||||
QString device = d.as<Solid::Block>()->device();
|
||||
return QUrl(QString("audiocd:/?device=%1").arg(device));
|
||||
} else if (m_mtp) {
|
||||
return QUrl(QString("mtp:udi=%1").arg(d.udi()));
|
||||
} else {
|
||||
return QVariant();
|
||||
}
|
||||
case KFilePlacesModel::SetupNeededRole:
|
||||
if (m_access) {
|
||||
return !m_isAccessible;
|
||||
} else {
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
case KFilePlacesModel::FixedDeviceRole:
|
||||
{
|
||||
Solid::StorageDrive *drive = 0;
|
||||
Solid::Device parentDevice = m_device;
|
||||
while (parentDevice.isValid() && !drive) {
|
||||
drive = parentDevice.as<Solid::StorageDrive>();
|
||||
parentDevice = parentDevice.parent();
|
||||
}
|
||||
if (drive!=0) {
|
||||
return !drive->isHotpluggable() && !drive->isRemovable();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
case KFilePlacesModel::CapacityBarRecommendedRole:
|
||||
return m_isAccessible && !m_isCdrom;
|
||||
|
||||
default:
|
||||
return QVariant();
|
||||
}
|
||||
} else {
|
||||
return QVariant();
|
||||
}
|
||||
}
|
||||
|
||||
KBookmark KFilePlacesItem::createBookmark(KBookmarkManager *manager,
|
||||
const QString &label,
|
||||
const KUrl &url,
|
||||
const QString &iconName,
|
||||
KFilePlacesItem *after)
|
||||
{
|
||||
KBookmarkGroup root = manager->root();
|
||||
if (root.isNull())
|
||||
return KBookmark();
|
||||
QString empty_icon = iconName;
|
||||
if (url==KUrl("trash:/")) {
|
||||
if (empty_icon.endsWith(QLatin1String("-full"))) {
|
||||
empty_icon.chop(5);
|
||||
} else if (empty_icon.isEmpty()) {
|
||||
empty_icon = "user-trash";
|
||||
}
|
||||
}
|
||||
KBookmark bookmark = root.addBookmark(label, url, empty_icon);
|
||||
bookmark.setMetaDataItem("ID", generateNewId());
|
||||
|
||||
if (after) {
|
||||
root.moveBookmark(bookmark, after->bookmark());
|
||||
}
|
||||
|
||||
return bookmark;
|
||||
}
|
||||
|
||||
KBookmark KFilePlacesItem::createSystemBookmark(KBookmarkManager *manager,
|
||||
const QString &untranslatedLabel,
|
||||
const QString &translatedLabel,
|
||||
const KUrl &url,
|
||||
const QString &iconName)
|
||||
{
|
||||
Q_UNUSED(translatedLabel); // parameter is only necessary to force the caller
|
||||
// providing a translated string for the label
|
||||
|
||||
KBookmark bookmark = createBookmark(manager, untranslatedLabel, url, iconName);
|
||||
if (!bookmark.isNull())
|
||||
bookmark.setMetaDataItem("isSystemItem", "true");
|
||||
return bookmark;
|
||||
}
|
||||
|
||||
|
||||
KBookmark KFilePlacesItem::createDeviceBookmark(KBookmarkManager *manager,
|
||||
const QString &udi)
|
||||
{
|
||||
KBookmarkGroup root = manager->root();
|
||||
if (root.isNull())
|
||||
return KBookmark();
|
||||
KBookmark bookmark = root.createNewSeparator();
|
||||
bookmark.setMetaDataItem("UDI", udi);
|
||||
bookmark.setMetaDataItem("isSystemItem", "true");
|
||||
return bookmark;
|
||||
}
|
||||
|
||||
QString KFilePlacesItem::generateNewId()
|
||||
{
|
||||
static int count = 0;
|
||||
|
||||
// return QString::number(count++);
|
||||
|
||||
return QString::number(QDateTime::currentDateTime().toTime_t())
|
||||
+ '/' + QString::number(count++);
|
||||
|
||||
|
||||
// return QString::number(QDateTime::currentDateTime().toTime_t())
|
||||
// + '/' + QString::number(qrand());
|
||||
}
|
||||
|
||||
void KFilePlacesItem::onAccessibilityChanged(bool isAccessible)
|
||||
{
|
||||
m_isAccessible = isAccessible;
|
||||
m_isCdrom = m_device.is<Solid::OpticalDrive>() || m_device.parent().is<Solid::OpticalDrive>();
|
||||
m_emblems = m_device.emblems();
|
||||
|
||||
emit itemChanged(id());
|
||||
}
|
||||
|
||||
bool KFilePlacesItem::hasFullIcon(const KBookmark &bookmark) const
|
||||
{
|
||||
return bookmark.url()==KUrl("trash:/");
|
||||
}
|
||||
|
||||
QString KFilePlacesItem::iconNameForBookmark(const KBookmark &bookmark) const
|
||||
{
|
||||
if (!m_folderIsEmpty && hasFullIcon(bookmark)) {
|
||||
return bookmark.icon()+"-full";
|
||||
} else {
|
||||
return bookmark.icon();
|
||||
}
|
||||
}
|
||||
|
||||
void KFilePlacesItem::onListerCompleted()
|
||||
{
|
||||
m_folderIsEmpty = m_lister->items().isEmpty();
|
||||
emit itemChanged(id());
|
||||
}
|
||||
|
||||
#include "moc_kfileplacesitem_p.cpp"
|
|
@ -1,102 +0,0 @@
|
|||
/* This file is part of the KDE project
|
||||
Copyright (C) 2007 Kevin Ottens <ervin@kde.org>
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Library General Public
|
||||
License version 2 as published by the Free Software Foundation.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Library General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Library General Public License
|
||||
along with this library; see the file COPYING.LIB. If not, write to
|
||||
the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
||||
Boston, MA 02110-1301, USA.
|
||||
|
||||
*/
|
||||
|
||||
#ifndef KFILEPLACESITEM_P_H
|
||||
#define KFILEPLACESITEM_P_H
|
||||
|
||||
|
||||
#include <QtCore/QObject>
|
||||
#include <QtCore/QPointer>
|
||||
#include <QtCore/qabstractitemmodel.h>
|
||||
#include <QtCore/QStringList>
|
||||
#include <kbookmark.h>
|
||||
#include <solid/device.h>
|
||||
|
||||
class KDirLister;
|
||||
namespace Solid
|
||||
{
|
||||
class StorageAccess;
|
||||
class StorageVolume;
|
||||
class OpticalDisc;
|
||||
class PortableMediaPlayer;
|
||||
}
|
||||
|
||||
class KFilePlacesItem : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
KFilePlacesItem(KBookmarkManager *manager,
|
||||
const QString &address,
|
||||
const QString &udi = QString());
|
||||
~KFilePlacesItem();
|
||||
|
||||
QString id() const;
|
||||
|
||||
bool isDevice() const;
|
||||
KBookmark bookmark() const;
|
||||
void setBookmark(const KBookmark &bookmark);
|
||||
Solid::Device device() const;
|
||||
QVariant data(int role) const;
|
||||
|
||||
static KBookmark createBookmark(KBookmarkManager *manager,
|
||||
const QString &label,
|
||||
const KUrl &url,
|
||||
const QString &iconName,
|
||||
KFilePlacesItem *after = 0);
|
||||
static KBookmark createSystemBookmark(KBookmarkManager *manager,
|
||||
const QString &untranslatedLabel,
|
||||
const QString &translatedLabel,
|
||||
const KUrl &url,
|
||||
const QString &iconName);
|
||||
static KBookmark createDeviceBookmark(KBookmarkManager *manager,
|
||||
const QString &udi);
|
||||
|
||||
Q_SIGNALS:
|
||||
void itemChanged(const QString &id);
|
||||
|
||||
private Q_SLOTS:
|
||||
void onAccessibilityChanged(bool);
|
||||
void onListerCompleted();
|
||||
|
||||
private:
|
||||
QVariant bookmarkData(int role) const;
|
||||
QVariant deviceData(int role) const;
|
||||
|
||||
bool hasFullIcon(const KBookmark &bookmark) const;
|
||||
QString iconNameForBookmark(const KBookmark &bookmark) const;
|
||||
|
||||
static QString generateNewId();
|
||||
|
||||
KBookmarkManager *m_manager;
|
||||
KBookmark m_bookmark;
|
||||
KDirLister *m_lister;
|
||||
bool m_folderIsEmpty;
|
||||
bool m_isCdrom;
|
||||
bool m_isAccessible;
|
||||
QString m_text;
|
||||
mutable Solid::Device m_device;
|
||||
mutable QPointer<Solid::StorageAccess> m_access;
|
||||
mutable QPointer<Solid::StorageVolume> m_volume;
|
||||
mutable QPointer<Solid::OpticalDisc> m_disc;
|
||||
mutable QPointer<Solid::PortableMediaPlayer> m_mtp;
|
||||
QString m_iconPath;
|
||||
QStringList m_emblems;
|
||||
};
|
||||
|
||||
#endif
|
|
@ -1,281 +0,0 @@
|
|||
/* This file is part of the KDE project
|
||||
Copyright (C) 2008 Norbert Frese <nf2@scheinwelt.at>
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Library General Public
|
||||
License version 2 as published by the Free Software Foundation.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Library General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Library General Public License
|
||||
along with this library; see the file COPYING.LIB. If not, write to
|
||||
the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
||||
Boston, MA 02110-1301, USA.
|
||||
|
||||
*/
|
||||
|
||||
#include "kfileplacessharedbookmarks_p.h"
|
||||
|
||||
#include <QtCore/QObject>
|
||||
#include <QtCore/QTextStream>
|
||||
#include <QtCore/QFile>
|
||||
#include <kstandarddirs.h>
|
||||
#include <kbookmarkmanager.h>
|
||||
#include <kbookmark.h>
|
||||
#include <kdebug.h>
|
||||
|
||||
//////////////// utility functions
|
||||
|
||||
static bool compareBookmarks(const KBookmark & bookmark1, const KBookmark & bookmark2)
|
||||
{
|
||||
return (bookmark1.url() == bookmark2.url() || bookmark1.text() == bookmark2.text());
|
||||
}
|
||||
|
||||
static bool deepCompareDomNodes(const QDomNode & node1, const QDomNode & node2)
|
||||
{
|
||||
|
||||
// compare name and value
|
||||
if (node1.nodeName() != node2.nodeName() || node1.nodeValue() != node2.nodeValue())
|
||||
return false;
|
||||
|
||||
// recursively compare children
|
||||
const QDomNodeList node1Children = node1.childNodes();
|
||||
const QDomNodeList node2Children = node2.childNodes();
|
||||
|
||||
if (node1Children.count () != node2Children.count ())
|
||||
return false;
|
||||
|
||||
for (int i=0; i<node1Children.count ();i++) {
|
||||
if (!deepCompareDomNodes(node1Children.at(i), node2Children.at(i) ))
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
static QString nodeAsString(const QDomNode & node1)
|
||||
{
|
||||
QString str;
|
||||
QTextStream ts( &str, QIODevice::WriteOnly );
|
||||
ts << node1;
|
||||
return str;
|
||||
}
|
||||
*/
|
||||
|
||||
static bool exactCompareBookmarks(const KBookmark & bookmark1, const KBookmark & bookmark2)
|
||||
{
|
||||
//kDebug() << "excat comparing:\n" << nodeAsString(bookmark1.internalElement()) << "\nwith:\n" << nodeAsString(bookmark2.internalElement());
|
||||
return deepCompareDomNodes(bookmark1.internalElement(), bookmark2.internalElement());
|
||||
}
|
||||
|
||||
static void cloneBookmarkContents(const KBookmark & target, const KBookmark & source)
|
||||
{
|
||||
const QDomElement targetEl = target.internalElement();
|
||||
QDomNode parent = targetEl.parentNode ();
|
||||
QDomNode clonedNode = source.internalElement().cloneNode(true);
|
||||
parent.replaceChild (clonedNode , targetEl );
|
||||
}
|
||||
|
||||
static KBookmark cloneBookmark(const KBookmark & toClone)
|
||||
{
|
||||
const QDomNode cloned = toClone.internalElement().cloneNode(true);
|
||||
return KBookmark(cloned.toElement ());
|
||||
}
|
||||
|
||||
|
||||
static void emptyBookmarkGroup(KBookmarkGroup & root)
|
||||
{
|
||||
KBookmark bookmark = root.first();
|
||||
while (!bookmark.isNull()) {
|
||||
KBookmark bookmarkToRemove = bookmark;
|
||||
bookmark = root.next(bookmark);
|
||||
root.deleteBookmark(bookmarkToRemove);
|
||||
}
|
||||
}
|
||||
|
||||
static int bookmarkGroupSize(KBookmarkGroup & root)
|
||||
{
|
||||
int count=0;
|
||||
KBookmark bookmark = root.first();
|
||||
while (!bookmark.isNull()) {
|
||||
count++;
|
||||
bookmark = root.next(bookmark);
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
//////////////// class KFilePlacesSharedBookmarks
|
||||
|
||||
KFilePlacesSharedBookmarks::KFilePlacesSharedBookmarks(KBookmarkManager * mgr)
|
||||
{
|
||||
m_placesBookmarkManager = mgr;
|
||||
|
||||
// we check later if the directory exists
|
||||
KStandardDirs::makeDir(KStandardDirs().localxdgdatadir());
|
||||
const QString file = KStandardDirs().localxdgdatadir() + "user-places.xbel";
|
||||
m_sharedBookmarkManager = KBookmarkManager::managerForExternalFile(file);
|
||||
|
||||
connect(m_sharedBookmarkManager, SIGNAL(changed(QString,QString)),
|
||||
this, SLOT(slotSharedBookmarksChanged()));
|
||||
connect(m_sharedBookmarkManager, SIGNAL(bookmarksChanged(QString)),
|
||||
this, SLOT(slotSharedBookmarksChanged()));
|
||||
|
||||
connect(m_placesBookmarkManager, SIGNAL(changed(QString,QString)),
|
||||
this, SLOT(slotBookmarksChanged()));
|
||||
connect(m_placesBookmarkManager, SIGNAL(bookmarksChanged(QString)),
|
||||
this, SLOT(slotBookmarksChanged()));
|
||||
|
||||
integrateSharedBookmarks();
|
||||
}
|
||||
|
||||
bool KFilePlacesSharedBookmarks::integrateSharedBookmarks()
|
||||
{
|
||||
KBookmarkGroup root = m_placesBookmarkManager->root();
|
||||
KBookmark bookmark = root.first();
|
||||
|
||||
KBookmarkGroup sharedRoot = m_sharedBookmarkManager->root();
|
||||
KBookmark sharedBookmark = sharedRoot.first();
|
||||
|
||||
bool dirty = false;
|
||||
|
||||
while (!bookmark.isNull()) {
|
||||
//kDebug() << "importing" << bookmark.text();
|
||||
|
||||
// skip over system items
|
||||
if (bookmark.metaDataItem("isSystemItem") == "true") {
|
||||
bookmark = root.next(bookmark);
|
||||
continue;
|
||||
}
|
||||
|
||||
// do the bookmarks match?
|
||||
if (!sharedBookmark.isNull() && compareBookmarks(bookmark, sharedBookmark)) {
|
||||
//kDebug() << "excat comparing: targetbk:\n" << nodeAsString(bookmark.internalElement()) << "\nsourcbk:\n" << nodeAsString(sharedBookmark.internalElement());
|
||||
|
||||
if (!exactCompareBookmarks(bookmark, sharedBookmark)) {
|
||||
KBookmark cloneTarget=bookmark;
|
||||
KBookmark cloneSource = sharedBookmark;
|
||||
|
||||
sharedBookmark = sharedRoot.next(sharedBookmark);
|
||||
bookmark = root.next(bookmark);
|
||||
|
||||
//kDebug() << "cloning" << cloneSource.text();
|
||||
//kDebug() << "cloning: target=\n" << nodeAsString(cloneTarget.internalElement()) << "\n source:\n" << nodeAsString(cloneSource.internalElement());
|
||||
|
||||
cloneBookmarkContents(cloneTarget, cloneSource);
|
||||
dirty = true;
|
||||
continue;
|
||||
} else {
|
||||
//kDebug() << "keeping" << bookmark.text();
|
||||
}
|
||||
sharedBookmark = sharedRoot.next(sharedBookmark);
|
||||
bookmark = root.next(bookmark);
|
||||
continue;
|
||||
}
|
||||
|
||||
// they don't match -> remove
|
||||
//kDebug() << "removing" << bookmark.text();
|
||||
KBookmark bookmarkToRemove = bookmark;
|
||||
bookmark = root.next(bookmark);
|
||||
root.deleteBookmark(bookmarkToRemove);
|
||||
|
||||
dirty = true;
|
||||
}
|
||||
|
||||
// append the remaining shared bookmarks
|
||||
while(!sharedBookmark.isNull()) {
|
||||
root.addBookmark(cloneBookmark(sharedBookmark));
|
||||
sharedBookmark = sharedRoot.next(sharedBookmark);
|
||||
dirty = true;
|
||||
}
|
||||
|
||||
return dirty;
|
||||
}
|
||||
|
||||
bool KFilePlacesSharedBookmarks::exportSharedBookmarks()
|
||||
{
|
||||
KBookmarkGroup root = m_placesBookmarkManager->root();
|
||||
KBookmark bookmark = root.first();
|
||||
|
||||
KBookmarkGroup sharedRoot = m_sharedBookmarkManager->root();
|
||||
KBookmark sharedBookmark = sharedRoot.first();
|
||||
|
||||
bool dirty = false;
|
||||
|
||||
// first check if they are the same
|
||||
int count=0;
|
||||
while (!bookmark.isNull()) {
|
||||
//kDebug() << "exporting..." << bookmark.text();
|
||||
|
||||
// skip over system items
|
||||
if (bookmark.metaDataItem("isSystemItem") == "true") {
|
||||
bookmark = root.next(bookmark);
|
||||
continue;
|
||||
}
|
||||
count++;
|
||||
|
||||
// end of sharedBookmarks?
|
||||
if (sharedBookmark.isNull()) {
|
||||
dirty=true;
|
||||
break;
|
||||
}
|
||||
|
||||
// do the bookmarks match?
|
||||
if (compareBookmarks(bookmark, sharedBookmark)) {
|
||||
if (!exactCompareBookmarks(bookmark, sharedBookmark)) {
|
||||
dirty = true;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
dirty=true;
|
||||
break;
|
||||
}
|
||||
sharedBookmark = sharedRoot.next(sharedBookmark);
|
||||
bookmark = root.next(bookmark);
|
||||
}
|
||||
|
||||
//kDebug() << "dirty=" << dirty << " oldsize=" << bookmarkGroupSize(sharedRoot) << " count=" << count;
|
||||
|
||||
if (bookmarkGroupSize(sharedRoot) != count)
|
||||
dirty=true;
|
||||
|
||||
if (dirty) {
|
||||
emptyBookmarkGroup(sharedRoot);
|
||||
|
||||
// append all bookmarks
|
||||
KBookmark bookmark = root.first();
|
||||
|
||||
while(!bookmark.isNull()) {
|
||||
|
||||
if (bookmark.metaDataItem("isSystemItem") == "true") {
|
||||
bookmark = root.next(bookmark);
|
||||
continue;
|
||||
}
|
||||
|
||||
sharedRoot.addBookmark(cloneBookmark(bookmark));
|
||||
bookmark = root.next(bookmark);
|
||||
dirty = true;
|
||||
}
|
||||
}
|
||||
|
||||
return dirty;
|
||||
|
||||
}
|
||||
|
||||
void KFilePlacesSharedBookmarks::slotSharedBookmarksChanged()
|
||||
{
|
||||
//kDebug() << "shared bookmarks changed";
|
||||
bool dirty = integrateSharedBookmarks();
|
||||
if (dirty) m_placesBookmarkManager->emitChanged();
|
||||
}
|
||||
|
||||
void KFilePlacesSharedBookmarks::slotBookmarksChanged()
|
||||
{
|
||||
//kDebug() << "places bookmarks changed";
|
||||
bool dirty = exportSharedBookmarks();
|
||||
if (dirty) m_sharedBookmarkManager->emitChanged();
|
||||
}
|
||||
|
||||
#include "moc_kfileplacessharedbookmarks_p.cpp"
|
|
@ -1,56 +0,0 @@
|
|||
/* This file is part of the KDE project
|
||||
Copyright (C) 2008 Norbert Frese <nf2@scheinwelt.at>
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Library General Public
|
||||
License version 2 as published by the Free Software Foundation.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Library General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Library General Public License
|
||||
along with this library; see the file COPYING.LIB. If not, write to
|
||||
the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
||||
Boston, MA 02110-1301, USA.
|
||||
|
||||
*/
|
||||
|
||||
#ifndef KFILEPLACESSHAREDBOOKMARKS_P_H
|
||||
#define KFILEPLACESSHAREDBOOKMARKS_P_H
|
||||
|
||||
#include <QtCore/QObject>
|
||||
#include <kbookmarkmanager.h>
|
||||
|
||||
/**
|
||||
* keeps the KFilePlacesModel bookmarks and the shared bookmark spec
|
||||
* shortcuts in sync
|
||||
*/
|
||||
class KFilePlacesSharedBookmarks : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
|
||||
KFilePlacesSharedBookmarks(KBookmarkManager * mgr);
|
||||
~KFilePlacesSharedBookmarks() { /* delete m_sharedBookmarkManager; */}
|
||||
|
||||
private:
|
||||
|
||||
bool integrateSharedBookmarks();
|
||||
bool exportSharedBookmarks();
|
||||
|
||||
KBookmarkManager *m_placesBookmarkManager;
|
||||
KBookmarkManager *m_sharedBookmarkManager;
|
||||
|
||||
private Q_SLOTS:
|
||||
|
||||
void slotSharedBookmarksChanged();
|
||||
void slotBookmarksChanged();
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
#endif /*KFILEPLACESSHARED_P_H_*/
|
|
@ -1,81 +0,0 @@
|
|||
/*
|
||||
Copyright 2013 Aurélien Gâteau <agateau@kde.org>
|
||||
Copyright 2013 Eike Hein <hein@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/>.
|
||||
*/
|
||||
// Self
|
||||
#include <changenotifier.h>
|
||||
|
||||
// Local
|
||||
|
||||
// KDE
|
||||
#include <KSycoca>
|
||||
#include <KDebug>
|
||||
|
||||
// Qt
|
||||
#include <QApplication>
|
||||
#include <QtCore/qcoreevent.h>
|
||||
#include <QTimer>
|
||||
|
||||
namespace Homerun {
|
||||
|
||||
ChangeNotifier::ChangeNotifier(QObject *parent)
|
||||
: QObject(parent)
|
||||
, mTimer(new QTimer(this))
|
||||
{
|
||||
// Use a timer to aggregate multiple KSycoca changes
|
||||
mTimer->setInterval(100);
|
||||
mTimer->setSingleShot(true);
|
||||
connect(mTimer, SIGNAL(timeout()), SLOT(timeout()));
|
||||
|
||||
connect(KSycoca::self(), SIGNAL(databaseChanged(QStringList)), SLOT(checkSycocaChanges(QStringList)));
|
||||
|
||||
mWatchedProps << "appletContainmentId" << "appletContainmentMutable"
|
||||
<< "desktopContainmentId" << "desktopContainmentMutable";
|
||||
qApp->installEventFilter(this);
|
||||
}
|
||||
|
||||
ChangeNotifier::~ChangeNotifier()
|
||||
{
|
||||
}
|
||||
|
||||
bool ChangeNotifier::eventFilter(QObject* watched, QEvent* event)
|
||||
{
|
||||
if (event->type() == QEvent::DynamicPropertyChange
|
||||
&& mWatchedProps.contains(static_cast<QDynamicPropertyChangeEvent *>(event)->propertyName())) {
|
||||
emit changeDetected(false);
|
||||
}
|
||||
|
||||
return QObject::eventFilter(watched, event);
|
||||
}
|
||||
|
||||
void ChangeNotifier::checkSycocaChanges(const QStringList &changes)
|
||||
{
|
||||
if (changes.contains("services") || changes.contains("apps") || changes.contains("xdgdata-apps")) {
|
||||
mTimer->start();
|
||||
}
|
||||
}
|
||||
|
||||
void ChangeNotifier::timeout()
|
||||
{
|
||||
emit changeDetected(true);
|
||||
}
|
||||
|
||||
} // namespace Homerun
|
||||
|
||||
#include "moc_changenotifier.cpp"
|
|
@ -1,62 +0,0 @@
|
|||
/*
|
||||
Copyright 2013 Aurélien Gâteau <agateau@kde.org>
|
||||
Copyright 2013 Eike Hein <hein@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 CHANGENOTIFIER_H
|
||||
#define CHANGENOTIFIER_H
|
||||
|
||||
// Local
|
||||
|
||||
// Qt
|
||||
#include <QObject>
|
||||
#include <QStringList>
|
||||
|
||||
// KDE
|
||||
|
||||
class QTimer;
|
||||
|
||||
namespace Homerun {
|
||||
|
||||
/**
|
||||
* Monitor application changes from KSycoca
|
||||
*/
|
||||
class ChangeNotifier : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit ChangeNotifier(QObject *parent = 0);
|
||||
~ChangeNotifier();
|
||||
|
||||
bool eventFilter(QObject *watched, QEvent *event);
|
||||
|
||||
Q_SIGNALS:
|
||||
void changeDetected(bool needsReload);
|
||||
|
||||
private Q_SLOTS:
|
||||
void checkSycocaChanges(const QStringList &changes);
|
||||
void timeout();
|
||||
|
||||
private:
|
||||
QTimer *mTimer;
|
||||
QStringList mWatchedProps;
|
||||
};
|
||||
|
||||
} // namespace Homerun
|
||||
|
||||
#endif /* CHANGENOTIFIER_H */
|
|
@ -1,319 +0,0 @@
|
|||
/*
|
||||
Copyright 2012 Aurélien Gâteau <agateau@kde.org>
|
||||
Copyright 2013 Eike Hein <hein@kde.org>
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) 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 6 of version 3 of the license.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
// Self
|
||||
#include <filterableinstalledappsmodel.h>
|
||||
|
||||
// Local
|
||||
#include <abstractsourceregistry.h>
|
||||
#include <changenotifier.h>
|
||||
#include <installedappsmodel.h>
|
||||
|
||||
// KDE
|
||||
#include <KConfigGroup>
|
||||
#include <KDebug>
|
||||
|
||||
// Qt
|
||||
|
||||
namespace Homerun {
|
||||
|
||||
InstalledAppsFilterModel::InstalledAppsFilterModel(const QString &entryPath, const QString &installer, QObject *parent)
|
||||
: QSortFilterProxyModel(parent)
|
||||
, m_installedAppsModel(new InstalledAppsModel(entryPath, installer, this))
|
||||
, m_hidden(true)
|
||||
{
|
||||
setSourceModel(m_installedAppsModel);
|
||||
setDynamicSortFilter(true);
|
||||
setFilterRole(InstalledAppsModel::CombinedNameRole);
|
||||
setFilterCaseSensitivity(Qt::CaseInsensitive);
|
||||
|
||||
connect(this, SIGNAL(modelReset()), this, SIGNAL(countChanged()));
|
||||
connect(this, SIGNAL(rowsInserted(QModelIndex,int,int)), this, SIGNAL(countChanged()));
|
||||
connect(this, SIGNAL(rowsRemoved(QModelIndex,int,int)), this, SIGNAL(countChanged()));
|
||||
|
||||
connect(m_installedAppsModel, SIGNAL(applicationLaunched(QString)), this, SIGNAL(applicationLaunched(QString)));
|
||||
}
|
||||
|
||||
InstalledAppsFilterModel::~InstalledAppsFilterModel()
|
||||
{
|
||||
}
|
||||
|
||||
QObject *InstalledAppsFilterModel::containment() const
|
||||
{
|
||||
return m_installedAppsModel->containment();
|
||||
}
|
||||
|
||||
void InstalledAppsFilterModel::setContainment(QObject *containment)
|
||||
{
|
||||
m_installedAppsModel->setContainment(containment);
|
||||
}
|
||||
|
||||
QString InstalledAppsFilterModel::name() const
|
||||
{
|
||||
return m_installedAppsModel->name();
|
||||
}
|
||||
|
||||
bool InstalledAppsFilterModel::hidden() const
|
||||
{
|
||||
return m_hidden;
|
||||
}
|
||||
|
||||
void InstalledAppsFilterModel::setHidden(bool hidden)
|
||||
{
|
||||
if (hidden != m_hidden) {
|
||||
m_hidden = hidden;
|
||||
emit hiddenChanged();
|
||||
}
|
||||
}
|
||||
|
||||
int InstalledAppsFilterModel::count() const
|
||||
{
|
||||
return rowCount();
|
||||
}
|
||||
|
||||
void InstalledAppsFilterModel::refresh(bool reload)
|
||||
{
|
||||
m_installedAppsModel->refresh(reload);
|
||||
}
|
||||
|
||||
bool InstalledAppsFilterModel::trigger(int row, const QString &actionId, const QVariant &actionArgument)
|
||||
{
|
||||
const QModelIndex &idx = index(row, 0);
|
||||
const QModelIndex &sourceIndex = mapToSource(idx);
|
||||
return m_installedAppsModel->trigger(sourceIndex.row(), actionId, actionArgument);
|
||||
}
|
||||
|
||||
SideBarModel::SideBarModel(FilterableInstalledAppsModel *parent)
|
||||
: QSortFilterProxyModel(parent)
|
||||
, m_sourceModel(parent)
|
||||
, m_activeSourceRow(0)
|
||||
{
|
||||
setSourceModel(m_sourceModel);
|
||||
setDynamicSortFilter(true);
|
||||
|
||||
QHash<int, QByteArray> roles;
|
||||
roles.insert(Qt::DisplayRole, "display");
|
||||
roles.insert(Qt::CheckStateRole, "checked");
|
||||
|
||||
setRoleNames(roles);
|
||||
}
|
||||
|
||||
SideBarModel::~SideBarModel()
|
||||
{
|
||||
}
|
||||
|
||||
QVariant SideBarModel::data(const QModelIndex& index, int role) const
|
||||
{
|
||||
QModelIndex sourceIndex = mapToSource(index);
|
||||
|
||||
if (role == Qt::CheckStateRole) {
|
||||
return (sourceIndex.row() == m_activeSourceRow);
|
||||
}
|
||||
|
||||
return QSortFilterProxyModel::data(index, role);
|
||||
}
|
||||
|
||||
void SideBarModel::trigger(int row)
|
||||
{
|
||||
const QModelIndex &idx = index(row, 0);
|
||||
const QModelIndex &sourceIndex = mapToSource(idx);
|
||||
|
||||
if (sourceIndex.row() != m_activeSourceRow) {
|
||||
const QModelIndex &oldActiveIndex = mapFromSource(m_sourceModel->index(m_activeSourceRow, 0));
|
||||
|
||||
m_activeSourceRow = sourceIndex.row();
|
||||
|
||||
InstalledAppsFilterModel* model = 0;
|
||||
|
||||
for(int i = 0; i < m_sourceModel->rowCount(); ++i) {
|
||||
model = static_cast<InstalledAppsFilterModel *>(m_sourceModel->modelForRow(i));
|
||||
model->setHidden(i != m_activeSourceRow);
|
||||
}
|
||||
|
||||
emit dataChanged(oldActiveIndex, oldActiveIndex);
|
||||
emit dataChanged(idx, idx);
|
||||
invalidateFilter();
|
||||
}
|
||||
}
|
||||
|
||||
bool SideBarModel::filterAcceptsRow(int source_row, const QModelIndex &source_parent) const
|
||||
{
|
||||
Q_UNUSED(source_parent)
|
||||
|
||||
return (m_activeSourceRow == source_row) || static_cast<InstalledAppsFilterModel *>(m_sourceModel->modelForRow(source_row))->count();
|
||||
}
|
||||
|
||||
FilterableInstalledAppsModel::FilterableInstalledAppsModel(const QString &installer, QObject *parent)
|
||||
: QAbstractListModel(parent)
|
||||
, m_installer(installer)
|
||||
, m_sideBarModel(new SideBarModel(this))
|
||||
{
|
||||
loadRootEntries();
|
||||
}
|
||||
|
||||
FilterableInstalledAppsModel::~FilterableInstalledAppsModel()
|
||||
{
|
||||
}
|
||||
|
||||
int FilterableInstalledAppsModel::count() const
|
||||
{
|
||||
return rowCount();
|
||||
}
|
||||
|
||||
QObject *FilterableInstalledAppsModel::modelForRow(int row) const
|
||||
{
|
||||
if (row < 0 || row >= m_models.count()) {
|
||||
kWarning() << "No model for row" << row << "!";
|
||||
return 0;
|
||||
}
|
||||
return m_models.value(row);
|
||||
}
|
||||
|
||||
void FilterableInstalledAppsModel::refresh(bool reload)
|
||||
{
|
||||
if (!reload) {
|
||||
foreach(InstalledAppsFilterModel* model, m_models) {
|
||||
model->refresh(false);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
beginResetModel();
|
||||
qDeleteAll(m_models);
|
||||
m_models.clear();
|
||||
m_pendingGroupList.clear();
|
||||
endResetModel();
|
||||
|
||||
loadRootEntries();
|
||||
|
||||
emit countChanged();
|
||||
}
|
||||
|
||||
void FilterableInstalledAppsModel::loadRootEntries()
|
||||
{
|
||||
InstalledAppsFilterModel *model = createInstalledAppsFilterModel(KServiceGroup::root());
|
||||
model->setHidden(false);
|
||||
model->setParent(this);
|
||||
beginInsertRows(QModelIndex(), m_models.count(), m_models.count());
|
||||
m_models << model;
|
||||
endInsertRows();
|
||||
|
||||
KServiceGroup::Ptr group = KServiceGroup::root();
|
||||
KServiceGroup::List list = group->entries(false /* sorted: set to false as it does not seem to work */);
|
||||
|
||||
QMap<QString, KServiceGroup::Ptr> groupMap;
|
||||
for( KServiceGroup::List::ConstIterator it = list.constBegin(); it != list.constEnd(); it++) {
|
||||
const KSycocaEntry::Ptr p = (*it);
|
||||
|
||||
if (p->isType(KST_KServiceGroup)) {
|
||||
KServiceGroup::Ptr subGroup = KServiceGroup::Ptr::staticCast(p);
|
||||
|
||||
if (!subGroup->noDisplay() && subGroup->childCount() > 0) {
|
||||
groupMap.insert(subGroup->caption().toLower(), subGroup);
|
||||
}
|
||||
}
|
||||
}
|
||||
m_pendingGroupList = groupMap.values();
|
||||
QMetaObject::invokeMethod(this, "loadNextGroup", Qt::QueuedConnection);
|
||||
}
|
||||
|
||||
void FilterableInstalledAppsModel::loadNextGroup()
|
||||
{
|
||||
if (m_pendingGroupList.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
KServiceGroup::Ptr group = m_pendingGroupList.takeFirst();
|
||||
InstalledAppsFilterModel *model = createInstalledAppsFilterModel(group);
|
||||
model->setParent(this);
|
||||
beginInsertRows(QModelIndex(), m_models.count(), m_models.count());
|
||||
m_models << model;
|
||||
endInsertRows();
|
||||
QMetaObject::invokeMethod(this, "loadNextGroup");
|
||||
}
|
||||
|
||||
int FilterableInstalledAppsModel::rowCount(const QModelIndex &parent) const
|
||||
{
|
||||
if (parent.isValid()) {
|
||||
return 0;
|
||||
}
|
||||
return m_models.count();
|
||||
}
|
||||
|
||||
QVariant FilterableInstalledAppsModel::data(const QModelIndex &index, int role) const
|
||||
{
|
||||
if (index.parent().isValid()) {
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
InstalledAppsFilterModel *model = m_models.value(index.row());
|
||||
if (!model) {
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
if (role == Qt::DisplayRole) {
|
||||
return model->name();
|
||||
} else {
|
||||
return QVariant();
|
||||
}
|
||||
}
|
||||
|
||||
SideBarModel* FilterableInstalledAppsModel::sideBarModel() const
|
||||
{
|
||||
return m_sideBarModel;
|
||||
}
|
||||
|
||||
QString FilterableInstalledAppsModel::currentQuery() const
|
||||
{
|
||||
return m_query;
|
||||
}
|
||||
|
||||
void FilterableInstalledAppsModel::scheduleQuery(const QString& query)
|
||||
{
|
||||
emit queryChanged(query);
|
||||
m_sideBarModel->invalidateFilter();
|
||||
}
|
||||
|
||||
InstalledAppsFilterModel *FilterableInstalledAppsModel::createInstalledAppsFilterModel(KServiceGroup::Ptr group)
|
||||
{
|
||||
InstalledAppsFilterModel *model = new InstalledAppsFilterModel(group->entryPath(), m_installer, this);
|
||||
connect(this, SIGNAL(queryChanged(QString)), model, SLOT(setFilterFixedString(QString)));
|
||||
connect(model, SIGNAL(applicationLaunched(QString)), this, SIGNAL(applicationLaunched(QString)));
|
||||
return model;
|
||||
}
|
||||
|
||||
//- FilterableInstalledAppsSource --------------------------------------
|
||||
FilterableInstalledAppsSource::FilterableInstalledAppsSource(QObject *parent)
|
||||
: AbstractSource(parent)
|
||||
{}
|
||||
|
||||
QAbstractItemModel *FilterableInstalledAppsSource::createModelFromConfigGroup(const KConfigGroup &)
|
||||
{
|
||||
KConfigGroup group(config(), "PackageManagement");
|
||||
QString installer = group.readEntry("categoryInstaller");
|
||||
FilterableInstalledAppsModel *model = new FilterableInstalledAppsModel(installer);
|
||||
ChangeNotifier *notifier = new ChangeNotifier(model);
|
||||
connect(notifier, SIGNAL(changeDetected(bool)), model, SLOT(refresh(bool)));
|
||||
return model;
|
||||
}
|
||||
|
||||
} // namespace Homerun
|
||||
|
||||
#include "moc_filterableinstalledappsmodel.cpp"
|
|
@ -1,158 +0,0 @@
|
|||
/*
|
||||
Copyright 2012 Aurélien Gâteau <agateau@kde.org>
|
||||
Copyright 2013 Eike Hein <hein@kde.org>
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) 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 6 of version 3 of the license.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#ifndef FILTERABLEINSTALLEDAPPSMODEL_H
|
||||
#define FILTERABLEINSTALLEDAPPSMODEL_H
|
||||
|
||||
// Local
|
||||
#include <abstractsource.h>
|
||||
|
||||
// Qt
|
||||
#include <QSortFilterProxyModel>
|
||||
|
||||
// KDE
|
||||
#include <KServiceGroup>
|
||||
|
||||
namespace Plasma {
|
||||
class Containment;
|
||||
}
|
||||
|
||||
namespace Homerun {
|
||||
|
||||
class InstalledAppsModel;
|
||||
class FilterableInstalledAppsModel;
|
||||
|
||||
class InstalledAppsFilterModel : public QSortFilterProxyModel
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_PROPERTY(bool hidden READ hidden WRITE setHidden NOTIFY hiddenChanged)
|
||||
Q_PROPERTY(int count READ count NOTIFY countChanged)
|
||||
Q_PROPERTY(QString name READ name CONSTANT)
|
||||
Q_PROPERTY(QObject* containment READ containment WRITE setContainment)
|
||||
|
||||
public:
|
||||
InstalledAppsFilterModel(const QString &entryPath, const QString &installer, QObject *parent = 0);
|
||||
~InstalledAppsFilterModel();
|
||||
|
||||
int count() const;
|
||||
|
||||
Q_INVOKABLE bool trigger(int row, const QString &actionId = QString(), const QVariant &actionArgument = QVariant());
|
||||
|
||||
QObject *containment() const;
|
||||
void setContainment(QObject *containment);
|
||||
|
||||
QString name() const;
|
||||
|
||||
bool hidden() const;
|
||||
void setHidden(bool hidden);
|
||||
|
||||
Q_SIGNALS:
|
||||
void countChanged();
|
||||
void hiddenChanged();
|
||||
void applicationLaunched(const QString& storageId);
|
||||
void addToDesktop(const QString& storageId);
|
||||
void addToPanel(const QString& storageId);
|
||||
|
||||
public Q_SLOTS:
|
||||
void refresh(bool reload = true);
|
||||
|
||||
private:
|
||||
InstalledAppsModel *m_installedAppsModel;
|
||||
bool m_hidden;
|
||||
};
|
||||
|
||||
class SideBarModel : public QSortFilterProxyModel
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit SideBarModel(FilterableInstalledAppsModel *parent = 0);
|
||||
~SideBarModel();
|
||||
|
||||
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const;
|
||||
|
||||
Q_INVOKABLE void trigger(int row);
|
||||
|
||||
protected:
|
||||
bool filterAcceptsRow(int source_row, const QModelIndex &source_parent) const;
|
||||
|
||||
private:
|
||||
FilterableInstalledAppsModel *m_sourceModel;
|
||||
int m_activeSourceRow;
|
||||
|
||||
friend class FilterableInstalledAppsModel;
|
||||
};
|
||||
|
||||
class FilterableInstalledAppsModel : public QAbstractListModel
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_PROPERTY(int count READ count NOTIFY countChanged)
|
||||
Q_PROPERTY(QString query WRITE scheduleQuery READ currentQuery NOTIFY queryChanged)
|
||||
Q_PROPERTY(QObject* sideBarModel READ sideBarModel CONSTANT)
|
||||
|
||||
public:
|
||||
explicit FilterableInstalledAppsModel(const QString &installer, QObject *parent = 0);
|
||||
~FilterableInstalledAppsModel();
|
||||
|
||||
int count() const;
|
||||
|
||||
int rowCount(const QModelIndex &parent = QModelIndex()) const; // reimp
|
||||
QVariant data(const QModelIndex &, int role = Qt::DisplayRole) const; // reimp
|
||||
|
||||
QString currentQuery() const;
|
||||
|
||||
SideBarModel *sideBarModel() const;
|
||||
|
||||
Q_INVOKABLE QObject *modelForRow(int row) const;
|
||||
|
||||
Q_SIGNALS:
|
||||
void countChanged();
|
||||
void installerChanged(const QString &);
|
||||
void queryChanged(const QString &);
|
||||
void applicationLaunched(const QString &);
|
||||
|
||||
public Q_SLOTS:
|
||||
void refresh(bool reload = true);
|
||||
void scheduleQuery(const QString &query);
|
||||
|
||||
private Q_SLOTS:
|
||||
void loadRootEntries();
|
||||
void loadNextGroup();
|
||||
|
||||
private:
|
||||
QString m_installer;
|
||||
QList<KServiceGroup::Ptr> m_pendingGroupList;
|
||||
QList<InstalledAppsFilterModel *> m_models;
|
||||
SideBarModel *m_sideBarModel;
|
||||
QString m_query;
|
||||
|
||||
InstalledAppsFilterModel *createInstalledAppsFilterModel(KServiceGroup::Ptr group);
|
||||
};
|
||||
|
||||
class FilterableInstalledAppsSource : public AbstractSource
|
||||
{
|
||||
public:
|
||||
FilterableInstalledAppsSource(QObject *parent);
|
||||
QAbstractItemModel *createModelFromConfigGroup(const KConfigGroup &);
|
||||
};
|
||||
|
||||
} // namespace Homerun
|
||||
|
||||
#endif /* FILTERABLEINSTALLEDAPPSMODEL_H */
|
|
@ -1,161 +0,0 @@
|
|||
/*
|
||||
Copyright 2012 Aurélien Gâteau <agateau@kde.org>
|
||||
Copyright 2013 Eike Hein <hein@kde.org>
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) 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 6 of version 3 of the license.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
// Self
|
||||
#include <groupedinstalledappsmodel.h>
|
||||
|
||||
// Local
|
||||
#include <abstractsourceregistry.h>
|
||||
#include <changenotifier.h>
|
||||
#include <installedappsmodel.h>
|
||||
|
||||
// KDE
|
||||
#include <KConfigGroup>
|
||||
#include <KDebug>
|
||||
|
||||
// Qt
|
||||
|
||||
namespace Homerun {
|
||||
|
||||
GroupedInstalledAppsModel::GroupedInstalledAppsModel(const QString &installer, QObject *parent)
|
||||
: QAbstractListModel(parent)
|
||||
, m_installer(installer)
|
||||
{
|
||||
loadRootEntries();
|
||||
}
|
||||
|
||||
GroupedInstalledAppsModel::~GroupedInstalledAppsModel()
|
||||
{
|
||||
}
|
||||
|
||||
QObject *GroupedInstalledAppsModel::modelForRow(int row) const
|
||||
{
|
||||
if (row < 0 || row >= m_models.count()) {
|
||||
kWarning() << "No model for row" << row << "!";
|
||||
return 0;
|
||||
}
|
||||
return m_models.value(row);
|
||||
}
|
||||
|
||||
void GroupedInstalledAppsModel::refresh(bool reload)
|
||||
{
|
||||
if (!reload) {
|
||||
foreach(InstalledAppsModel* model, m_models) {
|
||||
model->refresh(false);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
beginResetModel();
|
||||
qDeleteAll(m_models);
|
||||
m_models.clear();
|
||||
m_pendingGroupList.clear();
|
||||
endResetModel();
|
||||
|
||||
loadRootEntries();
|
||||
}
|
||||
|
||||
void GroupedInstalledAppsModel::loadRootEntries()
|
||||
{
|
||||
KServiceGroup::Ptr group = KServiceGroup::root();
|
||||
KServiceGroup::List list = group->entries(false /* sorted: set to false as it does not seem to work */);
|
||||
|
||||
QMap<QString, KServiceGroup::Ptr> groupMap;
|
||||
for( KServiceGroup::List::ConstIterator it = list.constBegin(); it != list.constEnd(); it++) {
|
||||
const KSycocaEntry::Ptr p = (*it);
|
||||
|
||||
if (p->isType(KST_KServiceGroup)) {
|
||||
KServiceGroup::Ptr subGroup = KServiceGroup::Ptr::staticCast(p);
|
||||
|
||||
if (!subGroup->noDisplay() && subGroup->childCount() > 0) {
|
||||
groupMap.insert(subGroup->caption().toLower(), subGroup);
|
||||
}
|
||||
}
|
||||
}
|
||||
m_pendingGroupList = groupMap.values();
|
||||
QMetaObject::invokeMethod(this, "loadNextGroup", Qt::QueuedConnection);
|
||||
}
|
||||
|
||||
void GroupedInstalledAppsModel::loadNextGroup()
|
||||
{
|
||||
if (m_pendingGroupList.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
KServiceGroup::Ptr group = m_pendingGroupList.takeFirst();
|
||||
InstalledAppsModel *model = createInstalledAppsModel(group);
|
||||
model->setParent(this);
|
||||
beginInsertRows(QModelIndex(), m_models.count(), m_models.count());
|
||||
m_models << model;
|
||||
endInsertRows();
|
||||
QMetaObject::invokeMethod(this, "loadNextGroup", Qt::QueuedConnection);
|
||||
}
|
||||
|
||||
int GroupedInstalledAppsModel::rowCount(const QModelIndex &parent) const
|
||||
{
|
||||
if (parent.isValid()) {
|
||||
return 0;
|
||||
}
|
||||
return m_models.count();
|
||||
}
|
||||
|
||||
QVariant GroupedInstalledAppsModel::data(const QModelIndex &index, int role) const
|
||||
{
|
||||
if (index.parent().isValid()) {
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
InstalledAppsModel *model = m_models.value(index.row());
|
||||
if (!model) {
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
if (role == Qt::DisplayRole) {
|
||||
return model->name();
|
||||
} else {
|
||||
return QVariant();
|
||||
}
|
||||
}
|
||||
|
||||
InstalledAppsModel *GroupedInstalledAppsModel::createInstalledAppsModel(KServiceGroup::Ptr group)
|
||||
{
|
||||
InstalledAppsModel *model = new InstalledAppsModel(group->entryPath(), m_installer, this);
|
||||
connect(model, SIGNAL(applicationLaunched(QString)), this, SIGNAL(applicationLaunched(QString)));
|
||||
return model;
|
||||
}
|
||||
|
||||
//- GroupedInstalledAppsSource --------------------------------------
|
||||
GroupedInstalledAppsSource::GroupedInstalledAppsSource(QObject *parent)
|
||||
: AbstractSource(parent)
|
||||
{}
|
||||
|
||||
QAbstractItemModel *GroupedInstalledAppsSource::createModelFromConfigGroup(const KConfigGroup &)
|
||||
{
|
||||
KConfigGroup group(config(), "PackageManagement");
|
||||
QString installer = group.readEntry("categoryInstaller");
|
||||
GroupedInstalledAppsModel *model = new GroupedInstalledAppsModel(installer);
|
||||
ChangeNotifier *notifier = new ChangeNotifier(model);
|
||||
connect(notifier, SIGNAL(changeDetected(bool)), model, SLOT(refresh(bool)));
|
||||
return model;
|
||||
}
|
||||
|
||||
} // namespace Homerun
|
||||
|
||||
#include "moc_groupedinstalledappsmodel.cpp"
|
|
@ -1,80 +0,0 @@
|
|||
/*
|
||||
Copyright 2012 Aurélien Gâteau <agateau@kde.org>
|
||||
Copyright 2013 Eike Hein <hein@kde.org>
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) 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 6 of version 3 of the license.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#ifndef GROUPEDINSTALLEDAPPSMODEL_H
|
||||
#define GROUPEDINSTALLEDAPPSMODEL_H
|
||||
|
||||
// Local
|
||||
#include <abstractsource.h>
|
||||
|
||||
// Qt
|
||||
#include <QtCore/qabstractitemmodel.h>
|
||||
|
||||
// KDE
|
||||
#include <KServiceGroup>
|
||||
|
||||
namespace Homerun {
|
||||
|
||||
class InstalledAppsModel;
|
||||
|
||||
/**
|
||||
* A model which returns all services in grouped sub-models
|
||||
*/
|
||||
class GroupedInstalledAppsModel : public QAbstractListModel
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit GroupedInstalledAppsModel(const QString &installer, QObject *parent = 0);
|
||||
~GroupedInstalledAppsModel();
|
||||
|
||||
int rowCount(const QModelIndex &parent = QModelIndex()) const; // reimp
|
||||
QVariant data(const QModelIndex &, int role = Qt::DisplayRole) const; // reimp
|
||||
|
||||
Q_INVOKABLE QObject *modelForRow(int row) const;
|
||||
|
||||
Q_SIGNALS:
|
||||
void installerChanged(const QString &);
|
||||
void applicationLaunched(const QString &);
|
||||
|
||||
public Q_SLOTS:
|
||||
void refresh(bool reload = true);
|
||||
|
||||
private Q_SLOTS:
|
||||
void loadRootEntries();
|
||||
void loadNextGroup();
|
||||
|
||||
private:
|
||||
QString m_installer;
|
||||
QList<KServiceGroup::Ptr> m_pendingGroupList;
|
||||
QList<InstalledAppsModel *> m_models;
|
||||
|
||||
InstalledAppsModel *createInstalledAppsModel(KServiceGroup::Ptr group);
|
||||
};
|
||||
|
||||
class GroupedInstalledAppsSource : public AbstractSource
|
||||
{
|
||||
public:
|
||||
GroupedInstalledAppsSource(QObject *parent);
|
||||
QAbstractItemModel *createModelFromConfigGroup(const KConfigGroup &);
|
||||
};
|
||||
|
||||
} // namespace Homerun
|
||||
|
||||
#endif /* GROUPEDINSTALLEDAPPSMODEL_H */
|
|
@ -1,146 +0,0 @@
|
|||
/*
|
||||
Copyright 2012 Aurélien Gâteau <agateau@kde.org>
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) 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 6 of version 3 of the license.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
// Self
|
||||
#include <installedappsconfigurationwidget.h>
|
||||
|
||||
// Local
|
||||
#include <ui_installedappsconfigurationwidget.h>
|
||||
|
||||
// KDE
|
||||
#include <KDebug>
|
||||
#include <KIcon>
|
||||
#include <KServiceGroup>
|
||||
#include <KSycocaEntry>
|
||||
#include <KConfigGroup>
|
||||
|
||||
// Qt
|
||||
#include <QtGui/qstandarditemmodel.h>
|
||||
#include <QStandardItemModel>
|
||||
|
||||
enum {
|
||||
EntryPathRole = Qt::UserRole + 1,
|
||||
SortRole,
|
||||
};
|
||||
|
||||
namespace Homerun
|
||||
{
|
||||
|
||||
InstalledAppsConfigurationWidget::InstalledAppsConfigurationWidget(const KConfigGroup &group)
|
||||
: SourceConfigurationWidget(group)
|
||||
, m_ui(new Ui_InstalledAppsConfigurationWidget)
|
||||
, m_model(new QStandardItemModel(this))
|
||||
{
|
||||
// Init model
|
||||
QStandardItem *defaultItem = fillModel(group.readEntry("entryPath"));
|
||||
m_model->setSortRole(SortRole);
|
||||
m_model->sort(0);
|
||||
|
||||
m_ui->setupUi(this);
|
||||
m_ui->treeView->setModel(m_model);
|
||||
|
||||
// Select currently configured item
|
||||
Q_ASSERT(defaultItem);
|
||||
QModelIndex index = defaultItem->index();
|
||||
m_ui->treeView->selectionModel()->select(index, QItemSelectionModel::Select);
|
||||
|
||||
// Expand up to the configured item
|
||||
index = index.parent();
|
||||
for (; index.isValid(); index = index.parent()) {
|
||||
m_ui->treeView->setExpanded(index, true);
|
||||
}
|
||||
|
||||
// Always expand top level
|
||||
m_ui->treeView->setExpanded(m_model->index(0, 0), true);
|
||||
}
|
||||
|
||||
InstalledAppsConfigurationWidget::~InstalledAppsConfigurationWidget()
|
||||
{
|
||||
delete m_ui;
|
||||
}
|
||||
|
||||
void InstalledAppsConfigurationWidget::save()
|
||||
{
|
||||
QModelIndex index = m_ui->treeView->selectionModel()->currentIndex();
|
||||
if (!index.isValid()) {
|
||||
kWarning() << "No item selected!";
|
||||
return;
|
||||
}
|
||||
QString entryPath = index.data(EntryPathRole).toString();
|
||||
configGroup().writeEntry("entryPath", entryPath);
|
||||
}
|
||||
|
||||
|
||||
// Helper struct for fillModel
|
||||
struct ItemCreator
|
||||
{
|
||||
ItemCreator()
|
||||
: m_item(0)
|
||||
{}
|
||||
QString m_entryPath;
|
||||
QStandardItem *m_item;
|
||||
|
||||
void createItemChildren(QStandardItem *parent, KServiceGroup::Ptr parentGroup)
|
||||
{
|
||||
KServiceGroup::List list = parentGroup->entries(false /* sorted: set to false as it does not seem to work */);
|
||||
|
||||
Q_FOREACH(const KSycocaEntry::Ptr entry, list) {
|
||||
if (!entry->isType(KST_KServiceGroup)) {
|
||||
continue;
|
||||
}
|
||||
KServiceGroup::Ptr group = KServiceGroup::Ptr::staticCast(entry);
|
||||
|
||||
if (group->noDisplay() || group->childCount() == 0) {
|
||||
continue;
|
||||
}
|
||||
QString entryPath = group->entryPath();
|
||||
|
||||
QStandardItem *item = new QStandardItem;
|
||||
item->setText(group->caption());
|
||||
item->setIcon(KIcon(group->icon()));
|
||||
item->setData(entryPath, EntryPathRole);
|
||||
item->setData(group->caption().toLower(), SortRole);
|
||||
|
||||
parent->appendRow(item);
|
||||
createItemChildren(item, group);
|
||||
|
||||
if (m_entryPath == entryPath) {
|
||||
m_item = item;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
QStandardItem *InstalledAppsConfigurationWidget::fillModel(const QString &entryPath)
|
||||
{
|
||||
KServiceGroup::Ptr group = KServiceGroup::root();
|
||||
QStandardItem *rootItem = new QStandardItem;
|
||||
rootItem->setText(i18n("All Applications"));
|
||||
rootItem->setData(QString(), EntryPathRole);
|
||||
m_model->appendRow(rootItem);
|
||||
|
||||
ItemCreator creator;
|
||||
creator.m_entryPath = entryPath;
|
||||
creator.createItemChildren(rootItem, group);
|
||||
return creator.m_item ? creator.m_item : rootItem;
|
||||
}
|
||||
|
||||
} // namespace Homerun
|
||||
|
||||
#include "moc_installedappsconfigurationwidget.cpp"
|
|
@ -1,63 +0,0 @@
|
|||
/*
|
||||
Copyright 2012 Aurélien Gâteau <agateau@kde.org>
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) 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 6 of version 3 of the license.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#ifndef INSTALLEDAPPSCONFIGURATIONWIDGET_H
|
||||
#define INSTALLEDAPPSCONFIGURATIONWIDGET_H
|
||||
|
||||
// Local
|
||||
#include <sourceconfigurationwidget.h>
|
||||
|
||||
// Qt
|
||||
|
||||
// KDE
|
||||
#include <KServiceGroup>
|
||||
|
||||
class QStandardItem;
|
||||
class QStandardItemModel;
|
||||
|
||||
class Ui_InstalledAppsConfigurationWidget;
|
||||
|
||||
namespace Homerun
|
||||
{
|
||||
|
||||
/**
|
||||
* Configuration widget for the InstalledApps source
|
||||
*/
|
||||
class InstalledAppsConfigurationWidget : public SourceConfigurationWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit InstalledAppsConfigurationWidget(const KConfigGroup &group);
|
||||
~InstalledAppsConfigurationWidget();
|
||||
|
||||
void save(); // reimp
|
||||
|
||||
private:
|
||||
Ui_InstalledAppsConfigurationWidget *m_ui;
|
||||
QStandardItemModel *m_model;
|
||||
|
||||
/**
|
||||
* Fill m_model, returns the item which corresponds to defaultEntryPath
|
||||
*/
|
||||
QStandardItem *fillModel(const QString &defaultEntryPath);
|
||||
};
|
||||
|
||||
} // namespace Homerun
|
||||
|
||||
#endif /* INSTALLEDAPPSCONFIGURATIONWIDGET_H */
|
|
@ -1,50 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>InstalledAppsConfigurationWidget</class>
|
||||
<widget class="QWidget" name="InstalledAppsConfigurationWidget">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>408</width>
|
||||
<height>327</height>
|
||||
</rect>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="text">
|
||||
<string>Pick the application folder to display:</string>
|
||||
</property>
|
||||
<property name="buddy">
|
||||
<cstring>treeView</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QTreeView" name="treeView">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>400</width>
|
||||
<height>300</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="editTriggers">
|
||||
<set>QAbstractItemView::NoEditTriggers</set>
|
||||
</property>
|
||||
<property name="showDropIndicator" stdset="0">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="rootIsDecorated">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="headerHidden">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
|
@ -1,484 +0,0 @@
|
|||
/*
|
||||
Copyright 2012 Aurélien Gâteau <agateau@kde.org>
|
||||
Copyright 2013 Eike Hein <hein@kde.org>
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) 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 6 of version 3 of the license.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
// Local
|
||||
#include <changenotifier.h>
|
||||
#include <pathmodel.h>
|
||||
#include <actionlist.h>
|
||||
#include <installedappsmodel.h>
|
||||
#include <installedappsconfigurationwidget.h>
|
||||
#include <sourceregistry.h>
|
||||
|
||||
// Qt
|
||||
#include <QApplication>
|
||||
#include <QIcon>
|
||||
#include <QAction>
|
||||
#include <QTimer>
|
||||
|
||||
// KDE
|
||||
#include <KDebug>
|
||||
#include <KLocale>
|
||||
#include <kmacroexpander.h>
|
||||
#include <KRun>
|
||||
#include <KService>
|
||||
#include <KServiceTypeTrader>
|
||||
#include <KSycocaEntry>
|
||||
|
||||
#include <Plasma/Containment>
|
||||
#include <Plasma/Corona>
|
||||
|
||||
namespace Homerun {
|
||||
|
||||
static const char *SOURCE_ID = "InstalledApps";
|
||||
|
||||
//- AbstractNode ---------------------------------------------------------------
|
||||
AbstractNode::~AbstractNode()
|
||||
{
|
||||
}
|
||||
|
||||
bool AbstractNode::lessThan(AbstractNode *n1, AbstractNode *n2)
|
||||
{
|
||||
Q_ASSERT(n1);
|
||||
Q_ASSERT(n2);
|
||||
return n1->m_sortKey < n2->m_sortKey;
|
||||
}
|
||||
|
||||
//- GroupNode ------------------------------------------------------------------
|
||||
GroupNode::GroupNode(KServiceGroup::Ptr group, InstalledAppsModel *model)
|
||||
: m_model(model)
|
||||
{
|
||||
m_icon = group->icon();
|
||||
m_name = group->caption();
|
||||
m_entryPath = group->entryPath();
|
||||
m_sortKey = m_name.toLower();
|
||||
}
|
||||
|
||||
bool GroupNode::trigger(const QString &actionId, const QVariant &actionArgument)
|
||||
{
|
||||
Q_UNUSED(actionId)
|
||||
Q_UNUSED(actionArgument)
|
||||
|
||||
QVariantMap args;
|
||||
args.insert("entryPath", m_entryPath);
|
||||
m_model->openSourceRequested(SOURCE_ID, args);
|
||||
return false;
|
||||
}
|
||||
|
||||
//- AppNode --------------------------------------------------------------------
|
||||
AppNode::AppNode(KService::Ptr service, InstalledAppsModel *model)
|
||||
: m_model(model)
|
||||
, m_service(service)
|
||||
{
|
||||
m_icon = service->icon();
|
||||
m_name = service->name();
|
||||
m_genericName = service->genericName();
|
||||
m_service = service;
|
||||
m_sortKey = m_name.toLower();
|
||||
}
|
||||
|
||||
bool AppNode::trigger(const QString &actionId, const QVariant &actionArgument)
|
||||
{
|
||||
Q_UNUSED(actionArgument)
|
||||
|
||||
if (!actionId.isEmpty()) {
|
||||
QVariant adaptor = qApp->property("HomerunViewerAdaptor");
|
||||
|
||||
if (adaptor.isValid()) {
|
||||
uint containmentId = (actionId == "addToDesktop") ? qApp->property("desktopContainmentId").toUInt()
|
||||
: qApp->property("appletContainmentId").toUInt();
|
||||
return QMetaObject::invokeMethod(adaptor.value<QObject *>(), actionId.toLocal8Bit(),
|
||||
Qt::DirectConnection, Q_ARG(uint, containmentId), Q_ARG(QString, m_service->storageId()));
|
||||
} else if (m_model->containment()) {
|
||||
Plasma::Containment *containment = static_cast<Plasma::Containment *>(m_model->containment());
|
||||
|
||||
if (actionId == "addToDesktop") {
|
||||
Plasma::Containment *desktop = containment->corona()->containmentForScreen(containment->screen());
|
||||
|
||||
if (desktop) {
|
||||
if (desktop->metaObject()->indexOfSlot("addUrls(KUrl::List)") != -1) {
|
||||
QMetaObject::invokeMethod(desktop, "addUrls",
|
||||
Qt::DirectConnection, Q_ARG(KUrl::List, KUrl::List(m_service->entryPath())));
|
||||
} else {
|
||||
desktop->addApplet("icon", QVariantList() << m_service->entryPath());
|
||||
}
|
||||
}
|
||||
} else if (actionId == "addToPanel") {
|
||||
QRectF rect(containment->geometry().width() / 3, 0, 150,
|
||||
containment->boundingRect().height());
|
||||
containment->addApplet("icon", QVariantList() << m_service->entryPath(), rect);
|
||||
} else if (actionId == "addLauncher") {
|
||||
QObject* taskManager = 0;
|
||||
|
||||
foreach(QObject* applet, containment->applets()) {
|
||||
if (applet->metaObject()->indexOfSlot("addLauncher(QString)") != -1) {
|
||||
taskManager = applet;
|
||||
}
|
||||
}
|
||||
|
||||
if (taskManager) {
|
||||
QMetaObject::invokeMethod(taskManager, "addLauncher", Qt::DirectConnection,
|
||||
Q_ARG(QString, m_service->storageId()));
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
bool ran = KRun::run(*m_service, KUrl::List(), 0);
|
||||
|
||||
if (ran) {
|
||||
emit m_model->applicationLaunched(m_service->storageId());
|
||||
}
|
||||
|
||||
return ran;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
QString AppNode::favoriteId() const
|
||||
{
|
||||
return QString("app:") + m_service->storageId();
|
||||
}
|
||||
|
||||
KService::Ptr AppNode::service() const
|
||||
{
|
||||
return m_service;
|
||||
}
|
||||
|
||||
//- InstallerNode --------------------------------------------------------------
|
||||
InstallerNode::InstallerNode(KServiceGroup::Ptr group, KService::Ptr installerService)
|
||||
: m_group(group)
|
||||
, m_service(installerService)
|
||||
{
|
||||
m_icon = m_service->icon();
|
||||
m_name = m_service->name();
|
||||
}
|
||||
|
||||
bool InstallerNode::trigger(const QString &actionId, const QVariant &actionArgument)
|
||||
{
|
||||
Q_UNUSED(actionId)
|
||||
Q_UNUSED(actionArgument)
|
||||
|
||||
QHash<QString, QString> map;
|
||||
QString category = m_group->entryPath();
|
||||
if (category.endsWith('/')) {
|
||||
category.truncate(category.length() - 1);
|
||||
}
|
||||
map.insert("category", category);
|
||||
|
||||
QString command = KMacroExpander::expandMacros(m_service->exec(), map, '@');
|
||||
return KRun::run(command, KUrl::List(), 0, m_service->name(), m_service->icon());
|
||||
}
|
||||
|
||||
//- InstalledAppsModel ------------------------------------------------------------
|
||||
InstalledAppsModel::InstalledAppsModel(const QString &entryPath, const QString &installer, QObject *parent)
|
||||
: QAbstractListModel(parent)
|
||||
, m_entryPath(entryPath)
|
||||
, m_pathModel(new PathModel(this))
|
||||
, m_installer(installer)
|
||||
, m_containment(0)
|
||||
{
|
||||
QHash<int, QByteArray> roles;
|
||||
roles.insert(Qt::DisplayRole, "display");
|
||||
roles.insert(Qt::DecorationRole, "decoration");
|
||||
roles.insert(FavoriteIdRole, "favoriteId");
|
||||
roles.insert(HasActionListRole, "hasActionList");
|
||||
roles.insert(ActionListRole, "actionList");
|
||||
roles.insert(GenericNameRole, "genericName");
|
||||
|
||||
setRoleNames(roles);
|
||||
|
||||
refresh();
|
||||
}
|
||||
|
||||
InstalledAppsModel::~InstalledAppsModel()
|
||||
{
|
||||
qDeleteAll(m_nodeList);
|
||||
}
|
||||
|
||||
QObject* InstalledAppsModel::containment() const
|
||||
{
|
||||
return m_containment;
|
||||
}
|
||||
|
||||
void InstalledAppsModel::setContainment(QObject* containment)
|
||||
{
|
||||
m_containment = containment;
|
||||
}
|
||||
|
||||
int InstalledAppsModel::rowCount(const QModelIndex& index) const
|
||||
{
|
||||
return index.isValid() ? 0 : m_nodeList.count();
|
||||
}
|
||||
|
||||
int InstalledAppsModel::count() const
|
||||
{
|
||||
return m_nodeList.count();
|
||||
}
|
||||
|
||||
QVariant InstalledAppsModel::data(const QModelIndex &index, int role) const
|
||||
{
|
||||
if (!index.isValid() || index.row() >= m_nodeList.count()) {
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
AbstractNode *node = m_nodeList.at(index.row());
|
||||
if (role == Qt::DisplayRole) {
|
||||
return node->name();
|
||||
} else if (role == Qt::DecorationRole) {
|
||||
// at least show the oxygen question-mark, otherwise it looks weird blank.
|
||||
return node->icon().isEmpty() ? QLatin1String("unknown") : node->icon();
|
||||
} else if (role == FavoriteIdRole) {
|
||||
return node->favoriteId();
|
||||
} else if (role == HasActionListRole) {
|
||||
return node->type() == AbstractNode::AppNodeType;
|
||||
} else if (role == ActionListRole && node->type() == AbstractNode::AppNodeType) {
|
||||
QVariantList actionList;
|
||||
|
||||
if (qApp->property("HomerunViewerAdaptor").isValid())
|
||||
{
|
||||
if (qApp->property("desktopContainmentId").toUInt() > 0
|
||||
&& qApp->property("desktopContainmentMutable").toBool()) {
|
||||
actionList << ActionList::createActionItem(i18n("Add to Desktop"), "addToDesktop");
|
||||
}
|
||||
if (qApp->property("appletContainmentId").toUInt() > 0
|
||||
&& qApp->property("appletContainmentMutable").toBool()) {
|
||||
actionList << ActionList::createActionItem(i18n("Add to Panel"), "addToPanel");
|
||||
}
|
||||
} else if (m_containment) {
|
||||
Plasma::Containment *containment = static_cast<Plasma::Containment *>(m_containment);
|
||||
Plasma::Containment *desktop = containment->corona()->containmentForScreen(containment->screen());
|
||||
|
||||
if (desktop && desktop->immutability() == Plasma::Mutable) {
|
||||
actionList << ActionList::createActionItem(i18n("Add to Desktop"), "addToDesktop");
|
||||
}
|
||||
|
||||
if (containment->immutability() == Plasma::Mutable) {
|
||||
actionList << ActionList::createActionItem(i18n("Add to Panel"), "addToPanel");
|
||||
}
|
||||
|
||||
QObject* taskManager = 0;
|
||||
|
||||
foreach(QObject* applet, containment->applets()) {
|
||||
if (applet->metaObject()->indexOfSlot("hasLauncher(QString)") != -1) {
|
||||
taskManager = applet;
|
||||
}
|
||||
}
|
||||
|
||||
if (taskManager) {
|
||||
AppNode* appNode = static_cast<AppNode *>(node);
|
||||
|
||||
bool hasLauncher = false;
|
||||
|
||||
QMetaObject::invokeMethod(taskManager, "hasLauncher", Qt::DirectConnection,
|
||||
Q_RETURN_ARG(bool, hasLauncher), Q_ARG(QString, appNode->service()->storageId()));
|
||||
|
||||
if (!hasLauncher) {
|
||||
actionList << ActionList::createActionItem(i18n("Add as Launcher"), "addLauncher");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return actionList;
|
||||
} else if (role == GenericNameRole && node->type() == AbstractNode::AppNodeType) {
|
||||
return static_cast<AppNode *>(node)->genericName();
|
||||
} else if (role == CombinedNameRole && node->type() == AbstractNode::AppNodeType) {
|
||||
AppNode *appNode = static_cast<AppNode *>(node);
|
||||
return QString(appNode->name() + ' ' + appNode->genericName());
|
||||
}
|
||||
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
bool InstalledAppsModel::trigger(int row, const QString &actionId, const QVariant &actionArgument)
|
||||
{
|
||||
return m_nodeList.at(row)->trigger(actionId, actionArgument);
|
||||
}
|
||||
|
||||
void InstalledAppsModel::refresh(bool reload)
|
||||
{
|
||||
if (!reload) {
|
||||
emit layoutAboutToBeChanged();
|
||||
emit layoutChanged();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
m_pathModel->clear();
|
||||
beginResetModel();
|
||||
qDeleteAll(m_nodeList);
|
||||
m_nodeList.clear();
|
||||
|
||||
if (m_entryPath.isEmpty()) {
|
||||
loadRootEntries();
|
||||
} else {
|
||||
KServiceGroup::Ptr group = KServiceGroup::group(m_entryPath);
|
||||
loadServiceGroup(group);
|
||||
QVariantMap args;
|
||||
args.insert("entryPath", m_entryPath);
|
||||
QString label = (m_entryPath == KServiceGroup::root()->entryPath()) ? i18n("All Applications")
|
||||
: group->caption();
|
||||
m_pathModel->addPath(label, SOURCE_ID, args);
|
||||
}
|
||||
|
||||
endResetModel();
|
||||
|
||||
emit countChanged();
|
||||
}
|
||||
|
||||
void InstalledAppsModel::loadRootEntries()
|
||||
{
|
||||
KServiceGroup::Ptr group = KServiceGroup::root();
|
||||
KServiceGroup::List list = group->entries(false /* sorted: set to false as it does not seem to work */);
|
||||
|
||||
for( KServiceGroup::List::ConstIterator it = list.constBegin(); it != list.constEnd(); it++) {
|
||||
const KSycocaEntry::Ptr p = (*it);
|
||||
|
||||
if (p->isType(KST_KServiceGroup)) {
|
||||
KServiceGroup::Ptr subGroup = KServiceGroup::Ptr::staticCast(p);
|
||||
|
||||
if (!subGroup->noDisplay() && subGroup->childCount() > 0) {
|
||||
m_nodeList << new GroupNode(subGroup, this);
|
||||
}
|
||||
}
|
||||
}
|
||||
qSort(m_nodeList.begin(), m_nodeList.end(), AbstractNode::lessThan);
|
||||
}
|
||||
|
||||
void InstalledAppsModel::loadServiceGroup(KServiceGroup::Ptr group)
|
||||
{
|
||||
doLoadServiceGroup(group);
|
||||
|
||||
qSort(m_nodeList.begin(), m_nodeList.end(), AbstractNode::lessThan);
|
||||
|
||||
if (!m_installer.isEmpty()) {
|
||||
KService::Ptr service = KService::serviceByDesktopName(m_installer);
|
||||
if (service) {
|
||||
m_nodeList << new InstallerNode(group, service);
|
||||
} else {
|
||||
kWarning() << "Could not find service for" << m_installer;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void InstalledAppsModel::doLoadServiceGroup(KServiceGroup::Ptr group)
|
||||
{
|
||||
/* This method is separate from loadServiceGroup so that
|
||||
* - only one installer node is added at the end
|
||||
* - sorting is done only once
|
||||
*/
|
||||
if (!group || !group->isValid()) {
|
||||
return;
|
||||
}
|
||||
|
||||
KServiceGroup::List list = group->entries(false /* see above */);
|
||||
|
||||
for( KServiceGroup::List::ConstIterator it = list.constBegin();
|
||||
it != list.constEnd(); it++) {
|
||||
const KSycocaEntry::Ptr p = (*it);
|
||||
|
||||
if (p->isType(KST_KService)) {
|
||||
const KService::Ptr service = KService::Ptr::staticCast(p);
|
||||
|
||||
if (!service->noDisplay()) {
|
||||
QString genericName = service->genericName();
|
||||
if (genericName.isNull()) {
|
||||
genericName = service->comment();
|
||||
}
|
||||
|
||||
bool found = false;
|
||||
|
||||
foreach(const AbstractNode *node, m_nodeList) {
|
||||
if (node->type() == AbstractNode::AppNodeType
|
||||
&& static_cast<const AppNode *>(node)->service()->storageId() == service->storageId()) {
|
||||
found = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (!found) {
|
||||
m_nodeList << new AppNode(service, this);
|
||||
}
|
||||
}
|
||||
|
||||
} else if (p->isType(KST_KServiceGroup)) {
|
||||
const KServiceGroup::Ptr subGroup = KServiceGroup::Ptr::staticCast(p);
|
||||
|
||||
if (!subGroup->noDisplay() && subGroup->childCount() > 0) {
|
||||
doLoadServiceGroup(subGroup);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
PathModel *InstalledAppsModel::pathModel() const
|
||||
{
|
||||
return m_pathModel;
|
||||
}
|
||||
|
||||
QString InstalledAppsModel::name() const
|
||||
{
|
||||
if (m_pathModel->count() > 0) {
|
||||
QModelIndex index = m_pathModel->index(m_pathModel->count() - 1, 0);
|
||||
return index.data().toString();
|
||||
} else {
|
||||
return i18n("Applications");
|
||||
}
|
||||
}
|
||||
|
||||
//- InstalledAppsSource ---------------------------------------------
|
||||
InstalledAppsSource::InstalledAppsSource(QObject *parent)
|
||||
: AbstractSource(parent)
|
||||
{}
|
||||
|
||||
QAbstractItemModel *InstalledAppsSource::createModelFromConfigGroup(const KConfigGroup &group)
|
||||
{
|
||||
QString entryPath = group.readEntry("entryPath");
|
||||
return createModel(entryPath);
|
||||
}
|
||||
|
||||
QAbstractItemModel *InstalledAppsSource::createModelFromArguments(const QVariantMap &arguments)
|
||||
{
|
||||
QString entryPath = arguments.value("entryPath").toString();
|
||||
return createModel(entryPath);
|
||||
}
|
||||
|
||||
QAbstractItemModel *InstalledAppsSource::createModel(const QString &entryPath)
|
||||
{
|
||||
KConfigGroup group(config(), "PackageManagement");
|
||||
QString installer = group.readEntry("categoryInstaller");
|
||||
|
||||
InstalledAppsModel *model = new InstalledAppsModel(entryPath, installer);
|
||||
ChangeNotifier *notifier = new ChangeNotifier(model);
|
||||
connect(notifier, SIGNAL(changeDetected(bool)), model, SLOT(refresh(bool)));
|
||||
return model;
|
||||
}
|
||||
|
||||
bool InstalledAppsSource::isConfigurable() const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
SourceConfigurationWidget *InstalledAppsSource::createConfigurationWidget(const KConfigGroup &group)
|
||||
{
|
||||
return new InstalledAppsConfigurationWidget(group);
|
||||
}
|
||||
|
||||
} // namespace Homerun
|
||||
|
||||
#include "moc_installedappsmodel.cpp"
|
|
@ -1,190 +0,0 @@
|
|||
/*
|
||||
Copyright 2012 Aurélien Gâteau <agateau@kde.org>
|
||||
Copyright 2013 Eike Hein <hein@kde.org>
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) 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 6 of version 3 of the license.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#ifndef INSTALLEDAPPSMODEL_H
|
||||
#define INSTALLEDAPPSMODEL_H
|
||||
|
||||
// Local
|
||||
#include <abstractsource.h>
|
||||
|
||||
// Qt
|
||||
#include <QtCore/qabstractitemmodel.h>
|
||||
#include <QSortFilterProxyModel>
|
||||
#include <QStringList>
|
||||
|
||||
// KDE
|
||||
#include <KIcon>
|
||||
#include <KService>
|
||||
#include <KServiceGroup>
|
||||
#include <KUrl>
|
||||
|
||||
namespace Homerun {
|
||||
|
||||
class PathModel;
|
||||
|
||||
class InstalledAppsModel;
|
||||
class InstalledAppsSource;
|
||||
|
||||
class AbstractNode
|
||||
{
|
||||
public:
|
||||
enum NodeType { AppNodeType, GroupNodeType, InstallerNodeType };
|
||||
|
||||
virtual ~AbstractNode();
|
||||
|
||||
virtual NodeType type() const = 0;
|
||||
|
||||
virtual bool trigger(const QString &actionId = QString(), const QVariant &actionArgument = QVariant()) = 0;
|
||||
virtual QString favoriteId() const { return QString(); }
|
||||
|
||||
QString icon() const { return m_icon; }
|
||||
QString name() const { return m_name; }
|
||||
QString genericName() const { return m_genericName; }
|
||||
|
||||
static bool lessThan(AbstractNode *n1, AbstractNode *n2);
|
||||
|
||||
protected:
|
||||
QString m_sortKey;
|
||||
QString m_icon;
|
||||
QString m_name;
|
||||
QString m_genericName;
|
||||
};
|
||||
|
||||
class GroupNode : public AbstractNode
|
||||
{
|
||||
public:
|
||||
GroupNode(KServiceGroup::Ptr group, InstalledAppsModel *model);
|
||||
|
||||
NodeType type() const { return GroupNodeType; }
|
||||
|
||||
bool trigger(const QString &actionId = QString(), const QVariant &actionArgument = QVariant()); // reimp
|
||||
|
||||
private:
|
||||
InstalledAppsModel *m_model;
|
||||
QString m_entryPath;
|
||||
};
|
||||
|
||||
class AppNode : public AbstractNode
|
||||
{
|
||||
public:
|
||||
AppNode(KService::Ptr service, InstalledAppsModel *model);
|
||||
|
||||
NodeType type() const { return AppNodeType; }
|
||||
|
||||
bool trigger(const QString &actionId = QString(), const QVariant &actionArgument = QVariant()); // reimp;
|
||||
QString favoriteId() const; // reimp
|
||||
|
||||
KService::Ptr service() const;
|
||||
|
||||
private:
|
||||
InstalledAppsModel *m_model;
|
||||
KService::Ptr m_service;
|
||||
};
|
||||
|
||||
class InstallerNode : public AbstractNode
|
||||
{
|
||||
public:
|
||||
InstallerNode(KServiceGroup::Ptr group, KService::Ptr installerService);
|
||||
|
||||
NodeType type() const { return InstallerNodeType; }
|
||||
|
||||
bool trigger(const QString &actionId = QString(), const QVariant &actionArgument = QVariant()); // reimp;
|
||||
|
||||
private:
|
||||
InstalledAppsModel *m_model;
|
||||
KServiceGroup::Ptr m_group;
|
||||
KService::Ptr m_service;
|
||||
};
|
||||
|
||||
class InstalledAppsModel : public QAbstractListModel
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_PROPERTY(int count READ count NOTIFY countChanged)
|
||||
Q_PROPERTY(QObject* pathModel READ pathModel CONSTANT)
|
||||
Q_PROPERTY(QString name READ name CONSTANT)
|
||||
Q_PROPERTY(QObject* containment READ containment WRITE setContainment)
|
||||
|
||||
public:
|
||||
enum Roles {
|
||||
FavoriteIdRole = Qt::UserRole + 1,
|
||||
HasActionListRole,
|
||||
ActionListRole,
|
||||
GenericNameRole,
|
||||
CombinedNameRole
|
||||
};
|
||||
|
||||
InstalledAppsModel(const QString &entryPath, const QString &installer, QObject *parent = 0);
|
||||
~InstalledAppsModel();
|
||||
|
||||
int rowCount(const QModelIndex &parent = QModelIndex()) const;
|
||||
int count() const;
|
||||
QVariant data(const QModelIndex &, int) const;
|
||||
|
||||
PathModel *pathModel() const;
|
||||
|
||||
Q_INVOKABLE bool trigger(int row, const QString &actionId = QString(), const QVariant &actionArgument = QVariant());
|
||||
|
||||
QObject *containment() const;
|
||||
void setContainment(QObject *containment);
|
||||
|
||||
QString name() const;
|
||||
|
||||
Q_SIGNALS:
|
||||
void countChanged();
|
||||
void openSourceRequested(const QString &sourceId, const QVariantMap &args);
|
||||
void applicationLaunched(const QString& storageId);
|
||||
|
||||
public Q_SLOTS:
|
||||
void refresh(bool reload = true);
|
||||
|
||||
private:
|
||||
void loadRootEntries();
|
||||
void loadServiceGroup(KServiceGroup::Ptr group);
|
||||
void doLoadServiceGroup(KServiceGroup::Ptr group);
|
||||
|
||||
QString m_entryPath;
|
||||
PathModel *m_pathModel;
|
||||
QList<AbstractNode *> m_nodeList;
|
||||
QString m_installer;
|
||||
QString m_arguments;
|
||||
|
||||
QObject *m_containment;
|
||||
|
||||
friend class GroupNode;
|
||||
friend class AppNode;
|
||||
};
|
||||
|
||||
class InstalledAppsSource : public AbstractSource
|
||||
{
|
||||
public:
|
||||
InstalledAppsSource(QObject *parent);
|
||||
QAbstractItemModel *createModelFromConfigGroup(const KConfigGroup &group); // reimp
|
||||
QAbstractItemModel *createModelFromArguments(const QVariantMap &arguments); // reimp
|
||||
|
||||
bool isConfigurable() const; // reimp
|
||||
SourceConfigurationWidget *createConfigurationWidget(const KConfigGroup &group); // reimp
|
||||
|
||||
private:
|
||||
QAbstractItemModel *createModel(const QString &entryPath);
|
||||
};
|
||||
|
||||
} // namespace Homerun
|
||||
|
||||
#endif
|
|
@ -1,321 +0,0 @@
|
|||
/*
|
||||
* Copyright 2013 Eike Hein <hein@kde.org>
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Library General Public License as
|
||||
* published by the Free Software Foundation; either version 2, 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 Library General Public License for more details
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this program; if not, write to the
|
||||
* Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#include "combinedpowersessionmodel.h"
|
||||
#include "actionlist.h"
|
||||
#include "powermodel.h"
|
||||
#include "sessionmodel.h"
|
||||
|
||||
#include <KIcon>
|
||||
#include <KLocale>
|
||||
|
||||
namespace Homerun {
|
||||
|
||||
PowerSessionFavoritesModel::PowerSessionFavoritesModel(const KConfigGroup &group, CombinedPowerSessionModel *parent) : QAbstractListModel(parent)
|
||||
, m_configGroup(group)
|
||||
, m_combinedPowerSessionModel(parent)
|
||||
{
|
||||
setRoleNames(m_combinedPowerSessionModel->roleNames());
|
||||
|
||||
readConfig();
|
||||
}
|
||||
|
||||
PowerSessionFavoritesModel::~PowerSessionFavoritesModel()
|
||||
{
|
||||
}
|
||||
|
||||
void PowerSessionFavoritesModel::readConfig()
|
||||
{
|
||||
beginResetModel();
|
||||
|
||||
m_favorites.clear();
|
||||
|
||||
QStringList favoriteIds = m_configGroup.readEntry("Favorites", QList<QString>() << "logout" << "restart" << "shutdown");
|
||||
|
||||
const QModelIndex &start = m_combinedPowerSessionModel->index(0, 0);
|
||||
|
||||
foreach(const QString &favoriteId, favoriteIds) {
|
||||
QModelIndexList indices = m_combinedPowerSessionModel->match(start, CombinedPowerSessionModel::FavoriteIdRole,
|
||||
favoriteId, 1, Qt::MatchExactly);
|
||||
|
||||
if (indices.count()) {
|
||||
m_favorites.append(QPersistentModelIndex(indices.at(0)));
|
||||
}
|
||||
}
|
||||
|
||||
endResetModel();
|
||||
|
||||
emit countChanged();
|
||||
|
||||
writeConfig();
|
||||
}
|
||||
|
||||
void PowerSessionFavoritesModel::writeConfig()
|
||||
{
|
||||
QStringList favoriteIds;
|
||||
|
||||
foreach(const QPersistentModelIndex &index, m_favorites) {
|
||||
favoriteIds << index.data(CombinedPowerSessionModel::FavoriteIdRole).toString();
|
||||
}
|
||||
|
||||
m_configGroup.writeEntry("Favorites", favoriteIds);
|
||||
m_configGroup.config()->sync();
|
||||
}
|
||||
|
||||
int PowerSessionFavoritesModel::count() const
|
||||
{
|
||||
return rowCount();
|
||||
}
|
||||
|
||||
int PowerSessionFavoritesModel::rowCount(const QModelIndex &parent) const
|
||||
{
|
||||
return parent.isValid() ? 0 : m_favorites.count();
|
||||
}
|
||||
|
||||
bool PowerSessionFavoritesModel::canMoveRow() const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
QVariant PowerSessionFavoritesModel::data(const QModelIndex &index, int role) const
|
||||
{
|
||||
if (!index.isValid() || index.row() > m_favorites.count() - 1) {
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
return m_favorites.at(index.row()).data(role);
|
||||
}
|
||||
|
||||
bool PowerSessionFavoritesModel::trigger(int row, const QString &actionId, const QVariant &)
|
||||
{
|
||||
if (row > m_favorites.count() - 1) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return m_combinedPowerSessionModel->trigger(m_favorites.at(row).row(), actionId, QString());
|
||||
}
|
||||
|
||||
void PowerSessionFavoritesModel::moveRow(int from, int to)
|
||||
{
|
||||
beginMoveRows(QModelIndex(), from, from, QModelIndex(), to > from ? to + 1 : to);
|
||||
|
||||
m_favorites.move(from, to);
|
||||
|
||||
endMoveRows();
|
||||
|
||||
writeConfig();
|
||||
}
|
||||
|
||||
void PowerSessionFavoritesModel::addFavorite(const QModelIndex &index)
|
||||
{
|
||||
QString favoriteId = index.data(CombinedPowerSessionModel::FavoriteIdRole).toString();
|
||||
|
||||
if (favoriteId.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
beginInsertRows(QModelIndex(), m_favorites.count(), m_favorites.count());
|
||||
|
||||
m_favorites.append(QPersistentModelIndex(index));
|
||||
|
||||
endInsertRows();
|
||||
|
||||
emit countChanged();
|
||||
|
||||
writeConfig();
|
||||
}
|
||||
|
||||
void PowerSessionFavoritesModel::removeFavorite(const QModelIndex &index)
|
||||
{
|
||||
int row = m_favorites.indexOf(index);
|
||||
|
||||
if (row != -1) {
|
||||
beginRemoveRows(QModelIndex(), row, row);
|
||||
|
||||
m_favorites.removeAt(row);
|
||||
|
||||
endRemoveRows();
|
||||
|
||||
emit countChanged();
|
||||
|
||||
writeConfig();
|
||||
}
|
||||
}
|
||||
|
||||
bool PowerSessionFavoritesModel::isFavorite(const QModelIndex &index)
|
||||
{
|
||||
return m_favorites.contains(index);
|
||||
}
|
||||
|
||||
QString PowerSessionFavoritesModel::name() const
|
||||
{
|
||||
return m_combinedPowerSessionModel->name();
|
||||
}
|
||||
|
||||
CombinedPowerSessionModel::CombinedPowerSessionModel(const KConfigGroup &group, QObject *parent) : QAbstractListModel(parent)
|
||||
, m_sessionModel(new SessionModel(this))
|
||||
, m_powerModel(new PowerModel(this))
|
||||
, m_showFavoritesActions(false)
|
||||
{
|
||||
QHash<int, QByteArray> roles;
|
||||
roles.insert(Qt::DisplayRole, "display");
|
||||
roles.insert(Qt::DecorationRole, "decoration");
|
||||
roles.insert(HasActionListRole, "hasActionList");
|
||||
roles.insert(ActionListRole, "actionList");
|
||||
|
||||
setRoleNames(roles);
|
||||
|
||||
m_favoriteIdMapping["system-lock-screen"] = "lock-screen";
|
||||
m_favoriteIdMapping["system-log-out"] = "logout";
|
||||
m_favoriteIdMapping["system-switch-user"] = "switch-user";
|
||||
m_favoriteIdMapping["system-suspend"] = "suspend";
|
||||
m_favoriteIdMapping["system-suspend-hibernate"] = "hibernate";
|
||||
m_favoriteIdMapping["system-reboot"] = "restart";
|
||||
m_favoriteIdMapping["system-shutdown"] = "shutdown";
|
||||
|
||||
m_favoritesModel = new PowerSessionFavoritesModel(group, this);
|
||||
|
||||
connect(m_sessionModel, SIGNAL(rowsInserted(QModelIndex,int,int)), SIGNAL(countChanged()));
|
||||
connect(m_sessionModel, SIGNAL(rowsRemoved(QModelIndex,int,int)), SIGNAL(countChanged()));
|
||||
connect(m_sessionModel, SIGNAL(modelReset()), SIGNAL(countChanged()));
|
||||
|
||||
connect(m_powerModel, SIGNAL(rowsInserted(QModelIndex,int,int)), SIGNAL(countChanged()));
|
||||
connect(m_powerModel, SIGNAL(rowsRemoved(QModelIndex,int,int)), SIGNAL(countChanged()));
|
||||
connect(m_powerModel, SIGNAL(modelReset()), SIGNAL(countChanged()));
|
||||
}
|
||||
|
||||
CombinedPowerSessionModel::~CombinedPowerSessionModel()
|
||||
{
|
||||
}
|
||||
|
||||
int CombinedPowerSessionModel::count() const
|
||||
{
|
||||
return rowCount();
|
||||
}
|
||||
|
||||
int CombinedPowerSessionModel::rowCount(const QModelIndex &parent) const
|
||||
{
|
||||
return parent.isValid() ? 0 : (m_powerModel->count() + m_sessionModel->count());
|
||||
}
|
||||
|
||||
QVariant CombinedPowerSessionModel::data(const QModelIndex &index, int role) const
|
||||
{
|
||||
if (role == FavoriteIdRole) {
|
||||
QString iconName;
|
||||
|
||||
if (index.row() >= m_sessionModel->count()) {
|
||||
iconName = m_powerModel->data(m_powerModel->index(index.row() - m_sessionModel->count(),
|
||||
index.column()), Qt::DecorationRole).toString();
|
||||
} else {
|
||||
iconName = m_sessionModel->data(m_sessionModel->index(index.row(), index.column()),
|
||||
Qt::DecorationRole).toString();
|
||||
}
|
||||
|
||||
if (m_favoriteIdMapping.contains(iconName)) {
|
||||
return m_favoriteIdMapping[iconName];
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
} else if (role == HasActionListRole) {
|
||||
return m_showFavoritesActions;
|
||||
} else if (role == ActionListRole) {
|
||||
QVariantList actionList;
|
||||
QVariantMap action;
|
||||
|
||||
if (m_favoritesModel->isFavorite(index)) {
|
||||
action = ActionList::createActionItem(i18n("Remove from Sidebar"), "removeFromFavorites");
|
||||
action["icon"] = KIcon("list-remove");
|
||||
actionList << action;
|
||||
} else {
|
||||
action = ActionList::createActionItem(i18n("Add to Sidebar"), "addToFavorites");
|
||||
action["icon"] = KIcon("bookmark-new");
|
||||
actionList << action;
|
||||
}
|
||||
|
||||
return actionList;
|
||||
}
|
||||
|
||||
if (index.row() >= m_sessionModel->count()) {
|
||||
return m_powerModel->data(m_powerModel->index(index.row() - m_sessionModel->count(), index.column()), role);
|
||||
}
|
||||
|
||||
return m_sessionModel->data(m_sessionModel->index(index.row(), index.column()), role);
|
||||
}
|
||||
|
||||
bool CombinedPowerSessionModel::trigger(int row, const QString &actionId, const QVariant &)
|
||||
{
|
||||
if (actionId == "addToFavorites") {
|
||||
QModelIndex idx = index(row);
|
||||
|
||||
m_favoritesModel->addFavorite(idx);
|
||||
|
||||
emit dataChanged(idx, idx);
|
||||
|
||||
return false;
|
||||
} else if (actionId == "removeFromFavorites") {
|
||||
QModelIndex idx = index(row);
|
||||
|
||||
m_favoritesModel->removeFavorite(idx);
|
||||
emit dataChanged(idx, idx);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if (row >= m_sessionModel->count()) {
|
||||
return m_powerModel->trigger(row - m_sessionModel->count(), QString(), QVariant());
|
||||
}
|
||||
|
||||
return m_sessionModel->trigger(row, QString(), QVariant());
|
||||
}
|
||||
|
||||
bool CombinedPowerSessionModel::showFavoritesActions() const
|
||||
{
|
||||
return m_showFavoritesActions;
|
||||
}
|
||||
|
||||
void CombinedPowerSessionModel::setShowFavoritesActions(bool show)
|
||||
{
|
||||
if (show != m_showFavoritesActions) {
|
||||
m_showFavoritesActions = show;
|
||||
|
||||
emit dataChanged(index(0), index(count() - 1));
|
||||
}
|
||||
}
|
||||
|
||||
QObject *CombinedPowerSessionModel::favoritesModel() const
|
||||
{
|
||||
return m_favoritesModel;
|
||||
}
|
||||
|
||||
QString CombinedPowerSessionModel::name() const
|
||||
{
|
||||
return i18n("Power / Session");
|
||||
}
|
||||
|
||||
CombinedPowerSessionSource::CombinedPowerSessionSource(QObject *parent) : AbstractSource(parent)
|
||||
{
|
||||
}
|
||||
|
||||
QAbstractItemModel *CombinedPowerSessionSource::createModelFromConfigGroup(const KConfigGroup &group)
|
||||
{
|
||||
return new CombinedPowerSessionModel(group);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#include "moc_combinedpowersessionmodel.cpp"
|
|
@ -1,128 +0,0 @@
|
|||
/*
|
||||
* Copyright 2013 Eike Hein <hein@kde.org>
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Library General Public License as
|
||||
* published by the Free Software Foundation; either version 2, 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 Library General Public License for more details
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this program; if not, write to the
|
||||
* Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#ifndef COMBINEDPOWERSESSIONMODEL_H
|
||||
#define COMBINEDPOWERSESSIONMODEL_H
|
||||
|
||||
#include <abstractsource.h>
|
||||
|
||||
#include <QtCore/qabstractitemmodel.h>
|
||||
|
||||
#include <KConfigGroup>
|
||||
|
||||
namespace Homerun {
|
||||
|
||||
class PowerModel;
|
||||
class SessionModel;
|
||||
class CombinedPowerSessionModel;
|
||||
|
||||
class PowerSessionFavoritesModel : public QAbstractListModel
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
Q_PROPERTY(int count READ count NOTIFY countChanged)
|
||||
Q_PROPERTY(QString name READ name CONSTANT)
|
||||
Q_PROPERTY(bool canMoveRow READ canMoveRow CONSTANT)
|
||||
|
||||
public:
|
||||
PowerSessionFavoritesModel(const KConfigGroup &group, CombinedPowerSessionModel *parent = 0);
|
||||
~PowerSessionFavoritesModel();
|
||||
|
||||
int count() const;
|
||||
int rowCount(const QModelIndex& parent = QModelIndex()) const;
|
||||
|
||||
bool canMoveRow() const;
|
||||
|
||||
QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const;
|
||||
|
||||
Q_INVOKABLE bool trigger(int row, const QString &actionId, const QVariant &/*actionArgument*/);
|
||||
|
||||
Q_INVOKABLE void moveRow(int from, int to);
|
||||
|
||||
void addFavorite(const QModelIndex &index);
|
||||
void removeFavorite(const QModelIndex &index);
|
||||
bool isFavorite(const QModelIndex &index);
|
||||
|
||||
QString name() const;
|
||||
|
||||
signals:
|
||||
void countChanged();
|
||||
|
||||
private:
|
||||
void readConfig();
|
||||
void writeConfig();
|
||||
|
||||
KConfigGroup m_configGroup;
|
||||
|
||||
QList<QPersistentModelIndex> m_favorites;
|
||||
CombinedPowerSessionModel* m_combinedPowerSessionModel;
|
||||
};
|
||||
|
||||
class CombinedPowerSessionModel : public QAbstractListModel
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
Q_PROPERTY(int count READ count NOTIFY countChanged)
|
||||
Q_PROPERTY(QString name READ name CONSTANT)
|
||||
Q_PROPERTY(bool showFavoritesActions READ showFavoritesActions WRITE setShowFavoritesActions)
|
||||
|
||||
public:
|
||||
enum Roles {
|
||||
FavoriteIdRole = Qt::UserRole + 1,
|
||||
HasActionListRole,
|
||||
ActionListRole
|
||||
};
|
||||
|
||||
CombinedPowerSessionModel(const KConfigGroup &group, QObject *parent = 0);
|
||||
~CombinedPowerSessionModel();
|
||||
|
||||
int count() const;
|
||||
int rowCount(const QModelIndex& parent = QModelIndex()) const;
|
||||
|
||||
QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const;
|
||||
|
||||
Q_INVOKABLE bool trigger(int row, const QString &actionId, const QVariant &/*actionArgument*/);
|
||||
|
||||
bool showFavoritesActions() const;
|
||||
void setShowFavoritesActions(bool show);
|
||||
Q_INVOKABLE QObject *favoritesModel() const;
|
||||
|
||||
QString name() const;
|
||||
|
||||
signals:
|
||||
void countChanged();
|
||||
|
||||
private:
|
||||
SessionModel *m_sessionModel;
|
||||
PowerModel *m_powerModel;
|
||||
|
||||
QHash<QString, QString> m_favoriteIdMapping;
|
||||
PowerSessionFavoritesModel* m_favoritesModel;
|
||||
bool m_showFavoritesActions;
|
||||
};
|
||||
|
||||
class CombinedPowerSessionSource : public AbstractSource
|
||||
{
|
||||
public:
|
||||
CombinedPowerSessionSource(QObject *parent);
|
||||
QAbstractItemModel *createModelFromConfigGroup(const KConfigGroup &group);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
|
@ -1,94 +0,0 @@
|
|||
/*
|
||||
Copyright 2012 Aurélien Gâteau <agateau@kde.org>
|
||||
Copyright (C) 2012 Shaun Reich <shaun.reich@blue-systems.com>
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Library General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Library General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Library General Public License
|
||||
along with this library; see the file COPYING.LIB. If not, write to
|
||||
the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
||||
Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
// Own
|
||||
#include "powermodel.h"
|
||||
|
||||
// KDE
|
||||
#include <KDebug>
|
||||
#include <KLocale>
|
||||
#include <kworkspace/kworkspace.h>
|
||||
#include <Solid/PowerManagement>
|
||||
|
||||
namespace Homerun {
|
||||
|
||||
enum Action
|
||||
{
|
||||
SuspendToRam,
|
||||
SuspendToDisk,
|
||||
Reboot,
|
||||
Halt
|
||||
};
|
||||
|
||||
PowerModel::PowerModel(QObject *parent)
|
||||
: StandardItemModel(parent)
|
||||
{
|
||||
setName(i18n("Power"));
|
||||
QSet<Solid::PowerManagement::SleepState> sleepStates = Solid::PowerManagement::supportedSleepStates();
|
||||
|
||||
if (sleepStates.contains(Solid::PowerManagement::SuspendState)) {
|
||||
StandardItem *item = new StandardItem(i18nc("an action", "Suspend"), "system-suspend");
|
||||
item->setData(SuspendToRam);
|
||||
appendRow(item);
|
||||
}
|
||||
|
||||
if (sleepStates.contains(Solid::PowerManagement::HibernateState)) {
|
||||
StandardItem *item = new StandardItem(i18nc("an action", "Hibernate"), "system-suspend-hibernate");
|
||||
item->setData(SuspendToDisk);
|
||||
appendRow(item);
|
||||
}
|
||||
|
||||
{
|
||||
StandardItem *item = new StandardItem(i18nc("an action", "Restart"), "system-reboot");
|
||||
item->setData(Reboot);
|
||||
appendRow(item);
|
||||
}
|
||||
{
|
||||
StandardItem *item = new StandardItem(i18nc("an action", "Shutdown"), "system-shutdown");
|
||||
item->setData(Halt);
|
||||
appendRow(item);
|
||||
}
|
||||
}
|
||||
|
||||
bool PowerModel::trigger(int row, const QString &/*actionId*/, const QVariant &/*actionArgument*/)
|
||||
{
|
||||
QStandardItem *itm = item(row);
|
||||
Q_ASSERT(itm);
|
||||
Action action = static_cast<Action>(itm->data().toInt());
|
||||
switch (action) {
|
||||
case SuspendToRam:
|
||||
Solid::PowerManagement::requestSleep(Solid::PowerManagement::SuspendState, 0, 0);
|
||||
break;
|
||||
case SuspendToDisk:
|
||||
Solid::PowerManagement::requestSleep(Solid::PowerManagement::HibernateState, 0, 0);
|
||||
break;
|
||||
case Halt:
|
||||
KWorkSpace::requestShutDown(KWorkSpace::ShutdownConfirmDefault, KWorkSpace::ShutdownTypeHalt);
|
||||
break;
|
||||
case Reboot:
|
||||
KWorkSpace::requestShutDown(KWorkSpace::ShutdownConfirmDefault, KWorkSpace::ShutdownTypeReboot);
|
||||
break;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace Homerun
|
||||
|
||||
#include "moc_powermodel.cpp"
|
|
@ -1,40 +0,0 @@
|
|||
/*
|
||||
Copyright 2012 Aurélien Gâteau <agateau@kde.org>
|
||||
Copyright 2012 (C) Shaun Reich <shaun.reich@blue-systems.com>
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Library General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Library General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Library General Public License
|
||||
along with this library; see the file COPYING.LIB. If not, write to
|
||||
the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
||||
Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#ifndef POWERMODEL_H
|
||||
#define POWERMODEL_H
|
||||
|
||||
// Local
|
||||
#include <standarditemmodel.h>
|
||||
|
||||
namespace Homerun {
|
||||
|
||||
class PowerModel : public StandardItemModel
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
PowerModel(QObject *parent = 0);
|
||||
bool trigger(int row, const QString &/*actionId*/, const QVariant &/*actionArgument*/) override;
|
||||
};
|
||||
|
||||
} // namespace Homerun
|
||||
|
||||
#endif
|
|
@ -1,305 +0,0 @@
|
|||
/*
|
||||
Copyright 2013 Eike Hein <hein@kde.org>
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) 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 6 of version 3 of the license.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
// Local
|
||||
#include <actionlist.h>
|
||||
#include <recentappsmodel.h>
|
||||
#include <sourceregistry.h>
|
||||
|
||||
// Qt
|
||||
#include <QApplication>
|
||||
|
||||
// KDE
|
||||
#include <KRun>
|
||||
#include <KService>
|
||||
|
||||
#include <Plasma/Containment>
|
||||
#include <Plasma/Corona>
|
||||
|
||||
namespace Homerun {
|
||||
|
||||
//- RecentAppsModel ------------------------------------------------------------
|
||||
RecentAppsModel::RecentAppsModel(const KConfigGroup &group, QObject *parent)
|
||||
: QAbstractListModel(parent)
|
||||
, m_configGroup(group)
|
||||
, m_containment(0)
|
||||
{
|
||||
QHash<int, QByteArray> roles;
|
||||
roles.insert(Qt::DisplayRole, "display");
|
||||
roles.insert(Qt::DecorationRole, "decoration");
|
||||
roles.insert(FavoriteIdRole, "favoriteId");
|
||||
roles.insert(HasActionListRole, "hasActionList");
|
||||
roles.insert(ActionListRole, "actionList");
|
||||
|
||||
setRoleNames(roles);
|
||||
|
||||
QList<QString> apps = group.readEntry("RecentApps", QList<QString>());
|
||||
|
||||
if (apps.isEmpty()) {
|
||||
addApp("systemsettings.desktop", false);
|
||||
} else {
|
||||
for (int i = apps.count() - 1; i >= 0; --i) {
|
||||
addApp(apps.at(i), false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
RecentAppsModel::~RecentAppsModel()
|
||||
{
|
||||
}
|
||||
|
||||
QObject *RecentAppsModel::containment() const
|
||||
{
|
||||
return m_containment;
|
||||
}
|
||||
|
||||
void RecentAppsModel::setContainment(QObject *containment)
|
||||
{
|
||||
m_containment = containment;
|
||||
}
|
||||
|
||||
int RecentAppsModel::count() const
|
||||
{
|
||||
return m_storageIdList.count();
|
||||
}
|
||||
|
||||
int RecentAppsModel::rowCount(const QModelIndex& index) const
|
||||
{
|
||||
return index.isValid() ? 0 : m_storageIdList.count();
|
||||
}
|
||||
|
||||
QVariant RecentAppsModel::data(const QModelIndex &index, int role) const
|
||||
{
|
||||
if (!index.isValid() || index.row() >= m_storageIdList.count()) {
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
const QString storageId = m_storageIdList.at(index.row());
|
||||
KService::Ptr service = KService::serviceByStorageId(storageId);
|
||||
|
||||
if (!service) {
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
if (role == Qt::DisplayRole) {
|
||||
return service->name();
|
||||
} else if (role == Qt::DecorationRole) {
|
||||
// at least show the oxygen question-mark, otherwise it looks weird blank.
|
||||
return service->icon().isEmpty() ? QLatin1String("unknown") : service->icon();
|
||||
} else if (role == FavoriteIdRole) {
|
||||
return QVariant(QString("app:") + storageId);
|
||||
} else if (role == HasActionListRole) {
|
||||
return true;
|
||||
} else if (role == ActionListRole) {
|
||||
QVariantList actionList;
|
||||
|
||||
QVariantMap forgetAction = Homerun::ActionList::createActionItem(i18n("Forget Application"), "forget");
|
||||
actionList.append(forgetAction);
|
||||
|
||||
actionList.append(Homerun::ActionList::createSeparatorActionItem());
|
||||
|
||||
if (qApp->property("HomerunViewerAdaptor").isValid())
|
||||
{
|
||||
if (qApp->property("desktopContainmentId").toUInt() > 0
|
||||
&& qApp->property("desktopContainmentMutable").toBool()) {
|
||||
actionList << ActionList::createActionItem(i18n("Add to Desktop"), "addToDesktop");
|
||||
}
|
||||
if (qApp->property("appletContainmentId").toUInt() > 0
|
||||
&& qApp->property("appletContainmentMutable").toBool()) {
|
||||
actionList << ActionList::createActionItem(i18n("Add to Panel"), "addToPanel");
|
||||
}
|
||||
} else if (m_containment) {
|
||||
Plasma::Containment *containment = static_cast<Plasma::Containment *>(m_containment);
|
||||
Plasma::Containment *desktop = containment->corona()->containmentForScreen(containment->screen());
|
||||
|
||||
if (desktop && desktop->immutability() == Plasma::Mutable) {
|
||||
actionList << ActionList::createActionItem(i18n("Add to Desktop"), "addToDesktop");
|
||||
}
|
||||
|
||||
if (containment->immutability() == Plasma::Mutable) {
|
||||
actionList << ActionList::createActionItem(i18n("Add to Panel"), "addToPanel");
|
||||
}
|
||||
|
||||
QObject* taskManager = 0;
|
||||
|
||||
foreach(QObject* applet, containment->applets()) {
|
||||
if (applet->metaObject()->indexOfSlot("hasLauncher(QString)") != -1) {
|
||||
taskManager = applet;
|
||||
}
|
||||
}
|
||||
|
||||
if (taskManager) {
|
||||
bool hasLauncher = false;
|
||||
|
||||
QMetaObject::invokeMethod(taskManager, "hasLauncher", Qt::DirectConnection,
|
||||
Q_RETURN_ARG(bool, hasLauncher), Q_ARG(QString, storageId));
|
||||
|
||||
if (!hasLauncher) {
|
||||
actionList << ActionList::createActionItem(i18n("Add as Launcher"), "addLauncher");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return actionList;
|
||||
}
|
||||
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
void RecentAppsModel::addApp(const QString& storageId, bool sync)
|
||||
{
|
||||
int index = m_storageIdList.indexOf(storageId);
|
||||
|
||||
if (index > 0) {
|
||||
beginMoveRows(QModelIndex(), index, index, QModelIndex(), 0);
|
||||
m_storageIdList.move(index, 0);
|
||||
endMoveRows();
|
||||
} else if (index == -1) {
|
||||
if (m_storageIdList.count() < 15) {
|
||||
beginInsertRows(QModelIndex(), 0, 0);
|
||||
m_storageIdList.prepend(storageId);
|
||||
endInsertRows();
|
||||
emit countChanged();
|
||||
} else {
|
||||
beginResetModel();
|
||||
m_storageIdList.prepend(storageId);
|
||||
m_storageIdList.removeLast();
|
||||
endResetModel();
|
||||
}
|
||||
}
|
||||
|
||||
if (sync) {
|
||||
m_configGroup.writeEntry("RecentApps", m_storageIdList);
|
||||
m_configGroup.config()->sync();
|
||||
}
|
||||
}
|
||||
|
||||
bool RecentAppsModel::forgetApp(int row, bool sync)
|
||||
{
|
||||
if (row >= m_storageIdList.count()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
beginRemoveRows(QModelIndex(), row, row);
|
||||
m_storageIdList.removeAt(row);
|
||||
endRemoveRows();
|
||||
|
||||
emit countChanged();
|
||||
|
||||
if (sync) {
|
||||
m_configGroup.writeEntry("RecentApps", m_storageIdList);
|
||||
m_configGroup.config()->sync();
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool RecentAppsModel::trigger(int row, const QString &actionId, const QVariant &actionArgument)
|
||||
{
|
||||
Q_UNUSED(actionArgument)
|
||||
|
||||
if (row >= m_storageIdList.count()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const QString storageId = m_storageIdList.at(row);
|
||||
|
||||
if (!actionId.isEmpty()) {
|
||||
if (actionId == "forget") {
|
||||
return forgetApp(row);
|
||||
} else {
|
||||
QVariant adaptor = qApp->property("HomerunViewerAdaptor");
|
||||
|
||||
if (adaptor.isValid()) {
|
||||
uint containmentId = (actionId == "addToDesktop") ? qApp->property("desktopContainmentId").toUInt()
|
||||
: qApp->property("appletContainmentId").toUInt();
|
||||
return QMetaObject::invokeMethod(adaptor.value<QObject *>(), actionId.toLocal8Bit(),
|
||||
Qt::DirectConnection, Q_ARG(uint, containmentId), Q_ARG(QString, storageId));
|
||||
} else if (m_containment) {
|
||||
Plasma::Containment *containment = static_cast<Plasma::Containment *>(m_containment);
|
||||
KService::Ptr service = KService::serviceByStorageId(storageId);
|
||||
|
||||
if (actionId == "addToDesktop" && service) {
|
||||
Plasma::Containment *desktop = containment->corona()->containmentForScreen(containment->screen());
|
||||
|
||||
if (desktop) {
|
||||
if (desktop->metaObject()->indexOfSlot("addUrls(KUrl::List)") != -1) {
|
||||
QMetaObject::invokeMethod(desktop, "addUrls",
|
||||
Qt::DirectConnection, Q_ARG(KUrl::List, KUrl::List(service->entryPath())));
|
||||
} else {
|
||||
desktop->addApplet("icon", QVariantList() << service->entryPath());
|
||||
}
|
||||
}
|
||||
} else if (actionId == "addToPanel" && service) {
|
||||
QRectF rect(containment->geometry().width() / 2, 0, 150,
|
||||
containment->boundingRect().height());
|
||||
containment->addApplet("icon", QVariantList() << service->entryPath(), rect);
|
||||
} else if (actionId == "addLauncher") {
|
||||
QObject* taskManager = 0;
|
||||
|
||||
foreach(QObject* applet, containment->applets()) {
|
||||
if (applet->metaObject()->indexOfSlot("addLauncher(QString)") != -1) {
|
||||
taskManager = applet;
|
||||
}
|
||||
}
|
||||
|
||||
if (taskManager) {
|
||||
QMetaObject::invokeMethod(taskManager, "addLauncher", Qt::DirectConnection,
|
||||
Q_ARG(QString, storageId));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
KService::Ptr service = KService::serviceByStorageId(storageId);
|
||||
|
||||
if (!service) {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ran = KRun::run(*service, KUrl::List(), 0);
|
||||
|
||||
if (ran) {
|
||||
addApp(storageId);
|
||||
}
|
||||
|
||||
return ran;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
QString RecentAppsModel::name() const
|
||||
{
|
||||
return i18n("Recent Applications");
|
||||
}
|
||||
|
||||
//- RecentAppsSource ---------------------------------------------
|
||||
RecentAppsSource::RecentAppsSource(QObject *parent)
|
||||
: AbstractSource(parent)
|
||||
{}
|
||||
|
||||
QAbstractItemModel *RecentAppsSource::createModelFromConfigGroup(const KConfigGroup &group)
|
||||
{
|
||||
return new RecentAppsModel(group);
|
||||
}
|
||||
|
||||
} // namespace Homerun
|
||||
|
||||
#include "moc_recentappsmodel.cpp"
|
|
@ -1,84 +0,0 @@
|
|||
/*
|
||||
Copyright 2013 Eike Hein <hein@kde.org>
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) 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 6 of version 3 of the license.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#ifndef RECENTAPPSMODEL_H
|
||||
#define RECENTAPPSMODEL_H
|
||||
|
||||
// Local
|
||||
#include <abstractsource.h>
|
||||
|
||||
// Qt
|
||||
#include <QtCore/qabstractitemmodel.h>
|
||||
|
||||
// KDE
|
||||
#include <KConfigGroup>
|
||||
|
||||
namespace Homerun {
|
||||
|
||||
class RecentAppsModel : public QAbstractListModel
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_PROPERTY(int count READ count NOTIFY countChanged)
|
||||
Q_PROPERTY(QString name READ name CONSTANT)
|
||||
Q_PROPERTY(QObject* containment READ containment WRITE setContainment)
|
||||
|
||||
public:
|
||||
enum Roles {
|
||||
FavoriteIdRole = Qt::UserRole + 1,
|
||||
HasActionListRole,
|
||||
ActionListRole
|
||||
};
|
||||
|
||||
RecentAppsModel(const KConfigGroup &group, QObject *parent = 0);
|
||||
~RecentAppsModel();
|
||||
|
||||
int rowCount(const QModelIndex &parent = QModelIndex()) const;
|
||||
int count() const;
|
||||
QVariant data(const QModelIndex &, int) const;
|
||||
|
||||
Q_INVOKABLE void addApp(const QString &storageId, bool sync = true);
|
||||
Q_INVOKABLE bool forgetApp(int row, bool sync = true);
|
||||
|
||||
Q_INVOKABLE bool trigger(int row, const QString &actionId = QString(), const QVariant &actionArgument = QVariant());
|
||||
|
||||
QObject *containment() const;
|
||||
void setContainment(QObject *containment);
|
||||
|
||||
QString name() const;
|
||||
|
||||
Q_SIGNALS:
|
||||
void countChanged();
|
||||
|
||||
private:
|
||||
QList<QString> m_storageIdList;
|
||||
KConfigGroup m_configGroup;
|
||||
|
||||
QObject *m_containment;
|
||||
};
|
||||
|
||||
class RecentAppsSource : public AbstractSource
|
||||
{
|
||||
public:
|
||||
RecentAppsSource(QObject *parent);
|
||||
QAbstractItemModel *createModelFromConfigGroup(const KConfigGroup &group); // reiml
|
||||
};
|
||||
|
||||
} // namespace Homerun
|
||||
|
||||
#endif
|
|
@ -1,194 +0,0 @@
|
|||
/*
|
||||
Copyright 2013 Aurélien Gâteau <agateau@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/>.
|
||||
*/
|
||||
// Self
|
||||
#include <querymatchmodel.h>
|
||||
|
||||
// Local
|
||||
#include <actionlist.h>
|
||||
|
||||
// KDE
|
||||
#include <KDebug>
|
||||
#include <KIcon>
|
||||
#include <KLocale>
|
||||
#include <KUrl>
|
||||
#include <Plasma/AbstractRunner>
|
||||
#include <Plasma/RunnerManager>
|
||||
|
||||
// Qt
|
||||
#include <QAction>
|
||||
#include <QIcon>
|
||||
|
||||
namespace Homerun
|
||||
{
|
||||
|
||||
QueryMatchModel::QueryMatchModel(QObject *parent)
|
||||
: QAbstractListModel(parent)
|
||||
{
|
||||
QHash<int, QByteArray> roles;
|
||||
roles.insert(Qt::DisplayRole, "display");
|
||||
roles.insert(Qt::DecorationRole, "decoration");
|
||||
roles.insert(FavoriteIdRole, "favoriteId");
|
||||
roles.insert(HasActionListRole, "hasActionList");
|
||||
roles.insert(ActionListRole, "actionList");
|
||||
setRoleNames(roles);
|
||||
}
|
||||
|
||||
int QueryMatchModel::count() const
|
||||
{
|
||||
return m_matches.count();
|
||||
}
|
||||
|
||||
int QueryMatchModel::rowCount(const QModelIndex& parent) const
|
||||
{
|
||||
return parent.isValid() ? 0 : m_matches.count();
|
||||
}
|
||||
|
||||
static QString favoriteIdFromMatch(const Plasma::QueryMatch &match)
|
||||
{
|
||||
QString runnerId = match.runner()->id();
|
||||
if (runnerId == "services") {
|
||||
return "app:" + match.data().toString();
|
||||
} else if (runnerId == "locations") {
|
||||
KUrl url(match.data().toString());
|
||||
return "place:" + url.url();
|
||||
} else if (runnerId == "places") {
|
||||
KUrl url(match.data().value<KUrl>());
|
||||
return "place:" + url.url();
|
||||
} else {
|
||||
return QString();
|
||||
}
|
||||
}
|
||||
|
||||
static bool matchHasActionList(const Plasma::QueryMatch &match)
|
||||
{
|
||||
// Hack to expose the protected Plasma::AbstractRunner::actions() method.
|
||||
class MyRunner : public Plasma::AbstractRunner
|
||||
{
|
||||
public:
|
||||
using Plasma::AbstractRunner::actions;;
|
||||
};
|
||||
|
||||
// Would be great if we could know if a match has actions without getting
|
||||
// them as getting the action list is costly. For now we can't, so pretend
|
||||
// all matches from runners which have registered actions have actions.
|
||||
MyRunner *runner = static_cast<MyRunner *>(match.runner());
|
||||
Q_ASSERT(runner);
|
||||
return !runner->actions().isEmpty();
|
||||
}
|
||||
|
||||
static QVariantList actionListFromMatch(Plasma::RunnerManager *manager, const Plasma::QueryMatch &match)
|
||||
{
|
||||
Q_ASSERT(manager);
|
||||
QVariantList actionList;
|
||||
Q_FOREACH(QAction *action, manager->actionsForMatch(match)) {
|
||||
QVariantMap item = ActionList::createActionItem(action->text(), "runnerAction",
|
||||
QVariant::fromValue<QObject *>(action));
|
||||
item["icon"] = KIcon(action->icon());
|
||||
actionList << item;
|
||||
}
|
||||
return actionList;
|
||||
}
|
||||
|
||||
QVariant QueryMatchModel::data(const QModelIndex& index, int role) const
|
||||
{
|
||||
if (index.row() < 0 || index.row() >= m_matches.count()) {
|
||||
return QVariant();
|
||||
}
|
||||
Plasma::QueryMatch match = m_matches.at(index.row());
|
||||
if (role == Qt::DisplayRole) {
|
||||
return match.text();
|
||||
} else if (role == Qt::DecorationRole) {
|
||||
return match.icon();
|
||||
} else if (role == FavoriteIdRole) {
|
||||
return favoriteIdFromMatch(match);
|
||||
} else if (role == HasActionListRole) {
|
||||
return matchHasActionList(match);
|
||||
} else if (role == ActionListRole) {
|
||||
return actionListFromMatch(m_manager, match);
|
||||
}
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
bool QueryMatchModel::trigger(int row, const QString &actionId, const QVariant &actionArgument)
|
||||
{
|
||||
Q_ASSERT(m_manager);
|
||||
Plasma::QueryMatch match = m_matches.at(row);
|
||||
if (!match.isEnabled()) {
|
||||
return false;
|
||||
}
|
||||
if (!actionId.isEmpty()) {
|
||||
QObject *obj = actionArgument.value<QObject *>();
|
||||
if (!obj) {
|
||||
kWarning() << "actionArgument is not a QObject";
|
||||
return false;
|
||||
}
|
||||
QAction *action = qobject_cast<QAction *>(obj);
|
||||
if (!action) {
|
||||
kWarning() << "actionArgument is not a QAction";
|
||||
return false;
|
||||
}
|
||||
match.setSelectedAction(action);
|
||||
}
|
||||
m_manager->run(match);
|
||||
return true;
|
||||
}
|
||||
|
||||
void QueryMatchModel::setMatches(const QList< Plasma::QueryMatch > &matches)
|
||||
{
|
||||
bool fullReset = false;
|
||||
int oldCount = m_matches.count();
|
||||
int newCount = matches.count();
|
||||
if (newCount > oldCount) {
|
||||
// We received more matches than we had. If all common matches are the
|
||||
// same, we can just append new matches instead of resetting the whole
|
||||
// model
|
||||
for (int row = 0; row < oldCount; ++row) {
|
||||
if (!(m_matches.at(row) == matches.at(row))) {
|
||||
fullReset = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!fullReset) {
|
||||
// Not a full reset, inserting rows
|
||||
beginInsertRows(QModelIndex(), oldCount, newCount - 1);
|
||||
m_matches = matches;
|
||||
endInsertRows();
|
||||
emit countChanged();
|
||||
}
|
||||
} else {
|
||||
fullReset = true;
|
||||
}
|
||||
|
||||
if (fullReset) {
|
||||
beginResetModel();
|
||||
m_matches = matches;
|
||||
endResetModel();
|
||||
emit countChanged();
|
||||
}
|
||||
}
|
||||
|
||||
void QueryMatchModel::setRunnerManager(Plasma::RunnerManager *manager)
|
||||
{
|
||||
m_manager = manager;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
#include "moc_querymatchmodel.cpp"
|
|
@ -1,84 +0,0 @@
|
|||
/*
|
||||
Copyright 2013 Aurélien Gâteau <agateau@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 QUERYMATCHMODEL_H
|
||||
#define QUERYMATCHMODEL_H
|
||||
|
||||
// Local
|
||||
|
||||
// KDE
|
||||
#include <Plasma/QueryMatch>
|
||||
|
||||
// Qt
|
||||
#include <QtCore/qabstractitemmodel.h>
|
||||
|
||||
namespace Plasma
|
||||
{
|
||||
class RunnerManager;
|
||||
}
|
||||
|
||||
namespace Homerun
|
||||
{
|
||||
|
||||
/**
|
||||
* This model exposes results from a list of Plasma::QueryMatch
|
||||
*/
|
||||
class QueryMatchModel : public QAbstractListModel
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_PROPERTY(int count READ count NOTIFY countChanged)
|
||||
public:
|
||||
explicit QueryMatchModel(QObject *parent = 0);
|
||||
|
||||
enum {
|
||||
FavoriteIdRole = Qt::UserRole + 1,
|
||||
HasActionListRole,
|
||||
ActionListRole,
|
||||
};
|
||||
|
||||
int count() const;
|
||||
|
||||
int rowCount(const QModelIndex &parent) const override;
|
||||
|
||||
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
|
||||
|
||||
Q_INVOKABLE bool trigger(int row, const QString &actionId, const QVariant &actionArgument);
|
||||
|
||||
/**
|
||||
* Sets the instance of RunnerManager which is handling the matches we show.
|
||||
* A manager *must* be defined before calling setMatches().
|
||||
*/
|
||||
void setRunnerManager(Plasma::RunnerManager *manager);
|
||||
|
||||
public Q_SLOTS:
|
||||
void setMatches(const QList<Plasma::QueryMatch> &matches);
|
||||
|
||||
Q_SIGNALS:
|
||||
void countChanged();
|
||||
|
||||
protected:
|
||||
QList<Plasma::QueryMatch> m_matches;
|
||||
|
||||
private:
|
||||
Plasma::RunnerManager *m_manager = 0;
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
#endif /* SINGLERUNNERMODEL_H */
|
|
@ -1,104 +0,0 @@
|
|||
/*
|
||||
Copyright 2012 Aurélien Gâteau <agateau@kde.org>
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) 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 6 of version 3 of the license.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
// Self
|
||||
#include <runnerconfigurationwidget.h>
|
||||
|
||||
// KDE
|
||||
#include <KIcon>
|
||||
#include <KDebug>
|
||||
#include <KPluginInfo>
|
||||
#include <Plasma/RunnerManager>
|
||||
|
||||
// Qt
|
||||
#include <QtGui/qlistwidget.h>
|
||||
|
||||
Q_DECLARE_METATYPE(KPluginInfo)
|
||||
|
||||
static const char *WHITELIST_KEY = "whitelist";
|
||||
|
||||
namespace Homerun
|
||||
{
|
||||
|
||||
static QListWidgetItem *createWidgetItem(const KPluginInfo &info)
|
||||
{
|
||||
QListWidgetItem *item = new QListWidgetItem(info.name());
|
||||
item->setIcon(KIcon(info.icon()));
|
||||
item->setFlags(item->flags() | Qt::ItemIsUserCheckable);
|
||||
item->setData(Qt::UserRole, QVariant::fromValue(info));
|
||||
return item;
|
||||
}
|
||||
|
||||
RunnerConfigurationWidget::RunnerConfigurationWidget(const KConfigGroup &group)
|
||||
: SourceConfigurationWidget(group)
|
||||
{
|
||||
setupUi(this);
|
||||
m_searchLine->setListWidget(m_listWidget);
|
||||
|
||||
// A runner is enabled if there is either a whitelist and it is part of it
|
||||
// or if there is no whitelist and its EnabledByDefault key is true
|
||||
|
||||
QStringList whiteList = group.readEntry(WHITELIST_KEY, QStringList());
|
||||
bool hasWhiteList = !whiteList.isEmpty();
|
||||
|
||||
KPluginInfo::List list = Plasma::RunnerManager::listRunnerInfo();
|
||||
Q_FOREACH(const KPluginInfo &info, list) {
|
||||
QListWidgetItem *item = createWidgetItem(info);
|
||||
bool selected;
|
||||
if (hasWhiteList) {
|
||||
selected = whiteList.contains(info.pluginName());
|
||||
} else {
|
||||
selected = info.isPluginEnabledByDefault();
|
||||
}
|
||||
item->setCheckState(selected ? Qt::Checked : Qt::Unchecked);
|
||||
m_listWidget->addItem(item);
|
||||
}
|
||||
m_listWidget->sortItems();
|
||||
}
|
||||
|
||||
void RunnerConfigurationWidget::save()
|
||||
{
|
||||
QStringList whiteList;
|
||||
bool hasChanges = false;
|
||||
|
||||
// Only write a whiteList if the selected runner list is not the same as
|
||||
// the list of all EnabledByDefault runners
|
||||
|
||||
for (int idx = 0; idx < m_listWidget->count(); ++idx) {
|
||||
QListWidgetItem *item = m_listWidget->item(idx);
|
||||
KPluginInfo info = item->data(Qt::UserRole).value<KPluginInfo>();
|
||||
|
||||
bool selected = item->checkState() == Qt::Checked;
|
||||
if (selected != info.isPluginEnabledByDefault()) {
|
||||
hasChanges = true;
|
||||
}
|
||||
if (selected) {
|
||||
whiteList << info.pluginName();
|
||||
}
|
||||
}
|
||||
if (hasChanges) {
|
||||
configGroup().writeEntry(WHITELIST_KEY, whiteList);
|
||||
} else {
|
||||
configGroup().deleteEntry(WHITELIST_KEY);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace Homerun
|
||||
|
||||
#include "moc_runnerconfigurationwidget.cpp"
|
|
@ -1,48 +0,0 @@
|
|||
/*
|
||||
Copyright 2012 Aurélien Gâteau <agateau@kde.org>
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) 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 6 of version 3 of the license.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#ifndef RUNNERCONFIGURATIONWIDGET_H
|
||||
#define RUNNERCONFIGURATIONWIDGET_H
|
||||
|
||||
// Local
|
||||
#include <sourceconfigurationwidget.h>
|
||||
#include <ui_runnerconfigurationwidget.h>
|
||||
|
||||
// Qt
|
||||
|
||||
// KDE
|
||||
|
||||
namespace Homerun
|
||||
{
|
||||
|
||||
/**
|
||||
* A configuration widget for the Runner source
|
||||
*/
|
||||
class RunnerConfigurationWidget : public SourceConfigurationWidget, private Ui_RunnerConfigurationWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit RunnerConfigurationWidget(const KConfigGroup &);
|
||||
|
||||
void save(); // reimp
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
#endif /* RUNNERCONFIGURATIONWIDGET_H */
|
|
@ -1,48 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>RunnerConfigurationWidget</class>
|
||||
<widget class="QWidget" name="RunnerConfigurationWidget">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>400</width>
|
||||
<height>300</height>
|
||||
</rect>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="text">
|
||||
<string>Pick the runners you would like to use in this source:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="KListWidgetSearchLine" name="m_searchLine"/>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="KListWidget" name="m_listWidget"/>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<customwidgets>
|
||||
<customwidget>
|
||||
<class>KListWidgetSearchLine</class>
|
||||
<extends>KLineEdit</extends>
|
||||
<header>klistwidgetsearchline.h</header>
|
||||
</customwidget>
|
||||
<customwidget>
|
||||
<class>KLineEdit</class>
|
||||
<extends>QLineEdit</extends>
|
||||
<header>klineedit.h</header>
|
||||
</customwidget>
|
||||
<customwidget>
|
||||
<class>KListWidget</class>
|
||||
<extends>QListWidget</extends>
|
||||
<header>klistwidget.h</header>
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
|
@ -1,292 +0,0 @@
|
|||
/*
|
||||
Copyright 2012 Aurélien Gâteau <agateau@kde.org>
|
||||
|
||||
Based on RunnerModel class. RunnerModel class copyright:
|
||||
|
||||
Copyright 2011 Aaron Seigo <aseigo@kde.org>
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Library General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Library General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Library General Public License
|
||||
along with this library; see the file COPYING.LIB. If not, write to
|
||||
the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
||||
Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
// Self
|
||||
#include <runnermodel.h>
|
||||
|
||||
// Local
|
||||
#include <runnerconfigurationwidget.h>
|
||||
|
||||
// KDE
|
||||
#include <KDebug>
|
||||
#include <KPluginInfo>
|
||||
#include <Plasma/AbstractRunner>
|
||||
#include <Plasma/RunnerManager>
|
||||
|
||||
// Qt
|
||||
#include <QStandardItemModel>
|
||||
#include <QTimer>
|
||||
|
||||
static const char *WHITELIST_KEY = "whitelist";
|
||||
|
||||
namespace Homerun {
|
||||
|
||||
RunnerSubModel::RunnerSubModel(const QString &runnerId, const QString &name, Plasma::RunnerManager *manager, QObject *parent)
|
||||
: QueryMatchModel(parent)
|
||||
, m_runnerId(runnerId)
|
||||
, m_name(name)
|
||||
{
|
||||
setRunnerManager(manager);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
RunnerModel::RunnerModel(const KConfigGroup &configGroup, QObject *parent)
|
||||
: QAbstractListModel(parent)
|
||||
, m_configGroup(configGroup)
|
||||
, m_manager(0)
|
||||
, m_startQueryTimer(new QTimer(this))
|
||||
, m_runningChangedTimeout(new QTimer(this))
|
||||
, m_running(false)
|
||||
{
|
||||
m_startQueryTimer->setSingleShot(true);
|
||||
m_startQueryTimer->setInterval(10);
|
||||
connect(m_startQueryTimer, SIGNAL(timeout()), this, SLOT(startQuery()));
|
||||
|
||||
//FIXME: HACK: some runners stay in a running but finished state, not possible to say if it's actually over
|
||||
m_runningChangedTimeout->setSingleShot(true);
|
||||
connect(m_runningChangedTimeout, SIGNAL(timeout()), this, SLOT(queryHasFinished()));
|
||||
|
||||
QStringList lst = m_configGroup.readEntry(WHITELIST_KEY, QStringList());
|
||||
setAllowedRunners(lst);
|
||||
}
|
||||
|
||||
RunnerModel::~RunnerModel()
|
||||
{
|
||||
}
|
||||
|
||||
int RunnerModel::rowCount(const QModelIndex &parent) const
|
||||
{
|
||||
if (parent.isValid()) {
|
||||
return 0;
|
||||
}
|
||||
return m_models.count();
|
||||
}
|
||||
|
||||
QVariant RunnerModel::data(const QModelIndex &index, int role) const
|
||||
{
|
||||
if (index.parent().isValid()) {
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
RunnerSubModel *model = m_models.value(index.row());
|
||||
if (!model) {
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
if (role == Qt::DisplayRole) {
|
||||
return model->name();
|
||||
} else {
|
||||
return QVariant();
|
||||
}
|
||||
}
|
||||
|
||||
bool RunnerModel::running() const
|
||||
{
|
||||
return m_running;
|
||||
}
|
||||
|
||||
QObject *RunnerModel::modelForRow(int row) const
|
||||
{
|
||||
if (row < 0 || row >= m_models.count()) {
|
||||
kWarning() << "No model for row" << row << "!";
|
||||
return 0;
|
||||
}
|
||||
return m_models.value(row);
|
||||
}
|
||||
|
||||
void RunnerModel::setAllowedRunners(const QStringList &list)
|
||||
{
|
||||
QStringList existingList = m_manager ? m_manager->allowedRunners() : m_pendingRunnersList;
|
||||
|
||||
if (existingList.toSet() == list.toSet()) {
|
||||
return;
|
||||
}
|
||||
m_pendingRunnersList = list;
|
||||
if (m_manager) {
|
||||
loadRunners();
|
||||
}
|
||||
}
|
||||
|
||||
QString RunnerModel::currentQuery() const
|
||||
{
|
||||
return m_manager ? m_manager->query() : QString();
|
||||
}
|
||||
|
||||
void RunnerModel::scheduleQuery(const QString &query)
|
||||
{
|
||||
m_pendingQuery = query;
|
||||
m_startQueryTimer->start();
|
||||
}
|
||||
|
||||
void RunnerModel::startQuery()
|
||||
{
|
||||
if (m_pendingQuery.isEmpty()) {
|
||||
clear();
|
||||
}
|
||||
|
||||
if (!m_manager && m_pendingQuery.isEmpty()) {
|
||||
// avoid creating a manager just so we can run nothing
|
||||
return;
|
||||
}
|
||||
|
||||
createManager();
|
||||
/* DEBUG
|
||||
kWarning() << "Start query" << m_pendingQuery << "on runners:";
|
||||
Q_FOREACH(Plasma::AbstractRunner *runner, m_manager->runners()) {
|
||||
kWarning() << "-" << runner->name();
|
||||
}
|
||||
*/
|
||||
m_manager->launchQuery(m_pendingQuery);
|
||||
emit queryChanged();
|
||||
m_running = true;
|
||||
emit runningChanged(true);
|
||||
}
|
||||
|
||||
void RunnerModel::createManager()
|
||||
{
|
||||
if (!m_manager) {
|
||||
// RunnerManager must have its own config group to store instance-specific config
|
||||
// (we don't want the manager from this RunnerModel to overwrite the config from another RunnerModel manager)
|
||||
m_manager = new Plasma::RunnerManager(m_configGroup, this);
|
||||
connect(m_manager, SIGNAL(matchesChanged(QList<Plasma::QueryMatch>)),
|
||||
this, SLOT(matchesChanged(QList<Plasma::QueryMatch>)));
|
||||
connect(m_manager, SIGNAL(queryFinished()),
|
||||
this, SLOT(queryHasFinished()));
|
||||
|
||||
if (!m_pendingRunnersList.isEmpty()) {
|
||||
loadRunners();
|
||||
}
|
||||
//connect(m_manager, SIGNAL(queryFinished()), this, SLOT(queryFinished()));
|
||||
}
|
||||
}
|
||||
|
||||
void RunnerModel::matchesChanged(const QList<Plasma::QueryMatch> &matches)
|
||||
{
|
||||
// Group matches by runner
|
||||
// We do not use a QMultiHash here because it keeps values in LIFO order, while we want FIFO.
|
||||
QHash<QString, QList<Plasma::QueryMatch> > matchesForRunner;
|
||||
Q_FOREACH(const Plasma::QueryMatch &match, matches) {
|
||||
QString runnerId = match.runner()->id();
|
||||
auto it = matchesForRunner.find(runnerId);
|
||||
if (it == matchesForRunner.end()) {
|
||||
it = matchesForRunner.insert(runnerId, QList<Plasma::QueryMatch>());
|
||||
}
|
||||
it.value().append(match);
|
||||
}
|
||||
|
||||
// Assign matches to existing models. If there is no match for a model, delete it.
|
||||
for (int row = m_models.count() - 1; row >= 0; --row) {
|
||||
RunnerSubModel *subModel = m_models.at(row);
|
||||
QList<Plasma::QueryMatch> matches = matchesForRunner.take(subModel->runnerId());
|
||||
if (matches.isEmpty()) {
|
||||
beginRemoveRows(QModelIndex(), row, row);
|
||||
m_models.removeAt(row);
|
||||
delete subModel;
|
||||
endRemoveRows();
|
||||
} else {
|
||||
subModel->setMatches(matches);
|
||||
}
|
||||
}
|
||||
|
||||
// At this point, matchesForRunner contains only matches for runners which
|
||||
// do not have a model yet. Create new models for them.
|
||||
if (!matchesForRunner.isEmpty()) {
|
||||
beginInsertRows(QModelIndex(), rowCount(), rowCount() + matchesForRunner.size() - 1);
|
||||
auto it = matchesForRunner.constBegin();
|
||||
auto end = matchesForRunner.constEnd();
|
||||
for (; it != end; ++it) {
|
||||
QList<Plasma::QueryMatch> matches = it.value();
|
||||
Q_ASSERT(!matches.isEmpty());
|
||||
QString name = matches.first().runner()->name();
|
||||
RunnerSubModel *subModel = new RunnerSubModel(it.key(), name, m_manager, this);
|
||||
subModel->setMatches(matches);
|
||||
m_models.append(subModel);
|
||||
}
|
||||
endInsertRows();
|
||||
}
|
||||
|
||||
m_runningChangedTimeout->start(3000);
|
||||
}
|
||||
|
||||
void RunnerModel::queryHasFinished()
|
||||
{
|
||||
m_running = false;
|
||||
emit runningChanged(false);
|
||||
}
|
||||
|
||||
void RunnerModel::clear()
|
||||
{
|
||||
if (m_models.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
beginResetModel();
|
||||
qDeleteAll(m_models);
|
||||
m_models.clear();
|
||||
endResetModel();
|
||||
}
|
||||
|
||||
void RunnerModel::loadRunners()
|
||||
{
|
||||
Q_ASSERT(m_manager);
|
||||
|
||||
KPluginInfo::List runners = m_manager->listRunnerInfo();
|
||||
|
||||
if (m_pendingRunnersList.count() > 0) {
|
||||
KPluginInfo::List list = Plasma::RunnerManager::listRunnerInfo();
|
||||
Q_FOREACH(const KPluginInfo &info, list) {
|
||||
if (m_pendingRunnersList.contains(info.pluginName())) {
|
||||
m_manager->loadRunner(info.service());
|
||||
}
|
||||
}
|
||||
}
|
||||
m_manager->setSingleMode(m_pendingRunnersList.count() == 1);
|
||||
m_pendingRunnersList.clear();
|
||||
}
|
||||
|
||||
Plasma::RunnerManager *RunnerModel::manager() const
|
||||
{
|
||||
return m_manager;
|
||||
}
|
||||
|
||||
//- RunnerSource ------------------------------
|
||||
RunnerSource::RunnerSource(QObject *parent)
|
||||
: AbstractSource(parent)
|
||||
{}
|
||||
|
||||
QAbstractItemModel *RunnerSource::createModelFromConfigGroup(const KConfigGroup &group)
|
||||
{
|
||||
return new RunnerModel(group);
|
||||
};
|
||||
|
||||
bool RunnerSource::isConfigurable() const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
SourceConfigurationWidget *RunnerSource::createConfigurationWidget(const KConfigGroup &group)
|
||||
{
|
||||
return new RunnerConfigurationWidget(group);
|
||||
}
|
||||
|
||||
} // namespace Homerun
|
||||
|
||||
#include "moc_runnermodel.cpp"
|
|
@ -1,133 +0,0 @@
|
|||
/*
|
||||
Copyright 2012 Aurélien Gâteau <agateau@kde.org>
|
||||
|
||||
Based on RunnerModel class. RunnerModel class copyright:
|
||||
|
||||
Copyright 2011 Aaron Seigo <aseigo@kde.org>
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Library General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Library General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Library General Public License
|
||||
along with this library; see the file COPYING.LIB. If not, write to
|
||||
the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
||||
Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
#ifndef RUNNERMODEL_H
|
||||
#define RUNNERMODEL_H
|
||||
|
||||
// Local
|
||||
#include <abstractsource.h>
|
||||
#include <querymatchmodel.h>
|
||||
|
||||
// Qt
|
||||
#include <QtCore/qabstractitemmodel.h>
|
||||
#include <QStringList>
|
||||
|
||||
// KDE
|
||||
#include <KConfig>
|
||||
#include <KConfigGroup>
|
||||
#include <Plasma/QueryMatch>
|
||||
|
||||
class QTimer;
|
||||
|
||||
namespace Plasma {
|
||||
class RunnerManager;
|
||||
}
|
||||
|
||||
namespace Homerun {
|
||||
|
||||
class RunnerModel;
|
||||
|
||||
class RunnerSubModel : public QueryMatchModel
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_PROPERTY(QString name READ name CONSTANT)
|
||||
public:
|
||||
RunnerSubModel(const QString &runnerId, const QString &name, Plasma::RunnerManager *manager, QObject *parent = 0);
|
||||
|
||||
QString runnerId() const { return m_runnerId; }
|
||||
QString name() const { return m_name; }
|
||||
|
||||
private:
|
||||
QString m_runnerId;
|
||||
QString m_name;
|
||||
};
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
class RunnerModel : public QAbstractListModel
|
||||
{
|
||||
Q_OBJECT
|
||||
/**
|
||||
* @property string set the KRunner query
|
||||
*/
|
||||
Q_PROPERTY(QString query WRITE scheduleQuery READ currentQuery NOTIFY queryChanged)
|
||||
|
||||
Q_PROPERTY(bool running READ running NOTIFY runningChanged)
|
||||
|
||||
public:
|
||||
explicit RunnerModel(const KConfigGroup &group, QObject *parent = 0);
|
||||
~RunnerModel();
|
||||
|
||||
Q_INVOKABLE QObject *modelForRow(int row) const;
|
||||
|
||||
void setAllowedRunners(const QStringList &runners);
|
||||
|
||||
int rowCount(const QModelIndex &parent = QModelIndex()) const; // reimp
|
||||
QVariant data(const QModelIndex &, int role = Qt::DisplayRole) const; // reimp
|
||||
|
||||
bool running() const;
|
||||
|
||||
QString currentQuery() const;
|
||||
|
||||
Plasma::RunnerManager *manager() const;
|
||||
|
||||
public Q_SLOTS:
|
||||
void scheduleQuery(const QString &query);
|
||||
|
||||
Q_SIGNALS:
|
||||
void queryChanged();
|
||||
void runningChanged(bool);
|
||||
|
||||
private Q_SLOTS:
|
||||
void startQuery();
|
||||
void queryHasFinished();
|
||||
void matchesChanged(const QList<Plasma::QueryMatch> &matches);
|
||||
|
||||
private:
|
||||
void createManager();
|
||||
void loadRunners();
|
||||
void clear();
|
||||
|
||||
KConfigGroup m_configGroup;
|
||||
Plasma::RunnerManager *m_manager;
|
||||
QTimer *m_startQueryTimer;
|
||||
QTimer *m_runningChangedTimeout;
|
||||
|
||||
QList<RunnerSubModel *> m_models;
|
||||
QStringList m_pendingRunnersList;
|
||||
bool m_running;
|
||||
QString m_pendingQuery;
|
||||
};
|
||||
|
||||
class RunnerSource : public AbstractSource
|
||||
{
|
||||
public:
|
||||
RunnerSource(QObject *parent);
|
||||
QAbstractItemModel *createModelFromConfigGroup(const KConfigGroup &group);
|
||||
SourceConfigurationWidget *createConfigurationWidget(const KConfigGroup &group);
|
||||
bool isConfigurable() const;
|
||||
};
|
||||
|
||||
} // namespace Homerun
|
||||
|
||||
#endif /* RUNNERMODEL_H */
|
|
@ -1,131 +0,0 @@
|
|||
/*
|
||||
Copyright 2013 Aurélien Gâteau <agateau@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/>.
|
||||
*/
|
||||
// Self
|
||||
#include <singlerunnermodel.h>
|
||||
|
||||
// Homerun
|
||||
#include <abstractsource.h>
|
||||
#include <actionlist.h>
|
||||
|
||||
// KDE
|
||||
#include <KDebug>
|
||||
#include <KLocale>
|
||||
#include <KPluginFactory>
|
||||
#include <Plasma/RunnerManager>
|
||||
|
||||
// Qt
|
||||
#include <QIcon>
|
||||
|
||||
namespace Homerun
|
||||
{
|
||||
|
||||
//- SingleRunnerModel -------------------------
|
||||
SingleRunnerModel::SingleRunnerModel(Plasma::RunnerManager *manager, QObject *parent)
|
||||
: QueryMatchModel(parent)
|
||||
, m_manager(manager)
|
||||
{
|
||||
setRunnerManager(manager);
|
||||
connect(m_manager, SIGNAL(matchesChanged(QList<Plasma::QueryMatch>)), SLOT(setMatches(QList<Plasma::QueryMatch>)));
|
||||
launchQuery(QString());
|
||||
}
|
||||
|
||||
void SingleRunnerModel::launchQuery(const QString &query)
|
||||
{
|
||||
QString term = prepareSearchTerm(query);
|
||||
m_manager->launchQuery(term, m_manager->singleModeRunnerId());
|
||||
}
|
||||
|
||||
QString SingleRunnerModel::name() const
|
||||
{
|
||||
return m_manager->singleModeRunner()->name();
|
||||
}
|
||||
|
||||
QString SingleRunnerModel::prepareSearchTerm(const QString &term)
|
||||
{
|
||||
const char *placeHolder = ":q:";
|
||||
Plasma::RunnerSyntax *syntax = m_manager->singleModeRunner()->defaultSyntax();
|
||||
QStringList queries = syntax->exampleQueries();
|
||||
Q_ASSERT(!queries.isEmpty());
|
||||
QString query = queries.first();
|
||||
return query.replace(placeHolder, term);
|
||||
}
|
||||
|
||||
//- SingleQueriableRunnerModel ----------------
|
||||
SingleQueriableRunnerModel::SingleQueriableRunnerModel(Plasma::RunnerManager *manager, QObject *parent)
|
||||
: SingleRunnerModel(manager, parent)
|
||||
{
|
||||
}
|
||||
|
||||
QString SingleQueriableRunnerModel::query() const
|
||||
{
|
||||
return m_query;
|
||||
}
|
||||
|
||||
void SingleQueriableRunnerModel::setQuery(const QString &value)
|
||||
{
|
||||
if (m_query == value) {
|
||||
return;
|
||||
}
|
||||
m_query = value;
|
||||
launchQuery(m_query);
|
||||
queryChanged(m_query);
|
||||
}
|
||||
|
||||
//- SingleRunnerSource ------------------------
|
||||
SingleRunnerSource::SingleRunnerSource(const QString &runnerId, QObject *parent)
|
||||
: AbstractSource(parent)
|
||||
, m_runnerId(runnerId)
|
||||
{}
|
||||
|
||||
QAbstractItemModel *SingleRunnerSource::createModelFromConfigGroup(const KConfigGroup &group_)
|
||||
{
|
||||
KConfigGroup group(group_);
|
||||
// RunnerManager must have its own config group to store instance-specific config
|
||||
// (we don't want the manager from this RunnerModel to overwrite the config from another RunnerModel manager)
|
||||
Plasma::RunnerManager *manager = new Plasma::RunnerManager(group, this);
|
||||
manager->setAllowedRunners(QStringList() << m_runnerId);
|
||||
manager->setSingleModeRunnerId(m_runnerId);
|
||||
manager->setSingleMode(true);
|
||||
if (!manager->singleModeRunner()) {
|
||||
kWarning() << "Failed to load runner" << m_runnerId << "as a single mode runner";
|
||||
delete manager;
|
||||
return 0;
|
||||
}
|
||||
|
||||
Plasma::RunnerSyntax *syntax = manager->singleModeRunner()->defaultSyntax();
|
||||
if (!syntax) {
|
||||
kWarning() << "Runner" << m_runnerId << "advertises itself as a single mode runner but does not provide a default syntax!";
|
||||
delete manager;
|
||||
return 0;
|
||||
}
|
||||
QStringList queries = syntax->exampleQueries();
|
||||
Q_ASSERT(!queries.isEmpty());
|
||||
QString query = queries.first();
|
||||
|
||||
if (query.contains(":q:")) {
|
||||
return new SingleQueriableRunnerModel(manager);
|
||||
} else {
|
||||
return new SingleRunnerModel(manager);
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace Homerun
|
||||
|
||||
#include "moc_singlerunnermodel.cpp"
|
|
@ -1,87 +0,0 @@
|
|||
/*
|
||||
Copyright 2013 Aurélien Gâteau <agateau@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 SINGLERUNNERMODEL_H
|
||||
#define SINGLERUNNERMODEL_H
|
||||
|
||||
// Local
|
||||
#include <abstractsource.h>
|
||||
#include <querymatchmodel.h>
|
||||
|
||||
// KDE
|
||||
#include <Plasma/RunnerManager>
|
||||
|
||||
namespace Homerun
|
||||
{
|
||||
|
||||
/**
|
||||
* This model exposes results from a runner with single-runner mode
|
||||
*/
|
||||
class SingleRunnerModel : public QueryMatchModel
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_PROPERTY(QString name READ name CONSTANT)
|
||||
public:
|
||||
explicit SingleRunnerModel(Plasma::RunnerManager *manager, QObject * parent = 0);
|
||||
|
||||
QString name() const;
|
||||
|
||||
void launchQuery(const QString &query);
|
||||
|
||||
private:
|
||||
KConfigGroup m_configGroup;
|
||||
Plasma::RunnerManager *m_manager;
|
||||
|
||||
QString prepareSearchTerm(const QString &term);
|
||||
};
|
||||
|
||||
/**
|
||||
* This model is the same as SingleRunnerModel, except it exposes a "query" property.
|
||||
* It is used when the Runner default syntax has a placeholder.
|
||||
*/
|
||||
class SingleQueriableRunnerModel : public SingleRunnerModel
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_PROPERTY(QString query READ query WRITE setQuery NOTIFY queryChanged)
|
||||
public:
|
||||
explicit SingleQueriableRunnerModel(Plasma::RunnerManager *manager, QObject * parent = 0);
|
||||
|
||||
QString query() const;
|
||||
void setQuery(const QString &query);
|
||||
|
||||
Q_SIGNALS:
|
||||
void queryChanged(const QString &);
|
||||
|
||||
private:
|
||||
QString m_query;
|
||||
};
|
||||
|
||||
class SingleRunnerSource : public AbstractSource
|
||||
{
|
||||
public:
|
||||
SingleRunnerSource(const QString &runnerId, QObject *parent);
|
||||
QAbstractItemModel *createModelFromConfigGroup(const KConfigGroup &group) override;
|
||||
|
||||
private:
|
||||
QString m_runnerId;
|
||||
};
|
||||
|
||||
} // namespace Homerun
|
||||
|
||||
#endif /* SINGLERUNNERMODEL_H */
|
|
@ -1,92 +0,0 @@
|
|||
/*
|
||||
Copyright 2013 Aurélien Gâteau <agateau@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/>.
|
||||
*/
|
||||
// Self
|
||||
#include <openedsessionsmodel.h>
|
||||
|
||||
// Local
|
||||
#include <sessionswatcher.h>
|
||||
|
||||
// KDE
|
||||
#include <KLocale>
|
||||
|
||||
// Qt
|
||||
#include <QTimer>
|
||||
|
||||
namespace Homerun
|
||||
{
|
||||
|
||||
class SwitchSessionItem : public StandardItem
|
||||
{
|
||||
public:
|
||||
SwitchSessionItem(KDisplayManager *manager, const SessEnt &session)
|
||||
: m_displayManager(manager)
|
||||
, m_vt(session.vt)
|
||||
{
|
||||
QString user, location;
|
||||
KDisplayManager::sess2Str2(session, user, location);
|
||||
setText(user + QString(" (Ctrl+Alt+F%1)").arg(session.vt));
|
||||
if (session.user.isEmpty() && session.session.isEmpty()) {
|
||||
setIconName("preferences-system-login");
|
||||
} else {
|
||||
setIconName("user-identity");
|
||||
}
|
||||
}
|
||||
|
||||
bool trigger(const QString &/*actionId*/, const QVariant &/*actionArgument*/) override
|
||||
{
|
||||
m_displayManager->lockSwitchVT(m_vt);
|
||||
return true;
|
||||
}
|
||||
|
||||
private:
|
||||
KDisplayManager *m_displayManager;
|
||||
int m_vt;
|
||||
};
|
||||
|
||||
OpenedSessionsModel::OpenedSessionsModel(QObject *parent)
|
||||
: StandardItemModel(parent)
|
||||
, m_watcher(new SessionsWatcher(this))
|
||||
{
|
||||
setName(i18n("Opened Sessions"));
|
||||
connect(m_watcher, SIGNAL(sessionsChanged()), SLOT(refresh()));
|
||||
}
|
||||
|
||||
OpenedSessionsModel::~OpenedSessionsModel()
|
||||
{
|
||||
}
|
||||
|
||||
void OpenedSessionsModel::refresh()
|
||||
{
|
||||
clear();
|
||||
|
||||
SessList sessions = m_watcher->sessions();
|
||||
|
||||
Q_FOREACH(const SessEnt &session, sessions) {
|
||||
if (!session.vt || session.self) {
|
||||
continue;
|
||||
}
|
||||
|
||||
appendRow(new SwitchSessionItem(&m_displayManager, session));
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
#include "moc_openedsessionsmodel.cpp"
|
|
@ -1,53 +0,0 @@
|
|||
/*
|
||||
Copyright 2013 Aurélien Gâteau <agateau@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 OPENEDSESSIONSMODEL_H
|
||||
#define OPENEDSESSIONSMODEL_H
|
||||
|
||||
// Local
|
||||
#include <standarditemmodel.h>
|
||||
|
||||
// Qt
|
||||
|
||||
// KDE
|
||||
#include <kworkspace/kdisplaymanager.h>
|
||||
|
||||
class SessionsWatcher;
|
||||
|
||||
namespace Homerun
|
||||
{
|
||||
|
||||
class OpenedSessionsModel : public StandardItemModel
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit OpenedSessionsModel(QObject *parent = 0);
|
||||
~OpenedSessionsModel();
|
||||
|
||||
private:
|
||||
KDisplayManager m_displayManager;
|
||||
SessionsWatcher *m_watcher;
|
||||
|
||||
private Q_SLOTS:
|
||||
void refresh();
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
#endif /* OPENEDSESSIONSMODEL_H */
|
|
@ -1,118 +0,0 @@
|
|||
/*
|
||||
Copyright 2012 Aurélien Gâteau <agateau@kde.org>
|
||||
Copyright (C) 2012 Shaun Reich <shaun.reich@blue-systems.com>
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Library General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Library General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Library General Public License
|
||||
along with this library; see the file COPYING.LIB. If not, write to
|
||||
the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
||||
Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
// Own
|
||||
#include "sessionmodel.h"
|
||||
|
||||
// Local
|
||||
|
||||
// KDE
|
||||
#include <KAuthorized>
|
||||
#include <KDebug>
|
||||
#include <KLocale>
|
||||
|
||||
// Qt
|
||||
#include <QDBusConnection>
|
||||
#include <QDBusInterface>
|
||||
#include <QDBusPendingCall>
|
||||
|
||||
namespace Homerun {
|
||||
|
||||
static void lockSession()
|
||||
{
|
||||
QDBusConnection bus = QDBusConnection::sessionBus();
|
||||
QDBusInterface interface("org.freedesktop.ScreenSaver", "/ScreenSaver", "org.freedesktop.ScreenSaver", bus);
|
||||
interface.asyncCall("Lock");
|
||||
}
|
||||
|
||||
//- Local items -------------------------------------------------------------------
|
||||
class LockSessionItem : public StandardItem
|
||||
{
|
||||
public:
|
||||
LockSessionItem()
|
||||
: StandardItem(i18nc("an action", "Lock"), "system-lock-screen")
|
||||
{
|
||||
}
|
||||
|
||||
bool trigger(const QString &/*actionId*/, const QVariant &/*actionArgument*/) override
|
||||
{
|
||||
lockSession();
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
class NewSessionItem : public StandardItem
|
||||
{
|
||||
public:
|
||||
NewSessionItem(KDisplayManager *manager)
|
||||
: StandardItem(i18nc("an action", "New Session"), "system-switch-user")
|
||||
, m_displayManager(manager)
|
||||
{
|
||||
}
|
||||
|
||||
bool trigger(const QString &/*actionId*/, const QVariant &/*actionArgument*/) override
|
||||
{
|
||||
lockSession();
|
||||
m_displayManager->startReserve();
|
||||
return true;
|
||||
}
|
||||
|
||||
private:
|
||||
KDisplayManager *m_displayManager;
|
||||
};
|
||||
|
||||
class LogoutItem : public StandardItem
|
||||
{
|
||||
public:
|
||||
LogoutItem()
|
||||
: StandardItem(i18nc("an action", "Logout"), "system-log-out")
|
||||
{}
|
||||
|
||||
bool trigger(const QString &/*actionId*/, const QVariant &/*actionArgument*/) override
|
||||
{
|
||||
KWorkSpace::requestShutDown(KWorkSpace::ShutdownConfirmDefault, KWorkSpace::ShutdownTypeNone);
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
SessionModel::SessionModel(QObject *parent)
|
||||
: StandardItemModel(parent)
|
||||
{
|
||||
setName(i18n("Session"));
|
||||
|
||||
if (KAuthorized::authorizeKAction("lock_screen")) {
|
||||
appendRow(new LockSessionItem);
|
||||
}
|
||||
|
||||
if (KAuthorized::authorizeKAction("logout") && KAuthorized::authorize("logout")) {
|
||||
appendRow(new LogoutItem);
|
||||
}
|
||||
|
||||
if (KAuthorized::authorizeKAction("start_new_session")
|
||||
&& m_displayManager.isSwitchable()
|
||||
&& m_displayManager.numReserve() >= 0)
|
||||
{
|
||||
appendRow(new NewSessionItem(&m_displayManager));
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace Homerun
|
||||
|
||||
#include "moc_sessionmodel.cpp"
|
|
@ -1,45 +0,0 @@
|
|||
/*
|
||||
Copyright 2012 Aurélien Gâteau <agateau@kde.org>
|
||||
Copyright 2012 (C) Shaun Reich <shaun.reich@blue-systems.com>
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Library General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Library General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Library General Public License
|
||||
along with this library; see the file COPYING.LIB. If not, write to
|
||||
the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
||||
Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#ifndef SESSIONMODEL_H
|
||||
#define SESSIONMODEL_H
|
||||
|
||||
// Local
|
||||
#include <standarditemmodel.h>
|
||||
|
||||
// KDE
|
||||
#include <kworkspace/kdisplaymanager.h>
|
||||
|
||||
namespace Homerun {
|
||||
|
||||
class SessionModel : public StandardItemModel
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
SessionModel(QObject *parent = 0);
|
||||
|
||||
private:
|
||||
KDisplayManager m_displayManager;
|
||||
void createUserItems();
|
||||
};
|
||||
|
||||
} // namespace Homerun
|
||||
|
||||
#endif
|
|
@ -1,92 +0,0 @@
|
|||
/*
|
||||
Copyright 2013 Aurélien Gâteau <agateau@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/>.
|
||||
*/
|
||||
// Self
|
||||
#include <sessionswatcher.h>
|
||||
|
||||
// Local
|
||||
|
||||
// KDE
|
||||
|
||||
// Qt
|
||||
#include <QTimer>
|
||||
|
||||
/*
|
||||
* Polling sucks, but I don't know a better way given the wild jungle of
|
||||
* display managers available. Let's poll only every 30 seconds to avoid
|
||||
* draining batteries.
|
||||
* Eventually support for being notified about session changes should be
|
||||
* implemented at least for consolekit and systemd-logind
|
||||
*/
|
||||
static const int POLL_INTERVAL = 30 * 1000;
|
||||
|
||||
SessionsWatcher::SessionsWatcher(QObject *parent)
|
||||
: QObject(parent)
|
||||
{
|
||||
QTimer *timer = new QTimer(this);
|
||||
timer->setInterval(POLL_INTERVAL);
|
||||
connect(timer, SIGNAL(timeout()), SLOT(checkSessions()));
|
||||
timer->start();
|
||||
|
||||
QMetaObject::invokeMethod(this, "checkSessions", Qt::QueuedConnection);
|
||||
}
|
||||
|
||||
// SessEnt has no operator==() :/
|
||||
inline bool sameSession(const SessEnt &s1, const SessEnt &s2)
|
||||
{
|
||||
#define CHECK_FIELD(f) if (s1.f != s2.f) { return false; }
|
||||
CHECK_FIELD(display)
|
||||
CHECK_FIELD(from)
|
||||
CHECK_FIELD(user)
|
||||
CHECK_FIELD(session)
|
||||
CHECK_FIELD(vt)
|
||||
CHECK_FIELD(self)
|
||||
CHECK_FIELD(tty)
|
||||
#undef CHECK_FIELD
|
||||
return true;
|
||||
}
|
||||
|
||||
void SessionsWatcher::checkSessions()
|
||||
{
|
||||
SessList newSessions;
|
||||
m_displayManager.localSessions(newSessions);
|
||||
if (m_sessions.count() != newSessions.count()) {
|
||||
m_sessions = newSessions;
|
||||
sessionsChanged();
|
||||
return;
|
||||
}
|
||||
auto oldIt = m_sessions.constBegin(), oldEnd = m_sessions.constEnd();
|
||||
auto newIt = newSessions.constBegin();
|
||||
for (; oldIt != oldEnd; ++oldIt, ++newIt) {
|
||||
if (!sameSession(*oldIt, *newIt)) {
|
||||
m_sessions = newSessions;
|
||||
sessionsChanged();
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SessList SessionsWatcher::sessions() const
|
||||
{
|
||||
return m_sessions;
|
||||
}
|
||||
|
||||
|
||||
|
||||
#include "moc_sessionswatcher.cpp"
|
|
@ -1,53 +0,0 @@
|
|||
/*
|
||||
Copyright 2013 Aurélien Gâteau <agateau@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 SESSIONSWATCHER_H
|
||||
#define SESSIONSWATCHER_H
|
||||
|
||||
// Local
|
||||
|
||||
// Qt
|
||||
#include <QObject>
|
||||
|
||||
// KDE
|
||||
#include <kworkspace/kdisplaymanager.h>
|
||||
|
||||
/**
|
||||
* Watch sessions, emit a signal when a session is opened or closed
|
||||
*/
|
||||
class SessionsWatcher : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit SessionsWatcher(QObject *parent = 0);
|
||||
|
||||
SessList sessions() const;
|
||||
|
||||
Q_SIGNALS:
|
||||
void sessionsChanged();
|
||||
|
||||
private Q_SLOTS:
|
||||
void checkSessions();
|
||||
|
||||
private:
|
||||
KDisplayManager m_displayManager;
|
||||
SessList m_sessions;
|
||||
};
|
||||
|
||||
#endif /* SESSIONSWATCHER_H */
|
|
@ -1,90 +0,0 @@
|
|||
/*
|
||||
Copyright 2013 Aurélien Gâteau <agateau@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/>.
|
||||
*/
|
||||
// Self
|
||||
#include <standarditemmodel.h>
|
||||
|
||||
// Local
|
||||
|
||||
// KDE
|
||||
|
||||
// Qt
|
||||
|
||||
namespace Homerun
|
||||
{
|
||||
|
||||
//- StandardItem ------------------------------------------------------------------
|
||||
StandardItem::StandardItem()
|
||||
{
|
||||
}
|
||||
|
||||
StandardItem::StandardItem(const QString& text, const QString& iconName)
|
||||
: QStandardItem(text)
|
||||
{
|
||||
setIconName(iconName);
|
||||
}
|
||||
|
||||
void StandardItem::setIconName(const QString &iconName)
|
||||
{
|
||||
setData(iconName, Qt::DecorationRole);
|
||||
}
|
||||
|
||||
bool StandardItem::trigger(const QString &/*actionId*/, const QVariant &/*actionArgument*/)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
//- StandardItemModel -------------------------------------------------------------
|
||||
StandardItemModel::StandardItemModel(QObject *parent)
|
||||
: QStandardItemModel(parent)
|
||||
{
|
||||
connect(this, SIGNAL(rowsInserted(QModelIndex,int,int)), SIGNAL(countChanged()));
|
||||
connect(this, SIGNAL(rowsRemoved(QModelIndex,int,int)), SIGNAL(countChanged()));
|
||||
connect(this, SIGNAL(modelReset()), SIGNAL(countChanged()));
|
||||
}
|
||||
|
||||
QString StandardItemModel::name() const
|
||||
{
|
||||
return m_name;
|
||||
}
|
||||
|
||||
void StandardItemModel::setName(const QString &name)
|
||||
{
|
||||
if (m_name == name) {
|
||||
return;
|
||||
}
|
||||
m_name = name;
|
||||
nameChanged();
|
||||
}
|
||||
|
||||
int StandardItemModel::count() const
|
||||
{
|
||||
return rowCount(QModelIndex());
|
||||
}
|
||||
|
||||
bool StandardItemModel::trigger(int row, const QString &actionId, const QVariant &actionArgument)
|
||||
{
|
||||
StandardItem *itm = static_cast<StandardItem *>(item(row));
|
||||
Q_ASSERT(itm);
|
||||
return itm->trigger(actionId, actionArgument);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
#include "moc_standarditemmodel.cpp"
|
|
@ -1,79 +0,0 @@
|
|||
/*
|
||||
Copyright 2013 Aurélien Gâteau <agateau@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 STANDARDITEMMODEL_H
|
||||
#define STANDARDITEMMODEL_H
|
||||
|
||||
// Local
|
||||
|
||||
// Qt
|
||||
#include <QStandardItemModel>
|
||||
|
||||
// KDE
|
||||
|
||||
namespace Homerun
|
||||
{
|
||||
|
||||
/**
|
||||
* An item to be used with StandardItemModel. Similar to QStandardItem, but
|
||||
* more adapted to Homerun needs.
|
||||
*/
|
||||
class StandardItem : public QStandardItem
|
||||
{
|
||||
public:
|
||||
StandardItem();
|
||||
StandardItem(const QString &text, const QString &iconName);
|
||||
virtual bool trigger(const QString &actionId, const QVariant &actionArgument);
|
||||
void setIconName(const QString &);
|
||||
};
|
||||
|
||||
/**
|
||||
* A simple model to use when a source does not have many items. Similar to
|
||||
* QStandardItemModel, but more adapted to Homerun needs.
|
||||
*
|
||||
* Important: One should always use items inheriting from StandardItem with this
|
||||
* model.
|
||||
*/
|
||||
class StandardItemModel : public QStandardItemModel
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_PROPERTY(QString name READ name NOTIFY nameChanged)
|
||||
Q_PROPERTY(int count READ count NOTIFY countChanged)
|
||||
|
||||
public:
|
||||
StandardItemModel(QObject *parent = 0);
|
||||
|
||||
int count() const;
|
||||
QString name() const;
|
||||
void setName(const QString &name);
|
||||
|
||||
Q_INVOKABLE virtual bool trigger(int row, const QString &actionId, const QVariant &actionArgument);
|
||||
|
||||
Q_SIGNALS:
|
||||
void countChanged();
|
||||
void nameChanged();
|
||||
|
||||
private:
|
||||
QString m_name;
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
|
||||
#endif /* STANDARDITEMMODEL_H */
|
|
@ -1,375 +0,0 @@
|
|||
/*
|
||||
Copyright 2012 Aurélien Gâteau <agateau@kde.org>
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) 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 6 of version 3 of the license.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#include "tabmodel.h"
|
||||
|
||||
// KDE
|
||||
#include <KConfigGroup>
|
||||
#include <KDebug>
|
||||
#include <KLocale>
|
||||
#include <KStandardDirs>
|
||||
|
||||
// Qt
|
||||
#include <QFile>
|
||||
|
||||
// Local
|
||||
#include <sourcemodel.h>
|
||||
#include <sourceregistry.h>
|
||||
|
||||
using namespace Homerun;
|
||||
|
||||
static const char *TAB_GROUP_PREFIX = "Tab";
|
||||
|
||||
static const char *GENERAL_GROUP = "General";
|
||||
static const char *GENERAL_TABS_KEY = "tabs";
|
||||
|
||||
class Tab
|
||||
{
|
||||
public:
|
||||
KConfigGroup m_group;
|
||||
|
||||
QString m_name;
|
||||
QString m_iconName;
|
||||
SourceModel *m_sourceModel;
|
||||
|
||||
Tab()
|
||||
: m_sourceModel(0)
|
||||
{
|
||||
}
|
||||
|
||||
~Tab()
|
||||
{
|
||||
delete m_sourceModel;
|
||||
}
|
||||
|
||||
bool setName(const QString &value)
|
||||
{
|
||||
if (m_name == value) {
|
||||
return false;
|
||||
}
|
||||
m_name = value;
|
||||
saveName();
|
||||
m_group.sync();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool setIconName(const QString &value)
|
||||
{
|
||||
if (m_iconName == value) {
|
||||
return false;
|
||||
}
|
||||
m_iconName = value;
|
||||
saveIconName();
|
||||
m_group.sync();
|
||||
return true;
|
||||
}
|
||||
|
||||
void saveName()
|
||||
{
|
||||
m_group.writeEntry("name", m_name);
|
||||
}
|
||||
|
||||
void saveIconName()
|
||||
{
|
||||
m_group.writeEntry("icon", m_iconName);
|
||||
}
|
||||
|
||||
void save()
|
||||
{
|
||||
// In case a deleted group is reused
|
||||
m_group.writeEntry("deleted", false);
|
||||
saveName();
|
||||
saveIconName();
|
||||
m_group.sync();
|
||||
}
|
||||
|
||||
static Tab *createFromGroup(const KConfigGroup &group, TabModel *tabModel)
|
||||
{
|
||||
Tab *tab = new Tab;
|
||||
|
||||
// (read "name" as QByteArray because i18n() wants a char* as argument)
|
||||
QByteArray name = group.readEntry("name", QByteArray());
|
||||
if (!name.isEmpty()) {
|
||||
// Only translate if not empty. If name is empty i18n(name)
|
||||
// returns I18N_EMPTY_MESSAGE.
|
||||
// Translation context must be the same as in internal/i18nconfig.cpp
|
||||
tab->m_name = i18nc("Tab title", name);
|
||||
}
|
||||
|
||||
tab->m_group = group;
|
||||
tab->m_sourceModel = new SourceModel(tabModel->sourceRegistry(), group, tabModel);
|
||||
tab->m_iconName = group.readEntry("icon");
|
||||
return tab;
|
||||
}
|
||||
|
||||
void remove()
|
||||
{
|
||||
m_group.deleteGroup();
|
||||
m_group.writeEntry("deleted", true);
|
||||
m_group.sync();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
TabModel::TabModel(QObject *parent)
|
||||
: QAbstractListModel(parent)
|
||||
, m_sourceRegistry(0)
|
||||
{
|
||||
QHash<int, QByteArray> roles;
|
||||
roles.insert(Qt::DisplayRole, "display");
|
||||
roles.insert(Qt::DecorationRole, "decoration");
|
||||
roles.insert(SourceModelRole, "sourceModel");
|
||||
|
||||
setRoleNames(roles);
|
||||
}
|
||||
|
||||
TabModel::~TabModel()
|
||||
{
|
||||
qDeleteAll(m_tabList);
|
||||
}
|
||||
|
||||
QStringList TabModel::tabGroupList() const
|
||||
{
|
||||
KConfigGroup group (m_config, GENERAL_GROUP);
|
||||
return group.readEntry(GENERAL_TABS_KEY, QStringList());
|
||||
}
|
||||
|
||||
void TabModel::setConfig(const KSharedConfig::Ptr &ptr)
|
||||
{
|
||||
beginResetModel();
|
||||
m_config = ptr;
|
||||
qDeleteAll(m_tabList);
|
||||
m_tabList.clear();
|
||||
QStringList list = tabGroupList();
|
||||
Q_FOREACH(const QString &groupName, list) {
|
||||
KConfigGroup group = m_config->group(groupName);
|
||||
Tab *tab = Tab::createFromGroup(group, this);
|
||||
if (tab) {
|
||||
m_tabList << tab;
|
||||
}
|
||||
}
|
||||
endResetModel();
|
||||
configFileNameChanged(m_config->name());
|
||||
}
|
||||
|
||||
static void copyGroup(const KConfigGroup &dst_, const KConfigGroup &src)
|
||||
{
|
||||
KConfigGroup dst = dst_;
|
||||
QMap<QString, QString> entryMap = src.entryMap();
|
||||
QSet<QString> keys = dst.keyList().toSet() | src.keyList().toSet();
|
||||
Q_FOREACH(const QString &key, keys) {
|
||||
auto it = entryMap.find(key);
|
||||
if (it == entryMap.end()) {
|
||||
dst.deleteEntry(key);
|
||||
} else {
|
||||
dst.writeEntry(key, src.readEntry(key));
|
||||
}
|
||||
}
|
||||
|
||||
QStringList srcGroupList = src.groupList();
|
||||
Q_FOREACH(const QString &groupName, dst.groupList()) {
|
||||
if (!srcGroupList.contains(groupName)) {
|
||||
dst.deleteGroup(groupName);
|
||||
}
|
||||
}
|
||||
Q_FOREACH(const QString &groupName, srcGroupList) {
|
||||
copyGroup(dst.group(groupName), src.group(groupName));
|
||||
}
|
||||
}
|
||||
|
||||
void TabModel::resetConfig()
|
||||
{
|
||||
KConfigGroup generalGroup = m_config->group(GENERAL_GROUP);
|
||||
generalGroup.revertToDefault(GENERAL_TABS_KEY);
|
||||
|
||||
QStringList tabs = generalGroup.readEntry(GENERAL_TABS_KEY, QStringList());
|
||||
|
||||
// FIXME: Should load all config files in cascade
|
||||
QStringList fileNames = KGlobal::dirs()->findAllResources("config", m_config->name());
|
||||
KConfig systemConfig(fileNames.last());
|
||||
|
||||
Q_FOREACH(const QString &groupName, m_config->groupList()) {
|
||||
if (!groupName.startsWith(TAB_GROUP_PREFIX)) {
|
||||
continue;
|
||||
}
|
||||
if (tabs.contains(groupName)) {
|
||||
copyGroup(m_config->group(groupName), systemConfig.group(groupName));
|
||||
} else {
|
||||
m_config->deleteGroup(groupName);
|
||||
}
|
||||
}
|
||||
m_config->sync();
|
||||
|
||||
setConfig(m_config);
|
||||
}
|
||||
|
||||
QString TabModel::configFileName() const
|
||||
{
|
||||
return m_config ? m_config->name() : QString();
|
||||
}
|
||||
|
||||
void TabModel::setConfigFileName(const QString &name)
|
||||
{
|
||||
if (name == configFileName()) {
|
||||
return;
|
||||
}
|
||||
setConfig(KSharedConfig::openConfig(name));
|
||||
}
|
||||
|
||||
AbstractSourceRegistry *TabModel::sourceRegistry() const
|
||||
{
|
||||
return m_sourceRegistry;
|
||||
}
|
||||
|
||||
void TabModel::setSourceRegistry(AbstractSourceRegistry *registry)
|
||||
{
|
||||
if (m_sourceRegistry != registry) {
|
||||
m_sourceRegistry = registry;
|
||||
sourceRegistryChanged();
|
||||
}
|
||||
}
|
||||
|
||||
int TabModel::rowCount(const QModelIndex &parent) const
|
||||
{
|
||||
if (m_config.isNull()) {
|
||||
return 0;
|
||||
}
|
||||
if (parent.isValid()) {
|
||||
return 0;
|
||||
}
|
||||
return m_tabList.count();
|
||||
}
|
||||
|
||||
QVariant TabModel::data(const QModelIndex &index, int role) const
|
||||
{
|
||||
Tab *tab = m_tabList.value(index.row());
|
||||
if (!tab) {
|
||||
return QVariant();
|
||||
}
|
||||
switch (role) {
|
||||
case Qt::DisplayRole:
|
||||
return tab->m_name;
|
||||
case Qt::DecorationRole:
|
||||
return tab->m_iconName;
|
||||
case SourceModelRole:
|
||||
return qVariantFromValue(static_cast<QObject *>(tab->m_sourceModel));
|
||||
default:
|
||||
kWarning() << "Unhandled role" << role;
|
||||
return QVariant();
|
||||
}
|
||||
}
|
||||
|
||||
void TabModel::setDataForRow(int row, const QByteArray &roleName, const QVariant &value)
|
||||
{
|
||||
Tab *tab = m_tabList.value(row);
|
||||
if (!tab) {
|
||||
kWarning() << "Invalid row number" << row;
|
||||
return;
|
||||
}
|
||||
|
||||
if (roleName == "display") {
|
||||
if (!tab->setName(value.toString())) {
|
||||
return;
|
||||
}
|
||||
} else if (roleName == "decoration") {
|
||||
if (!tab->setIconName(value.toString())) {
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
kWarning() << "Don't know how to handle role" << roleName;
|
||||
return;
|
||||
}
|
||||
|
||||
QModelIndex idx = index(row, 0);
|
||||
dataChanged(idx, idx);
|
||||
}
|
||||
|
||||
void TabModel::appendRow()
|
||||
{
|
||||
QStringList list = tabGroupList();
|
||||
int lastId;
|
||||
if (list.isEmpty()) {
|
||||
lastId = -1;
|
||||
} else {
|
||||
bool ok;
|
||||
lastId = list.last().mid(3).toInt(&ok);
|
||||
if (!ok) {
|
||||
kWarning() << "Cannot extract a valid lastId from" << list.last();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
KConfigGroup tabGroup = m_config->group(QLatin1String(TAB_GROUP_PREFIX) + QString::number(lastId + 1));
|
||||
Tab *tab = Tab::createFromGroup(tabGroup, this);
|
||||
|
||||
int count = m_tabList.count();
|
||||
beginInsertRows(QModelIndex(), count, count);
|
||||
m_tabList.append(tab);
|
||||
endInsertRows();
|
||||
|
||||
tab->save();
|
||||
writeGeneralTabsEntry();
|
||||
}
|
||||
|
||||
#define CHECK_ROW(row) \
|
||||
if (row < 0 || row >= m_tabList.count()) { \
|
||||
kWarning() << "Invalid row number" << row; \
|
||||
return; \
|
||||
}
|
||||
|
||||
void TabModel::removeRow(int row)
|
||||
{
|
||||
CHECK_ROW(row)
|
||||
beginRemoveRows(QModelIndex(), row, row);
|
||||
Tab *tab = m_tabList.takeAt(row);
|
||||
Q_ASSERT(tab);
|
||||
tab->remove();
|
||||
delete tab;
|
||||
writeGeneralTabsEntry();
|
||||
endRemoveRows();
|
||||
}
|
||||
|
||||
void TabModel::moveRow(int from, int to)
|
||||
{
|
||||
CHECK_ROW(from)
|
||||
CHECK_ROW(to)
|
||||
if (from == to) {
|
||||
kWarning() << "Cannot move row to itself";
|
||||
return;
|
||||
}
|
||||
// See beginMoveRows() doc for an explanation on modelTo
|
||||
int modelTo = to + (to > from ? 1 : 0);
|
||||
beginMoveRows(QModelIndex(), from, from, QModelIndex(), modelTo);
|
||||
m_tabList.move(from, to);
|
||||
writeGeneralTabsEntry();
|
||||
endMoveRows();
|
||||
}
|
||||
|
||||
void TabModel::writeGeneralTabsEntry()
|
||||
{
|
||||
QStringList lst;
|
||||
Q_FOREACH(const Tab *tab, m_tabList) {
|
||||
lst << tab->m_group.name();
|
||||
}
|
||||
KConfigGroup group(m_config, GENERAL_GROUP);
|
||||
group.writeEntry(GENERAL_TABS_KEY, lst);
|
||||
m_config->sync();
|
||||
}
|
||||
|
||||
#include "moc_tabmodel.cpp"
|
|
@ -1,87 +0,0 @@
|
|||
/*
|
||||
Copyright 2012 Aurélien Gâteau <agateau@kde.org>
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) 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 6 of version 3 of the license.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#ifndef TABMODEL_H
|
||||
#define TABMODEL_H
|
||||
|
||||
#include <QtCore/qabstractitemmodel.h>
|
||||
|
||||
#include <KSharedConfig>
|
||||
|
||||
namespace Homerun {
|
||||
class AbstractSourceRegistry;
|
||||
}
|
||||
class Tab;
|
||||
|
||||
/**
|
||||
* A TabModel loads the definition of Homerun tabs from a configuration file
|
||||
*/
|
||||
class TabModel : public QAbstractListModel
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_PROPERTY(QString configFileName READ configFileName WRITE setConfigFileName NOTIFY configFileNameChanged)
|
||||
Q_PROPERTY(Homerun::AbstractSourceRegistry *sourceRegistry READ sourceRegistry WRITE setSourceRegistry NOTIFY sourceRegistryChanged)
|
||||
|
||||
public:
|
||||
enum {
|
||||
SourceModelRole = Qt::UserRole + 1,
|
||||
};
|
||||
|
||||
TabModel(QObject *parent = 0);
|
||||
~TabModel();
|
||||
|
||||
void setConfig(const KSharedConfig::Ptr &);
|
||||
|
||||
QString configFileName() const;
|
||||
void setConfigFileName(const QString &name);
|
||||
|
||||
Homerun::AbstractSourceRegistry *sourceRegistry() const;
|
||||
void setSourceRegistry(Homerun::AbstractSourceRegistry *registry);
|
||||
|
||||
int rowCount(const QModelIndex &parent = QModelIndex()) const; // reimp
|
||||
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const; // reimp
|
||||
|
||||
Q_INVOKABLE void setDataForRow(int row, const QByteArray &role, const QVariant &value);
|
||||
|
||||
Q_INVOKABLE void appendRow();
|
||||
|
||||
Q_INVOKABLE void removeRow(int row);
|
||||
|
||||
Q_INVOKABLE void moveRow(int from, int to);
|
||||
|
||||
/**
|
||||
* Reset configuration to default setup
|
||||
*/
|
||||
Q_INVOKABLE void resetConfig();
|
||||
|
||||
Q_SIGNALS:
|
||||
void configFileNameChanged(const QString &);
|
||||
void sourceRegistryChanged();
|
||||
|
||||
private:
|
||||
KSharedConfig::Ptr m_config;
|
||||
QList<Tab*> m_tabList;
|
||||
Homerun::AbstractSourceRegistry *m_sourceRegistry;
|
||||
|
||||
QStringList tabGroupList() const;
|
||||
|
||||
void writeGeneralTabsEntry();
|
||||
};
|
||||
|
||||
#endif /* TABMODEL_H */
|
|
@ -1,26 +0,0 @@
|
|||
[General]
|
||||
tabs=Tab0
|
||||
|
||||
[Tab0]
|
||||
name=Home
|
||||
icon=go-home
|
||||
sources=Source0,Source1,Source2,Source3,Source4,Source5
|
||||
|
||||
[Tab0][Source0]
|
||||
sourceId=RecentApps
|
||||
|
||||
[Tab0][Source1]
|
||||
sourceId=FilterableInstalledApps
|
||||
|
||||
[Tab0][Source2]
|
||||
sourceId=RecentDocuments
|
||||
|
||||
[Tab0][Source3]
|
||||
sourceId=CombinedPowerSession
|
||||
|
||||
[Tab0][Source4]
|
||||
sourceId=FavoriteApps
|
||||
|
||||
[Tab0][Source5]
|
||||
sourceId=Runner
|
||||
whitelist=bookmarks
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Reference in a new issue