parent
372eae0604
commit
34deeaf154
@ -1,13 +0,0 @@
|
||||
Upstream Authors:
|
||||
LXQt team: http://lxqt.org
|
||||
Razor team: http://razor-qt.org
|
||||
|
||||
Copyright:
|
||||
Copyright (c) 2010-2012 Razor team
|
||||
Copyright (c) 2012-2017 LXQt team
|
||||
|
||||
License: GPL-2 and LGPL-2.1+
|
||||
The full text of the licenses can be found in the 'LICENSE' file.
|
||||
|
||||
The lxqt-config-cursor component is based on the "qt-xcurtheme" project
|
||||
and is licensed under GPL 2, GPL 3, LGPL-2, LGPL-2.1 and WTFPL 2.
|
@ -1,65 +0,0 @@
|
||||
cmake_minimum_required(VERSION 3.0.2 FATAL_ERROR)
|
||||
|
||||
project(lxqt-config)
|
||||
set(LXQT_CONFIG_PROJECT "${PROJECT_NAME}")
|
||||
|
||||
option(UPDATE_TRANSLATIONS "Update source translation translations/*.ts files" OFF)
|
||||
option(WITH_INPUT "Build the 'lxqt-config-input'" ON)
|
||||
option(WITH_FILE_ASSOCIATIONS "Build the 'lxqt-config-file-associations'" ON)
|
||||
option(WITH_APPEARANCE "Build the 'lxqt-config-appearance'" ON)
|
||||
option(WITH_MONITOR "Build the 'lxqt-config-monitor'" ON)
|
||||
option(WITH_BRIGHTNESS "Build the 'lxqt-config-brightness'" ON)
|
||||
option(WITH_LOCALE "Build the 'lxqt-config-locale'" ON)
|
||||
|
||||
include(GNUInstallDirs)
|
||||
|
||||
set(CMAKE_INCLUDE_CURRENT_DIR ON)
|
||||
set(CMAKE_POSITION_INDEPENDENT_CODE ON)
|
||||
set(CMAKE_AUTOMOC ON)
|
||||
set(CMAKE_AUTOUIC ON)
|
||||
set(CMAKE_AUTORCC ON)
|
||||
|
||||
find_package(Qt5Widgets REQUIRED)
|
||||
find_package(Qt5DBus REQUIRED)
|
||||
find_package(Qt5Xml REQUIRED)
|
||||
find_package(Qt5Concurrent REQUIRED)
|
||||
find_package(Qt5X11Extras REQUIRED)
|
||||
find_package(Qt5LinguistTools REQUIRED)
|
||||
find_package(lxqt REQUIRED)
|
||||
|
||||
include(LXQtCompilerSettings NO_POLICY_SCOPE)
|
||||
|
||||
if(NOT CMAKE_BUILD_TYPE)
|
||||
set(CMAKE_BUILD_TYPE Release)
|
||||
endif()
|
||||
|
||||
# Patch Version
|
||||
set(LXQT_CONFIG_PATCH_VERSION 0)
|
||||
|
||||
set(LXQT_CONFIG_VERSION ${LXQT_MAJOR_VERSION}.${LXQT_MINOR_VERSION}.${LXQT_CONFIG_PATCH_VERSION})
|
||||
add_definitions("-DLXQT_CONFIG_VERSION=\"${LXQT_CONFIG_VERSION}\"")
|
||||
|
||||
include(LXQtTranslate)
|
||||
|
||||
add_subdirectory(src)
|
||||
if (WITH_INPUT OR WITH_APPEARANCE)
|
||||
add_subdirectory(liblxqt-config-cursor)
|
||||
endif()
|
||||
if (WITH_INPUT)
|
||||
add_subdirectory(lxqt-config-input)
|
||||
endif()
|
||||
if (WITH_FILE_ASSOCIATIONS)
|
||||
add_subdirectory(lxqt-config-file-associations)
|
||||
endif()
|
||||
if (WITH_APPEARANCE)
|
||||
add_subdirectory(lxqt-config-appearance)
|
||||
endif()
|
||||
if (WITH_MONITOR)
|
||||
add_subdirectory(lxqt-config-monitor)
|
||||
endif()
|
||||
if (WITH_BRIGHTNESS)
|
||||
add_subdirectory(lxqt-config-brightness)
|
||||
endif()
|
||||
if (WITH_LOCALE)
|
||||
add_subdirectory(lxqt-config-locale)
|
||||
endif()
|
@ -1,458 +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
|
@ -1,77 +0,0 @@
|
||||
# lxqt-config
|
||||
|
||||
## Overview
|
||||
|
||||
This repository is providing several tools involved in the configuration of both LXQt and the underlying operating system.
|
||||
|
||||
On the one hand it is featuring several GUI tools to configure topics like general appearance, pointer devices or screen resolutions.
|
||||
On the other hand there's a GUI "Configuration Center" which summarizes all those configuration tools as well as counterparts of other LXQt components or third-party applications.
|
||||
|
||||
### Configuration GUI tools
|
||||
|
||||
#### LXQt Appearance Configuration
|
||||
|
||||
Appearance of LXQt, that is topics like icon and LXQt theme or fonts.
|
||||
|
||||
![LXQt Appearance Configuration (lxqt-config-appearance)](lxqt-config-appearance.png)
|
||||
|
||||
Binary `lxqt-config-appearance`.
|
||||
|
||||
#### Brightness
|
||||
|
||||
Brightness settings of output devices.
|
||||
|
||||
Technically colors are adjusted to simulate varying brightness if the system LXQt is running on doesn't allow for adjusting the brightness itself.
|
||||
|
||||
Binary `lxqt-config-brightness`.
|
||||
|
||||
#### File Associations
|
||||
|
||||
Assigns MIME types to applications used to handle them. Not too user-friendly so far, see e. g. discussion in https://github.com/lxde/lxqt/issues/433.
|
||||
|
||||
Binary `lxqt-config-file-associations`.
|
||||
|
||||
#### Keyboard and Mouse
|
||||
|
||||
Configures hardware of pointer devices. Settings like repeat delay and interval of keyboards or acceleration of pointer devices.
|
||||
|
||||
Binary `lxqt-config-input`.
|
||||
|
||||
#### Locale
|
||||
|
||||
Locale used within LXQt sessions. Basically this GUI sets the well-known environment variables like `LANG` or `LC_*`. The settings apply to the session as a whole, that is to applications running within LXQt sessions but not belonging to LXQt, too.
|
||||
|
||||
Binary `lxqt-config-locale`.
|
||||
|
||||
#### Monitor Settings
|
||||
|
||||
Adjusts screen resolutions, positioning of screens and the likes.
|
||||
|
||||
Binary `lxqt-config-monitor`.
|
||||
|
||||
### Configuration Center
|
||||
|
||||
The "Configuration Center" (binary `lxqt-config`) is summarizing and providing various configuration GUIs.
|
||||
|
||||
![Configuration Center (lxqt-config)](lxqt-config.png)
|
||||
|
||||
First of all these are the ones belonging to repository lxqt-config described [above](https://github.com/lxde/lxqt-config#configuration-gui-tools). Next, it is hosting counterparts of several other LXQt components like "Desktop Notifications" of [lxqt-notificationd](https://github.com/lxde/lxqt-notificationd), "Shortcut Keys" of [lxqt-globalkeyshortcuts](https://github.com/lxde/lxqt-globalkeyshortcuts) or the tools provided by [lxqt-admin](https://github.com/lxde/lxqt-admin). Third-party applications can include their configuration tools in "Configuration Center", too. This applies e. g. to "Connman UI Setup" of [cmst](https://github.com/andrew-bibb/cmst) or "SDDM Configuration" of [sddm-config-editor](https://github.com/hagabaka/sddm-config-editor).
|
||||
|
||||
## Installation
|
||||
|
||||
### Compiling source code
|
||||
|
||||
Runtime dependencies are Xcursor, qtsvg, KScreen and [liblxqt](https://github.com/lxde/liblxqt).
|
||||
Additional build dependencies are CMake and optionally Git to pull latest VCS checkouts. The localization files were outsourced to repository [lxqt-l10n](https://github.com/lxde/lxqt-l10n) so the corresponding dependencies are needed, too. Please refer to this repository's `README.md` for further information.
|
||||
|
||||
Code configuration is handled by CMake. CMake variable `CMAKE_INSTALL_PREFIX` has to be set to `/usr` on most operating systems, depending on the way library paths are dealt with on 64bit systems variables like `CMAKE_INSTALL_LIBDIR` may have to be set as well.
|
||||
|
||||
To build run `make`, to install `make install` which accepts variable `DESTDIR` as usual.
|
||||
|
||||
### Binary packages
|
||||
|
||||
The library is provided by all major Linux distributions like Arch Linux, Debian (as of Debian stretch only), Fedora and openSUSE. Just use your package manager to search for string `lxqt-config`.
|
||||
|
||||
## Usage
|
||||
|
||||
Both the various configuration tools and the Configuration Center can be launched from the panel's main menu - Preferences - LXQt settings. Obviously the former can be launched from the latter, too.
|
@ -1,98 +0,0 @@
|
||||
project(lxqt-config-cursor)
|
||||
find_package(X11 REQUIRED)
|
||||
|
||||
find_package(XCB REQUIRED xcb)
|
||||
include_directories(${XCB_INCLUDE_DIRS})
|
||||
link_libraries(${XCB_LIBRARIES})
|
||||
|
||||
include_directories (
|
||||
${X11_INCLUDE_DIR}
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/xcr
|
||||
)
|
||||
|
||||
set(lxqt-config-cursor_HDRS
|
||||
thememodel.h
|
||||
previewwidget.h
|
||||
itemdelegate.h
|
||||
selectwnd.h
|
||||
warninglabel.h
|
||||
)
|
||||
|
||||
set(lxqt-config-cursor_SRCS
|
||||
crtheme.cpp
|
||||
selectwnd.cpp
|
||||
xcr/xcrimg.cpp
|
||||
xcr/xcrxcur.cpp
|
||||
xcr/xcrthemefx.cpp
|
||||
xcr/xcrtheme.cpp
|
||||
xcr/xcrthemexp.cpp
|
||||
cfgfile.cpp
|
||||
previewwidget.cpp
|
||||
itemdelegate.cpp
|
||||
thememodel.cpp
|
||||
warninglabel.cpp
|
||||
)
|
||||
|
||||
set(lxqt-config-cursor_UIS
|
||||
selectwnd.ui
|
||||
warninglabel.ui
|
||||
)
|
||||
|
||||
find_package(ZLIB REQUIRED)
|
||||
|
||||
# Translations **********************************
|
||||
lxqt_translate_ts(QM_FILES
|
||||
UPDATE_TRANSLATIONS
|
||||
${UPDATE_TRANSLATIONS}
|
||||
SOURCES
|
||||
${lxqt-config-cursor_HDRS}
|
||||
${lxqt-config-cursor_SRCS}
|
||||
${lxqt-config-cursor_UIS}
|
||||
INSTALL_DIR
|
||||
"${LXQT_TRANSLATIONS_DIR}/${PROJECT_NAME}"
|
||||
PULL_TRANSLATIONS
|
||||
${PULL_TRANSLATIONS}
|
||||
CLEAN_TRANSLATIONS
|
||||
${CLEAN_TRANSLATIONS}
|
||||
TRANSLATIONS_REPO
|
||||
${TRANSLATIONS_REPO}
|
||||
TRANSLATIONS_REFSPEC
|
||||
${TRANSLATIONS_REFSPEC}
|
||||
REPO_SUBDIR
|
||||
"lxqt-config/liblxqt-config-cursor"
|
||||
)
|
||||
|
||||
lxqt_app_translation_loader(lxqt-config-cursor_QM_LOADER ${PROJECT_NAME})
|
||||
|
||||
#************************************************
|
||||
|
||||
add_library(lxqt-config-cursor
|
||||
SHARED
|
||||
${lxqt-config-cursor_SRCS}
|
||||
${DESKTOP_FILES}
|
||||
${QM_FILES}
|
||||
${lxqt-config-cursor_QM_LOADER}
|
||||
)
|
||||
|
||||
target_link_libraries(lxqt-config-cursor
|
||||
Qt5::X11Extras
|
||||
Qt5::DBus
|
||||
Qt5::Xml
|
||||
${X11_X11_LIB}
|
||||
${X11_Xcursor_LIB}
|
||||
lxqt
|
||||
${ZLIB_LIBRARY}
|
||||
${X11_Xfixes_LIB}
|
||||
)
|
||||
# not needed probably ${X11_Xfixes_LIB})
|
||||
|
||||
install(TARGETS
|
||||
lxqt-config-cursor
|
||||
DESTINATION "${CMAKE_INSTALL_LIBDIR}/${LXQT_CONFIG_PROJECT}"
|
||||
COMPONENT Runtime
|
||||
)
|
||||
install(FILES
|
||||
${DESKTOP_FILES}
|
||||
DESTINATION "${CMAKE_INSTALL_DATAROOTDOR}/applications"
|
||||
COMPONENT Runtime
|
||||
)
|
@ -1,122 +0,0 @@
|
||||
/* coded by Ketmar // Vampire Avalon (psyc://ketmar.no-ip.org/~Ketmar)
|
||||
* (c)DWTFYW
|
||||
*
|
||||
* This program is free software. It comes without any warranty, to
|
||||
* the extent permitted by applicable law. You can redistribute it
|
||||
* and/or modify it under the terms of the Do What The Fuck You Want
|
||||
* To Public License, Version 2, as published by Sam Hocevar. See
|
||||
* http://sam.zoy.org/wtfpl/COPYING for more details.
|
||||
*/
|
||||
#include "cfgfile.h"
|
||||
|
||||
#include <QDir>
|
||||
#include <QFile>
|
||||
#include <QStringList>
|
||||
#include <QTextStream>
|
||||
|
||||
QMultiMap<QString, QString> loadCfgFile(const QString &fname, bool forceLoCase)
|
||||
{
|
||||
QMultiMap<QString, QString> res;
|
||||
QFile fl(fname);
|
||||
if (fl.open(QIODevice::ReadOnly))
|
||||
{
|
||||
QTextStream stream;
|
||||
stream.setDevice(&fl);
|
||||
stream.setCodec("UTF-8");
|
||||
QString curPath = "/";
|
||||
while (1)
|
||||
{
|
||||
QString s = stream.readLine();
|
||||
if (s.isNull()) break;
|
||||
s = s.trimmed();
|
||||
if (s.isEmpty() || s[0] == '#' || s[0] == ';') continue;
|
||||
if (s[0] == '[')
|
||||
{
|
||||
// new path
|
||||
int len = s.length()-1;
|
||||
if (s[len] == ']') len--;
|
||||
s = s.mid(1, len).simplified();
|
||||
s += '/';
|
||||
curPath = s;
|
||||
continue;
|
||||
}
|
||||
int eqp = s.indexOf('=');
|
||||
if (eqp < 0) continue; // invalid entry
|
||||
QString name = s.left(eqp).simplified();
|
||||
QString value = s.mid(eqp+1).simplified();
|
||||
if (name.isEmpty()) continue; // invalid entry
|
||||
name.prepend(curPath);
|
||||
if (forceLoCase) name = name.toLower();
|
||||
res.insert(name, value);
|
||||
}
|
||||
fl.close();
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
void fixXDefaults(const QString &themeName)
|
||||
{
|
||||
QStringList lst;
|
||||
{
|
||||
QFile fl(QDir::home().path()+"/.Xdefaults");
|
||||
if (fl.open(QIODevice::ReadOnly))
|
||||
{
|
||||
QTextStream stream;
|
||||
stream.setDevice(&fl);
|
||||
while (1)
|
||||
{
|
||||
QString s = stream.readLine();
|
||||
if (s.isNull())
|
||||
break;
|
||||
// if the line does not contain Xcursor?theme, save it to a list
|
||||
if (!(s.startsWith(QLatin1String("Xcursor")) && s.midRef(8).startsWith(QLatin1String("theme"))))
|
||||
lst << s;
|
||||
}
|
||||
fl.close();
|
||||
}
|
||||
}
|
||||
while (lst.size() > 0)
|
||||
{
|
||||
QString s(lst[lst.size()-1]);
|
||||
if (!s.trimmed().isEmpty()) break;
|
||||
lst.removeAt(lst.size()-1);
|
||||
}
|
||||
{
|
||||
//QByteArray ba(themeName.toUtf8());
|
||||
QFile fl(QDir::home().path()+"/.Xdefaults");
|
||||
if (fl.open(QIODevice::WriteOnly))
|
||||
{
|
||||
QTextStream stream;
|
||||
stream.setDevice(&fl);
|
||||
foreach (const QString &s, lst)
|
||||
{
|
||||
stream << s << "\n";
|
||||
}
|
||||
stream << "\nXcursor.theme: " << themeName << "\n";
|
||||
fl.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const QString findDefaultTheme()
|
||||
{
|
||||
QString res = "default";
|
||||
QFile fl(QDir::home().path()+"/.Xdefaults");
|
||||
if (fl.open(QIODevice::ReadOnly))
|
||||
{
|
||||
QTextStream stream;
|
||||
stream.setDevice(&fl);
|
||||
while (1)
|
||||
{
|
||||
QString s = stream.readLine();
|
||||
if (s.isNull()) break;
|
||||
if (!s.startsWith("Xcursor.theme:")) continue;
|
||||
s.remove(0, 14);
|
||||
s = s.trimmed();
|
||||
if (s.isEmpty()) s = "default";
|
||||
res = s;
|
||||
}
|
||||
fl.close();
|
||||
}
|
||||
return res;
|
||||
}
|
@ -1,20 +0,0 @@
|
||||
/* coded by Ketmar // Vampire Avalon (psyc://ketmar.no-ip.org/~Ketmar)
|
||||
* (c)DWTFYW
|
||||
*
|
||||
* This program is free software. It comes without any warranty, to
|
||||
* the extent permitted by applicable law. You can redistribute it
|
||||
* and/or modify it under the terms of the Do What The Fuck You Want
|
||||
* To Public License, Version 2, as published by Sam Hocevar. See
|
||||
* http://sam.zoy.org/wtfpl/COPYING for more details.
|
||||
*/
|
||||
#ifndef CFGFILE_H
|
||||
#define CFGFILE_H
|
||||
|
||||
#include <QMultiMap>
|
||||
#include <QString>
|
||||
|
||||
QMultiMap<QString, QString> loadCfgFile(const QString &fname, bool forceLoCase=false);
|
||||
void fixXDefaults(const QString &themeName);
|
||||
const QString findDefaultTheme();
|
||||
|
||||
#endif
|
@ -1,276 +0,0 @@
|
||||
/* Copyright © 2006-2007 Fredrik Höglund <fredrik@kde.org>
|
||||
* (c)GPL2 (c)GPL3
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public
|
||||
* License version 2 or at your option version 3 as published
|
||||
* by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
||||
* Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
/*
|
||||
* additional code: Ketmar // Vampire Avalon (psyc://ketmar.no-ip.org/~Ketmar)
|
||||
*/
|
||||
#include <QDebug>
|
||||
|
||||
#include "crtheme.h"
|
||||
|
||||
#include <QStyle>
|
||||
#include <QX11Info>
|
||||
|
||||
#include "cfgfile.h"
|
||||
|
||||
#include <X11/Xlib.h>
|
||||
#include <X11/Xcursor/Xcursor.h>
|
||||
#include <X11/extensions/Xfixes.h>
|
||||
|
||||
// Static variable holding alternative names for some cursors
|
||||
static QHash<QString, QString> alternatives;
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
XCursorThemeData::XCursorThemeData(const QDir &aDir)
|
||||
{
|
||||
mHidden = false;
|
||||
// parse configs, etc
|
||||
mPath = aDir.path();
|
||||
setName(aDir.dirName());
|
||||
if (aDir.exists("index.theme")) parseIndexFile();
|
||||
if (mDescription.isEmpty()) mDescription = "no description";
|
||||
if (mTitle.isEmpty()) mTitle = mName;
|
||||
}
|
||||
|
||||
void XCursorThemeData::parseIndexFile()
|
||||
{
|
||||
QMultiMap<QString, QString> cfg = loadCfgFile(mPath+"/index.theme", true);
|
||||
if (cfg.contains("icon theme/name")) mTitle = cfg.values("icon theme/name").at(0).trimmed();
|
||||
if (cfg.contains("icon theme/comment")) mDescription = cfg.values("icon theme/comment").at(0).trimmed();
|
||||
if (cfg.contains("icon theme/example")) mSample = cfg.values("icon theme/example").at(0).trimmed();
|
||||
if (cfg.contains("icon theme/hidden"))
|
||||
{
|
||||
QString hiddenValue = cfg.values("icon theme/hidden").at(0).toLower();
|
||||
mHidden = hiddenValue=="false" ? false : true;
|
||||
}
|
||||
if (cfg.contains("icon theme/inherits"))
|
||||
{
|
||||
QStringList i = cfg.values("icon theme/inherits"), res;
|
||||
for (int f = i.size()-1; f >= 0; f--) res << i.at(f).trimmed();
|
||||
}
|
||||
if (mDescription.startsWith("- Converted by")) mDescription.remove(0, 2);
|
||||
}
|
||||
|
||||
QString XCursorThemeData::findAlternative(const QString &name) const
|
||||
{
|
||||
if (alternatives.isEmpty())
|
||||
{
|
||||
alternatives.reserve(18);
|
||||
|
||||
// Qt uses non-standard names for some core cursors.
|
||||
// If Xcursor fails to load the cursor, Qt creates it with the correct name using the
|
||||
// core protcol instead (which in turn calls Xcursor). We emulate that process here.
|
||||
// Note that there's a core cursor called cross, but it's not the one Qt expects.
|
||||
alternatives.insert("cross", "crosshair");
|
||||
alternatives.insert("up_arrow", "center_ptr");
|
||||
alternatives.insert("wait", "watch");
|
||||
alternatives.insert("ibeam", "xterm");
|
||||
alternatives.insert("size_all", "fleur");
|
||||
alternatives.insert("pointing_hand", "hand2");
|
||||
|
||||
// Precomputed MD5 hashes for the hardcoded bitmap cursors in Qt and KDE.
|
||||
// Note that the MD5 hash for left_ptr_watch is for the KDE version of that cursor.
|
||||
alternatives.insert("size_ver", "00008160000006810000408080010102");
|
||||
alternatives.insert("size_hor", "028006030e0e7ebffc7f7070c0600140");
|
||||
alternatives.insert("size_bdiag", "c7088f0f3e6c8088236ef8e1e3e70000");
|
||||
alternatives.insert("size_fdiag", "fcf1c3c7cd4491d801f1e1c78f100000");
|
||||
alternatives.insert("whats_this", "d9ce0ab605698f320427677b458ad60b");
|
||||
alternatives.insert("split_h", "14fef782d02440884392942c11205230");
|
||||
alternatives.insert("split_v", "2870a09082c103050810ffdffffe0204");
|
||||
alternatives.insert("forbidden", "03b6e0fcb3499374a867c041f52298f0");
|
||||
alternatives.insert("left_ptr_watch", "3ecb610c1bf2410f44200f48c40d3599");
|
||||
alternatives.insert("hand2", "e29285e634086352946a0e7090d73106");
|
||||
alternatives.insert("openhand", "9141b49c8149039304290b508d208c40");
|
||||
alternatives.insert("closedhand", "05e88622050804100c20044008402080");
|
||||
}
|
||||
|
||||
return alternatives.value(name, QString());
|
||||
}
|
||||
|
||||
QPixmap XCursorThemeData::icon() const
|
||||
{
|
||||
if (mIcon.isNull()) mIcon = createIcon();
|
||||
return mIcon;
|
||||
}
|
||||
|
||||
QImage XCursorThemeData::autoCropImage(const QImage &image) const
|
||||
{
|
||||
// Compute an autocrop rectangle for the image
|
||||
QRect r(image.rect().bottomRight(), image.rect().topLeft());
|
||||
const quint32 *pixels = reinterpret_cast<const quint32*>(image.bits());
|
||||
for (int y = 0; y < image.height(); ++y)
|
||||
{
|
||||
for (int x = 0; x < image.width(); ++x)
|
||||
{
|
||||
if (*(pixels++))
|
||||
{
|
||||
if (x < r.left()) r.setLeft(x);
|
||||
if (x > r.right()) r.setRight(x);
|
||||
if (y < r.top()) r.setTop(y);
|
||||
if (y > r.bottom()) r.setBottom(y);
|
||||
}
|
||||
}
|
||||
}
|
||||
// Normalize the rectangle
|
||||
return image.copy(r.normalized());
|
||||
}
|
||||
|
||||
static int nominalCursorSize(int iconSize)
|
||||
{
|
||||
for (int i = 512; i > 8; i /= 2)
|
||||
{
|
||||
if (i < iconSize) return i;
|
||||
if ((i*0.75) < iconSize) return int(i*0.75);
|
||||
}
|
||||
return 8;
|
||||
}
|
||||
|
||||
QPixmap XCursorThemeData::createIcon() const
|
||||
{
|
||||
int iconSize = QApplication::style()->pixelMetric(QStyle::PM_LargeIconSize);
|
||||
int cursorSize = nominalCursorSize(iconSize);
|
||||
QSize size = QSize(iconSize, iconSize);
|
||||
|
||||
QPixmap pixmap;
|
||||
QImage image = loadImage(sample(), cursorSize);
|
||||
if (image.isNull() && sample() != "left_ptr") image = loadImage("left_ptr", cursorSize);
|
||||
if (!image.isNull())
|
||||
{
|
||||
// Scale the image if it's larger than the preferred icon size
|
||||
if (image.width() > size.width() || image.height() > size.height())
|
||||
{
|
||||
image = image.scaled(size, Qt::KeepAspectRatio, Qt::SmoothTransformation);
|
||||
pixmap = QPixmap::fromImage(image);
|
||||
}
|
||||
}
|
||||
return pixmap;
|
||||
}
|
||||
|
||||
XcursorImage *XCursorThemeData::xcLoadImage(const QString &image, int size) const
|
||||
{
|
||||
QByteArray cursorName = QFile::encodeName(image);
|
||||
QByteArray themeName = QFile::encodeName(name());
|
||||
return XcursorLibraryLoadImage(cursorName, themeName, size);
|
||||
}
|
||||
|
||||
XcursorImages *XCursorThemeData::xcLoadImages(const QString &image, int size) const
|
||||
{
|
||||
QByteArray cursorName = QFile::encodeName(image);
|
||||
QByteArray themeName = QFile::encodeName(name());
|
||||
return XcursorLibraryLoadImages(cursorName, themeName, size);
|
||||
}
|
||||
|
||||
unsigned long XCursorThemeData::loadCursorHandle(const QString &name, int size) const
|
||||
{
|
||||
if (size == -1) size = XcursorGetDefaultSize(QX11Info::display());
|
||||
// Load the cursor images
|
||||
XcursorImages *images = xcLoadImages(name, size);
|
||||
if (!images) images = xcLoadImages(findAlternative(name), size);
|
||||
// Fall back to a legacy cursor
|
||||
//if (!images) return LegacyTheme::loadCursor(name);
|
||||
if (!images) return 0;
|
||||
// Create the cursor
|
||||
unsigned long handle = (unsigned long)XcursorImagesLoadCursor(QX11Info::display(), images);
|
||||
XcursorImagesDestroy(images);
|
||||
//setCursorName(cursor, name);
|
||||
return handle;
|
||||
}
|
||||
|
||||
QImage XCursorThemeData::loadImage(const QString &name, int size) const
|
||||
{
|
||||
if (size == -1) size = XcursorGetDefaultSize(QX11Info::display());
|
||||
// Load the image
|
||||
XcursorImage *xcimage = xcLoadImage(name, size);
|
||||
if (!xcimage) xcimage = xcLoadImage(findAlternative(name), size);
|
||||
// Fall back to a legacy cursor
|
||||
//if (!xcimage) return LegacyTheme::loadImage(name);
|
||||
if (!xcimage) return QImage();
|
||||
// Convert the XcursorImage to a QImage, and auto-crop it
|
||||
QImage image((uchar *)xcimage->pixels, xcimage->width, xcimage->height, QImage::Format_ARGB32_Premultiplied);
|
||||
image = autoCropImage(image);
|
||||
XcursorImageDestroy(xcimage);
|
||||
return image;
|
||||
}
|
||||
|
||||
bool XCursorThemeData::isWritable() const
|
||||
{
|
||||
QFileInfo fi(path());
|
||||
return fi.isWritable();
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
bool haveXfixes()
|
||||
{
|
||||
bool result = false;
|
||||
int event_base, error_base;
|
||||
if (XFixesQueryExtension(QX11Info::display(), &event_base, &error_base))
|
||||
{
|
||||
int major, minor;
|
||||
XFixesQueryVersion(QX11Info::display(), &major, &minor);
|
||||
result = (major >= 2);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
bool applyTheme(const XCursorThemeData &theme)
|
||||
{
|
||||
// Require the Xcursor version that shipped with X11R6.9 or greater, since
|
||||
// in previous versions the Xfixes code wasn't enabled due to a bug in the
|
||||
// build system (freedesktop bug #975).
|
||||
if (!haveXfixes()) return false;
|
||||
|
||||
QByteArray themeName = QFile::encodeName(theme.name());
|
||||
|
||||
// Set up the proper launch environment for newly started apps
|
||||
//k8:!!!:KToolInvocation::klauncher()->setLaunchEnv("XCURSOR_THEME", themeName);
|
||||
|
||||
// Update the Xcursor X resources
|
||||
//k8:!!!:runRdb(0);
|
||||
|
||||
// Reload the standard cursors
|
||||
QStringList names;
|
||||
// Qt cursors
|
||||
names << "left_ptr" << "up_arrow" << "cross" << "wait"
|
||||
<< "left_ptr_watch" << "ibeam" << "size_ver" << "size_hor"
|
||||
<< "size_bdiag" << "size_fdiag" << "size_all" << "split_v"
|
||||
<< "split_h" << "pointing_hand" << "openhand"
|
||||
<< "closedhand" << "forbidden" << "whats_this";
|
||||
// X core cursors
|
||||
names << "X_cursor" << "right_ptr" << "hand1"
|
||||
<< "hand2" << "watch" << "xterm"
|
||||
<< "crosshair" << "left_ptr_watch" << "center_ptr"
|
||||
<< "sb_h_double_arrow" << "sb_v_double_arrow" << "fleur"
|
||||
<< "top_left_corner" << "top_side" << "top_right_corner"
|
||||
<< "right_side" << "bottom_right_corner" << "bottom_side"
|
||||
<< "bottom_left_corner" << "left_side" << "question_arrow"
|
||||
<< "pirate";
|
||||
|
||||
//QX11Info x11Info;
|
||||
foreach (const QString &name, names)
|
||||
{
|
||||
Cursor cursor = (Cursor)theme.loadCursorHandle(name);
|
||||
XFixesChangeCursorByName(QX11Info::display(), cursor, QFile::encodeName(name));
|
||||
// FIXME: do we need to free the cursor?
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
QString getCurrentTheme()
|
||||
{
|
||||
return XcursorGetTheme(QX11Info::display());
|
||||
}
|
@ -1,119 +0,0 @@
|
||||
/* Copyright © 2006-2007 Fredrik Höglund <fredrik@kde.org>
|
||||
* (c)GPL2 (c)GPL3
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public
|
||||
* License version 2 or at your option version 3 as published
|
||||
* by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
||||
* Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
/*
|
||||
* additional code: Ketmar // Vampire Avalon (psyc://ketmar.no-ip.org/~Ketmar)
|
||||
*/
|
||||
#ifndef CRTHEME_H
|
||||
#define CRTHEME_H
|
||||
|
||||
#include <QApplication>
|
||||
#include <QCursor>
|
||||
#include <QDir>
|
||||
#include <QFile>
|
||||
#include <QIcon>
|
||||
#include <QImage>
|
||||
#include <QString>
|
||||
#include <QStringList>
|
||||
|
||||
#include <xcb/xcb.h>
|
||||
#include <xcb/xproto.h>
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// X11 is SHIT!
|
||||
struct _XcursorImage;
|
||||
struct _XcursorImages;
|
||||
|
||||
typedef _XcursorImage XcursorImage;
|
||||
typedef _XcursorImages XcursorImages;
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
class XCursorThemeData
|
||||
{
|
||||
public:
|
||||
enum ItemDataRole {
|
||||
// Note: use printf "0x%08X\n" $(($RANDOM*$RANDOM))
|
||||
// to define additional roles.
|
||||
DisplayDetailRole = 0x24A3DAF8
|
||||
};
|
||||
|
||||
XCursorThemeData(const QDir &aDir);
|
||||
|
||||
const QString &name() const { return mName; }
|
||||
const QString &title() const { return mTitle; }
|
||||
const QString &description() const { return mDescription; }
|
||||
const QString &sample() const { return mSample; }
|
||||
const QString &path() const { return mPath; }
|
||||
bool isHidden() const { return mHidden; }
|
||||
QPixmap icon() const;
|
||||
const QStringList &inherits() const { return mInherits; }
|
||||
|
||||
inline void setName(const QString &name)
|
||||
{
|
||||
mName = name;
|
||||
mHash = qHash(name);
|
||||
}
|
||||
|
||||
bool isWritable() const;
|
||||
|
||||
/// Hash value for the internal name
|
||||
uint hash() const { return mHash; }
|
||||
|
||||
/// Loads the cursor @p name, with the nominal size @p size.
|
||||
/// If the theme doesn't have the cursor @p name, it should return
|
||||
/// the default cursor from the active theme instead.
|
||||
unsigned long loadCursorHandle(const QString &name, int size=-1) const;
|
||||
|
||||
/// Loads the cursor image @p name, with the nominal size @p size.
|
||||
/// The image should be autocropped to the smallest possible size.
|
||||
/// If the theme doesn't have the cursor @p name, it should return a null image.
|
||||
QImage loadImage(const QString &name, int size=-1) const;
|
||||
|
||||
XcursorImage *xcLoadImage(const QString &image, int size=-1) const;
|
||||
XcursorImages *xcLoadImages(const QString &image, int size=-1) const;
|
||||
|
||||
QString findAlternative(const QString &name) const;
|
||||
|
||||
protected:
|
||||
void parseIndexFile();
|
||||
|
||||
/// Creates the icon returned by @ref icon().
|
||||
QPixmap createIcon() const;
|
||||
|
||||
/// Convenience function for cropping an image.
|
||||
QImage autoCropImage(const QImage &image) const;
|
||||
|
||||
protected:
|
||||
QString mName;
|
||||
QString mTitle;
|
||||
QString mDescription;
|
||||
QString mPath;
|
||||
QString mSample;
|
||||
mutable QPixmap mIcon;
|
||||
bool mHidden;
|
||||
uint mHash;
|
||||
QStringList mInherits;
|
||||
};
|
||||
|
||||
bool haveXfixes();
|
||||
bool applyTheme(const XCursorThemeData &theme);
|
||||
|
||||
QString getCurrentTheme();
|
||||
|
||||
#endif
|
@ -1,141 +0,0 @@
|
||||
/* Copyright © 2006-2007 Fredrik Höglund <fredrik@kde.org>
|
||||
* (c)GPL2 (c)GPL3
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public
|
||||
* License version 2 or at your option version 3 as published
|
||||
* by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
||||
* Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
/*
|
||||
* additional code: Ketmar // Vampire Avalon (psyc://ketmar.no-ip.org/~Ketmar)
|
||||
*/
|
||||
#include "itemdelegate.h"
|
||||
#include "crtheme.h"
|
||||
|
||||
#include <QApplication>
|
||||
#include <QModelIndex>
|
||||
#include <QPainter>
|
||||
|
||||
|
||||
namespace {
|
||||
const int decorationMargin = 8;
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
ItemDelegate::ItemDelegate(QObject *parent) : QAbstractItemDelegate(parent)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
ItemDelegate::~ItemDelegate()
|
||||
{
|
||||
}
|
||||
|
||||
QString ItemDelegate::firstLine(const QModelIndex &index) const
|
||||
{
|
||||
if (index.isValid()) return index.model()->data(index, Qt::DisplayRole).toString();
|
||||
return QString();
|
||||
}
|
||||
|
||||
QString ItemDelegate::secondLine(const QModelIndex &index) const
|
||||
{
|
||||
if (index.isValid()) return index.model()->data(index, XCursorThemeData::DisplayDetailRole).toString();
|
||||
return QString();
|
||||
}
|
||||
|
||||
QPixmap ItemDelegate::decoration(const QModelIndex &index) const
|
||||
{
|
||||
if (index.isValid()) return qvariant_cast<QPixmap>(index.model()->data(index, Qt::DecorationRole));
|
||||
return QPixmap();
|
||||
}
|
||||
|
||||
QSize ItemDelegate::sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const
|
||||
{
|
||||
if (!index.isValid()) return QSize();
|
||||
|
||||
QFont normalfont = option.font;
|
||||
QFont boldfont = normalfont;
|
||||
boldfont.setBold(true);
|
||||
// Extract the items we want to measure
|
||||
QString firstRow = firstLine(index);
|
||||
QString secondRow = secondLine(index);
|
||||
// Compute the height
|
||||
QFontMetrics fm1(boldfont);
|
||||
QFontMetrics fm2(normalfont);
|
||||
int height = fm1.lineSpacing() + fm2.lineSpacing();
|
||||
height = qMax(height, option.decorationSize.height());
|
||||
// Compute the text width
|
||||
int width = fm1.width(firstRow);
|
||||
width = qMax(width, fm2.width(secondRow));
|
||||
// Add decoration width + margin
|
||||
width += option.decorationSize.width()+decorationMargin;
|
||||
return QSize(width, height+16);
|
||||
}
|
||||
|
||||
QPalette::ColorRole ItemDelegate::foregroundRole(const QStyleOptionViewItem &option, const QModelIndex &index) const
|
||||
{
|
||||
Q_UNUSED(index)
|
||||
if (option.state & QStyle::State_Selected) return QPalette::HighlightedText;
|
||||
return QPalette::Text;
|
||||
}
|
||||
|
||||
void ItemDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
|
||||
{
|
||||
if (!index.isValid()) return;
|
||||
painter->save();
|
||||
|
||||
QFont normalfont = option.font;
|
||||
QFont boldfont = normalfont;
|
||||
boldfont.setBold(true);
|
||||
|
||||
QString firstRow = firstLine(index);
|
||||
QString secondRow = secondLine(index);
|
||||
QPixmap pixmap = decoration(index);
|
||||
|
||||
QColor textcol = option.palette.color(foregroundRole(option, index));
|
||||
|
||||
// Draw the background
|
||||
QStyleOptionViewItem opt = option;
|
||||
QStyle *style = opt.widget ? opt.widget->style() : QApplication::style();
|
||||
style->drawPrimitive(QStyle::PE_PanelItemViewItem, &opt, painter, opt.widget);
|
||||
|
||||
// Draw the icon
|
||||
int x = option.rect.left()+(option.decorationSize.width()-pixmap.width()+decorationMargin)/2;
|
||||
int y = option.rect.top()+(option.rect.height()-pixmap.height())/2;
|
||||
QRect pixmapRect = QStyle::visualRect(option.direction, option.rect, QRect(x, y, pixmap.width(), pixmap.height()));
|
||||
painter->drawPixmap(pixmapRect.x(), pixmapRect.y(), pixmap);
|
||||
|
||||
// Draw the text
|
||||
QFontMetrics fm1(boldfont);
|
||||
QFontMetrics fm2(normalfont);
|
||||
|
||||
int textAreaHeight = fm1.lineSpacing()+fm2.lineSpacing();
|
||||
|
||||
x = option.rect.left()+option.decorationSize.width()+decorationMargin;
|
||||
int y1 = option.rect.top()+(option.rect.height()-textAreaHeight)/2;
|
||||
int y2 = y1+fm1.lineSpacing();
|
||||
QRect firstRowRect = QStyle::visualRect(option.direction, option.rect, QRect(x, y1, fm1.width(firstRow), fm1.lineSpacing()));
|
||||
QRect secondRowRect = QStyle::visualRect(option.direction, option.rect, QRect(x, y2, fm2.width(secondRow), fm2.lineSpacing()));
|
||||
painter->setPen(textcol);
|
||||
|
||||
// First line
|
||||
painter->setFont(boldfont);
|
||||
painter->drawText(firstRowRect, Qt::AlignCenter, firstRow);
|
||||
|
||||
// Second line
|
||||
painter->setFont(normalfont);
|
||||
painter->drawText(secondRowRect, Qt::AlignCenter, secondRow);
|
||||
|
||||
painter->restore();
|
||||
}
|
@ -1,48 +0,0 @@
|
||||
/* Copyright © 2006-2007 Fredrik Höglund <fredrik@kde.org>
|
||||
* (c)GPL2 (c)GPL3
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public
|
||||
* License version 2 or at your option version 3 as published
|
||||
* by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
||||
* Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
/*
|
||||
* additional code: Ketmar // Vampire Avalon (psyc://ketmar.no-ip.org/~Ketmar)
|
||||
*/
|
||||
#ifndef ITEMDELEGATE_H
|
||||
#define ITEMDELEGATE_H
|
||||
|
||||
#include <QAbstractItemDelegate>
|
||||
|
||||
class QPainter;
|
||||
|
||||
|
||||
class ItemDelegate : public QAbstractItemDelegate
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
ItemDelegate(QObject *parent = 0);
|
||||
~ItemDelegate();
|
||||
|
||||
QSize sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const;
|
||||
void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const;
|
||||
|
||||
private:
|
||||
QString firstLine(const QModelIndex &index) const;
|
||||
QString secondLine(const QModelIndex &index) const;
|
||||
QPixmap decoration(const QModelIndex &index) const;
|
||||
QPalette::ColorRole foregroundRole(const QStyleOptionViewItem &option, const QModelIndex &index) const;
|
||||
};
|
||||
|
||||
#endif
|
@ -1,44 +0,0 @@
|
||||
/* coded by Ketmar // Vampire Avalon (psyc://ketmar.no-ip.org/~Ketmar)
|
||||
* (c)DWTFYW
|
||||
*
|
||||
* This program is free software. It comes without any warranty, to
|
||||
* the extent permitted by applicable law. You can redistribute it
|
||||
* and/or modify it under the terms of the Do What The Fuck You Want
|
||||
* To Public License, Version 2, as published by Sam Hocevar. See
|
||||
* http://sam.zoy.org/wtfpl/COPYING for more details.
|
||||
*/
|
||||
//#include <QtCore>
|
||||
#include <QDebug>
|
||||
|
||||
#include <XdgIcon>
|
||||
#include <LXQt/Settings>
|
||||
#include "main.h"
|
||||
#include "lxqttranslate.h"
|
||||
|
||||
#include <LXQt/Application>
|
||||
#include <QFile>
|
||||
#include <QImage>
|
||||
#include <QString>
|
||||
#include <QStringList>
|
||||
#include <QTextCodec>
|
||||
#include <QTextStream>
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
int main (int argc, char *argv[])
|
||||
{
|
||||
//QTextCodec::setCodecForCStrings(QTextCodec::codecForName("koi8-r"));
|
||||
//QTextCodec::setCodecForLocale(QTextCodec::codecForName("koi8-r"));
|
||||
|
||||
LXQt::Application app(argc, argv);
|
||||
app.setAttribute(Qt::AA_UseHighDpiPixmaps, true);
|
||||
|
||||
TRANSLATE_APP;
|
||||
|
||||
//qDebug() << findDefaultTheme() << getCurrentTheme();
|
||||
|
||||
SelectWnd *sw = new SelectWnd;
|
||||
sw->show();
|
||||
sw->setCurrent();
|
||||
return app.exec();
|
||||
}
|
@ -1,19 +0,0 @@
|
||||
/* coded by Ketmar // Vampire Avalon (psyc://ketmar.no-ip.org/~Ketmar)
|
||||
* (c)DWTFYW
|
||||
*
|
||||
* This program is free software. It comes without any warranty, to
|
||||
* the extent permitted by applicable law. You can redistribute it
|
||||
* and/or modify it under the terms of the Do What The Fuck You Want
|
||||
* To Public License, Version 2, as published by Sam Hocevar. See
|
||||
* http://sam.zoy.org/wtfpl/COPYING for more details.
|
||||
*/
|
||||
#ifndef MAIN_H
|
||||
#define MAIN_H
|
||||
|
||||
|
||||
#include "cfgfile.h"
|
||||
#include "crtheme.h"
|
||||
#include "selectwnd.h"
|
||||
|
||||
|
||||
#endif
|
@ -1,39 +0,0 @@
|
||||
.TH lxqt-config-cursor "1" "September 2012" "LXQt\ 0.7.0" "LXQt\ Cursor settings"
|
||||
.SH NAME
|
||||
lxqt-config-cursor \- Application of \fBLXQt\fR: the faster and lighter Qt Desktop Environment
|
||||
.SH SYNOPSIS
|
||||
.B lxqt-config-cursor
|
||||
.br
|
||||
.SH DESCRIPTION
|
||||
This is a simple GUI cursor theme configuration (at the moment) for the LXQt desktop environment.
|
||||
Also can manage theme installation for it (locally for/per user only).
|
||||
.P
|
||||
\fBLXQt\fR is an advanced, easy-to-use, and fast desktop environment based on Qt
|
||||
technologies, ships several core desktop components, all of which are optional:
|
||||
.P
|
||||
* Panel
|
||||
* Desktop
|
||||
* Application launcher
|
||||
* Settings center \fI(related to this)\fR
|
||||
* Session handler
|
||||
* Polkit handler
|
||||
* SSH password access
|
||||
* Display manager handler
|
||||
.P
|
||||
These components perform similar actions to those available in other desktop
|
||||
environments, and their name is self-descriptive. They are usually not launched
|
||||
by hand but automatically, when choosing a \fBLXQt\-qt\fR session in the Display
|
||||
Manager.
|
||||
.P
|
||||
.SH "REPORTING BUGS"
|
||||
Report bugs to https://github.com/lxde/lxqt/issues
|
||||
.SH "SEE ALSO"
|
||||
\fBLXQt\fR has been tailored for users who value simplicity, speed, and
|
||||
an intuitive interface, also intended for less powerful machines. See also:
|
||||
.\" any module must refers to session app, for more info on start it
|
||||
.P
|
||||
\fBlxqt-config(1)\fR LXQt application for performing settings on many applications
|
||||
.P
|
||||
.SH AUTHOR
|
||||
This manual page was created by \fBPICCORO Lenz McKAY\fR \fI<mckaygerhard@gmail.com>\fR
|
||||
for \fBLXQt\fR project and VENENUX GNU/Linux but can be used by others.
|
@ -1,221 +0,0 @@
|
||||
/* Copyright © 2003-2007 Fredrik Höglund <fredrik@kde.org>
|
||||
* (c)GPL2 (c)GPL3
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public
|
||||
* License version 2 as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
||||
* Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
/*
|
||||
* additional code: Ketmar // Vampire Avalon (psyc://ketmar.no-ip.org/~Ketmar)
|
||||
*/
|
||||
#include <QDebug>
|
||||
|
||||
#include <QPainter>
|
||||
#include <QMouseEvent>
|
||||
|
||||
#include "previewwidget.h"
|
||||
|
||||
#include "crtheme.h"
|
||||
|
||||
#include <X11/Xlib.h>
|
||||
#include <X11/Xcursor/Xcursor.h>
|
||||
|
||||
#include <QX11Info>
|
||||
#include <QWindow>
|
||||
|
||||
namespace {
|
||||
// Preview cursors
|
||||
const char *const cursorNames[] = {
|
||||
"left_ptr",
|
||||
"left_ptr_watch",
|
||||
"wait",
|
||||
"pointing_hand",
|
||||
"whats_this",
|
||||
"ibeam",
|
||||
"size_all",
|
||||
"size_fdiag",
|
||||
"cross",
|
||||
"split_h",
|
||||
"size_ver",
|
||||
"size_hor",
|
||||
"size_bdiag",
|
||||
"split_v",
|
||||
};
|
||||
|
||||
const int numCursors = 9; // The number of cursors from the above list to be previewed
|
||||
const int previewSize = 24; // The nominal cursor size to be used in the preview widget
|
||||
const int cursorSpacing = 20; // Spacing between preview cursors
|
||||
const int widgetMinWidth = 10; // The minimum width of the preview widget
|
||||
const int widgetMinHeight = 48; // The minimum height of the preview widget
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
class PreviewCursor
|
||||
{
|
||||
public:
|
||||
PreviewCursor (const XCursorThemeData &theme, const QString &name);
|
||||
~PreviewCursor () {}
|
||||
|
||||
const QPixmap &pixmap () const { return mPixmap; }
|
||||
int width () const { return mPixmap.width(); }
|
||||
int height () const { return mPixmap.height(); }
|
||||
inline QRect rect () const;
|
||||
void setPosition (const QPoint &p) { mPos = p; }
|
||||
void setPosition (int x, int y) { mPos = QPoint(x, y); }
|
||||
QPoint position () const { return mPos; }
|
||||
operator const xcb_cursor_t& () const { return mCursorHandle; }
|
||||
operator const QPixmap& () const { return pixmap(); }
|
||||
|
||||
private:
|
||||
QPixmap mPixmap;
|
||||
xcb_cursor_t mCursorHandle;
|
||||
QPoint mPos;
|
||||
};
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
PreviewCursor::PreviewCursor(const XCursorThemeData &theme, const QString &name)
|
||||
{
|
||||
// Create the preview pixmap
|
||||
QImage image = theme.loadImage(name, previewSize);
|
||||
if (image.isNull()) return;
|
||||
int maxSize = previewSize*2;
|
||||
if (image.height() > maxSize || image.width() > maxSize)
|
||||
image = image.scaled(maxSize, maxSize, Qt::KeepAspectRatio, Qt::SmoothTransformation);
|
||||
mPixmap = QPixmap::fromImage(image);
|
||||
// load the cursor
|
||||
mCursorHandle = theme.loadCursorHandle(name, previewSize);
|
||||
}
|
||||
|
||||
QRect PreviewCursor::rect() const
|
||||
{
|
||||
return QRect(mPos, mPixmap.size()).adjusted(-(cursorSpacing/2), -(cursorSpacing/2), cursorSpacing/2, cursorSpacing/2);
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
PreviewWidget::PreviewWidget(QWidget *parent) : QWidget(parent)
|
||||
{
|
||||
setMouseTracking(true);
|
||||
mCurrent = NULL;
|
||||
}
|
||||
|
||||
PreviewWidget::~PreviewWidget()
|
||||
{
|
||||
qDeleteAll(mList);
|
||||
mList.clear();
|
||||
}
|
||||
|
||||
|
||||
// Since Qt5, wrapping a Cursor handle with QCursor is no longer supported.
|
||||
// So we have to do it ourselves. I really hate Qt 5!
|
||||
void PreviewWidget::setCursorHandle(xcb_cursor_t cursorHandle)
|
||||
{
|
||||
WId wid = nativeParentWidget()->windowHandle()->winId();
|
||||
xcb_change_window_attributes(QX11Info::connection(), wid, XCB_CW_CURSOR, &cursorHandle);
|
||||
xcb_flush(QX11Info::connection());
|
||||
}
|
||||
|
||||
|
||||
QSize PreviewWidget::sizeHint() const
|
||||
{
|
||||
int totalWidth = 0, maxHeight = 0;
|
||||
foreach (const PreviewCursor *c, mList)
|
||||
{
|
||||
totalWidth += c->width();
|
||||
maxHeight = qMax(c->height(), maxHeight);
|
||||
}
|
||||
totalWidth += (mList.count()-1)*cursorSpacing;
|
||||
maxHeight = qMax(maxHeight, widgetMinHeight);
|
||||
return QSize(qMax(totalWidth, widgetMinWidth), qMax(height(), maxHeight));
|
||||
}
|
||||
|
||||
void PreviewWidget::layoutItems()
|
||||
{
|
||||
if (!mList.isEmpty())
|
||||
{
|
||||
QSize size = sizeHint();
|
||||
int cursorWidth = size.width()/mList.count();
|
||||
int nextX = (width()-size.width())/2;
|
||||
foreach (PreviewCursor *c, mList)
|
||||
{
|
||||
c->setPosition(nextX+(cursorWidth-c->width())/2, (height()-c->height())/2);
|
||||
nextX += cursorWidth;
|
||||
}
|
||||
}
|
||||
mNeedLayout = false;
|
||||
}
|
||||
|
||||
void PreviewWidget::setTheme(const XCursorThemeData &theme)
|
||||
{
|
||||
qDeleteAll(mList);
|
||||
mList.clear();
|
||||
for (int i = 0; i < numCursors; ++i) mList << new PreviewCursor(theme, cursorNames[i]);
|
||||
mNeedLayout = true;
|
||||
updateGeometry();
|
||||
mCurrent = NULL;
|
||||
update();
|
||||
}
|
||||
|
||||
|
||||
void PreviewWidget::clearTheme()
|
||||
{
|
||||
qDeleteAll(mList);
|
||||
mList.clear();
|
||||
mCurrent = NULL;
|
||||
update();
|
||||
}
|
||||
|
||||
void PreviewWidget::paintEvent(QPaintEvent *)
|
||||
{
|
||||
QPainter p(this);
|
||||
if (mNeedLayout) layoutItems();
|
||||
foreach (const PreviewCursor *c, mList)
|
||||
{
|
||||
if (c->pixmap().isNull()) continue;
|
||||
p.drawPixmap(c->position(), *c);
|
||||
}
|
||||
}
|
||||
|
||||
void PreviewWidget::mouseMoveEvent(QMouseEvent *e)
|
||||
{
|
||||
if (mNeedLayout) layoutItems();
|
||||
foreach (const PreviewCursor *c, mList)
|
||||
{
|
||||
if (c->rect().contains(e->pos()))
|
||||
{
|
||||
if (c != mCurrent)
|
||||
{
|
||||
// NOTE: we have to set the Qt cursor value to something other than Qt::ArrowCursor
|
||||
// Otherwise, though we set the xcursor handle to the underlying window, Qt still
|
||||
// thinks that the current cursor is Qt::ArrowCursor and will not restore the cursor
|
||||
// later when we call setCursor(Qt::ArrowCursor). So, we set it to BlankCursor to
|
||||
// cheat Qt so it knows that the current cursor is not Qt::ArrowCursor.
|
||||
// This is a dirty hack, but without this, Qt cannot restore Qt::ArrowCursor later.
|
||||
setCursor(Qt::BlankCursor);
|
||||
setCursorHandle(*c);
|
||||
mCurrent = c;
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
setCursor(Qt::ArrowCursor);
|
||||
mCurrent = NULL;
|
||||
}
|
||||
|
||||
|
||||
void PreviewWidget::resizeEvent(QResizeEvent *)
|
||||
{
|
||||
if (!mList.isEmpty()) mNeedLayout = true;
|
||||
}
|
@ -1,60 +0,0 @@
|
||||
/* Copyright © 2003-2007 Fredrik Höglund <fredrik@kde.org>
|
||||
* (c)GPL2
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public
|
||||
* License version 2 as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
||||
* Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
/*
|
||||
* additional code: Ketmar // Vampire Avalon (psyc://ketmar.no-ip.org/~Ketmar)
|
||||
*/
|
||||
#ifndef PREVIEWWIDGET_H
|
||||
#define PREVIEWWIDGET_H
|
||||
|
||||
#include <QWidget>
|
||||
|
||||
#include <xcb/xcb.h>
|
||||
#include <xcb/xproto.h>
|
||||
|
||||
class XCursorThemeData;
|
||||
class PreviewCursor;
|
||||
|
||||
class PreviewWidget : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
PreviewWidget (QWidget *parent=0);
|
||||
~PreviewWidget ();
|
||||
|
||||
void setTheme (const XCursorThemeData &theme);
|
||||
void clearTheme ();
|
||||
|
||||
QSize sizeHint () const;
|
||||
|
||||
void setCursorHandle(xcb_cursor_t cursorHandle);
|
||||
|
||||
protected:
|
||||
void paintEvent (QPaintEvent *e);
|
||||
void mouseMoveEvent(QMouseEvent *e);
|
||||
void resizeEvent (QResizeEvent *e);
|
||||
|
||||
private:
|
||||
void layoutItems ();
|
||||
|
||||
QList<PreviewCursor *> mList;
|
||||
const PreviewCursor *mCurrent;
|
||||
bool mNeedLayout;
|
||||
};
|
||||
|
||||
#endif
|
@ -1,233 +0,0 @@
|
||||
/* coded by Ketmar // Vampire Avalon (psyc://ketmar.no-ip.org/~Ketmar)
|
||||
* (c)DWTFYW
|
||||
*
|
||||
* This program is free software. It comes without any warranty, to
|
||||
* the extent permitted by applicable law. You can redistribute it
|
||||
* and/or modify it under the terms of the Do What The Fuck You Want
|
||||
* To Public License, Version 2, as published by Sam Hocevar. See
|
||||
* http://sam.zoy.org/wtfpl/COPYING for more details.
|
||||
*/
|
||||
|
||||
// 2014-04-10 modified by Hong Jen Yee (PCMan) for integration with lxqt-config-input
|
||||
|
||||
#include <QDebug>
|
||||
|
||||
#include "selectwnd.h"
|
||||
#include "ui_selectwnd.h"
|
||||
|
||||
#include <QKeyEvent>
|
||||
#include <QMessageBox>
|
||||
#include <QTimer>
|
||||
#include <QWidget>
|
||||
#include <QPushButton>
|
||||
#include <QToolTip>
|
||||
|
||||
#include "cfgfile.h"
|
||||
#include "crtheme.h"
|
||||
#include "thememodel.h"
|
||||
#include "itemdelegate.h"
|
||||
|
||||
#include "xcrimg.h"
|
||||
#include "xcrxcur.h"
|
||||
#include "xcrtheme.h"
|
||||
|
||||
#include <LXQt/Settings>
|
||||
#include <XdgIcon>
|
||||
#include <QTextStream>
|
||||
#include <QProcess>
|
||||
|
||||
#define HOME_ICON_DIR QDir::homePath() + "/.icons"
|
||||
|
||||
SelectWnd::SelectWnd(LXQt::Settings* settings, QWidget *parent)
|
||||
: QWidget(parent),
|
||||
mSettings(settings),
|
||||
ui(new Ui::SelectWnd)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
ui->warningLabel->hide();
|
||||
|
||||
mModel = new XCursorThemeModel(this);
|
||||
|
||||
int size = style()->pixelMetric(QStyle::PM_LargeIconSize);
|
||||
ui->lbThemes->setModel(mModel);
|
||||
ui->lbThemes->setItemDelegate(new ItemDelegate(this));
|
||||
ui->lbThemes->setIconSize(QSize(size, size));
|
||||
ui->lbThemes->setSelectionMode(QAbstractItemView::SingleSelection);
|
||||
|
||||
// Make sure we find out about selection changes
|
||||
connect(ui->lbThemes->selectionModel(), SIGNAL(currentChanged(const QModelIndex &, const QModelIndex &)),
|
||||
SLOT(currentChanged(const QModelIndex &, const QModelIndex &)));
|
||||
// display/hide warning label
|
||||
connect(mModel, SIGNAL(modelReset()),
|
||||
this, SLOT(handleWarning()));
|
||||
connect(mModel, SIGNAL(rowsInserted(const QModelIndex&, int, int)),
|
||||
this, SLOT(handleWarning()));
|
||||
connect(mModel, SIGNAL(rowsRemoved(const QModelIndex&, int, int)),
|
||||
this, SLOT(handleWarning()));
|
||||
|
||||
connect(ui->warningLabel, SIGNAL(showDirInfo()),
|
||||
this, SLOT(showDirInfo()));
|
||||
|
||||
// Disable the install button if we can't install new themes to ~/.icons,
|
||||
// or Xcursor isn't set up to look for cursor themes there
|
||||
ui->btInstall->setEnabled(mModel->searchPaths().contains(HOME_ICON_DIR) && iconsIsWritable());
|
||||
// TODO/FIXME: btInstall functionality
|
||||
ui->btInstall->hide();
|
||||
ui->btRemove->hide();
|
||||
|
||||
//QTimer::singleShot(0, this, SLOT(setCurrent()));
|
||||
|
||||
handleWarning();
|
||||
}
|
||||
|
||||
|
||||
SelectWnd::~SelectWnd()
|
||||
{
|
||||
delete ui;
|
||||
}
|
||||
|
||||
void SelectWnd::setCurrent()
|
||||
{
|
||||
ui->lbThemes->selectionModel()->clear();
|
||||
|
||||
QString ct = getCurrentTheme();
|
||||
mAppliedIndex = mModel->defaultIndex();
|
||||
|
||||
if (!ct.isEmpty()) mAppliedIndex = mModel->findIndex(ct);
|
||||
else mAppliedIndex = mModel->defaultIndex();
|
||||
|
||||
if (mAppliedIndex.isValid())
|
||||
{
|
||||
const XCursorThemeData *theme = mModel->theme(mAppliedIndex);
|
||||
// Select the current theme
|
||||
selectRow(mAppliedIndex);
|
||||
ui->lbThemes->scrollTo(mAppliedIndex, QListView::PositionAtCenter);
|
||||
// Update the preview widget as well
|
||||
if (theme) ui->preview->setTheme(*theme);// else ui->preview->clearTheme();
|
||||
}
|
||||
}
|
||||
|
||||
bool SelectWnd::iconsIsWritable() const
|
||||
{
|
||||
const QFileInfo icons = QFileInfo(HOME_ICON_DIR);
|
||||
const QFileInfo home = QFileInfo(QDir::homePath());
|
||||
return ((icons.exists() && icons.isDir() && icons.isWritable()) || (!icons.exists() && home.isWritable()));
|
||||
}
|
||||
|
||||
/*
|
||||
void SelectWnd::keyPressEvent(QKeyEvent *e)
|
||||
{
|
||||
if (e->key() == Qt::Key_Escape) close();
|
||||
}
|
||||
*/
|
||||
|
||||
void SelectWnd::selectRow(int row) const
|
||||
{
|
||||
// Create a selection that stretches across all columns
|
||||
QModelIndex from = mModel->index(row, 0);
|
||||
QModelIndex to = mModel->index(row, mModel->columnCount()-1);
|
||||
QItemSelection selection(from, to);
|
||||
ui->lbThemes->selectionModel()->select(selection, QItemSelectionModel::Select);
|
||||
ui->lbThemes->selectionModel()->setCurrentIndex(mAppliedIndex, QItemSelectionModel::NoUpdate);
|
||||
}
|
||||
|
||||
void SelectWnd::currentChanged(const QModelIndex ¤t, const QModelIndex &previous)
|
||||
{
|
||||
Q_UNUSED(previous)
|
||||
if (current.isValid()) {
|
||||
const XCursorThemeData *theme = mModel->theme(current);
|
||||
if (theme) {
|
||||
ui->preview->setTheme(*theme);
|
||||
ui->btRemove->setEnabled(theme->isWritable());
|
||||
} else {
|
||||
ui->preview->clearTheme();
|
||||
}
|
||||
|
||||
// directly apply the current settings
|
||||
applyCurrent();
|
||||
} else {
|
||||
ui->preview->clearTheme();
|
||||
}
|
||||
//emit changed(mAppliedIndex != current);
|
||||
}
|
||||
|
||||
void SelectWnd::on_btInstall_clicked()
|
||||
{
|
||||
qDebug() << "'install' clicked";
|
||||
}
|
||||
|
||||
void SelectWnd::applyCurrent()
|
||||
{
|
||||
//qDebug() << "'set' clicked";
|
||||
const XCursorThemeData *theme = mModel->theme(ui->lbThemes->currentIndex());
|
||||
if (!theme) return;
|
||||
applyTheme(*theme);
|
||||
fixXDefaults(theme->name());
|
||||
|
||||
// call xrdb to merge the new settings in ~/.Xdefaults
|
||||
// FIXME: need to check if we're running in X?
|
||||
QProcess xrdb;
|
||||
xrdb.start("xrdb -merge " + QDir::home().path() + "/.Xdefaults");
|
||||
xrdb.waitForFinished();
|
||||
|
||||
// old razor-qt and lxqt versions use $XCURSOR_THEME environment variable
|
||||
// for this, but it's less flexible and more problematic. Let's deprecate its use.
|
||||
mSettings->beginGroup("Environment");
|
||||
mSettings->remove("XCURSOR_THEME"); // ensure that we're not using XCURSOR_THEME
|
||||
mSettings->endGroup();
|
||||
// save to Mouse/cursor_theme instead
|
||||
mSettings->beginGroup("Mouse");
|
||||
mSettings->setValue("cursor_theme", theme->name());
|
||||
mSettings->endGroup();
|
||||
|
||||
// The XCURSOR_THEME environment varialbe does not work sometimes.
|
||||
// Besides, XDefaults values are not used by Qt.
|
||||
// So, let's write the new theme name to ~/.icons/default/index.theme.
|
||||
// This is the most reliable way.
|
||||
// QSettings will encode the group name "Icon Theme" to "Icon%20Theme" and there is no way to turn it off.
|
||||
// So let's not use it here. :-(
|
||||
QString dirPath = HOME_ICON_DIR + "/default";
|
||||
QDir().mkpath(dirPath); // ensure the existence of the ~/.icons/default dir
|
||||
QFile indexTheme(dirPath + "/index.theme");
|
||||
if(indexTheme.open(QIODevice::WriteOnly|QIODevice::Truncate))
|
||||
{
|
||||
QTextStream(&indexTheme) <<
|
||||
"# Written by lxqt-config-appearance\n" <<
|
||||
"[Icon Theme]\n" <<
|
||||
"Name=Default\n" <<
|
||||
"Comment=Default cursor theme\n" <<
|
||||
"Inherits=" << theme->name() << "\n";
|
||||
indexTheme.close();
|
||||
}
|
||||
}
|
||||
|
||||
void SelectWnd::on_btRemove_clicked()
|
||||
{
|
||||
qDebug() << "'remove' clicked";
|
||||
const XCursorThemeData *theme = mModel->theme(ui->lbThemes->currentIndex());
|
||||
if (!theme) return;
|
||||
QString ct = getCurrentTheme();
|
||||
if (ct == theme->name())
|
||||
{
|
||||
QMessageBox::warning(this, tr("XCurTheme error"),
|
||||
tr("You can't remove active theme!"), QMessageBox::Ok, QMessageBox::Ok);
|
||||
return;
|
||||
}
|
||||
QDir d(theme->path());
|
||||
ui->preview->clearTheme();
|
||||
mModel->removeTheme(ui->lbThemes->currentIndex());
|
||||
removeXCursorTheme(d);
|
||||
}
|
||||
|
||||
void SelectWnd::handleWarning()
|
||||
{
|
||||
bool empty = mModel->rowCount();
|
||||
ui->warningLabel->setVisible(!empty);
|
||||
ui->preview->setVisible(empty);
|
||||
ui->infoLabel->setVisible(empty);
|
||||
}
|
||||
|
||||
void SelectWnd::showDirInfo()
|
||||
{
|
||||
QToolTip::showText(mapToGlobal(ui->warningLabel->buttonPos()), mModel->searchPaths().join("\n"));
|
||||
}
|
@ -1,65 +0,0 @@
|
||||
/* coded by Ketmar // Vampire Avalon (psyc://ketmar.no-ip.org/~Ketmar)
|
||||
* (c)DWTFYW
|
||||
*
|
||||
* This program is free software. It comes without any warranty, to
|
||||
* the extent permitted by applicable law. You can redistribute it
|
||||
* and/or modify it under the terms of the Do What The Fuck You Want
|
||||
* To Public License, Version 2, as published by Sam Hocevar. See
|
||||
* http://sam.zoy.org/wtfpl/COPYING for more details.
|
||||
*/
|
||||
|
||||
// 2014-04-10 modified by Hong Jen Yee (PCMan) for integration with lxqt-config-input
|
||||
|
||||
#ifndef SELECTWND_H
|
||||
#define SELECTWND_H
|
||||
|
||||
#include <QObject>
|
||||
#include <QWidget>
|
||||
#include <QPersistentModelIndex>
|
||||
#include <lxqtglobals.h>
|
||||
|
||||
namespace LXQt {
|
||||
class Settings;
|
||||
}
|
||||
|
||||
namespace Ui {
|
||||
class SelectWnd;
|
||||
}
|
||||
|
||||
class XCursorThemeModel;
|
||||
|
||||
class LXQT_API SelectWnd : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
SelectWnd (LXQt::Settings* settings, QWidget *parent=0);
|
||||
~SelectWnd ();
|
||||
|
||||
public slots:
|
||||
void setCurrent ();
|
||||
|
||||
protected:
|
||||
// void keyPressEvent (QKeyEvent *e);
|
||||
|
||||
private:
|
||||
bool iconsIsWritable () const;
|
||||
void selectRow (int) const;
|
||||
void selectRow (const QModelIndex &index) const { selectRow(index.row()); }
|
||||
void applyCurrent ();
|
||||
|
||||
private slots:
|
||||
void currentChanged (const QModelIndex ¤t, const QModelIndex &previous);
|
||||
void on_btInstall_clicked ();
|
||||
void on_btRemove_clicked ();
|
||||
void handleWarning();
|
||||
void showDirInfo();
|
||||
|
||||
private:
|
||||
XCursorThemeModel *mModel;
|
||||
QPersistentModelIndex mAppliedIndex;
|
||||
LXQt::Settings* mSettings;
|
||||
Ui::SelectWnd *ui;
|
||||
};
|
||||
|
||||
#endif
|
@ -1,114 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>SelectWnd</class>
|
||||
<widget class="QWidget" name="SelectWnd">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>384</width>
|
||||
<height>353</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>LXQt Mouse Theme Configuration</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<item row="0" column="0" colspan="4">
|
||||
<widget class="QLabel" name="infoLabel">
|
||||
<property name="text">
|
||||
<string>Select the cursor theme you want to use (hover preview to test cursor). <b>LXQt session needs restart after this change</b>:</string>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0" colspan="4">
|
||||
<widget class="WarningLabel" name="warningLabel" native="true"/>
|
||||
</item>
|
||||
<item row="2" column="0" colspan="4">
|
||||
<widget class="PreviewWidget" name="preview" native="true">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>48</height>
|
||||
</size>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0" colspan="4">
|
||||
<widget class="QListView" name="lbThemes">
|
||||
<property name="editTriggers">
|
||||
<set>QAbstractItemView::NoEditTriggers</set>
|
||||
</property>
|
||||
<property name="showDropIndicator" stdset="0">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="alternatingRowColors">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="verticalScrollMode">
|
||||
<enum>QAbstractItemView::ScrollPerPixel</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="0">
|
||||
<spacer>
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>174</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item row="4" column="1">
|
||||
<widget class="QPushButton" name="btInstall">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>&Install New Theme...</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="2">
|
||||
<widget class="QPushButton" name="btRemove">
|
||||
<property name="text">
|
||||
<string>&Remove Theme</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<customwidgets>
|
||||
<customwidget>
|
||||
<class>PreviewWidget</class>
|
||||
<extends>QWidget</extends>
|
||||
<header>previewwidget.h</header>
|
||||
</customwidget>
|
||||
<customwidget>
|
||||
<class>WarningLabel</class>
|
||||
<extends>QWidget</extends>
|
||||
<header>warninglabel.h</header>
|
||||
<container>1</container>
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<tabstops>
|
||||
<tabstop>lbThemes</tabstop>
|
||||
<tabstop>btInstall</tabstop>
|
||||
<tabstop>btRemove</tabstop>
|
||||
</tabstops>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
@ -1,328 +0,0 @@
|
||||
/* Copyright © 2005-2007 Fredrik Höglund <fredrik@kde.org>
|
||||
* (c)GPL2 (c)GPL3
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public
|
||||
* License version 2 or at your option version 3 as published
|
||||
* by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
||||
* Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
/*
|
||||
* additional code: Ketmar // Vampire Avalon (psyc://ketmar.no-ip.org/~Ketmar)
|
||||
*/
|
||||
#include <QDebug>
|
||||
|
||||
#include "thememodel.h"
|
||||
|
||||
#include <QDir>
|
||||
|
||||
#include "crtheme.h"
|
||||
#include "cfgfile.h"
|
||||
|
||||
#include <X11/Xlib.h>
|
||||
#include <X11/Xcursor/Xcursor.h>
|
||||
|
||||
|
||||
//#define DUMP_FOUND_THEMES
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
XCursorThemeModel::XCursorThemeModel (QObject *parent) : QAbstractTableModel(parent)
|
||||
{
|
||||
insertThemes();
|
||||
}
|
||||
|
||||
|
||||
XCursorThemeModel::~XCursorThemeModel()
|
||||
{
|
||||
qDeleteAll(mList);
|
||||
mList.clear();
|
||||
}
|
||||
|
||||
|
||||
QVariant XCursorThemeModel::headerData(int section, Qt::Orientation orientation, int role) const
|
||||
{
|
||||
// Only provide text for the headers
|
||||
if (role != Qt::DisplayRole) return QVariant();
|
||||
// Horizontal header labels
|
||||
if (orientation == Qt::Horizontal)
|
||||
{
|
||||
switch (section)
|
||||
{
|
||||
case NameColumn: return tr("Name");
|
||||
case DescColumn: return tr("Description");
|
||||
default: return QVariant();
|
||||
}
|
||||
}
|
||||
// Numbered vertical header lables
|
||||
return QString(section);
|
||||
}
|
||||
|
||||
QVariant XCursorThemeModel::data(const QModelIndex &index, int role) const
|
||||
{
|
||||
if (!index.isValid() || index.row() < 0 || index.row() >= mList.count()) return QVariant();
|
||||
const XCursorThemeData *theme = mList.at(index.row());
|
||||
// Text label
|
||||
if (role == Qt::DisplayRole)
|
||||
{
|
||||
switch (index.column())
|
||||
{
|
||||
case NameColumn: return theme->title();
|
||||
case DescColumn: return theme->description();
|
||||
default: return QVariant();
|
||||
}
|
||||
}
|
||||
// Description for the first name column
|
||||
if (role == XCursorThemeData::DisplayDetailRole && index.column() == NameColumn) return theme->description();
|
||||
// Icon for the name column
|
||||
if (role == Qt::DecorationRole && index.column() == NameColumn) return theme->icon();
|
||||
//
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
void XCursorThemeModel::sort(int column, Qt::SortOrder order)
|
||||
{
|
||||
Q_UNUSED(column);
|
||||
Q_UNUSED(order);
|
||||
// Sorting of the model isn't implemented, as the KCM currently uses
|
||||
// a sorting proxy model.
|
||||
}
|
||||
|
||||
const XCursorThemeData *XCursorThemeModel::theme(const QModelIndex &index)
|
||||
{
|
||||
if (!index.isValid()) return NULL;
|
||||
if (index.row() < 0 || index.row() >= mList.count()) return NULL;
|
||||
return mList.at(index.row());
|
||||
}
|
||||
|
||||
QModelIndex XCursorThemeModel::findIndex(const QString &name)
|
||||
{
|
||||
uint hash = qHash(name);
|
||||
for (int i = 0; i < mList.count(); ++i)
|
||||
{
|
||||
const XCursorThemeData *theme = mList.at(i);
|
||||
if (theme->hash() == hash) return index(i, 0);
|
||||
}
|
||||
return QModelIndex();
|
||||
}
|
||||
|
||||
QModelIndex XCursorThemeModel::defaultIndex()
|
||||
{
|
||||
return findIndex(mDefaultName);
|
||||
}
|
||||
|
||||
const QStringList XCursorThemeModel::searchPaths()
|
||||
{
|
||||
if (!mBaseDirs.isEmpty()) return mBaseDirs;
|
||||
// Get the search path from Xcursor
|
||||
QString path = XcursorLibraryPath();
|
||||
// Separate the paths
|
||||
mBaseDirs = path.split(':', QString::SkipEmptyParts);
|
||||
// Remove duplicates
|
||||
QMutableStringListIterator i(mBaseDirs);
|
||||
while (i.hasNext())
|
||||
{
|
||||
const QString path = i.next();
|
||||
QMutableStringListIterator j(i);
|
||||
while (j.hasNext()) if (j.next() == path) j.remove();
|
||||
}
|
||||
// Expand all occurrences of ~/ to the home dir
|
||||
mBaseDirs.replaceInStrings(QRegExp("^~\\/"), QDir::home().path() + '/');
|
||||
return mBaseDirs;
|
||||
}
|
||||
|
||||
bool XCursorThemeModel::hasTheme(const QString &name) const
|
||||
{
|
||||
const uint hash = qHash(name);
|
||||
foreach (const XCursorThemeData *theme, mList) if (theme->hash() == hash) return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool XCursorThemeModel::isCursorTheme(const QString &theme, const int depth)
|
||||
{
|
||||
// Prevent infinite recursion
|
||||
if (depth > 10) return false;
|
||||
// Search each icon theme directory for 'theme'
|
||||
foreach (const QString &baseDir, searchPaths())
|
||||
{
|
||||
QDir dir(baseDir);
|
||||
if (!dir.exists() || !dir.cd(theme)) continue;
|
||||
// If there's a cursors subdir, we'll assume this is a cursor theme
|
||||
if (dir.exists("cursors")) return true;
|
||||
// If the theme doesn't have an index.theme file, it can't inherit any themes
|
||||
if (!dir.exists("index.theme")) continue;
|
||||
// Open the index.theme file, so we can get the list of inherited themes
|
||||
QMultiMap<QString, QString> cfg = loadCfgFile(dir.path()+"/index.theme", true);
|
||||
QStringList inherits = cfg.values("icon theme/inherits");
|
||||
// Recurse through the list of inherited themes, to check if one of them is a cursor theme
|
||||
// note that items are reversed
|
||||
for (int f = inherits.size()-1; f >= 0; --f)
|
||||
{
|
||||
QString inh = inherits.at(f);
|
||||
// Avoid possible DoS
|
||||
if (inh == theme) continue;
|
||||
if (isCursorTheme(inh, depth+1)) return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool XCursorThemeModel::handleDefault(const QDir &themeDir)
|
||||
{
|
||||
QFileInfo info(themeDir.path());
|
||||
// If "default" is a symlink
|
||||
if (info.isSymLink())
|
||||
{
|
||||
QFileInfo target(info.symLinkTarget());
|
||||
if (target.exists() && (target.isDir() || target.isSymLink())) mDefaultName = target.fileName();
|
||||
return true;
|
||||
}
|
||||
// If there's no cursors subdir, or if it's empty
|
||||
if (!themeDir.exists("cursors") ||
|
||||
QDir(themeDir.path() + "/cursors").entryList(QDir::Files |
|
||||
QDir::NoDotAndDotDot).isEmpty())
|
||||
{
|
||||
if (themeDir.exists("index.theme"))
|
||||
{
|
||||
XCursorThemeData theme(themeDir);
|
||||
if (!theme.inherits().isEmpty()) mDefaultName = theme.inherits().at(0);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
mDefaultName = QLatin1String("default");
|
||||
return false;
|
||||
}
|
||||
|
||||
//#define DUMP_FOUND_THEMES
|
||||
void XCursorThemeModel::processThemeDir(const QDir &themeDir)
|
||||
{
|
||||
#ifdef DUMP_FOUND_THEMES
|
||||
qDebug() << "looking at:" << themeDir.path();
|
||||
#endif
|
||||
bool haveCursors = themeDir.exists("cursors");
|
||||
// Special case handling of "default", since it's usually either a
|
||||
// symlink to another theme, or an empty theme that inherits another theme
|
||||
if (mDefaultName.isNull() && themeDir.dirName() == "default")
|
||||
{
|
||||
if (handleDefault(themeDir)) return;
|
||||
}
|
||||
// If the directory doesn't have a cursors subdir and lacks an
|
||||
// index.theme file it can't be a cursor theme.
|
||||
if (!themeDir.exists("index.theme") && !haveCursors)
|
||||
{
|
||||
//qDebug() << "IS NOT THEME" << themeDir;
|
||||
return;
|
||||
}
|
||||
// Create a cursor theme object for the theme dir
|
||||
XCursorThemeData *theme = new XCursorThemeData(themeDir);
|
||||
// Skip this theme if it's hidden
|
||||
#ifdef DUMP_FOUND_THEMES
|
||||
qDebug() <<
|
||||
" theme name:" << theme->name() <<
|
||||
"\n theme title:" << theme->title() <<
|
||||
"\n theme desc:" << theme->description() <<
|
||||
"\n theme sample:" << theme->sample() <<
|
||||
"\n theme inherits:" << theme->inherits();
|
||||
#endif
|
||||
if (theme->isHidden())
|
||||
{
|
||||
//qDebug() << "HIDDEN THEME" << theme->name() << themeDir;
|
||||
delete theme;
|
||||
return;
|
||||
}
|
||||
// If there's no cursors subdirectory we'll do a recursive scan
|
||||
// to check if the theme inherits a theme with one
|
||||
if (!haveCursors)
|
||||
{
|
||||
bool foundCursorTheme = false;
|
||||
foreach (const QString &name, theme->inherits())
|
||||
{
|
||||
if ((foundCursorTheme = isCursorTheme(name))) break;
|
||||
}
|
||||
if (!foundCursorTheme)
|
||||
{
|
||||
delete theme;
|
||||
return;
|
||||
}
|
||||
}
|
||||
// Append the theme to the list
|
||||
mList.append(theme);
|
||||
}
|
||||
|
||||
void XCursorThemeModel::insertThemes()
|
||||
{
|
||||
// Scan each base dir for Xcursor themes and add them to the list
|
||||
foreach (const QString &baseDir, searchPaths())
|
||||
{
|
||||
QDir dir(baseDir);
|
||||
//qDebug() << "TOPLEVEL" << baseDir;
|
||||
if (!dir.exists()) continue;
|
||||
//qDebug() << " continue passed";
|
||||
// Process each subdir in the directory
|
||||
foreach (const QString &name, dir.entryList(QDir::AllDirs |
|
||||
QDir::NoDotAndDotDot | QDir::Readable | QDir::Executable))
|
||||
{
|
||||
//qDebug() << " SUBDIR" << name;
|
||||
// Don't process the theme if a theme with the same name already exists
|
||||
// in the list. Xcursor will pick the first one it finds in that case,
|
||||
// and since we use the same search order, the one Xcursor picks should
|
||||
// be the one already in the list
|
||||
if (hasTheme(name))
|
||||
{
|
||||
qDebug() << "duplicate theme:" << dir.path()+name;
|
||||
}
|
||||
if (!dir.cd(name))
|
||||
{
|
||||
qDebug() << "can't cd:" << dir.path()+name;
|
||||
continue;
|
||||
}
|
||||
processThemeDir(dir);
|
||||
dir.cdUp(); // Return to the base dir
|
||||
}
|
||||
}
|
||||
// The theme Xcursor will end up using if no theme is configured
|
||||
//if (mDefaultName.isNull() || !hasTheme(mDefaultName)) mDefaultName = legacy->name();
|
||||
}
|
||||
|
||||
bool XCursorThemeModel::addTheme(const QDir &dir)
|
||||
{
|
||||
XCursorThemeData *theme = new XCursorThemeData(dir);
|
||||
// Don't add the theme to the list if it's hidden
|
||||
if (theme->isHidden())
|
||||
{
|
||||
delete theme;
|
||||
return false;
|
||||
}
|
||||
// If an item with the same name already exists in the list,
|
||||
// we'll remove it before inserting the new one.
|
||||
for (int i = 0; i < mList.count(); ++i)
|
||||
{
|
||||
if (mList.at(i)->hash() == theme->hash())
|
||||
{
|
||||
removeTheme(index(i, 0));
|
||||
break;
|
||||
}
|
||||
}
|
||||
// Append the theme to the list
|
||||
beginInsertRows(QModelIndex(), rowCount(), rowCount());
|
||||
mList.append(theme);
|
||||
endInsertRows();
|
||||
return true;
|
||||
}
|
||||
|
||||
void XCursorThemeModel::removeTheme(const QModelIndex &index)
|
||||
{
|
||||
if (!index.isValid()) return;
|
||||
beginRemoveRows(QModelIndex(), index.row(), index.row());
|
||||
delete mList.takeAt(index.row());
|
||||
endRemoveRows();
|
||||
}
|
@ -1,116 +0,0 @@
|
||||
/* Copyright © 2005-2007 Fredrik Höglund <fredrik@kde.org>
|
||||
* (c)GPL2 (c)GPL3
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public
|
||||
* License version 2 or at your option version 3 as published
|
||||
* by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
||||
* Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
/*
|
||||
* additional code: Ketmar // Vampire Avalon (psyc://ketmar.no-ip.org/~Ketmar)
|
||||
*/
|
||||
#ifndef THEMEMODEL_H
|
||||
#define THEMEMODEL_H
|
||||
|
||||
#include <QAbstractTableModel>
|
||||
#include <QStringList>
|
||||
|
||||
class QDir;
|
||||
class XCursorThemeData;
|
||||
|
||||
|
||||
// The two TableView/TreeView columns provided by the model
|
||||
enum Columns { NameColumn = 0, DescColumn };
|
||||
|
||||
|
||||
/**
|
||||
* The XCursorThemeModel class provides a model for all locally installed
|
||||
* Xcursor themes, and the KDE/Qt legacy bitmap theme.
|
||||
*
|
||||
* This class automatically scans the locations in the file system from
|
||||
* which Xcursor loads cursors, and creates an internal list of all
|
||||
* available cursor themes.
|
||||
*
|
||||
* The model provides this theme list to item views in the form of a list
|
||||
* of rows with two columns; the first column has the theme's descriptive
|
||||
* name and its sample cursor as its icon, and the second column contains
|
||||
* the theme's description.
|
||||
*
|
||||
* Additional Xcursor themes can be added to a model after it's been
|
||||
* created, by calling addTheme(), which takes QDir as a parameter,
|
||||
* with the themes location. The intention is for this function to be
|
||||
* called when a new Xcursor theme has been installed, after the model
|
||||
* was instantiated.
|
||||
*
|
||||
* The KDE legacy theme is a read-only entry, with the descriptive name
|
||||
* "KDE Classic", and the internal name "#kde_legacy#".
|
||||
*
|
||||
* Calling defaultIndex() will return the index of the theme Xcursor
|
||||
* will use if the user hasn't explicitly configured a cursor theme.
|
||||
*/
|
||||
class XCursorThemeModel : public QAbstractTableModel
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
XCursorThemeModel (QObject *parent = 0);
|
||||
~XCursorThemeModel ();
|
||||
|
||||
inline int columnCount (const QModelIndex &parent = QModelIndex()) const;
|
||||
inline int rowCount (const QModelIndex &parent = QModelIndex()) const;
|
||||
QVariant headerData (int section, Qt::Orientation orientation, int role) const;
|
||||
QVariant data (const QModelIndex &index, int role) const;
|
||||
void sort (int column, Qt::SortOrder order = Qt::AscendingOrder);
|
||||
|
||||
/// Returns the CursorTheme at @p index.
|
||||
const XCursorThemeData *theme (const QModelIndex &index);
|
||||
|
||||
/// Returns the index for the CursorTheme with the internal name @p name,
|
||||
/// or an invalid index if no matching theme can be found.
|
||||
QModelIndex findIndex (const QString &name);
|
||||
|
||||
/// Returns the index for the default theme.
|
||||
QModelIndex defaultIndex ();
|
||||
|
||||
/// Adds the theme in @p dir, and returns @a true if successful or @a false otherwise.
|
||||
bool addTheme (const QDir &dir);
|
||||
void removeTheme (const QModelIndex &index);
|
||||
|
||||
/// Returns the list of base dirs Xcursor looks for themes in.
|
||||
const QStringList searchPaths ();
|
||||
|
||||
private:
|
||||
bool handleDefault (const QDir &dir);
|
||||
void processThemeDir (const QDir &dir);
|
||||
void insertThemes ();
|
||||
bool hasTheme (const QString &theme) const;
|
||||
bool isCursorTheme (const QString &theme, const int depth = 0);
|
||||
|
||||
private:
|
||||
QList<XCursorThemeData *>mList;
|
||||
QStringList mBaseDirs;
|
||||
QString mDefaultName;
|
||||
};
|
||||
|
||||
int XCursorThemeModel::rowCount (const QModelIndex &) const
|
||||
{
|
||||
return mList.count();
|
||||
}
|
||||
|
||||
|
||||
int XCursorThemeModel::columnCount (const QModelIndex &) const
|
||||
{
|
||||
return 2;
|
||||
}
|
||||
|
||||
#endif
|
@ -1,43 +0,0 @@
|
||||
/* BEGIN_COMMON_COPYRIGHT_HEADER
|
||||
* (c)LGPL2+
|
||||
*
|
||||
* LXQt - a lightweight, Qt based, desktop toolset
|
||||
* http://razor-qt.org
|
||||
*
|
||||
* Copyright: 2010-2012 Razor team
|
||||
* Authors:
|
||||
* Petr Vanek <petr@scribus.info>
|
||||
*
|
||||
* This program or 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
|
||||
*
|
||||
* END_COMMON_COPYRIGHT_HEADER */
|
||||
|
||||
#include <XdgIcon>
|
||||
|
||||
#include "warninglabel.h"
|
||||
|
||||
|
||||
|
||||
WarningLabel::WarningLabel(QWidget *parent)
|
||||
: QWidget(parent)
|
||||
{
|
||||
setupUi(this);
|
||||
|
||||
iconLabel->setPixmap(XdgIcon::fromTheme("dialog-warning").pixmap(64, 64));
|
||||
|
||||
connect(showDirButton, SIGNAL(pressed()),
|
||||
this, SIGNAL(showDirInfo()));
|
||||
}
|
@ -1,47 +0,0 @@
|
||||
/* BEGIN_COMMON_COPYRIGHT_HEADER
|
||||
* (c)LGPL2+
|
||||
*
|
||||
* LXQt - a lightweight, Qt based, desktop toolset
|
||||
* http://razor-qt.org
|
||||
*
|
||||
* Copyright: 2010-2012 Razor team
|
||||
* Authors:
|
||||
* Petr Vanek <petr@scribus.info>
|
||||
*
|
||||
* This program or 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
|
||||
*
|
||||
* END_COMMON_COPYRIGHT_HEADER */
|
||||
|
||||
#ifndef WARNINGLABEL_H
|
||||
#define WARNINGLABEL_H
|
||||
|
||||
#include "ui_warninglabel.h"
|
||||
|
||||
|
||||
class WarningLabel : public QWidget, public Ui::WarningLabel
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
WarningLabel (QWidget *parent=0);
|
||||
|
||||
QPoint buttonPos() { return showDirButton->pos(); }
|
||||
|
||||
signals:
|
||||
void showDirInfo();
|
||||
};
|
||||
|
||||
#endif
|
@ -1,64 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>WarningLabel</class>
|
||||
<widget class="QWidget" name="WarningLabel">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>334</width>
|
||||
<height>72</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Form</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<item row="0" column="0">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<item>
|
||||
<widget class="QLabel" name="iconLabel">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>64</width>
|
||||
<height>64</height>
|
||||
</size>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="warningLabel">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>LXQt could not find any cursor theme. The default X11 cursor theme will be used instead. LXQt looked in the following directories:</string>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="showDirButton">
|
||||
<property name="text">
|
||||
<string>Show...</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
@ -1,262 +0,0 @@
|
||||
/* coded by Ketmar // Vampire Avalon (psyc://ketmar.no-ip.org/~Ketmar)
|
||||
* (c)DWTFYW
|
||||
*
|
||||
* This program is free software. It comes without any warranty, to
|
||||
* the extent permitted by applicable law. You can redistribute it
|
||||
* and/or modify it under the terms of the Do What The Fuck You Want
|
||||
* To Public License, Version 2, as published by Sam Hocevar. See
|
||||
* http://sam.zoy.org/wtfpl/COPYING for more details.
|
||||
*/
|
||||
#include <QDebug>
|
||||
|
||||
#include "xcrimg.h"
|
||||
|
||||
#include <QApplication>
|
||||
#include <QPaintEngine>
|
||||
#include <QStringList>
|
||||
#include <QStyle>
|
||||
#include <QTextCodec>
|
||||
#include <QTextStream>
|
||||
|
||||
#include <QX11Info>
|
||||
|
||||
|
||||
#include <X11/Xlib.h>
|
||||
#include <X11/Xcursor/Xcursor.h>
|
||||
#include <X11/extensions/Xfixes.h>
|
||||
|
||||
|
||||
inline static quint8 alphaPreMul (quint8 clr, quint8 alpha) {
|
||||
quint32 c32 = clr, a32 = alpha;
|
||||
c32 = c32*a32/255;
|
||||
if (c32 > a32) c32 = a32;
|
||||
return c32&0xff;
|
||||
}
|
||||
|
||||
|
||||
static int nominalCursorSize (int iconSize) {
|
||||
for (int i = 512; i > 8; i /= 2) {
|
||||
if (i < iconSize) return i;
|
||||
if (int(i*0.75) < iconSize) return int(i*0.75);
|
||||
}
|
||||
return 8;
|
||||
}
|
||||
|
||||
|
||||
static void baPutDW (QByteArray &ba, quint32 v) {
|
||||
ba.append('\0'); ba.append('\0');
|
||||
ba.append('\0'); ba.append('\0');
|
||||
uchar *d = (uchar *)ba.data();
|
||||
d += ba.size()-4;
|
||||
for (int f = 4; f > 0; f--, d++) {
|
||||
*d = (v&0xff);
|
||||
v >>= 8;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void XCursorImage::convertARGB2PreMul (QImage &img) {
|
||||
switch (img.format()) {
|
||||
case QImage::Format_ARGB32_Premultiplied: return;
|
||||
case QImage::Format_ARGB32: break;
|
||||
default: (void) img.convertToFormat(QImage::Format_ARGB32/*_Premultiplied*/);
|
||||
}
|
||||
(void) img.convertToFormat(QImage::Format_ARGB32_Premultiplied); // this shouldn't convert anything
|
||||
// so convert it!
|
||||
for (int y = img.height()-1; y >= 0; y--) {
|
||||
quint8 *line = (quint8 *)img.scanLine(y);
|
||||
for (int x = 0; x < img.width(); x++, line += 4) {
|
||||
// convert to 'premultiplied'
|
||||
line[0] = alphaPreMul(line[0], line[3]);
|
||||
line[1] = alphaPreMul(line[1], line[3]);
|
||||
line[2] = alphaPreMul(line[2], line[3]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
XCursorImage::XCursorImage (const QString &aName, const QImage &aImg, int aXHot, int aYHot, quint32 aDelay, quint32 aCSize) :
|
||||
mIsValid(true), mName(aName), mImage(0), mDelay(aDelay), mXHot(aXHot), mYHot(aYHot), mCSize(aCSize)
|
||||
{
|
||||
mImage = new QImage(aImg.copy());
|
||||
convertARGB2PreMul(*mImage);
|
||||
}
|
||||
|
||||
|
||||
XCursorImage::XCursorImage (const QString &aName) :
|
||||
mIsValid(false), mName(aName), mImage(0), mDelay(50), mXHot(0), mYHot(0)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
XCursorImage::~XCursorImage () {
|
||||
delete mImage; // or memory will leak!
|
||||
}
|
||||
|
||||
|
||||
QPixmap XCursorImage::icon () const {
|
||||
if (mIcon.isNull()) mIcon = createIcon();
|
||||
return mIcon;
|
||||
}
|
||||
|
||||
|
||||
QCursor XCursorImage::cursor () const {
|
||||
return QCursor(icon(), mXHot, mYHot);
|
||||
}
|
||||
|
||||
|
||||
QImage XCursorImage::image (int size) const {
|
||||
if (size == -1) size = XcursorGetDefaultSize(QX11Info::display());
|
||||
if (!mImage) return QImage();
|
||||
return mImage->copy();
|
||||
}
|
||||
|
||||
|
||||
QPixmap XCursorImage::createIcon () const {
|
||||
QPixmap pixmap;
|
||||
int iconSize = QApplication::style()->pixelMetric(QStyle::PM_LargeIconSize);
|
||||
int cursorSize = nominalCursorSize(iconSize);
|
||||
QSize size = QSize(iconSize, iconSize);
|
||||
QImage img = image(cursorSize);
|
||||
if (!img.isNull()) {
|
||||
// Scale the image if it's larger than the preferred icon size
|
||||
if (img.width() > size.width() || img.height() > size.height())
|
||||
img = img.scaled(size, Qt::KeepAspectRatio, Qt::SmoothTransformation);
|
||||
pixmap = QPixmap::fromImage(img);
|
||||
}
|
||||
return pixmap;
|
||||
}
|
||||
|
||||
|
||||
quint32 XCursorImage::xcurSize () const {
|
||||
if (!mImage || !mIsValid) return 0;
|
||||
quint32 res = 9*4; // header
|
||||
res += mImage->width()*mImage->height()*4;
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
void XCursorImage::genXCursorImg (QByteArray &res) const {
|
||||
if (!mImage || !mIsValid) return;
|
||||
baPutDW(res, 36); // header size
|
||||
baPutDW(res, 0xfffd0002); // chunk type
|
||||
baPutDW(res, mCSize); // subtype
|
||||
baPutDW(res, 1); // version
|
||||
baPutDW(res, (quint32)mImage->width());
|
||||
baPutDW(res, (quint32)mImage->height());
|
||||
baPutDW(res, (quint32)mXHot);
|
||||
baPutDW(res, (quint32)mYHot);
|
||||
baPutDW(res, (quint32)mDelay);
|
||||
// now put the pixels
|
||||
QImage i = mImage->copy();
|
||||
(void) i.convertToFormat(QImage::Format_ARGB32_Premultiplied);
|
||||
//i.convertToFormat(QImage::Format_ARGB32);
|
||||
for (int y = 0; y < i.height(); y++) {
|
||||
const uchar *sl = i.scanLine(y);
|
||||
const quint32 *d = (const quint32 *)sl;
|
||||
for (int x = 0; x < i.width(); x++, d++) baPutDW(res, *d);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
XCursorImages::XCursorImages (const QString &aName, const QString &aPath) :
|
||||
mName(aName), mPath(aPath), mTitle(""), mAuthor(""), mLicense(""),
|
||||
mEMail(""), mSite(""), mDescr(""), mIM("")
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
XCursorImages::~XCursorImages () {
|
||||
qDeleteAll(mList);
|
||||
mList.clear();
|
||||
}
|
||||
|
||||
|
||||
QByteArray XCursorImages::genXCursor () const {
|
||||
QByteArray res;
|
||||
// build 'credits' block
|
||||
QByteArray crdBA[7];
|
||||
{
|
||||
QStringList crb;
|
||||
crb << mAuthor << mLicense << mDescr << mTitle << mEMail << mSite << mIM;
|
||||
for (int f = 0; f < crb.size(); f++) {
|
||||
QString s(crb[f]);
|
||||
if (s.isEmpty()) crdBA[f].clear(); else crdBA[f] = s.toUtf8();
|
||||
}
|
||||
}
|
||||
//
|
||||
res.append("Xcur"); // signature
|
||||
baPutDW(res, 16); // header size
|
||||
baPutDW(res, 65536); // version number
|
||||
// TOC
|
||||
quint32 cnt = 0;
|
||||
foreach (const XCursorImage *i, mList) if (i->xcurSize() > 0) cnt++;
|
||||
// 'credits'
|
||||
for (int f = 0; f < 7; f++) if (!crdBA[f].isEmpty()) cnt++;
|
||||
//
|
||||
baPutDW(res, cnt); // # of chunks
|
||||
if (!cnt) return res;
|
||||
quint32 dataOfs = cnt*(3*4)+16;
|
||||
// add 'credits' chunks
|
||||
for (int f = 0; f < 7; f++) {
|
||||
if (crdBA[f].isEmpty()) continue;
|
||||
baPutDW(res, 0xfffd0001); // entry type
|
||||
baPutDW(res, f+1); // subtype
|
||||
baPutDW(res, dataOfs); // offset
|
||||
dataOfs += crdBA[f].size()+20;
|
||||
}
|
||||
// add image chunks
|
||||
foreach (const XCursorImage *i, mList) {
|
||||
quint32 isz = i->xcurSize();
|
||||
if (!isz) continue;
|
||||
baPutDW(res, 0xfffd0002); // entry type
|
||||
baPutDW(res, i->csize()); // subtype
|
||||
baPutDW(res, dataOfs); // offset
|
||||
dataOfs += isz;
|
||||
}
|
||||
// credits
|
||||
for (int f = 0; f < 7; f++) {
|
||||
if (crdBA[f].isEmpty()) continue;
|
||||
baPutDW(res, 20); // header size
|
||||
baPutDW(res, 0xfffd0001); // entry type
|
||||
baPutDW(res, f+1); // subtype
|
||||
baPutDW(res, 1); // version
|
||||
baPutDW(res, crdBA[f].size()); // length
|
||||
res.append(crdBA[f]);
|
||||
}
|
||||
// images
|
||||
foreach (const XCursorImage *i, mList) {
|
||||
quint32 isz = i->xcurSize();
|
||||
if (!isz) continue;
|
||||
i->genXCursorImg(res);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
QImage XCursorImages::buildImage () const {
|
||||
int width = 0, height = 0, cnt = 0;
|
||||
foreach (const XCursorImage *i, mList) {
|
||||
if (i->xcurSize() > 0) {
|
||||
QImage img = i->image();
|
||||
width = qMax(width, img.width());
|
||||
height = qMax(height, img.height());
|
||||
++cnt;
|
||||
}
|
||||
}
|
||||
//qDebug() << cnt << "images; size" << width << "by" << height;
|
||||
|
||||
QImage res(width*cnt, height, QImage::Format_ARGB32);
|
||||
QPainter p(&res);
|
||||
int x = 0;
|
||||
foreach (const XCursorImage *i, mList) {
|
||||
if (i->xcurSize() > 0) {
|
||||
QImage img = i->image();
|
||||
p.drawImage(QPoint(x, 0), img);
|
||||
x += img.width();
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}
|
@ -1,116 +0,0 @@
|
||||
/* coded by Ketmar // Vampire Avalon (psyc://ketmar.no-ip.org/~Ketmar)
|
||||
* (c)DWTFYW
|
||||
*
|
||||
* This program is free software. It comes without any warranty, to
|
||||
* the extent permitted by applicable law. You can redistribute it
|
||||
* and/or modify it under the terms of the Do What The Fuck You Want
|
||||
* To Public License, Version 2, as published by Sam Hocevar. See
|
||||
* http://sam.zoy.org/wtfpl/COPYING for more details.
|
||||
*/
|
||||
#ifndef XCRIMG_H
|
||||
#define XCRIMG_H
|
||||
|
||||
#include <QtCore>
|
||||
#include <QCursor>
|
||||
#include <QPixmap>
|
||||
|
||||
|
||||
class XCursorImage {
|
||||
public:
|
||||
XCursorImage (const QString &aName, const QImage &aImg, int aXHot=0, int aYHot=0, quint32 aDelay=50, quint32 aCSize=1);
|
||||
XCursorImage (const QString &aName);
|
||||
virtual ~XCursorImage ();
|
||||
|
||||
inline bool isValid () const { return mIsValid; }
|
||||
inline const QString &name () const { return mName; }
|
||||
inline quint32 delay () const { return mDelay; }
|
||||
inline int xhot () const { return mXHot; }
|
||||
inline int yhot () const { return mYHot; }
|
||||
inline quint32 csize () const { return mCSize; }
|
||||
|
||||
inline void setXHot (int v) { mXHot = v; }
|
||||
inline void setYHot (int v) { mYHot = v; }
|
||||
inline void setDelay (quint32 v) { mDelay = v; }
|
||||
inline void setName (const QString &n) { mName = n; }
|
||||
inline void setCSize (quint32 v) { mCSize = v; }
|
||||
|
||||
virtual QPixmap icon () const;
|
||||
virtual QCursor cursor () const;
|
||||
virtual QImage image (int size=-1) const;
|
||||
|
||||
quint32 xcurSize () const; // size in bytes
|
||||
|
||||
virtual void genXCursorImg (QByteArray &res) const; // generate Xcursor image
|
||||
|
||||
static void convertARGB2PreMul (QImage &img);
|
||||
|
||||
protected:
|
||||
virtual QPixmap createIcon () const;
|
||||
|
||||
protected:
|
||||
bool mIsValid;
|
||||
QString mName;
|
||||
QImage *mImage;
|
||||
quint32 mDelay; // milliseconds
|
||||
int mXHot;
|
||||
int mYHot;
|
||||
quint32 mCSize;
|
||||
mutable QPixmap mIcon;
|
||||
};
|
||||
|
||||
|
||||
class XCursorImages {
|
||||
public:
|
||||
XCursorImages (const QString &aName, const QString &aPath="");
|
||||
virtual ~XCursorImages ();
|
||||
|
||||
inline const QString &name () const { return mName; }
|
||||
inline const QString &path () const { return mPath; }
|
||||
inline const QString &title () const { return mTitle; }
|
||||
inline const QString &author () const { return mAuthor; }
|
||||
inline const QString &license () const { return mLicense; }
|
||||
inline const QString &mail () const { return mEMail; }
|
||||
inline const QString &site () const { return mSite; }
|
||||
inline const QString &descr () const { return mDescr; }
|
||||
inline const QString &im () const { return mIM; }
|
||||
inline const QString &script () const { return mScript; }
|
||||
|
||||
inline void setName (const QString &v) { mName = v; }
|
||||
inline void setPath (const QString &v) { mPath = v; }
|
||||
inline void setTitle (const QString &v) { mTitle = v; }
|
||||
inline void setAuthor (const QString &v) { mAuthor = v; }
|
||||
inline void setLicense (const QString &v) { mLicense = v; }
|
||||
inline void setMail (const QString &v) { mEMail = v; }
|
||||
inline void setSite (const QString &v) { mSite = v; }
|
||||
inline void setDescr (const QString &v) { mDescr = v; }
|
||||
inline void setIM (const QString &v) { mIM = v; }
|
||||
inline void setScript (const QString &v) { mScript = v; }
|
||||
|
||||
inline const QList<XCursorImage *> &list () const { return mList; }
|
||||
inline XCursorImage *item (int idx) { return mList.at(idx); }
|
||||
inline const XCursorImage *at (int idx) const { return mList.at(idx); }
|
||||
inline int count () const { return mList.size(); }
|
||||
inline int size () const { return mList.size(); }
|
||||
|
||||
inline void append (XCursorImage *img) { mList << img; }
|
||||
|
||||
QByteArray genXCursor () const; // generate Xcursor file
|
||||
|
||||
QImage buildImage () const;
|
||||
|
||||
protected:
|
||||
QString mName;
|
||||
QString mPath;
|
||||
QString mTitle;
|
||||
QString mAuthor;
|
||||
QString mLicense;
|
||||
QString mEMail;
|
||||
QString mSite;
|
||||
QString mDescr;
|
||||
QString mIM;
|
||||
QString mScript; // just for writing it back
|
||||
QList<XCursorImage *> mList;
|
||||
};
|
||||
|
||||
|
||||
#endif
|
@ -1,742 +0,0 @@
|
||||
/* coded by Ketmar // Vampire Avalon (psyc://ketmar.no-ip.org/~Ketmar)
|
||||
* (c)DWTFYW
|
||||
*
|
||||
* This program is free software. It comes without any warranty, to
|
||||
* the extent permitted by applicable law. You can redistribute it
|
||||
* and/or modify it under the terms of the Do What The Fuck You Want
|
||||
* To Public License, Version 2, as published by Sam Hocevar. See
|
||||
* http://sam.zoy.org/wtfpl/COPYING for more details.
|
||||
*/
|
||||
#include <QDebug>
|
||||
//#include <QtCore>
|
||||
|
||||
#include "xcrtheme.h"
|
||||
|
||||
#include <unistd.h>
|
||||
|
||||
#include <QStringList>
|
||||
#include <QTextStream>
|
||||
|
||||
#include "xcrimg.h"
|
||||
#include "xcrxcur.h"
|
||||
|
||||
/*
|
||||
0 standard arrow
|
||||
1 help arrow (the one with '?')
|
||||
2 working arrow
|
||||
3 busy cursor
|
||||
4 precision select
|
||||
5 text select
|
||||
6 handwriting
|
||||
7 unavailable
|
||||
8 north (vert) resize
|
||||
9 south resize
|
||||
10 west (vert-means horiz???) resize
|
||||
11 east resize
|
||||
12 north-west resize
|
||||
13 south-east resize
|
||||
14 north-east resize
|
||||
15 south-west resize
|
||||
16 move
|
||||
17 alternate select
|
||||
18 hand
|
||||
19 button
|
||||
*/
|
||||
|
||||
|
||||
static const char *nameTransTbl[] = {
|
||||
// curFX idx, curXP name, [...altnames], finalname, 0
|
||||
// end with 0
|
||||
"", // standard arrow (it's \x00)
|
||||
"Arrow",
|
||||
"left_ptr", "X_cursor", "right_ptr", "top_left_arrow", "move",
|
||||
"4498f0e0c1937ffe01fd06f973665830",
|
||||
0,
|
||||
//
|
||||
"\x04", // precision select
|
||||
"Cross",
|
||||
"tcross", "cross", "crosshair", "cross_reverse",
|
||||
"draped_box",
|
||||
0,
|
||||
//
|
||||
"\x12", // hand
|
||||
"Hand",
|
||||
"hand", "hand1", "hand2", "9d800788f1b08800ae810202380a0822",
|
||||
"e29285e634086352946a0e7090d73106",
|
||||
0,
|
||||
//
|
||||
"\x05", // text select
|
||||
"IBeam",
|
||||
"xterm",
|
||||
0,
|
||||
//
|
||||
"\x11", // alternate select
|
||||
"UpArrow",
|
||||
"center_ptr",
|
||||
0,
|
||||
//
|
||||
"\x0c",
|
||||
"SizeNWSE", // north-west resize
|
||||
"bottom_right_corner", "top_left_corner", "bd_double_arrow", "lr_angle",
|
||||
"c7088f0f3e6c8088236ef8e1e3e70000",
|
||||
0,
|
||||
//
|
||||
"\x0e", // north-east resize
|
||||
"SizeNESW",
|
||||
"bottom_left_corner", "top_right_corner", "fd_double_arrow", "ll_angle",
|
||||
"fcf1c3c7cd4491d801f1e1c78f100000",
|
||||
0,
|
||||
//
|
||||
"\x0a", // west resize
|
||||
"SizeWE",
|
||||
"sb_h_double_arrow", "left_side", "right_side", "h_double_arrow", "028006030e0e7ebffc7f7070c0600140",
|
||||
"14fef782d02440884392942c11205230",
|
||||
0,
|
||||
//
|
||||
"\x08", // north resize
|
||||
"SizeNS",
|
||||
"double_arrow", "bottom_side", "top_side", "v_double_arrow", "sb_v_double_arrow", "00008160000006810000408080010102",
|
||||
"2870a09082c103050810ffdffffe0204",
|
||||
0,
|
||||
//
|
||||
"\x01", // help arrow
|
||||
"Help",
|
||||
"question_arrow",
|
||||
"d9ce0ab605698f320427677b458ad60b",
|
||||
0,
|
||||
//
|
||||
"\x06", // handwriting
|
||||
"Handwriting",
|
||||
"pencil",
|
||||
0,
|
||||
//
|
||||
"\x02", // working arrow
|
||||
"AppStarting",
|
||||
"left_ptr_watch", "08e8e1c95fe2fc01f976f1e063a24ccd",
|
||||
"3ecb610c1bf2410f44200f48c40d3599",
|
||||
0,
|
||||
//
|
||||
"\x10", // move (???)
|
||||
"SizeAll",
|
||||
"fleur",
|
||||
0,
|
||||
//
|
||||
"\x03", // busy cursor
|
||||
"Wait",
|
||||
"watch",
|
||||
0,
|
||||
//
|
||||
"\x07", // unavailable
|
||||
"NO",
|
||||
"crossed_circle",
|
||||
"03b6e0fcb3499374a867c041f52298f0",
|
||||
0,
|
||||
0
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
static QString convertFXIndexToXPName (qint32 idx) {
|
||||
int f = 0;
|
||||
do {
|
||||
if (nameTransTbl[f][0] == idx) return QString(nameTransTbl[f+1]);
|
||||
f += 2;
|
||||
while (nameTransTbl[f]) ++f;
|
||||
++f;
|
||||
} while (nameTransTbl[f]);
|
||||
return QString();
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
static void removeFilesAndDirs (QDir &dir) {
|
||||
//qDebug() << "dir:" << dir.path();
|
||||
// files
|
||||
QFileInfoList lst = dir.entryInfoList(QDir::Files | QDir::NoDotAndDotDot | QDir::Hidden);
|
||||
foreach (const QFileInfo &fi, lst) {
|
||||
//qDebug() << "removing" << fi.fileName() << fi.absoluteFilePath();
|
||||
dir.remove(fi.fileName());
|
||||
}
|
||||
// dirs
|
||||
lst = dir.entryInfoList(QDir::AllDirs | QDir::NoDotAndDotDot | QDir::Hidden);
|
||||
foreach (const QFileInfo &fi, lst) {
|
||||
dir.cd(fi.fileName());
|
||||
removeFilesAndDirs(dir);
|
||||
dir.cd("..");
|
||||
//qDebug() << "removing dir" << fi.fileName();
|
||||
dir.rmdir(fi.fileName());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void removeFiles (QDir &dir) {
|
||||
//
|
||||
QFileInfoList lst = dir.entryInfoList(QDir::Files | QDir::NoDotAndDotDot | QDir::Hidden);
|
||||
foreach (const QFileInfo &fi, lst) {
|
||||
qDebug() << "removing" << fi.fileName() << fi.absoluteFilePath();
|
||||
QFile fl(fi.absoluteFilePath());
|
||||
fl.remove();
|
||||
}
|
||||
//
|
||||
}
|
||||
|
||||
|
||||
static void removeCursorFiles (QDir &dir) {
|
||||
QString pt = dir.path();
|
||||
if (!pt.isEmpty() && pt != "/") pt += "/";
|
||||
const char **nlst = nameTransTbl;
|
||||
while (*nlst) {
|
||||
nlst += 2; // skip non-files
|
||||
while (*nlst) {
|
||||
QString n(*nlst);
|
||||
QFile fl(pt+n);
|
||||
qDebug() << "removing" << fl.fileName();
|
||||
fl.remove();
|
||||
nlst++;
|
||||
}
|
||||
nlst++;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
const char **XCursorTheme::findCursorByFXId (int id) {
|
||||
if (id < 0 || id > 19) return 0; // invalid id
|
||||
const char **nlst = nameTransTbl;
|
||||
while (*nlst) {
|
||||
int lid = (**nlst)&0xff;
|
||||
nlst += 2; // skip unnecessary
|
||||
if (lid == id) return nlst;
|
||||
while (nlst[-1]) nlst++ ; // skip
|
||||
}
|
||||
return 0; // none found
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* type:
|
||||
* 0: by CursorXP name
|
||||
* 1: by Xcursor name
|
||||
* return:
|
||||
* pointer to Xcursor name list
|
||||
*/
|
||||
const char **XCursorTheme::findCursorRecord (const QString &cname, int type) {
|
||||
QByteArray ba(cname.toUtf8());
|
||||
const char *name = ba.constData();
|
||||
const char **nlst = nameTransTbl;
|
||||
while (*nlst) {
|
||||
nlst += 2; // skip unnecessary
|
||||
if (!type) {
|
||||
// by CursorXP name
|
||||
if (!strcmp(name, nlst[-1])) return nlst;
|
||||
} else {
|
||||
// by Xcursor name
|
||||
// find name
|
||||
const char **nx = nlst;
|
||||
while (*nx && strcmp(*nx, name)) nx++;
|
||||
if (*nx) return nlst; // we got it!
|
||||
}
|
||||
while (nlst[-1]) nlst++ ; // skip
|
||||
}
|
||||
return 0; // none found
|
||||
}
|
||||
|
||||
|
||||
QString XCursorTheme::findCursorFile (const QDir &dir, const char *name) {
|
||||
QString d(dir.path());
|
||||
if (d != "/") d += "/";
|
||||
d += "cursors/";
|
||||
const char **nlst = nameTransTbl;
|
||||
while (*nlst) {
|
||||
nlst += 2; // skip unnecessary
|
||||
// find name
|
||||
const char **nx = nlst;
|
||||
while (*nx && strcmp(*nx, name)) nx++;
|
||||
if (*nx) {
|
||||
// we got it!
|
||||
//qDebug() << "found" << *nx << "(" << *nlst << ")";
|
||||
nx = nlst;
|
||||
while (*nx) {
|
||||
QString s(*nx);
|
||||
//qDebug() << "checking" << s;
|
||||
QFileInfo fl(d+s);
|
||||
if (fl.exists() && fl.isReadable()) {
|
||||
//qDebug() << " ok" << s;
|
||||
return s;
|
||||
}
|
||||
nx++;
|
||||
}
|
||||
}
|
||||
while (nlst[-1]) nlst++ ; // skip
|
||||
}
|
||||
return QString(); // none found
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
XCursorTheme::XCursorTheme () :
|
||||
mName(""), mPath(""), mTitle(""), mAuthor(""), mLicense(""),
|
||||
mEMail(""), mSite(""), mDescr(""), mIM(""), mSample("left_ptr")
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
XCursorTheme::XCursorTheme (const QDir &aDir, const QString &aName) :
|
||||
mName(aName), mPath(aDir.path()), mTitle(""), mAuthor(""), mLicense(""),
|
||||
mEMail(""), mSite(""), mDescr(""), mIM(""), mSample("left_ptr")
|
||||
{
|
||||
parseXCursorTheme(aDir);
|
||||
}
|
||||
|
||||
|
||||
XCursorTheme::~XCursorTheme () {
|
||||
qDeleteAll(mList);
|
||||
mList.clear();
|
||||
}
|
||||
|
||||
|
||||
bool XCursorTheme::writeToDir (const QDir &destDir) {
|
||||
bool res = true;
|
||||
QDir dir (destDir);
|
||||
dir.mkdir("cursors");
|
||||
if (!dir.exists("cursors")) return false;
|
||||
dir.cd("cursors");
|
||||
removeCursorFiles(dir);
|
||||
//
|
||||
foreach (const XCursorImages *ci, mList) {
|
||||
const char **nlst = findCursorRecord(ci->name());
|
||||
if (!nlst) continue; // unknown cursor, skip it
|
||||
qDebug() << "writing" << *nlst;
|
||||
{
|
||||
QByteArray ba(ci->genXCursor());
|
||||
QFile fo(dir.path()+"/"+ci->name());
|
||||
if (fo.open(QIODevice::WriteOnly)) {
|
||||
fo.write(ba);
|
||||
fo.close();
|
||||
} else {
|
||||
res = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
// make symlinks
|
||||
const char *orig = *nlst;
|
||||
nlst++;
|
||||
while (*nlst) {
|
||||
qDebug() << "symlinking to" << orig << "as" << *nlst;
|
||||
QByteArray newName(QFile::encodeName(dir.path()+"/"+(*nlst)));
|
||||
qDebug() << "old" << orig << "new" << newName.constData();
|
||||
if (symlink(orig, newName.constData())) {
|
||||
res = false;
|
||||
break;
|
||||
}
|
||||
nlst++;
|
||||
}
|
||||
if (!res) break;
|
||||
nlst++;
|
||||
}
|
||||
if (res) res = writeIndexTheme(destDir);
|
||||
if (!res) removeCursorFiles(dir);
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
void XCursorTheme::parseThemeIndex (const QDir &dir) {
|
||||
QString ifn = dir.path();
|
||||
if (!ifn.isEmpty() && ifn != "/") ifn += "/";
|
||||
ifn += "index.theme";
|
||||
qDebug() << "reading theme index:" << ifn;
|
||||
QFile fl(ifn);
|
||||
//
|
||||
QString cmt;
|
||||
mInherits.clear();
|
||||
// read config file, drop out 'icon theme' section (IT'S BAD!)
|
||||
if (fl.open(QIODevice::ReadOnly)) {
|
||||
QTextStream stream;
|
||||
stream.setDevice(&fl);
|
||||
stream.setCodec("UTF-8");
|
||||
bool inIconTheme = false;
|
||||
QString curPath;
|
||||
while (1) {
|
||||
QString s = stream.readLine();
|
||||
if (s.isNull()) break;
|
||||
QString orig(s);
|
||||
s = s.trimmed();
|
||||
if (s.isEmpty() || s[0] == '#' || s[0] == ';') continue;
|
||||
if (s[0] == '[') {
|
||||
// new path
|
||||
int len = s.length()-1;
|
||||
if (s[len] == ']') len--;
|
||||
s = s.mid(1, len).simplified();
|
||||
curPath = s.toLower();
|
||||
inIconTheme = (curPath == "icon theme");
|
||||
continue;
|
||||
}
|
||||
if (!inIconTheme) continue;
|
||||
int eqp = s.indexOf('=');
|
||||
if (eqp < 0) continue; // invalid entry
|
||||
QString name = s.left(eqp).simplified().toLower();
|
||||
QString value = s.mid(eqp+1).simplified();
|
||||
qDebug() << name << value;
|
||||
if (name == "name" && !value.isEmpty()) mTitle = value;
|
||||
else if (name == "comment" && !value.isEmpty()) cmt = value;
|
||||
else if (name == "author" && !value.isEmpty()) mAuthor = value;
|
||||
else if (name == "url" && !value.isEmpty()) mSite = value;
|
||||
else if (name == "description" && !value.isEmpty()) mDescr = value;
|
||||
else if (name == "example" && !value.isEmpty()) mSample = value;
|
||||
else if (name == "inherits" && !value.isEmpty()) mInherits << value;
|
||||
}
|
||||
fl.close();
|
||||
}
|
||||
if (mDescr.isEmpty() && !cmt.isEmpty()) mDescr = cmt;
|
||||
if (mSample.isEmpty()) mSample = "left_ptr";
|
||||
mInherits.removeDuplicates();
|
||||
}
|
||||
|
||||
|
||||
void XCursorTheme::dumpInfo () {
|
||||
/*
|
||||
qDebug() <<
|
||||
"INFO:" <<
|
||||
"\n name:" << mName <<
|
||||
"\n path:" << mPath <<
|
||||
"\n title:" << mTitle <<
|
||||
"\n author:" << mAuthor <<
|
||||
"\n license:" << mLicense <<
|
||||
"\n mail:" << mEMail <<
|
||||
"\n site:" << mSite <<
|
||||
"\n dscr:" << mDescr <<
|
||||
"\n im:" << mIM <<
|
||||
"\n sample:" << mSample <<
|
||||
"\n inherits:" << mInherits
|
||||
;
|
||||
*/
|
||||
}
|
||||
|
||||
|
||||
void XCursorTheme::parseXCursorTheme (const QDir &dir) {
|
||||
parseThemeIndex(dir);
|
||||
dumpInfo();
|
||||
const char **nlst = nameTransTbl;
|
||||
QDir dr(dir); dr.cd("cursors");
|
||||
while (*nlst) {
|
||||
//qDebug() << "CurFX: (" << nlst[1] << ")";
|
||||
nlst += 2; // skip unnecessary
|
||||
//qDebug() << "searching" << *nlst;
|
||||
QString fn = findCursorFile(dir, *nlst);
|
||||
if (fn.isEmpty()) continue; // no such file
|
||||
//qDebug() << " Xcrusor: (" << nlst[0] << ")";
|
||||
while (nlst[-1]) nlst++ ; // skip
|
||||
//qDebug() << " skiped: (" << nlst[1] << ")";
|
||||
qDebug() << "loading" << fn;
|
||||
XCursorImages *ci = new XCursorImagesXCur(dr, fn);
|
||||
if (ci->count()) {
|
||||
qDebug() << " OK:" << fn << "name:" << ci->name();
|
||||
if (mTitle.isEmpty() && !ci->title().isEmpty()) mTitle = ci->title();
|
||||
if (mAuthor.isEmpty() && !ci->author().isEmpty()) mAuthor = ci->author();
|
||||
if (mLicense.isEmpty() && !ci->license().isEmpty()) mLicense = ci->license();
|
||||
if (mEMail.isEmpty() && !ci->mail().isEmpty()) mEMail = ci->mail();
|
||||
if (mSite.isEmpty() && !ci->site().isEmpty()) mSite = ci->site();
|
||||
if (mDescr.isEmpty() && !ci->descr().isEmpty()) mDescr = ci->descr();
|
||||
if (mIM.isEmpty() && !ci->im().isEmpty()) mIM = ci->im();
|
||||
mList << ci;
|
||||
dumpInfo();
|
||||
} else {
|
||||
qWarning() << "can't load" << fn << nlst[-2];
|
||||
delete ci;
|
||||
}
|
||||
}
|
||||
dumpInfo();
|
||||
fixInfoFields();
|
||||
dumpInfo();
|
||||
}
|
||||
|
||||
|
||||
void XCursorTheme::fixInfoFields () {
|
||||
foreach (XCursorImages *ci, mList) {
|
||||
if (!mTitle.isEmpty() && ci->title().isEmpty()) ci->setTitle(title());
|
||||
if (!mAuthor.isEmpty() && ci->author().isEmpty()) ci->setAuthor(author());
|
||||
if (!mLicense.isEmpty() && ci->license().isEmpty()) ci->setLicense(license());
|
||||
if (!mEMail.isEmpty() && ci->mail().isEmpty()) ci->setMail(mail());
|
||||
if (!mSite.isEmpty() && ci->site().isEmpty()) ci->setSite(site());
|
||||
if (!mDescr.isEmpty() && ci->descr().isEmpty()) ci->setDescr(descr());
|
||||
if (!mIM.isEmpty() && ci->im().isEmpty()) ci->setIM(im());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool XCursorTheme::writeIndexTheme (const QDir &destDir) {
|
||||
QString ifn = destDir.path();
|
||||
if (!ifn.isEmpty() && ifn != "/") ifn += "/";
|
||||
ifn += "index.theme";
|
||||
qDebug() << "writing theme index:" << ifn;
|
||||
QFile fl(ifn);
|
||||
//
|
||||
QStringList cfg, inhs, iconOther;
|
||||
QString name, cmt, author, url, dscr, sample;
|
||||
inhs.append(mInherits);
|
||||
// read config file, drop out 'icon theme' section (IT'S BAD!)
|
||||
if (fl.open(QIODevice::ReadOnly)) {
|
||||
QTextStream stream;
|
||||
stream.setDevice(&fl);
|
||||
stream.setCodec("UTF-8");
|
||||
QString curPath;
|
||||
while (1) {
|
||||
QString s = stream.readLine();
|
||||
if (s.isNull()) break;
|
||||
QString orig(s);
|
||||
s = s.trimmed();
|
||||
if (s.isEmpty() || s[0] == '#' || s[0] == ';') {
|
||||
if (curPath != "icon theme") cfg << orig;
|
||||
continue;
|
||||
}
|
||||
if (s[0] == '[') {
|
||||
// new path
|
||||
int len = s.length()-1;
|
||||
if (s[len] == ']') len--;
|
||||
s = s.mid(1, len).simplified();
|
||||
curPath = s.toLower();
|
||||
if (curPath != "icon theme") cfg << orig;
|
||||
continue;
|
||||
}
|
||||
if (curPath != "icon theme") cfg << orig;
|
||||
else {
|
||||
int eqp = s.indexOf('=');
|
||||
if (eqp < 0) {
|
||||
// invalid entry
|
||||
iconOther << orig;
|
||||
continue;
|
||||
}
|
||||
QString name = s.left(eqp).simplified();
|
||||
QString value = s.mid(eqp+1).simplified();
|
||||
if (name.isEmpty()) {
|
||||
// invalid entry
|
||||
iconOther << orig;
|
||||
continue;
|
||||
}
|
||||
QString nn(name.toLower());
|
||||
if (nn == "name") name = value;
|
||||
else if (nn == "comment") cmt = value;
|
||||
else if (nn == "author") author = value;
|
||||
else if (nn == "url") url = value;
|
||||
else if (nn == "description") dscr = value;
|
||||
else if (nn == "example") sample = value;
|
||||
else if (nn == "inherits") { if (!value.isEmpty()) inhs << value; }
|
||||
else iconOther << orig;
|
||||
/*
|
||||
Name=Fire Dragon
|
||||
Comment=Fire Dragon Cursor Theme -- part of the 'Four Dragons' suite; (c) Sleeping Dragon, http://sleeping-dragon.deviantart.com/art/Fire-Dragon-30419542
|
||||
Author=Sleeping Dragon
|
||||
Url=http://sleeping-dragon.deviantart.com/art/Fire-Dragon-30419542
|
||||
Description=Fire Dragon Cursor Theme -- part of the 'Four Dragons' suite
|
||||
Example=left_ptr
|
||||
Inherits=core
|
||||
*/
|
||||
}
|
||||
}
|
||||
fl.close();
|
||||
}
|
||||
// theme file parsed; rewrite it!
|
||||
if (cfg.size() > 0 && !cfg.at(cfg.size()-1).isEmpty()) cfg << "";
|
||||
if (!fl.open(QIODevice::WriteOnly)) return false;
|
||||
if (name.isEmpty()) name = mTitle;
|
||||
if (author.isEmpty()) author = mAuthor;
|
||||
if (url.isEmpty()) url = mSite;
|
||||
if (dscr.isEmpty()) dscr = mDescr;
|
||||
if (cmt.isEmpty()) cmt = dscr;
|
||||
/*if (sample.isEmpty())*/ sample = "left_ptr";
|
||||
if (inhs.size() == 0) inhs << "core";
|
||||
inhs.removeDuplicates();
|
||||
dumpInfo();
|
||||
/*
|
||||
qDebug() <<
|
||||
"***INFO:" <<
|
||||
"\n name:" << name <<
|
||||
"\n cmt:" << cmt <<
|
||||
"\n author:" << author <<
|
||||
"\n site:" << url <<
|
||||
"\n dscr:" << dscr <<
|
||||
"\n sample:" << mSample <<
|
||||
"\n inherits:" << inhs
|
||||
;
|
||||
*/
|
||||
{
|
||||
QTextStream stream;
|
||||
stream.setDevice(&fl);
|
||||
stream.setCodec("UTF-8");
|
||||
foreach (const QString &s, cfg) stream << s << "\n";
|
||||
stream << "[Icon Theme]\n";
|
||||
stream << "Name=" << name << "\n";
|
||||
stream << "Comment=" << cmt << "\n";
|
||||
stream << "Author=" << author << "\n";
|
||||
stream << "Url=" << url << "\n";
|
||||
stream << "Description=" << dscr << "\n";
|
||||
stream << "Example=" << mSample << "\n";
|
||||
foreach (const QString &s, inhs) stream << "Inherits=" << s << "\n";
|
||||
}
|
||||
fl.close();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
static bool removeXCTheme (const QDir &thDir) {
|
||||
if (thDir.exists("cursors")) {
|
||||
QDir d(thDir);
|
||||
d.cd("cursors");
|
||||
//removeCursorFiles(d);
|
||||
removeFiles(d);
|
||||
}
|
||||
thDir.rmdir("cursors");
|
||||
// check if there are some other files
|
||||
QFileInfoList lst = thDir.entryInfoList(QDir::AllDirs | QDir::Files | QDir::NoDotAndDotDot | QDir::Hidden);
|
||||
bool cantKill = false;
|
||||
foreach (const QFileInfo &fi, lst) {
|
||||
QString s(fi.fileName());
|
||||
if (s != "icon-theme.cache" && s != "index.theme") {
|
||||
cantKill = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
// can kill this?
|
||||
if (!cantKill) {
|
||||
QDir d(thDir);
|
||||
d.remove("icon-theme.cache");
|
||||
d.remove("index.theme");
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool removeXCursorTheme (const QDir &thDir, const QString &name) {
|
||||
qDebug() << "to kill:" << thDir.path() << name;
|
||||
QDir d(thDir);
|
||||
if (!d.exists(name)) return false;
|
||||
qDebug() << "removing" << d.path() << name;
|
||||
d.cd(name);
|
||||
removeXCTheme(d);
|
||||
d.cd("..");
|
||||
d.rmdir(name);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool removeXCursorTheme (const QString &name) {
|
||||
QDir d(QDir::homePath());
|
||||
return removeXCursorTheme(d, name);
|
||||
}
|
||||
|
||||
|
||||
bool removeXCursorTheme (const QDir &thDir) {
|
||||
QString name(thDir.path());
|
||||
while (!name.isEmpty() && name.endsWith('/')) name.chop(1);
|
||||
int i = name.lastIndexOf('/');
|
||||
if (i < 1) return false;
|
||||
name = name.mid(i+1);
|
||||
QDir d(thDir);
|
||||
d.cd("..");
|
||||
return removeXCursorTheme(d, name);
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
/*
|
||||
* returns temporary dir or empty string
|
||||
*/
|
||||
static bool tarDir (const QString &destFName, const QDir &pth, const QString &dir) {
|
||||
QStringList args;
|
||||
|
||||
QFile fl(destFName);
|
||||
fl.remove();
|
||||
|
||||
args << "-c"; // create archive...
|
||||
args << "-z"; // and gzip it
|
||||
QString ps(pth.path());
|
||||
if (!ps.isEmpty() && ps != ".") {
|
||||
args << "-C"; // dir to go
|
||||
args << ps;
|
||||
}
|
||||
args << "-f"; // to file
|
||||
args << destFName;
|
||||
QString s(dir);
|
||||
if (!s.endsWith('/')) s += '/';
|
||||
args << s;
|
||||
|
||||
QProcess pr;
|
||||
pr.setStandardInputFile("/dev/null");
|
||||
pr.setStandardOutputFile("/dev/null");
|
||||
pr.setStandardErrorFile("/dev/null");
|
||||
|
||||
pr.start("tar", args);
|
||||
|
||||
if (pr.waitForStarted()) {
|
||||
if (pr.waitForFinished()) return true;
|
||||
}
|
||||
|
||||
// cleanup
|
||||
fl.remove();
|
||||
return false;
|
||||
}
|
||||
//tar -c -C /home/ketmar/k8prj/xcurtheme/src -f z.tar xcr/
|
||||
|
||||
|
||||
bool packXCursorTheme (const QString &destFName, const QDir &thDir, const QString &thName, bool removeTheme) {
|
||||
if (destFName.isEmpty() || thName.isEmpty()) return false;
|
||||
QDir d(thDir);
|
||||
if (!d.cd(thName)) return false;
|
||||
|
||||
bool res = tarDir(destFName, thDir, thName);
|
||||
if (res && removeTheme) {
|
||||
removeFilesAndDirs(d);
|
||||
d.cd("..");
|
||||
d.rmdir(thName);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
bool XCursorTheme::writeXPTheme (const QDir &destDir) {
|
||||
QString ifn = destDir.path();
|
||||
if (!ifn.isEmpty() && ifn != "/") ifn += '/';
|
||||
|
||||
QFile fl(ifn+"Scheme.ini");
|
||||
if (fl.open(QIODevice::WriteOnly)) {
|
||||
QTextStream stream;
|
||||
stream.setDevice(&fl);
|
||||
stream.setCodec("UTF-8");
|
||||
stream << "[General]\r\n";
|
||||
stream << "Version=130\r\n";
|
||||
qDebug() << "writing images...";
|
||||
foreach (XCursorImages *ci, mList) {
|
||||
const char **nlst = findCursorRecord(ci->name());
|
||||
if (!nlst) continue; // unknown cursor, skip it
|
||||
qDebug() << "image:" << *(nlst-1);
|
||||
QImage img(ci->buildImage());
|
||||
if (!img.save(ifn+(*(nlst-1))+".png")) return false;
|
||||
stream << "["+QString(*(nlst-1))+"]\r\n";
|
||||
stream << "StdCursor=0\r\n";
|
||||
stream << "Frames=" << ci->count() << "\r\n";
|
||||
stream << "Hot spot x=" << ci->at(0)->xhot() << "\r\n";
|
||||
stream << "Hot spot y=" << ci->at(0)->yhot() << "\r\n";
|
||||
stream << "Interval=" << (ci->at(0)->delay() == 2147483647 ? 100 : ci->at(0)->delay()) << "\r\n";
|
||||
// x2, y2? wtf?
|
||||
if (ci->count() > 1) {
|
||||
stream << "Frames=" << ci->count() << "\r\n";
|
||||
stream << "Animation style=0\r\n";
|
||||
} else {
|
||||
stream << "Frames=1\r\n";
|
||||
stream << "Animation style=0\r\n";
|
||||
}
|
||||
}
|
||||
stream << "[[Description]\r\n";
|
||||
if (!mName.isEmpty()) stream << mName << "\r\n";
|
||||
if (!mTitle.isEmpty()) stream << mTitle << "\r\n";
|
||||
if (!mAuthor.isEmpty()) stream << mAuthor << "\r\n";
|
||||
if (!mLicense.isEmpty()) stream << mLicense << "\r\n";
|
||||
if (!mEMail.isEmpty()) stream << mEMail << "\r\n";
|
||||
if (!mSite.isEmpty()) stream << mSite << "\r\n";
|
||||
if (!mDescr.isEmpty()) stream << mDescr << "\r\n";
|
||||
if (!mIM.isEmpty()) stream << mIM << "\r\n";
|
||||
}
|
||||
fl.close();
|
||||
return true;
|
||||
}
|
@ -1,97 +0,0 @@
|
||||
/* coded by Ketmar // Vampire Avalon (psyc://ketmar.no-ip.org/~Ketmar)
|
||||
* (c)DWTFYW
|
||||
*
|
||||
* This program is free software. It comes without any warranty, to
|
||||
* the extent permitted by applicable law. You can redistribute it
|
||||
* and/or modify it under the terms of the Do What The Fuck You Want
|
||||
* To Public License, Version 2, as published by Sam Hocevar. See
|
||||
* http://sam.zoy.org/wtfpl/COPYING for more details.
|
||||
*/
|
||||
#ifndef XCRTHEME_H
|
||||
#define XCRTHEME_H
|
||||
|
||||
#include <QtCore>
|
||||
#include <QCursor>
|
||||
#include <QPixmap>
|
||||
|
||||
#include "xcrimg.h"
|
||||
|
||||
|
||||
class XCursorTheme {
|
||||
public:
|
||||
XCursorTheme (const QDir &aDir, const QString &aName);
|
||||
XCursorTheme ();
|
||||
virtual ~XCursorTheme ();
|
||||
|
||||
inline const QString &name () const { return mName; }
|
||||
inline const QString &path () const { return mPath; }
|
||||
inline const QString &title () const { return mTitle; }
|
||||
inline const QString &author () const { return mAuthor; }
|
||||
inline const QString &license () const { return mLicense; }
|
||||
inline const QString &mail () const { return mEMail; }
|
||||
inline const QString &site () const { return mSite; }
|
||||
inline const QString &descr () const { return mDescr; }
|
||||
inline const QString &im () const { return mIM; }
|
||||
inline const QString &sample () const { return mSample; }
|
||||
inline const QStringList &inherits () const { return mInherits; }
|
||||
|
||||
inline void setName (const QString &v) { mName = v; }
|
||||
inline void setPath (const QString &v) { mPath = v; }
|
||||
inline void setTitle (const QString &v) { mTitle = v; }
|
||||
inline void setAuthor (const QString &v) { mAuthor = v; }
|
||||
inline void setLicense (const QString &v) { mLicense = v; }
|
||||
inline void setMail (const QString &v) { mEMail = v; }
|
||||
inline void setSite (const QString &v) { mSite = v; }
|
||||
inline void setDescr (const QString &v) { mDescr = v; }
|
||||
inline void setIM (const QString &v) { mIM = v; }
|
||||
inline void setSample (const QString &v) { mSample = v; }
|
||||
inline void setInherits (const QStringList &v) { mInherits.clear(); mInherits.append(v); }
|
||||
|
||||
inline const QList<XCursorImages *> &list () const { return mList; }
|
||||
inline const XCursorImages *at (int idx) const { return mList.at(idx); }
|
||||
inline int count () const { return mList.size(); }
|
||||
inline int size () const { return mList.size(); }
|
||||
|
||||
inline void append (XCursorImages *img) { mList << img; }
|
||||
|
||||
bool writeToDir (const QDir &destDir);
|
||||
|
||||
void fixInfoFields ();
|
||||
|
||||
bool writeXPTheme (const QDir &destDir);
|
||||
|
||||
protected:
|
||||
static const char **findCursorByFXId (int id);
|
||||
static QString findCursorFile (const QDir &dir, const char *name);
|
||||
static const char **findCursorRecord (const QString &cname, int type=1);
|
||||
|
||||
bool writeIndexTheme (const QDir &destDir);
|
||||
void parseXCursorTheme (const QDir &dir);
|
||||
void parseThemeIndex (const QDir &dir);
|
||||
|
||||
void dumpInfo ();
|
||||
|
||||
protected:
|
||||
QString mName;
|
||||
QString mPath;
|
||||
QString mTitle;
|
||||
QString mAuthor;
|
||||
QString mLicense;
|
||||
QString mEMail;
|
||||
QString mSite;
|
||||
QString mDescr;
|
||||
QString mIM;
|
||||
QString mSample;
|
||||
QStringList mInherits;
|
||||
QList<XCursorImages *> mList;
|
||||
};
|
||||
|
||||
|
||||
bool removeXCursorTheme (const QDir &thDir, const QString &name);
|
||||
bool removeXCursorTheme (const QString &name);
|
||||
bool removeXCursorTheme (const QDir &thDir);
|
||||
|
||||
bool packXCursorTheme (const QString &destFName, const QDir &thDir, const QString &thName, bool removeTheme=false);
|
||||
|
||||
|
||||
#endif
|
@ -1,400 +0,0 @@
|
||||
/* coded by Ketmar // Vampire Avalon (psyc://ketmar.no-ip.org/~Ketmar)
|
||||
* (c)DWTFYW
|
||||
*
|
||||
* This program is free software. It comes without any warranty, to
|
||||
* the extent permitted by applicable law. You can redistribute it
|
||||
* and/or modify it under the terms of the Do What The Fuck You Want
|
||||
* To Public License, Version 2, as published by Sam Hocevar. See
|
||||
* http://sam.zoy.org/wtfpl/COPYING for more details.
|
||||
*/
|
||||
#include <QDebug>
|
||||
//#include <QtCore>
|
||||
|
||||
#include "xcrthemefx.h"
|
||||
|
||||
#include <unistd.h>
|
||||
#include <zlib.h>
|
||||
|
||||
#include <QSet>
|
||||
#include <QStringList>
|
||||
#include <QTextStream>
|
||||
|
||||
#include "xcrimg.h"
|
||||
#include "xcrxcur.h"
|
||||
#include "xcrtheme.h"
|
||||
|
||||
|
||||
static const char *curShapeName[] = {
|
||||
"standard arrow",
|
||||
"help arrow (the one with '?')",
|
||||
"working arrow",
|
||||
"busy cursor",
|
||||
"precision select",
|
||||
"text select",
|
||||
"handwriting",
|
||||
"unavailable",
|
||||
"north (vert) resize",
|
||||
"south resize",
|
||||
"west (vert-means horiz?) resize",
|
||||
"east resize",
|
||||
"north-west resize",
|
||||
"south-east resize",
|
||||
"north-east resize",
|
||||
"south-west resize",
|
||||
"move",
|
||||
"alternate select",
|
||||
"hand",
|
||||
"button"
|
||||
};
|
||||
|
||||
|
||||
bool XCursorThemeFX::str2num (const QString &s, quint32 &res) {
|
||||
quint64 n = 0;
|
||||
if (s.isEmpty()) return false;
|
||||
for (int f = 0; f < s.length(); f++) {
|
||||
QChar ch = s.at(f);
|
||||
if (!ch.isDigit()) return false;
|
||||
n = n*10+ch.unicode()-'0';
|
||||
}
|
||||
//if (n >= (quint64)0x100000000LL) n = 0xffffffffLL;
|
||||
if (n >= (quint64)0x80000000LL) n = 0x7fffffffLL;
|
||||
res = n;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
QList<XCursorThemeFX::tAnimSeq> XCursorThemeFX::parseScript (const QString &script, quint32 maxFrame) {
|
||||
QList<tAnimSeq> res;
|
||||
QString scp = script; scp.replace("\r", "\n");
|
||||
QStringList scpL = scp.split('\n', QString::SkipEmptyParts);
|
||||
foreach (QString s, scpL) {
|
||||
s = s.simplified();
|
||||
//qDebug() << s;
|
||||
QStringList fld = s.split(',', QString::SkipEmptyParts); //BUG!BUG!BUG!
|
||||
if (fld.size() != 2) {
|
||||
qDebug() << "script error:" << s;
|
||||
qWarning() << "script error:" << s;
|
||||
continue;
|
||||
}
|
||||
// frame[s]
|
||||
int hyph = fld[0].indexOf('-');
|
||||
tAnimSeq a;
|
||||
if (hyph == -1) {
|
||||
// just a number
|
||||
if (!str2num(fld[0], a.from)) {
|
||||
qDebug() << "script error (frame):" << s;
|
||||
qWarning() << "script error (frame):" << s;
|
||||
continue;
|
||||
}
|
||||
a.from = qMax(qMin(maxFrame, a.from), (quint32)1)-1;
|
||||
a.to = a.from;
|
||||
} else {
|
||||
// a..b
|
||||
if (!str2num(fld[0].left(hyph), a.from)) {
|
||||
qDebug() << "script error (frame from):" << s;
|
||||
qWarning() << "script error (frame from):" << s;
|
||||
continue;
|
||||
}
|
||||
a.from = qMax(qMin(maxFrame, a.from), (quint32)1)-1;
|
||||
if (!str2num(fld[0].mid(hyph+1), a.to)) {
|
||||
qDebug() << "script error (frame to):" << s;
|
||||
qWarning() << "script error (frame to):" << s;
|
||||
continue;
|
||||
}
|
||||
a.to = qMax(qMin(maxFrame, a.to), (quint32)1)-1;
|
||||
}
|
||||
// delay
|
||||
if (!str2num(fld[1], a.delay)) {
|
||||
qDebug() << "script error (delay):" << s;
|
||||
qWarning() << "script error (delay):" << s;
|
||||
continue;
|
||||
}
|
||||
if (a.delay < 10) a.delay = 10;
|
||||
qDebug() << "from" << a.from << "to" << a.to << "delay" << a.delay;
|
||||
res << a;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
static QByteArray zlibInflate (const void *buf, int bufSz, int destSz) {
|
||||
QByteArray res;
|
||||
z_stream stream;
|
||||
int err;
|
||||
|
||||
res.resize(destSz+1);
|
||||
stream.next_in = (Bytef *)buf;
|
||||
stream.avail_in = bufSz;
|
||||
stream.zalloc = (alloc_func)0;
|
||||
stream.zfree = (free_func)0;
|
||||
stream.next_out = (Bytef *)res.data();
|
||||
stream.avail_out = destSz;
|
||||
|
||||
err = inflateInit(&stream);
|
||||
if (err != Z_OK) return QByteArray();
|
||||
err = inflate(&stream, Z_SYNC_FLUSH);
|
||||
fprintf(stderr, "inflate result: %i\n", err);
|
||||
switch (err) {
|
||||
case Z_STREAM_END:
|
||||
err = inflateEnd(&stream);
|
||||
fprintf(stderr, "Z_STREAM_END: inflate result: %i\n", err);
|
||||
if (err != Z_OK) return QByteArray();
|
||||
break;
|
||||
case Z_OK:
|
||||
err = inflateEnd(&stream);
|
||||
fprintf(stderr, "Z_OK: inflate result: %i\n", err);
|
||||
if (err != Z_OK) return QByteArray();
|
||||
break;
|
||||
default: return QByteArray();
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
static quint32 baGetDW (QByteArray &ba, int &pos) {
|
||||
const uchar *d = (const uchar *)ba.constData();
|
||||
d += pos+3;
|
||||
pos += 4;
|
||||
quint32 res = 0;
|
||||
for (int f = 4; f > 0; f--, d--) {
|
||||
res <<= 8;
|
||||
res |= *d;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
XCursorThemeFX::XCursorThemeFX (const QString &aFileName) : XCursorTheme() {
|
||||
if (!parseCursorFXTheme(aFileName)) {
|
||||
qDeleteAll(mList);
|
||||
mList.clear();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool XCursorThemeFX::parseCursorFXTheme (const QString &aFileName) {
|
||||
qDebug() << "loading" << aFileName;
|
||||
QFile fl(aFileName);
|
||||
if (!fl.open(QIODevice::ReadOnly)) return false; // shit!
|
||||
QByteArray ba(fl.readAll());
|
||||
fl.close();
|
||||
if (ba.size() < 0xb8) return false; // shit!
|
||||
int pos = 0;
|
||||
if (baGetDW(ba, pos) != 1) return false; // invalid version
|
||||
quint32 mainHdrSize = baGetDW(ba, pos);
|
||||
if (mainHdrSize < 0xb8) return false; // invalid header size
|
||||
quint32 unDataSize = baGetDW(ba, pos);
|
||||
if (unDataSize < 0x4c) return false; // no cursors anyway
|
||||
struct {
|
||||
quint32 ofs;
|
||||
quint32 len;
|
||||
} infoFields[6];
|
||||
pos = 0x84;
|
||||
for (int f = 0; f < 6; f++) {
|
||||
infoFields[f].ofs = baGetDW(ba, pos);
|
||||
infoFields[f].len = baGetDW(ba, pos);
|
||||
}
|
||||
pos = 0xb4;
|
||||
quint32 ihdrSize = baGetDW(ba, pos);
|
||||
// now read data
|
||||
pos = mainHdrSize;
|
||||
qDebug() << "reading data from" << pos;
|
||||
QByteArray unp(zlibInflate(ba.constData()+pos, ba.size()-pos, unDataSize));
|
||||
if (unp.isEmpty()) {
|
||||
qDebug() << "CursorFX: can't depack data";
|
||||
qWarning() << "CursorFX: can't depack data";
|
||||
return false;
|
||||
}
|
||||
// process info section
|
||||
for (int f = 0; f < 6; f++) {
|
||||
int len = infoFields[f].len;
|
||||
if (!len) continue;
|
||||
pos = infoFields[f].ofs;
|
||||
if ((quint32)pos >= ihdrSize || (quint32)pos+len >= ihdrSize) continue; // skip invalid one
|
||||
QByteArray sBA(unp.mid(pos, len));
|
||||
sBA.append('\0'); sBA.append('\0');
|
||||
QString s = QString::fromUtf16((const ushort *)sBA.constData()).simplified();
|
||||
switch (f) {
|
||||
case 0: setTitle(s); break;
|
||||
case 1: setAuthor(s); break;
|
||||
//case 2: setVersion(s); break;
|
||||
case 3: setSite(s); break;
|
||||
case 4: setMail(s); break;
|
||||
case 5: setDescr(s); break;
|
||||
default: ;
|
||||
}
|
||||
}
|
||||
// process resources
|
||||
QSet<quint8> shapesSeen;
|
||||
pos = ihdrSize;
|
||||
qDebug() << "resources started at hex" << QString::number(pos, 16);
|
||||
while (pos <= unp.size()-12) {
|
||||
quint32 ipos = pos; // will be fixed later
|
||||
quint32 rtype = baGetDW(unp, pos);
|
||||
quint32 basicHdrSize = baGetDW(unp, pos);
|
||||
quint32 itemSize = baGetDW(unp, pos);
|
||||
qDebug() << "pos hex:" << QString::number(pos, 16) << "rtype:" << rtype << "bhdrsz hex:" << QString::number(basicHdrSize, 16) << "itemsz hex:" << QString::number(itemSize, 16);
|
||||
if (itemSize < 12) {
|
||||
// invalid data
|
||||
qDebug() << "CursorFX: invalid data chunk size";
|
||||
qWarning() << "CursorFX: invalid data chunk size";
|
||||
return false;
|
||||
}
|
||||
pos = ipos+itemSize; // skip it
|
||||
if (rtype != 2) continue; // not cursor resource
|
||||
if (itemSize < 0x4c) {
|
||||
qDebug() << "CursorFX: invalid cursor chunk size:" << itemSize;
|
||||
qWarning() << "CursorFX: invalid cursor chunk size:" << itemSize;
|
||||
return false;
|
||||
}
|
||||
// cursor
|
||||
int cps = ipos+3*4;
|
||||
rtype = baGetDW(unp, cps);
|
||||
if (rtype != 2) {
|
||||
qDebug() << "CursorFX: invalid cursor chunk type:" << rtype;
|
||||
qWarning() << "CursorFX: invalid cursor chunk type:" << rtype;
|
||||
return false;
|
||||
}
|
||||
quint32 curShape = baGetDW(unp, cps);
|
||||
quint32 curType = baGetDW(unp, cps);
|
||||
if (curShape > 19) {
|
||||
qDebug() << "CursorFX: unknown cursor shape:" << curShape;
|
||||
qWarning() << "CursorFX: unknown cursor shape:" << curShape;
|
||||
return false;
|
||||
}
|
||||
if (curType != 1) {
|
||||
qDebug() << "skipping 'press' cursor; shape no" << curShape << "named" << curShapeName[curShape];
|
||||
continue;
|
||||
// we need only 'normal' cursors
|
||||
}
|
||||
qDebug() << "cursor shape:" << curShape;
|
||||
const char **nlst = findCursorByFXId((int)curShape);
|
||||
if (!nlst) {
|
||||
// unknown cursor type, skip it
|
||||
qDebug() << "CursorFX: skipping cursor shape:" << curShapeName[curShape];
|
||||
qWarning() << "CursorFX: skipping cursor shape:" << curShapeName[curShape];
|
||||
continue;
|
||||
}
|
||||
if (shapesSeen.contains(curShape&0xff)) {
|
||||
// unknown cursor type, skip it
|
||||
qDebug() << "CursorFX: skipping duplicate cursor shape:" << curShapeName[curShape];
|
||||
qWarning() << "CursorFX: skipping duplicate cursor shape:" << curShapeName[curShape];
|
||||
continue;
|
||||
}
|
||||
shapesSeen << (curShape&0xff);
|
||||
qDebug() << "importing cursor" << *nlst;
|
||||
quint32 unk0 = baGetDW(unp, cps); // unknown field
|
||||
quint32 frameCnt = baGetDW(unp, cps);
|
||||
if (frameCnt < 1) frameCnt = 1; // just in case
|
||||
quint32 imgWdt = baGetDW(unp, cps);
|
||||
quint32 imgHgt = baGetDW(unp, cps);
|
||||
quint32 imgDelay = baGetDW(unp, cps);
|
||||
quint32 aniFlags = baGetDW(unp, cps);
|
||||
quint32 unk1 = baGetDW(unp, cps); // unknown field
|
||||
quint32 imgXHot = baGetDW(unp, cps);
|
||||
quint32 imgYHot = baGetDW(unp, cps);
|
||||
quint32 realHdrSize = baGetDW(unp, cps);
|
||||
quint32 imgDataSize = baGetDW(unp, cps);
|
||||
quint32 addonOfs = baGetDW(unp, cps);
|
||||
quint32 addonLen = baGetDW(unp, cps);
|
||||
if (imgDelay < 10) imgDelay = 10;
|
||||
if (imgDelay >= (quint32)0x80000000LL) imgDelay = 0x7fffffffLL;
|
||||
qDebug() <<
|
||||
"cursor data:" <<
|
||||
"\n frames:" << frameCnt <<
|
||||
"\n width:" << imgWdt <<
|
||||
"\n height:" << imgHgt <<
|
||||
"\n delay:" << imgDelay <<
|
||||
"\n flags:" << QString::number(aniFlags, 2) <<
|
||||
"\n xhot:" << imgXHot <<
|
||||
"\n yhot:" << imgYHot <<
|
||||
"\n unk0:" << unk0 <<
|
||||
"\n unk1:" << unk1 <<
|
||||
"\n rhdata:" << QString::number(realHdrSize, 16) <<
|
||||
"\n dataOfs:" << QString::number(ipos+realHdrSize, 16) <<
|
||||
"\n cdataOfs:" << QString::number(ipos+basicHdrSize+addonLen, 16)
|
||||
;
|
||||
// now check if we have enought data
|
||||
if (ipos+realHdrSize+imgDataSize > (quint32)pos) {
|
||||
qDebug() << "CursorFX: cursor data too big";
|
||||
qWarning() << "CursorFX: cursor data too big";
|
||||
return false;
|
||||
}
|
||||
// addon is the script; parse it later
|
||||
QList<tAnimSeq> aseq;
|
||||
QString script;
|
||||
if (addonLen) {
|
||||
// script
|
||||
if (addonOfs < 0x4c || addonOfs > realHdrSize) {
|
||||
qDebug() << "CursorFX: invalid addon data offset";
|
||||
qWarning() << "CursorFX: invalid addon data offset";
|
||||
return false;
|
||||
}
|
||||
QByteArray bs(unp.mid(ipos+addonOfs, addonLen));
|
||||
bs.append('\0'); bs.append('\0');
|
||||
script = QString::fromUtf16((const ushort *)bs.constData());
|
||||
qDebug() << "script:\n" << script;
|
||||
// create animseq
|
||||
aseq = parseScript(script, frameCnt);
|
||||
} else {
|
||||
// create 'standard' animseq
|
||||
tAnimSeq a;
|
||||
a.from = 0; a.to = frameCnt-1; a.delay = imgDelay;
|
||||
aseq << a;
|
||||
// and back if 'alternate' flag set
|
||||
if (aniFlags&0x01) {
|
||||
a.from = frameCnt-1; a.to = 0;
|
||||
aseq << a;
|
||||
}
|
||||
}
|
||||
if (imgWdt*imgHgt*4 != imgDataSize) {
|
||||
qDebug() << "data size:" << imgDataSize << "but should be" << imgWdt*imgHgt*4;
|
||||
continue;
|
||||
}
|
||||
// decode image
|
||||
QImage img((const uchar *)unp.constData()+ipos+realHdrSize, imgWdt, imgHgt, QImage::Format_ARGB32);
|
||||
img = img.mirrored(false, true);
|
||||
//
|
||||
XCursorImages *cim = new XCursorImages(*nlst);
|
||||
cim->setScript(script);
|
||||
//!!!
|
||||
//!!!img.save(QString("_png/%1.png").arg(cim->name()));
|
||||
//!!!
|
||||
quint32 frameWdt = img.width()/frameCnt;
|
||||
qDebug() << "frameWdt:" << frameWdt << "left:" << img.width()%(frameWdt*frameCnt);
|
||||
// now build animation sequence
|
||||
int fCnt = 0;
|
||||
foreach (const tAnimSeq &a, aseq) {
|
||||
bool back = a.from > a.to; // going backwards
|
||||
quint32 fNo = a.from;
|
||||
for (;; fCnt++) {
|
||||
//k8:qDebug() << " frame:" << fNo << "delay:" << a.delay;
|
||||
// copy frame
|
||||
QImage frame(img.copy(fNo*frameWdt, 0, frameWdt, img.height()));
|
||||
//frame.save(QString("_png/%1_%2.png").arg(cim->name()).arg(QString::number(f)));
|
||||
XCursorImage *i = new XCursorImage(QString("%1%2").arg(cim->name()).arg(QString::number(fCnt)),
|
||||
frame, imgXHot, imgYHot, a.delay, 1
|
||||
);
|
||||
cim->append(i);
|
||||
//
|
||||
if (fNo == a.to) break;
|
||||
if (back) fNo--; else fNo++;
|
||||
}
|
||||
}
|
||||
// append if not empty
|
||||
if (cim->count()) {
|
||||
// now check if it is looped and cancel looping if necessary
|
||||
if ((aniFlags & 0x02) == 0) {
|
||||
// not looped
|
||||
qDebug() << " anti-loop fix";
|
||||
XCursorImage *i = cim->item(cim->count()-1);
|
||||
i->setDelay(0x7fffffffL);
|
||||
//i->setCSize(2); // ???
|
||||
}
|
||||
mList << cim;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
@ -1,40 +0,0 @@
|
||||
/* coded by Ketmar // Vampire Avalon (psyc://ketmar.no-ip.org/~Ketmar)
|
||||
* (c)DWTFYW
|
||||
*
|
||||
* This program is free software. It comes without any warranty, to
|
||||
* the extent permitted by applicable law. You can redistribute it
|
||||
* and/or modify it under the terms of the Do What The Fuck You Want
|
||||
* To Public License, Version 2, as published by Sam Hocevar. See
|
||||
* http://sam.zoy.org/wtfpl/COPYING for more details.
|
||||
*/
|
||||
#ifndef XCRTHEMEFX_H
|
||||
#define XCRTHEMEFX_H
|
||||
|
||||
#include <QtCore>
|
||||
#include <QCursor>
|
||||
#include <QPixmap>
|
||||
|
||||
#include "xcrimg.h"
|
||||
#include "xcrtheme.h"
|
||||
|
||||
|
||||
class XCursorThemeFX : public XCursorTheme {
|
||||
public:
|
||||
XCursorThemeFX (const QString &aFileName);
|
||||
|
||||
public:
|
||||
class tAnimSeq {
|
||||
public:
|
||||
quint32 from, to;
|
||||
quint32 delay;
|
||||
};
|
||||
|
||||
static QList<tAnimSeq> parseScript (const QString &script, quint32 maxFrame);
|
||||
static bool str2num (const QString &s, quint32 &res);
|
||||
|
||||
protected:
|
||||
bool parseCursorFXTheme (const QString &aFileName);
|
||||
};
|
||||
|
||||
|
||||
#endif
|
@ -1,352 +0,0 @@
|
||||
/* coded by Ketmar // Vampire Avalon (psyc://ketmar.no-ip.org/~Ketmar)
|
||||
* (c)DWTFYW
|
||||
*
|
||||
* This program is free software. It comes without any warranty, to
|
||||
* the extent permitted by applicable law. You can redistribute it
|
||||
* and/or modify it under the terms of the Do What The Fuck You Want
|
||||
* To Public License, Version 2, as published by Sam Hocevar. See
|
||||
* http://sam.zoy.org/wtfpl/COPYING for more details.
|
||||
*/
|
||||
#include <QDebug>
|
||||
//#include <QtCore>
|
||||
|
||||
#include "xcrthemexp.h"
|
||||
|
||||
#include <unistd.h>
|
||||
#include <zlib.h>
|
||||
|
||||
#include <QSet>
|
||||
#include <QStringList>
|
||||
#include <QTextStream>
|
||||
|
||||
#include "xcrimg.h"
|
||||
#include "xcrxcur.h"
|
||||
#include "xcrtheme.h"
|
||||
#include "xcrthemefx.h"
|
||||
|
||||
|
||||
static const char *curShapeName[] = {
|
||||
"Arrow",
|
||||
"Cross",
|
||||
"Hand",
|
||||
"IBeam",
|
||||
"UpArrow",
|
||||
"SizeNWSE",
|
||||
"SizeNESW",
|
||||
"SizeWE",
|
||||
"SizeNS",
|
||||
"Help",
|
||||
"Handwriting",
|
||||
"AppStarting",
|
||||
"SizeAll",
|
||||
"Wait",
|
||||
"NO",
|
||||
0
|
||||
};
|
||||
|
||||
|
||||
static const char *findCurShapeName (const QString &s) {
|
||||
QByteArray ba(s.toUtf8());
|
||||
const char *name = ba.constData();
|
||||
const char **nlst = curShapeName;
|
||||
while (*nlst) {
|
||||
if (!strcasecmp(name, *nlst)) return *nlst;
|
||||
nlst++;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static QString findFile (const QDir &dir, const QString &name, bool fullName=false) {
|
||||
QFileInfoList lst = dir.entryInfoList(QDir::Files | QDir::NoDotAndDotDot | QDir::Hidden);
|
||||
foreach (const QFileInfo &fi, lst) {
|
||||
if (!name.compare(fi.fileName(), Qt::CaseInsensitive)) {
|
||||
if (fullName) return fi.absoluteFilePath();
|
||||
return fi.fileName();
|
||||
}
|
||||
}
|
||||
return QString();
|
||||
}
|
||||
|
||||
|
||||
class CursorInfo {
|
||||
public:
|
||||
CursorInfo () { clear(); curSection.clear(); }
|
||||
|
||||
void clear () {
|
||||
frameCnt = 1; delay = 50; xhot = yhot = 0;
|
||||
script.clear();
|
||||
wasFrameCnt = wasXHot = wasYHot = wasDelay = wasScript = wasAStyle = wasStdCur = false;
|
||||
isStdCursor = false;
|
||||
isLooped = true; is2way = false;
|
||||
}
|
||||
|
||||
public:
|
||||
quint32 frameCnt, delay, xhot, yhot;
|
||||
QString script;
|
||||
bool wasFrameCnt, wasXHot, wasYHot, wasDelay, wasScript, wasAStyle, wasStdCur;
|
||||
bool isStdCursor;
|
||||
bool isLooped, is2way;
|
||||
QString curSection;
|
||||
QString nextSection;
|
||||
};
|
||||
|
||||
|
||||
/* true: EOF */
|
||||
static bool readNextSection (QTextStream &stream, CursorInfo &info) {
|
||||
info.clear();
|
||||
if (info.nextSection.isEmpty()) {
|
||||
// find next section
|
||||
//qDebug() << "searching section...";
|
||||
for (;;) {
|
||||
QString s;
|
||||
info.curSection.clear();
|
||||
info.nextSection.clear();
|
||||
for (;;) {
|
||||
s = stream.readLine();
|
||||
if (s.isNull()) return true;
|
||||
s = s.trimmed();
|
||||
//qDebug() << "*" << s;
|
||||
if (s.isEmpty() || s[0] == '#' || s[0] == ';') continue;
|
||||
if (s[0] == '[') break;
|
||||
}
|
||||
int len = s.length()-1;
|
||||
if (s[len] == ']') len--;
|
||||
s = s.mid(1, len);
|
||||
const char *csn = findCurShapeName(s);
|
||||
if (!csn) continue;
|
||||
// section found
|
||||
info.curSection = csn;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
info.curSection = info.nextSection;
|
||||
info.nextSection.clear();
|
||||
}
|
||||
// section found; read it
|
||||
for (;;) {
|
||||
QString s = stream.readLine();
|
||||
if (s.isNull()) return true;
|
||||
s = s.trimmed();
|
||||
//qDebug() << "+" << s;
|
||||
if (s.isEmpty() || s[0] == '#' || s[0] == ';') continue;
|
||||
if (s[0] == '[') {
|
||||
int len = s.length()-1;
|
||||
if (s[len] == ']') len--;
|
||||
s = s.mid(1, len);
|
||||
const char *csn = findCurShapeName(s);
|
||||
if (csn) info.nextSection = csn; else info.nextSection.clear();
|
||||
break;
|
||||
}
|
||||
QStringList nv(s.split('='));
|
||||
if (nv.size() != 2) continue; // invalid
|
||||
QString name = nv[0].simplified().toLower();
|
||||
quint32 num = 0;
|
||||
bool numOk = XCursorThemeFX::str2num(nv[1].trimmed(), num);
|
||||
if (!numOk) num = 0;
|
||||
if (name == "frames") {
|
||||
info.frameCnt = qMax(num, (quint32)1);
|
||||
info.wasFrameCnt = true;
|
||||
} else if (name == "interval") {
|
||||
info.delay = qMax(qMin(num, (quint32)0x7fffffffL), (quint32)10);
|
||||
info.wasDelay = true;
|
||||
} else if (name == "animation style") {
|
||||
info.isLooped = true;
|
||||
info.is2way = (num != 0);
|
||||
info.wasAStyle = true;
|
||||
} else if (name == "hot spot x") {
|
||||
info.xhot = num;
|
||||
info.wasXHot = true;
|
||||
} else if (name == "hot spot y") {
|
||||
info.yhot = num;
|
||||
info.wasYHot = true;
|
||||
} else if (name == "framescript") {
|
||||
// 1 or 0
|
||||
} else if (name == "stdcursor") {
|
||||
info.isStdCursor = (num!=0);
|
||||
info.wasStdCur = true;
|
||||
} else if (name == "hot spot x2" || name == "hot spot y2") {
|
||||
} else if (name == "stdcursor" || name == "hot spot x2" || name == "hot spot y2") {
|
||||
// nothing
|
||||
} else {
|
||||
qDebug() << "unknown param:" << name << nv[1];
|
||||
qWarning() << "unknown param:" << name << nv[1];
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
static void removeFilesAndDirs (QDir &dir) {
|
||||
//qDebug() << "dir:" << dir.path();
|
||||
// files
|
||||
QFileInfoList lst = dir.entryInfoList(QDir::Files | QDir::NoDotAndDotDot | QDir::Hidden);
|
||||
foreach (const QFileInfo &fi, lst) {
|
||||
//qDebug() << "removing" << fi.fileName() << fi.absoluteFilePath();
|
||||
dir.remove(fi.fileName());
|
||||
}
|
||||
// dirs
|
||||
lst = dir.entryInfoList(QDir::AllDirs | QDir::NoDotAndDotDot | QDir::Hidden);
|
||||
foreach (const QFileInfo &fi, lst) {
|
||||
dir.cd(fi.fileName());
|
||||
removeFilesAndDirs(dir);
|
||||
dir.cd("..");
|
||||
//qDebug() << "removing dir" << fi.fileName();
|
||||
dir.rmdir(fi.fileName());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* returns temporary dir or empty string
|
||||
*/
|
||||
static QString unzipFile (const QString &zipFile) {
|
||||
QStringList args;
|
||||
|
||||
char tmpDirName[18];
|
||||
strcpy(tmpDirName, "/tmp/unzXXXXXX");
|
||||
char *td = mkdtemp(tmpDirName);
|
||||
if (!td) return QString();
|
||||
|
||||
QDir dir(td);
|
||||
|
||||
args << "-b"; // all files are binary
|
||||
args << "-D"; // skip timestamps
|
||||
args << "-n"; // never overwrite (just in case)
|
||||
args << "-qq"; // be very quiet
|
||||
args << zipFile;
|
||||
args << "-d" << dir.absolutePath(); // dest dir
|
||||
|
||||
QProcess pr;
|
||||
pr.setStandardInputFile("/dev/null");
|
||||
pr.setStandardOutputFile("/dev/null");
|
||||
pr.setStandardErrorFile("/dev/null");
|
||||
|
||||
pr.start("unzip", args);
|
||||
|
||||
if (pr.waitForStarted()) {
|
||||
if (pr.waitForFinished()) return QLatin1String(td);
|
||||
}
|
||||
|
||||
// cleanup
|
||||
removeFilesAndDirs(dir);
|
||||
dir.cd("..");
|
||||
QString s = QLatin1String(strchr(td+1, '/')+1);
|
||||
//qDebug() << s;
|
||||
dir.rmdir(s);
|
||||
|
||||
return QString();
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
XCursorThemeXP::XCursorThemeXP (const QString &aFileName) : XCursorTheme() {
|
||||
QFileInfo fi(aFileName);
|
||||
if (fi.exists() && fi.isReadable()) {
|
||||
QString dst = unzipFile(aFileName);
|
||||
if (!dst.isEmpty()) {
|
||||
QDir d(dst);
|
||||
if (!parseCursorXPTheme(d)) {
|
||||
qDeleteAll(mList);
|
||||
mList.clear();
|
||||
}
|
||||
qDebug() << "doing cleanup...";
|
||||
dst.remove(0, dst.indexOf('/', 1)+1);
|
||||
removeFilesAndDirs(d);
|
||||
d.cd("..");
|
||||
qDebug() << dst;
|
||||
d.rmdir(dst);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool XCursorThemeXP::parseCursorXPTheme (const QDir &thDir) {
|
||||
qDebug() << "loading" << thDir.path();
|
||||
QString ifn = findFile(thDir, "scheme.ini", true);
|
||||
if (ifn.isEmpty()) return false;
|
||||
qDebug() << "reading scheme:" << ifn;
|
||||
//
|
||||
QFile fl(ifn);
|
||||
if (!fl.open(QIODevice::ReadOnly)) return false; // no scheme --> no fun!
|
||||
QTextStream stream;
|
||||
stream.setDevice(&fl);
|
||||
stream.setCodec("UTF-8");
|
||||
CursorInfo info;
|
||||
QSet<QString> sectionsSeen;
|
||||
bool eof = false;
|
||||
do {
|
||||
eof = readNextSection(stream, info);
|
||||
if (info.curSection.isEmpty()) break;
|
||||
/*
|
||||
qDebug() << "section:" << info.curSection <<
|
||||
"\n stdcr was:" << info.wasStdCur << "value:" << info.isStdCursor <<
|
||||
"\n frame was:" << info.wasFrameCnt << "value:" << info.frameCnt <<
|
||||
"\n delay was:" << info.wasDelay << "value:" << info.delay <<
|
||||
"\n xhot was:" << info.wasXHot << "value:" << info.xhot <<
|
||||
"\n yhot was:" << info.wasYHot << "value:" << info.yhot <<
|
||||
"\n style was:" << info.wasAStyle << "loop:" << info.isLooped << "2way:" << info.is2way <<
|
||||
"\n scrpt was:" << info.wasScript << "value:" << info.script <<
|
||||
"\n next section:" << info.nextSection
|
||||
;
|
||||
*/
|
||||
const char ** nlst = XCursorTheme::findCursorRecord(info.curSection, 0);
|
||||
QString imgFile = findFile(thDir, info.curSection+".png", true);
|
||||
if (!sectionsSeen.contains(info.curSection) && nlst && !imgFile.isEmpty()) {
|
||||
qDebug() << "section" << info.curSection << "file:" << imgFile;
|
||||
sectionsSeen << info.curSection;
|
||||
//TODO: script
|
||||
QList<XCursorThemeFX::tAnimSeq> aseq;
|
||||
{
|
||||
// create 'standard' animseq
|
||||
XCursorThemeFX::tAnimSeq a;
|
||||
a.from = 0; a.to = info.frameCnt-1; a.delay = info.delay;
|
||||
aseq << a;
|
||||
// and back if 'alternate' flag set
|
||||
if (info.is2way) {
|
||||
a.from = info.frameCnt-1; a.to = 0;
|
||||
aseq << a;
|
||||
}
|
||||
}
|
||||
// load image
|
||||
QImage img(imgFile);
|
||||
if (!img.isNull()) {
|
||||
XCursorImages *cim = new XCursorImages(*nlst);
|
||||
quint32 frameWdt = img.width()/info.frameCnt;
|
||||
qDebug() << "frameWdt:" << frameWdt << "left:" << img.width()%(frameWdt*info.frameCnt);
|
||||
// now build animation sequence
|
||||
int fCnt = 0;
|
||||
foreach (const XCursorThemeFX::tAnimSeq &a, aseq) {
|
||||
bool back = a.from > a.to; // going backwards
|
||||
quint32 fNo = a.from;
|
||||
for (;; fCnt++) {
|
||||
//k8:qDebug() << " frame:" << fNo << "delay:" << a.delay;
|
||||
// copy frame
|
||||
QImage frame(img.copy(fNo*frameWdt, 0, frameWdt, img.height()));
|
||||
//frame.save(QString("_png/%1_%2.png").arg(cim->name()).arg(QString::number(f)));
|
||||
XCursorImage *i = new XCursorImage(QString("%1%2").arg(cim->name()).arg(QString::number(fCnt)),
|
||||
frame, info.xhot, info.yhot, a.delay, 1
|
||||
);
|
||||
cim->append(i);
|
||||
//
|
||||
if (fNo == a.to) break;
|
||||
if (back) fNo--; else fNo++;
|
||||
}
|
||||
}
|
||||
// append if not empty
|
||||
if (cim->count()) {
|
||||
// now check if it is looped and cancel looping if necessary
|
||||
if (!info.isLooped) {
|
||||
// not looped
|
||||
qDebug() << " anti-loop fix";
|
||||
XCursorImage *i = cim->item(cim->count()-1);
|
||||
i->setDelay(0x7fffffffL);
|
||||
//i->setCSize(2); // ???
|
||||
}
|
||||
mList << cim;
|
||||
}
|
||||
}
|
||||
}
|
||||
} while (!eof);
|
||||
return true;
|
||||
}
|
@ -1,31 +0,0 @@
|
||||
/* coded by Ketmar // Vampire Avalon (psyc://ketmar.no-ip.org/~Ketmar)
|
||||
* (c)DWTFYW
|
||||
*
|
||||
* This program is free software. It comes without any warranty, to
|
||||
* the extent permitted by applicable law. You can redistribute it
|
||||
* and/or modify it under the terms of the Do What The Fuck You Want
|
||||
* To Public License, Version 2, as published by Sam Hocevar. See
|
||||
* http://sam.zoy.org/wtfpl/COPYING for more details.
|
||||
*/
|
||||
#ifndef XCRTHEMEXP_H
|
||||
#define XCRTHEMEXP_H
|
||||
|
||||
#include <QtCore>
|
||||
#include <QCursor>
|
||||
#include <QPixmap>
|
||||
|
||||
#include "xcrimg.h"
|
||||
#include "xcrtheme.h"
|
||||
#include "xcrthemefx.h"
|
||||
|
||||
|
||||
class XCursorThemeXP : public XCursorTheme {
|
||||
public:
|
||||
XCursorThemeXP (const QString &aFileName);
|
||||
|
||||
protected:
|
||||
bool parseCursorXPTheme (const QDir &thDir);
|
||||
};
|
||||
|
||||
|
||||
#endif
|
@ -1,248 +0,0 @@
|
||||
/* coded by Ketmar // Vampire Avalon (psyc://ketmar.no-ip.org/~Ketmar)
|
||||
* (c)DWTFYW
|
||||
*
|
||||
* This program is free software. It comes without any warranty, to
|
||||
* the extent permitted by applicable law. You can redistribute it
|
||||
* and/or modify it under the terms of the Do What The Fuck You Want
|
||||
* To Public License, Version 2, as published by Sam Hocevar. See
|
||||
* http://sam.zoy.org/wtfpl/COPYING for more details.
|
||||
*/
|
||||
#include <QDebug>
|
||||
//#include <QtCore>
|
||||
|
||||
#include "xcrxcur.h"
|
||||
|
||||
#include <QApplication>
|
||||
#include <QStringList>
|
||||
#include <QStyle>
|
||||
#include <QTextCodec>
|
||||
#include <QTextStream>
|
||||
|
||||
#include <QX11Info>
|
||||
|
||||
|
||||
#include <X11/Xlib.h>
|
||||
#include <X11/Xcursor/Xcursor.h>
|
||||
#include <X11/extensions/Xfixes.h>
|
||||
|
||||
|
||||
/*
|
||||
static QImage autoCropImage (const QImage &image) {
|
||||
// Compute an autocrop rectangle for the image
|
||||
QRect r(image.rect().bottomRight(), image.rect().topLeft());
|
||||
const quint32 *pixels = reinterpret_cast<const quint32*>(image.bits());
|
||||
for (int y = 0; y < image.height(); y++) {
|
||||
for (int x = 0; x < image.width(); x++) {
|
||||
if (*(pixels++)) {
|
||||
if (x < r.left()) r.setLeft(x);
|
||||
if (x > r.right()) r.setRight(x);
|
||||
if (y < r.top()) r.setTop(y);
|
||||
if (y > r.bottom()) r.setBottom(y);
|
||||
}
|
||||
}
|
||||
}
|
||||
// Normalize the rectangle
|
||||
return image.copy(r.normalized());
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
inline static quint32 getDW (const void *data) {
|
||||
const quint8 *d = (const quint8 *)data;
|
||||
d += 3;
|
||||
quint32 res = 0;
|
||||
for (int f = 4; f > 0; f--, d--) {
|
||||
res <<= 8;
|
||||
res |= *d;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
static quint32 baGetDW (QByteArray &ba, int &pos) {
|
||||
const uchar *d = (const uchar *)ba.constData();
|
||||
d += pos+3;
|
||||
pos += 4;
|
||||
quint32 res = 0;
|
||||
for (int f = 4; f > 0; f--, d--) {
|
||||
res <<= 8;
|
||||
res |= *d;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
XCursorImageXCur::XCursorImageXCur (const QString &aName, const void *aImgData) : XCursorImage(aName) {
|
||||
parseImgData(aImgData);
|
||||
}
|
||||
|
||||
|
||||
XCursorImageXCur::~XCursorImageXCur () {
|
||||
}
|
||||
|
||||
|
||||
void XCursorImageXCur::parseImgData (const void *aImgData) {
|
||||
mIsValid = false;
|
||||
delete mImage; // It's fine to delete a null pointer
|
||||
mImage = 0;
|
||||
const quint32 *data = (const quint32 *)aImgData;
|
||||
if (getDW(data) != 36) return; // header size
|
||||
if (getDW(data+1) != 0xfffd0002L) return; // magic
|
||||
//if (getDW(data+2) != 1) return; // image subtype
|
||||
if (getDW(data+3) != 1) return; // version
|
||||
mCSize = getDW(data+2);
|
||||
data += 4;
|
||||
quint32 wdt = getDW(data++); // width
|
||||
quint32 hgt = getDW(data++); // height
|
||||
if (wdt > 0x7fff) return;
|
||||
if (hgt > 0x7fff) return;
|
||||
/*
|
||||
quint32 xhot = getDW(data++);
|
||||
quint32 yhot = getDW(data++);
|
||||
assert(xhot <= wdt);
|
||||
assert(yhot <= hgt);
|
||||
*/
|
||||
mXHot = *((const qint32 *)data); data++;
|
||||
mYHot = *((const qint32 *)data); data++;
|
||||
mDelay = getDW(data++); // milliseconds
|
||||
// got to pixels (ARGB)
|
||||
QImage img((const uchar *)data, wdt, hgt, QImage::Format_ARGB32_Premultiplied);
|
||||
mImage = new QImage(img.copy());
|
||||
mIsValid = true;
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
XCursorImagesXCur::XCursorImagesXCur (const QDir &aDir, const QString &aName) : XCursorImages(aName, aDir.path()) {
|
||||
parseCursorFile(aDir.path()+"/"+aName);
|
||||
}
|
||||
|
||||
|
||||
XCursorImagesXCur::XCursorImagesXCur (const QString &aFileName) : XCursorImages("", "") {
|
||||
QString name(aFileName);
|
||||
if (name.isEmpty() || name.endsWith('/')) return;
|
||||
int i = name.lastIndexOf('/');
|
||||
QString dir;
|
||||
if (i < 0) dir = "./"; else dir = name.left(i);
|
||||
name = name.mid(i+1);
|
||||
setName(name); setPath(dir);
|
||||
parseCursorFile(aFileName);
|
||||
}
|
||||
|
||||
|
||||
bool XCursorImagesXCur::parseCursorFile (const QString &fname) {
|
||||
//qDebug() << fname;
|
||||
qDeleteAll(mList);
|
||||
mList.clear();
|
||||
QFile fl(fname);
|
||||
if (!fl.open(QIODevice::ReadOnly)) return false; // shit!
|
||||
QByteArray ba(fl.readAll());
|
||||
fl.close();
|
||||
if (ba.size() < 4*4) return false; // shit!
|
||||
if (ba[0] != 'X' || ba[1] != 'c' || ba[2] != 'u' || ba[3] != 'r') return false; // shit!
|
||||
//FIXME: add more checks!
|
||||
int pos = 4;
|
||||
quint32 hdrSize = baGetDW(ba, pos);
|
||||
if (hdrSize < 16) return false; // invalid header size
|
||||
quint32 version = baGetDW(ba, pos);
|
||||
if (version != 65536) return false; // invalid version
|
||||
quint32 ntoc = baGetDW(ba, pos);
|
||||
if (!ntoc) return true; // nothing to parse
|
||||
if (ntoc >= 65536) return false; // idiot or what?
|
||||
quint32 tocEndOfs = hdrSize+(ntoc*(3*4));
|
||||
if (tocEndOfs > (quint32)ba.size()) return false; // out of data
|
||||
pos = hdrSize;
|
||||
// parse TOC
|
||||
int cnt = -1;
|
||||
bool wasTitle = false, wasAuthor = false, wasLic = false;
|
||||
bool wasMail = false, wasSite = false, wasDescr = false, wasIM = false;
|
||||
while (ntoc-- > 0) {
|
||||
cnt++;
|
||||
quint32 type = baGetDW(ba, pos);
|
||||
pos += 4; // skip the shit
|
||||
quint32 dataOfs = baGetDW(ba, pos);
|
||||
if (type == 0xfffd0001) {
|
||||
// text
|
||||
if (dataOfs < tocEndOfs || dataOfs > (quint32)ba.size()-20) continue; // invalid text
|
||||
// parse text
|
||||
int ipos = dataOfs;
|
||||
if (baGetDW(ba, ipos) != 20) continue; // invalid header size
|
||||
if (baGetDW(ba, ipos) != 0xfffd0001) continue; // invalid type
|
||||
quint32 subT = baGetDW(ba, ipos);
|
||||
if (baGetDW(ba, ipos) != 1) continue; // invalid version
|
||||
quint32 len = baGetDW(ba, ipos);
|
||||
// check for data presence
|
||||
if (ipos+len > (quint32)ba.size()) continue; // out of data
|
||||
QByteArray stBA(ba.mid(ipos, len));
|
||||
QString s(QString::fromUtf8(stBA));
|
||||
switch (subT) {
|
||||
case 1: // copyright (author)
|
||||
if (!wasAuthor) {
|
||||
wasAuthor = true;
|
||||
mAuthor = s;
|
||||
}
|
||||
break;
|
||||
case 2: // license
|
||||
if (!wasLic) {
|
||||
wasLic = true;
|
||||
mLicense = s;
|
||||
}
|
||||
break;
|
||||
case 3: // other (description)
|
||||
if (!wasDescr) {
|
||||
wasDescr = true;
|
||||
mDescr = s;
|
||||
}
|
||||
break;
|
||||
// my extensions
|
||||
case 4: // title
|
||||
if (!wasTitle) {
|
||||
wasTitle = true;
|
||||
mTitle = s;
|
||||
}
|
||||
break;
|
||||
case 5: // e-mail
|
||||
if (!wasMail) {
|
||||
wasMail = true;
|
||||
mEMail = s;
|
||||
}
|
||||
break;
|
||||
case 6: // site
|
||||
if (!wasSite) {
|
||||
wasSite = true;
|
||||
mSite = s;
|
||||
}
|
||||
break;
|
||||
case 7: // IM
|
||||
if (!wasIM) {
|
||||
wasIM = true;
|
||||
mIM = s;
|
||||
}
|
||||
break;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if (type != 0xfffd0002) continue; // not an image, skip this one
|
||||
// image
|
||||
// check
|
||||
if (dataOfs < tocEndOfs || dataOfs > (quint32)ba.size()-36) continue; // invalid image
|
||||
// parse image
|
||||
int ipos = dataOfs;
|
||||
if (baGetDW(ba, ipos) != 36) continue; // invalid image (header size)
|
||||
if (baGetDW(ba, ipos) != 0xfffd0002) continue; // invalid type
|
||||
ipos += 4; // skip the shit
|
||||
if (baGetDW(ba, ipos) != 1) continue; // invalid image (version)
|
||||
quint32 wdt = baGetDW(ba, ipos);
|
||||
quint32 hgt = baGetDW(ba, ipos);
|
||||
if (wdt > 0x7fff || hgt > 0x7fff) continue; // invalid sizes
|
||||
// check for data presence
|
||||
if ((ipos+3*4)+(wdt*hgt*4) > (quint32)ba.size()) continue; // out of data
|
||||
// load image
|
||||
const uchar *dta = (const uchar *)ba.constData();
|
||||
dta += dataOfs;
|
||||
XCursorImage *img = new XCursorImageXCur(mName+"_"+QString::number(cnt), dta);
|
||||
if (img->isValid()) mList << img; else delete img;
|
||||
}
|
||||
return true;
|
||||
}
|
@ -1,40 +0,0 @@
|
||||
/* coded by Ketmar // Vampire Avalon (psyc://ketmar.no-ip.org/~Ketmar)
|
||||
* (c)DWTFYW
|
||||
*
|
||||
* This program is free software. It comes without any warranty, to
|
||||
* the extent permitted by applicable law. You can redistribute it
|
||||
* and/or modify it under the terms of the Do What The Fuck You Want
|
||||
* To Public License, Version 2, as published by Sam Hocevar. See
|
||||
* http://sam.zoy.org/wtfpl/COPYING for more details.
|
||||
*/
|
||||
#ifndef XCRXCUR_H
|
||||
#define XCRXCUR_H
|
||||
|
||||
#include <QtCore>
|
||||
#include <QCursor>
|
||||
#include <QPixmap>
|
||||
|
||||
#include "xcrimg.h"
|
||||
|
||||
|
||||
class XCursorImageXCur : public XCursorImage {
|
||||
public:
|
||||
XCursorImageXCur (const QString &aName, const void *aImgData); // create from Xcursor file contents (ptr to image)
|
||||
virtual ~XCursorImageXCur ();
|
||||
|
||||
protected:
|
||||
void parseImgData (const void *aImgData);
|
||||
};
|
||||
|
||||
|
||||
class XCursorImagesXCur : public XCursorImages {
|
||||
public:
|
||||
XCursorImagesXCur (const QDir &aDir, const QString &aName);
|
||||
XCursorImagesXCur (const QString &aFileName);
|
||||
|
||||
protected:
|
||||
bool parseCursorFile (const QString &fname);
|
||||
};
|
||||
|
||||
|
||||
#endif
|
Before Width: | Height: | Size: 29 KiB |
@ -1,101 +0,0 @@
|
||||
project(lxqt-config-appearance)
|
||||
|
||||
include_directories(
|
||||
${Qt5Gui_PRIVATE_INCLUDE_DIRS}
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/../liblxqt-config-cursor"
|
||||
)
|
||||
|
||||
set(H_FILES
|
||||
iconthemeinfo.h
|
||||
)
|
||||
|
||||
set(MOC_FILES
|
||||
iconthemeconfig.h
|
||||
lxqtthemeconfig.h
|
||||
fontsconfig.h
|
||||
styleconfig.h
|
||||
fontconfigfile.h
|
||||
)
|
||||
|
||||
set(CPP_FILES
|
||||
main.cpp
|
||||
iconthemeconfig.cpp
|
||||
iconthemeinfo.cpp
|
||||
lxqtthemeconfig.cpp
|
||||
fontsconfig.cpp
|
||||
styleconfig.cpp
|
||||
fontconfigfile.cpp
|
||||
)
|
||||
|
||||
set(UI_FILES
|
||||
iconthemeconfig.ui
|
||||
lxqtthemeconfig.ui
|
||||
fontsconfig.ui
|
||||
styleconfig.ui
|
||||
)
|
||||
|
||||
set(QRC_FILES "")
|
||||
|
||||
set(LIBRARIES
|
||||
lxqt
|
||||
)
|
||||
|
||||
|
||||
# Translations **********************************
|
||||
lxqt_translate_ts(QM_FILES
|
||||
UPDATE_TRANSLATIONS ${UPDATE_TRANSLATIONS}
|
||||
SOURCES
|
||||
${H_FILES}
|
||||
${CPP_FILES}
|
||||
${UI_FILES}
|
||||
INSTALL_DIR
|
||||
"${LXQT_TRANSLATIONS_DIR}/${PROJECT_NAME}"
|
||||
PULL_TRANSLATIONS
|
||||
${PULL_TRANSLATIONS}
|
||||
CLEAN_TRANSLATIONS
|
||||
${CLEAN_TRANSLATIONS}
|
||||
TRANSLATIONS_REPO
|
||||
${TRANSLATIONS_REPO}
|
||||
TRANSLATIONS_REFSPEC
|
||||
${TRANSLATIONS_REFSPEC}
|
||||
REPO_SUBDIR
|
||||
"lxqt-config/${PROJECT_NAME}"
|
||||
)
|
||||
|
||||
lxqt_app_translation_loader(QM_LOADER ${PROJECT_NAME})
|
||||
lxqt_translate_desktop(DESKTOP_FILES SOURCES ${PROJECT_NAME}.desktop.in)
|
||||
|
||||
#************************************************
|
||||
|
||||
add_executable(${PROJECT_NAME}
|
||||
${CPP_FILES}
|
||||
${RESOURCES}
|
||||
${QRC_FILES}
|
||||
${QM_FILES}
|
||||
${QM_LOADER}
|
||||
${DESKTOP_FILES}
|
||||
)
|
||||
|
||||
target_link_libraries(${PROJECT_NAME}
|
||||
Qt5::Widgets
|
||||
Qt5::X11Extras
|
||||
Qt5::Xml
|
||||
${LIBRARIES}
|
||||
lxqt-config-cursor
|
||||
)
|
||||
|
||||
set_target_properties("${PROJECT_NAME}"
|
||||
PROPERTIES
|
||||
INSTALL_RPATH "${CMAKE_INSTALL_FULL_LIBDIR}/${LXQT_CONFIG_PROJECT}"
|
||||
)
|
||||
|
||||
install(TARGETS
|
||||
${PROJECT_NAME}
|
||||
RUNTIME DESTINATION "${CMAKE_INSTALL_BINDIR}"
|
||||
COMPONENT Runtime
|
||||
)
|
||||
install(FILES
|
||||
${DESKTOP_FILES}
|
||||
DESTINATION "${CMAKE_INSTALL_DATAROOTDIR}/applications"
|
||||
COMPONENT Runtime
|
||||
)
|
@ -1,236 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2014 Hong Jen Yee (PCMan) <pcman.tw@gmail.com>
|
||||
* LXQt project: http://lxde.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) 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
|
||||
*
|
||||
*/
|
||||
|
||||
#include "fontconfigfile.h"
|
||||
#include <QTextStream>
|
||||
#include <QByteArray>
|
||||
#include <QFile>
|
||||
#include <QDir>
|
||||
#include <QDesktopServices>
|
||||
#include <QStringBuilder>
|
||||
#include <QDomDocument>
|
||||
#include <QTimer>
|
||||
#include <QDebug>
|
||||
#include <QStandardPaths>
|
||||
|
||||
FontConfigFile::FontConfigFile(QObject* parent):
|
||||
QObject(parent),
|
||||
mAntialias(true),
|
||||
mHinting(true),
|
||||
mSubpixel("rgb"),
|
||||
mHintStyle("hintslight"),
|
||||
mDpi(96),
|
||||
mAutohint(false),
|
||||
mSaveTimer(NULL)
|
||||
{
|
||||
mDirPath = QString::fromLocal8Bit(qgetenv("XDG_CONFIG_HOME"));
|
||||
QString homeDir = QStandardPaths::writableLocation(QStandardPaths::HomeLocation);
|
||||
if(mDirPath.isEmpty())
|
||||
mDirPath = homeDir % "/.config";
|
||||
mDirPath += "/fontconfig";
|
||||
mFilePath = mDirPath + "/fonts.conf";
|
||||
|
||||
load();
|
||||
}
|
||||
|
||||
FontConfigFile::~FontConfigFile()
|
||||
{
|
||||
if(mSaveTimer) // has pending save request
|
||||
{
|
||||
delete mSaveTimer;
|
||||
mSaveTimer = NULL;
|
||||
save();
|
||||
}
|
||||
}
|
||||
|
||||
void FontConfigFile::setAntialias(bool value)
|
||||
{
|
||||
mAntialias = value;
|
||||
queueSave();
|
||||
}
|
||||
|
||||
void FontConfigFile::setSubpixel(QByteArray value)
|
||||
{
|
||||
mSubpixel = value;
|
||||
queueSave();
|
||||
}
|
||||
|
||||
void FontConfigFile::setHinting(bool value)
|
||||
{
|
||||
mHinting = value;
|
||||
queueSave();
|
||||
}
|
||||
|
||||
void FontConfigFile::setHintStyle(QByteArray value)
|
||||
{
|
||||
mHintStyle = value;
|
||||
queueSave();
|
||||
}
|
||||
|
||||
void FontConfigFile::setDpi(int value)
|
||||
{
|
||||
mDpi = value;
|
||||
queueSave();
|
||||
}
|
||||
|
||||
void FontConfigFile::setAutohint(bool value)
|
||||
{
|
||||
mAutohint = value;
|
||||
queueSave();
|
||||
}
|
||||
|
||||
void FontConfigFile::load()
|
||||
{
|
||||
QFile file(mFilePath);
|
||||
if(file.open(QIODevice::ReadOnly))
|
||||
{
|
||||
QByteArray buffer = file.readAll();
|
||||
file.close();
|
||||
if(buffer.contains("lxqt-config-appearance")) // the config file is created by us
|
||||
{
|
||||
// doing full xml parsing is over-kill. let's use some simpler brute-force methods.
|
||||
QDomDocument doc;
|
||||
doc.setContent(&file);
|
||||
file.close();
|
||||
QDomElement docElem = doc.documentElement();
|
||||
QDomNodeList editNodes = docElem.elementsByTagName("edit");
|
||||
for(int i = 0; i < editNodes.count(); ++i)
|
||||
{
|
||||
QDomElement editElem = editNodes.at(i).toElement();
|
||||
QByteArray name = editElem.attribute("name").toLatin1();
|
||||
if(name == "antialias")
|
||||
{
|
||||
QString value = editElem.firstChildElement("bool").text();
|
||||
mAntialias = value[0] == 't' ? true : false;
|
||||
}
|
||||
else if(name == "rgba")
|
||||
{
|
||||
QString value = editElem.firstChildElement("const").text();
|
||||
mSubpixel = value.toLatin1();
|
||||
}
|
||||
else if(name == "hinting")
|
||||
{
|
||||
QString value = editElem.firstChildElement("bool").text();
|
||||
mHinting = value[0] == 't' ? true : false;
|
||||
}
|
||||
else if(name == "hintstyle")
|
||||
{
|
||||
QString value = editElem.firstChildElement("const").text();
|
||||
mHintStyle = value.toLatin1();
|
||||
}
|
||||
else if(name == "dpi")
|
||||
{
|
||||
QString value = editElem.firstChildElement("double").text();
|
||||
mDpi = value.toInt();
|
||||
}
|
||||
else if(name == "autohint")
|
||||
{
|
||||
QString value = editElem.firstChildElement("bool").text();
|
||||
mAutohint = value[0] == 't' ? true : false;
|
||||
}
|
||||
}
|
||||
}
|
||||
else // the config file is created by others => make a backup and write our config
|
||||
{
|
||||
QFile backup(mFilePath + ".bak");
|
||||
if(backup.open(QIODevice::WriteOnly))
|
||||
{
|
||||
backup.write(buffer);
|
||||
backup.close();
|
||||
}
|
||||
queueSave(); // overwrite with our file
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void FontConfigFile::save()
|
||||
{
|
||||
if(mSaveTimer)
|
||||
{
|
||||
mSaveTimer->deleteLater();
|
||||
mSaveTimer = NULL;
|
||||
}
|
||||
|
||||
QFile file(mFilePath);
|
||||
QDir().mkdir(mDirPath);
|
||||
// References: https://wiki.archlinux.org/index.php/Font_Configuration
|
||||
if(file.open(QIODevice::WriteOnly))
|
||||
{
|
||||
QTextStream s(&file);
|
||||
s <<
|
||||
"<?xml version=\"1.0\"?>\n"
|
||||
"<!DOCTYPE fontconfig SYSTEM \"fonts.dtd\">\n"
|
||||
"<!-- created by lxqt-config-appearance (DO NOT EDIT!) -->\n"
|
||||
"<fontconfig>\n"
|
||||
" <include ignore_missing=\"yes\">conf.d</include>\n"
|
||||
" <match target=\"font\">\n"
|
||||
" <edit name=\"antialias\" mode=\"assign\">\n"
|
||||
" <bool>" << (mAntialias ? "true" : "false") << "</bool>\n"
|
||||
" </edit>\n"
|
||||
" </match>\n"
|
||||
" <match target=\"font\">\n"
|
||||
" <edit name=\"rgba\" mode=\"assign\">\n"
|
||||
" <const>" << mSubpixel << "</const>\n"
|
||||
" </edit>\n"
|
||||
" </match>\n"
|
||||
" <match target=\"font\">\n"
|
||||
" <edit name=\"lcdfilter\" mode=\"assign\">\n"
|
||||
" <const>lcddefault</const>\n"
|
||||
" </edit>\n"
|
||||
" </match>\n"
|
||||
" <match target=\"font\">\n"
|
||||
" <edit name=\"hinting\" mode=\"assign\">\n"
|
||||
" <bool>" << (mHinting ? "true" : "false") << "</bool>\n"
|
||||
" </edit>\n"
|
||||
" </match>\n"
|
||||
" <match target=\"font\">\n"
|
||||
" <edit name=\"hintstyle\" mode=\"assign\">\n"
|
||||
" <const>" << mHintStyle << "</const>\n"
|
||||
" </edit>\n"
|
||||
" </match>\n"
|
||||
" <match target=\"font\">\n"
|
||||
" <edit name=\"autohint\" mode=\"assign\">\n"
|
||||
" <bool>" << (mAutohint ? "true" : "false") << "</bool>\n"
|
||||
" </edit>\n"
|
||||
" </match>\n"
|
||||
" <match target=\"pattern\">\n"
|
||||
" <edit name=\"dpi\" mode=\"assign\">\n"
|
||||
" <double>" << mDpi << "</double>\n"
|
||||
" </edit>\n"
|
||||
" </match>\n"
|
||||
"</fontconfig>";
|
||||
s.flush();
|
||||
file.close();
|
||||
}
|
||||
}
|
||||
|
||||
void FontConfigFile::queueSave()
|
||||
{
|
||||
if(mSaveTimer)
|
||||
mSaveTimer->start(1500);
|
||||
else
|
||||
{
|
||||
mSaveTimer = new QTimer();
|
||||
mSaveTimer->setSingleShot(true);
|
||||
connect(mSaveTimer, SIGNAL(timeout()), this, SLOT(save()));
|
||||
mSaveTimer->start(1500);
|
||||
}
|
||||
}
|
||||
|
@ -1,86 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2014 Hong Jen Yee (PCMan) <pcman.tw@gmail.com>
|
||||
* LXQt project: http://lxde.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) 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
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef FONTCONFIGFILE_H
|
||||
#define FONTCONFIGFILE_H
|
||||
|
||||
#include <QString>
|
||||
#include <QByteArray>
|
||||
#include <QObject>
|
||||
|
||||
class QTimer;
|
||||
|
||||
class FontConfigFile: public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit FontConfigFile(QObject* parent = 0);
|
||||
virtual ~FontConfigFile();
|
||||
|
||||
bool antialias() const {
|
||||
return mAntialias;
|
||||
}
|
||||
void setAntialias(bool value);
|
||||
|
||||
bool hinting() const {
|
||||
return mHinting;
|
||||
}
|
||||
void setHinting(bool value);
|
||||
|
||||
QByteArray subpixel() const {
|
||||
return mSubpixel;
|
||||
}
|
||||
void setSubpixel(QByteArray value);
|
||||
|
||||
QByteArray hintStyle() const {
|
||||
return mHintStyle;
|
||||
}
|
||||
void setHintStyle(QByteArray value);
|
||||
|
||||
int dpi() const {
|
||||
return mDpi;
|
||||
}
|
||||
void setDpi(int value);
|
||||
|
||||
bool autohint() const {
|
||||
return mAutohint;
|
||||
}
|
||||
void setAutohint(bool value);
|
||||
|
||||
private Q_SLOTS:
|
||||
void save();
|
||||
|
||||
private:
|
||||
void load();
|
||||
void queueSave();
|
||||
|
||||
private:
|
||||
bool mAntialias;
|
||||
bool mHinting;
|
||||
QByteArray mSubpixel;
|
||||
QByteArray mHintStyle;
|
||||
int mDpi;
|
||||
bool mAutohint;
|
||||
QString mDirPath;
|
||||
QString mFilePath;
|
||||
QTimer* mSaveTimer;
|
||||
};
|
||||
|
||||
#endif // FONTCONFIGFILE_H
|
@ -1,196 +0,0 @@
|
||||
/* BEGIN_COMMON_COPYRIGHT_HEADER
|
||||
* (c)LGPL2+
|
||||
*
|
||||
* LXQt - a lightweight, Qt based, desktop toolset
|
||||
* http://lxde.org/
|
||||
*
|
||||
* Copyright: 2014 LXQt team
|
||||
* Authors:
|
||||
* Hong Jen Yee (PCMan) <pcman.tw@gmail.com>
|
||||
*
|
||||
* This program or 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
|
||||
*
|
||||
* END_COMMON_COPYRIGHT_HEADER */
|
||||
|
||||
#include "fontsconfig.h"
|
||||
#include "ui_fontsconfig.h"
|
||||
#include <QTreeWidget>
|
||||
#include <QDebug>
|
||||
#include <QSettings>
|
||||
#include <QFont>
|
||||
#include <QFile>
|
||||
#include <QDir>
|
||||
#include <QDesktopServices>
|
||||
#include <QTextStream>
|
||||
#include <QStringBuilder>
|
||||
#include <QDomDocument>
|
||||
|
||||
#ifdef Q_WS_X11
|
||||
extern void qt_x11_apply_settings_in_all_apps();
|
||||
#endif
|
||||
|
||||
static const char* subpixelNames[] = {"none", "rgb", "bgr", "vrgb", "vbgr"};
|
||||
static const char* hintStyleNames[] = {"hintnone", "hintslight", "hintmedium", "hintfull"};
|
||||
|
||||
FontsConfig::FontsConfig(LXQt::Settings* settings, QSettings* qtSettings, QWidget* parent) :
|
||||
QWidget(parent),
|
||||
ui(new Ui::FontsConfig),
|
||||
mQtSettings(qtSettings),
|
||||
mSettings(settings),
|
||||
mFontConfigFile()
|
||||
{
|
||||
ui->setupUi(this);
|
||||
|
||||
initControls();
|
||||
|
||||
connect(ui->fontName, SIGNAL(currentFontChanged(QFont)), SLOT(updateQtFont()));
|
||||
connect(ui->fontStyle, SIGNAL(currentIndexChanged(int)), SLOT(updateQtFont()));
|
||||
connect(ui->fontSize, SIGNAL(valueChanged(int)), SLOT(updateQtFont()));
|
||||
|
||||
connect(ui->antialias, SIGNAL(toggled(bool)), SLOT(antialiasToggled(bool)));
|
||||
connect(ui->subpixel, SIGNAL(currentIndexChanged(int)), SLOT(subpixelChanged(int)));
|
||||
connect(ui->hinting, SIGNAL(toggled(bool)), SLOT(hintingToggled(bool)));
|
||||
connect(ui->hintStyle, SIGNAL(currentIndexChanged(int)), SLOT(hintStyleChanged(int)));
|
||||
connect(ui->dpi, SIGNAL(valueChanged(int)), SLOT(dpiChanged(int)));
|
||||
connect(ui->autohint, SIGNAL(toggled(bool)), SLOT(autohintToggled(bool)));
|
||||
}
|
||||
|
||||
|
||||
FontsConfig::~FontsConfig()
|
||||
{
|
||||
delete ui;
|
||||
}
|
||||
|
||||
|
||||
void FontsConfig::initControls()
|
||||
{
|
||||
// read Qt style settings from Qt Trolltech.conf config
|
||||
mQtSettings->beginGroup(QLatin1String("Qt"));
|
||||
|
||||
QString fontName = mQtSettings->value("font").toString();
|
||||
QFont font;
|
||||
font.fromString(fontName);
|
||||
ui->fontName->setCurrentFont(font);
|
||||
ui->fontSize->setValue(font.pointSize());
|
||||
int fontStyle = 0;
|
||||
if(font.bold())
|
||||
fontStyle = font.italic() ? 3 : 1;
|
||||
else if(font.italic())
|
||||
fontStyle = 2;
|
||||
ui->fontStyle->setCurrentIndex(fontStyle);
|
||||
|
||||
mQtSettings->endGroup();
|
||||
|
||||
// load fontconfig config
|
||||
ui->antialias->setChecked(mFontConfigFile.antialias());
|
||||
ui->autohint->setChecked(mFontConfigFile.autohint());
|
||||
|
||||
QByteArray subpixelStr = mFontConfigFile.subpixel();
|
||||
int subpixel;
|
||||
for(subpixel = 0; subpixel < 5; ++subpixel)
|
||||
{
|
||||
if(subpixelStr == subpixelNames[subpixel])
|
||||
break;
|
||||
}
|
||||
if(subpixel < 5)
|
||||
ui->subpixel->setCurrentIndex(subpixel);
|
||||
|
||||
ui->hinting->setChecked(mFontConfigFile.hinting());
|
||||
|
||||
QByteArray hintStyleStr = mFontConfigFile.hintStyle();
|
||||
int hintStyle;
|
||||
for(hintStyle = 0; hintStyle < 4; ++hintStyle)
|
||||
{
|
||||
if(hintStyleStr == hintStyleNames[hintStyle])
|
||||
break;
|
||||
}
|
||||
if(hintStyle < 4)
|
||||
ui->hintStyle->setCurrentIndex(hintStyle);
|
||||
|
||||
int dpi = mFontConfigFile.dpi();
|
||||
ui->dpi->setValue(dpi);
|
||||
|
||||
update();
|
||||
}
|
||||
|
||||
void FontsConfig::antialiasToggled(bool toggled)
|
||||
{
|
||||
mFontConfigFile.setAntialias(toggled);
|
||||
}
|
||||
|
||||
void FontsConfig::dpiChanged(int value)
|
||||
{
|
||||
mFontConfigFile.setDpi(value);
|
||||
}
|
||||
|
||||
void FontsConfig::hintingToggled(bool toggled)
|
||||
{
|
||||
mFontConfigFile.setHinting(toggled);
|
||||
}
|
||||
|
||||
void FontsConfig::subpixelChanged(int index)
|
||||
{
|
||||
mFontConfigFile.setSubpixel(subpixelNames[index]);
|
||||
}
|
||||
|
||||
void FontsConfig::hintStyleChanged(int index)
|
||||
{
|
||||
mFontConfigFile.setHintStyle(hintStyleNames[index]);
|
||||
}
|
||||
|
||||
void FontsConfig::autohintToggled(bool toggled)
|
||||
{
|
||||
mFontConfigFile.setAutohint(toggled);
|
||||
}
|
||||
|
||||
void FontsConfig::updateQtFont()
|
||||
{
|
||||
// FIXME: the change does not apply to some currently running Qt programs.
|
||||
// FIXME: does not work with KDE apps
|
||||
// TODO: also write the config values to GTK+ config files (gtk-2.0.rc and gtk3/settings.ini)
|
||||
// FIXME: the selected font does not apply to our own application. Why?
|
||||
|
||||
QFont font = ui->fontName->currentFont();
|
||||
int size = ui->fontSize->value();
|
||||
bool bold = false;
|
||||
bool italic = false;
|
||||
switch(ui->fontStyle->currentIndex())
|
||||
{
|
||||
case 1:
|
||||
bold = true;
|
||||
break;
|
||||
case 2:
|
||||
italic = true;
|
||||
break;
|
||||
case 3:
|
||||
bold = italic = true;
|
||||
}
|
||||
|
||||
font.setPointSize(size);
|
||||
font.setBold(bold);
|
||||
font.setItalic(italic);
|
||||
|
||||
mQtSettings->beginGroup(QLatin1String("Qt"));
|
||||
mQtSettings->setValue("font", font.toString());
|
||||
mQtSettings->endGroup();
|
||||
mQtSettings->sync();
|
||||
|
||||
#ifdef Q_WS_X11
|
||||
qt_x11_apply_settings_in_all_apps();
|
||||
#endif
|
||||
|
||||
update();
|
||||
}
|
@ -1,70 +0,0 @@
|
||||
/* BEGIN_COMMON_COPYRIGHT_HEADER
|
||||
* (c)LGPL2+
|
||||
*
|
||||
* LXQt - a lightweight, Qt based, desktop toolset
|
||||
* http://razor-qt.org
|
||||
*
|
||||
* Copyright: 2012 Razor team
|
||||
* Authors:
|
||||
* Alexander Sokoloff <sokoloff.a@gmail.com>
|
||||
*
|
||||
* This program or 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
|
||||
*
|
||||
* END_COMMON_COPYRIGHT_HEADER */
|
||||
|
||||
#ifndef FONTSCONFIG_H
|
||||
#define FONTSCONFIG_H
|
||||
|
||||
#include <QWidget>
|
||||
#include <QFont>
|
||||
#include <LXQt/Settings>
|
||||
#include "fontconfigfile.h"
|
||||
|
||||
class QTreeWidgetItem;
|
||||
class QSettings;
|
||||
|
||||
namespace Ui {
|
||||
class FontsConfig;
|
||||
}
|
||||
|
||||
class FontsConfig : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit FontsConfig(LXQt::Settings *settings, QSettings *qtSettings, QWidget *parent = 0);
|
||||
~FontsConfig();
|
||||
|
||||
public Q_SLOTS:
|
||||
void initControls();
|
||||
|
||||
private Q_SLOTS:
|
||||
void updateQtFont();
|
||||
void antialiasToggled(bool toggled);
|
||||
void hintingToggled(bool toggled);
|
||||
void subpixelChanged(int index);
|
||||
void hintStyleChanged(int index);
|
||||
void dpiChanged(int value);
|
||||
void autohintToggled(bool toggled);
|
||||
|
||||
private:
|
||||
Ui::FontsConfig *ui;
|
||||
QSettings *mQtSettings;
|
||||
LXQt::Settings *mSettings;
|
||||
FontConfigFile mFontConfigFile;
|
||||
};
|
||||
|
||||
#endif // FONTSCONFIG_H
|
@ -1,261 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>FontsConfig</class>
|
||||
<widget class="QWidget" name="FontsConfig">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>421</width>
|
||||
<height>379</height>
|
||||
</rect>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="font">
|
||||
<font>
|
||||
<weight>75</weight>
|
||||
<bold>true</bold>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Font</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupBox">
|
||||
<property name="title">
|
||||
<string>Default font for user interface</string>
|
||||
</property>
|
||||
<layout class="QFormLayout" name="formLayout_3">
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label_2">
|
||||
<property name="text">
|
||||
<string>Font name:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QFontComboBox" name="fontName"/>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="label_6">
|
||||
<property name="text">
|
||||
<string>Style:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="label_7">
|
||||
<property name="text">
|
||||
<string>Point size:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QSpinBox" name="fontSize">
|
||||
<property name="minimum">
|
||||
<number>4</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QComboBox" name="fontStyle">
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Normal</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Bold</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Italic</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Bold Italic</string>
|
||||
</property>
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="xftSettings">
|
||||
<property name="title">
|
||||
<string>The following settings only affect newly started applications</string>
|
||||
</property>
|
||||
<layout class="QFormLayout" name="formLayout_2">
|
||||
<item row="0" column="0" colspan="2">
|
||||
<widget class="QCheckBox" name="antialias">
|
||||
<property name="text">
|
||||
<string>Use antialias fonts</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<widget class="QLabel" name="label_3">
|
||||
<property name="text">
|
||||
<string>Font hinting style:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="1">
|
||||
<widget class="QComboBox" name="hintStyle">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>None</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Slight</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Medium</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Full</string>
|
||||
</property>
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0" colspan="2">
|
||||
<widget class="QCheckBox" name="hinting">
|
||||
<property name="text">
|
||||
<string>Font hinting</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="0">
|
||||
<widget class="QLabel" name="label_5">
|
||||
<property name="text">
|
||||
<string>Resolution (DPI):</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="6" column="0" colspan="2">
|
||||
<widget class="QCheckBox" name="autohint">
|
||||
<property name="text">
|
||||
<string>Autohint</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="1">
|
||||
<widget class="QSpinBox" name="dpi">
|
||||
<property name="minimum">
|
||||
<number>-1</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>1048576</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="label_4">
|
||||
<property name="text">
|
||||
<string>Subpixel antialiasing:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QComboBox" name="subpixel">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>None</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>RGB</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>BGR</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>VRGB</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>VBGR</string>
|
||||
</property>
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="verticalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>40</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections>
|
||||
<connection>
|
||||
<sender>antialias</sender>
|
||||
<signal>toggled(bool)</signal>
|
||||
<receiver>subpixel</receiver>
|
||||
<slot>setEnabled(bool)</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>225</x>
|
||||
<y>109</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>298</x>
|
||||
<y>140</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>hinting</sender>
|
||||
<signal>toggled(bool)</signal>
|
||||
<receiver>hintStyle</receiver>
|
||||
<slot>setEnabled(bool)</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>225</x>
|
||||
<y>171</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>298</x>
|
||||
<y>202</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
</connections>
|
||||
</ui>
|
@ -1,155 +0,0 @@
|
||||
/* BEGIN_COMMON_COPYRIGHT_HEADER
|
||||
* (c)LGPL2+
|
||||
*
|
||||
* LXQt - a lightweight, Qt based, desktop toolset
|
||||
* http://razor-qt.org
|
||||
*
|
||||
* Copyright: 2010-2011 Razor team
|
||||
* Authors:
|
||||
* Petr Vanek <petr@scribus.info>
|
||||
*
|
||||
* This program or 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
|
||||
*
|
||||
* END_COMMON_COPYRIGHT_HEADER */
|
||||
|
||||
#include "iconthemeconfig.h"
|
||||
|
||||
#include <LXQt/Settings>
|
||||
#include <QStringList>
|
||||
#include <QStringBuilder>
|
||||
#include <QIcon>
|
||||
|
||||
IconThemeConfig::IconThemeConfig(LXQt::Settings* settings, QWidget* parent):
|
||||
QWidget(parent),
|
||||
m_settings(settings)
|
||||
{
|
||||
setupUi(this);
|
||||
|
||||
initIconsThemes();
|
||||
initControls();
|
||||
connect(iconThemeList, SIGNAL(itemClicked(QTreeWidgetItem*,int)),
|
||||
this, SLOT(iconThemeSelected(QTreeWidgetItem*,int)));
|
||||
connect(iconFollowColorSchemeCB, &QAbstractButton::toggled, this, [this] (bool checked) {
|
||||
m_settings->setValue("icon_follow_color_scheme", checked);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
void IconThemeConfig::initIconsThemes()
|
||||
{
|
||||
QStringList processed;
|
||||
const QStringList baseDirs = QIcon::themeSearchPaths();
|
||||
static const QStringList iconNames = QStringList()
|
||||
<< QStringLiteral("document-open")
|
||||
<< QStringLiteral("document-new")
|
||||
<< QStringLiteral("edit-undo")
|
||||
<< QStringLiteral("media-playback-start");
|
||||
|
||||
const int iconNamesN = iconNames.size();
|
||||
iconThemeList->setColumnCount(iconNamesN + 2);
|
||||
|
||||
QList<QTreeWidgetItem *> items;
|
||||
foreach (const QString &baseDirName, baseDirs)
|
||||
{
|
||||
QDir baseDir(baseDirName);
|
||||
if (!baseDir.exists())
|
||||
continue;
|
||||
|
||||
const QFileInfoList dirs = baseDir.entryInfoList(QDir::AllDirs | QDir::NoDotAndDotDot, QDir::Name);
|
||||
foreach (const QFileInfo &dir, dirs)
|
||||
{
|
||||
if (!processed.contains(dir.canonicalFilePath()))
|
||||
{
|
||||
processed << dir.canonicalFilePath();
|
||||
|
||||
IconThemeInfo theme(QDir(dir.canonicalFilePath()));
|
||||
if (theme.isValid() && (!theme.isHidden()))
|
||||
{
|
||||
QTreeWidgetItem *item = new QTreeWidgetItem((QTreeWidget*)0);
|
||||
item->setSizeHint(0, QSize(42,42)); // make icons non-cropped
|
||||
item->setData(0, Qt::UserRole, theme.name());
|
||||
|
||||
const QVector<QIcon> icons = theme.icons(iconNames);
|
||||
|
||||
const int K = icons.size();
|
||||
for (int i = 0; i < K; ++i)
|
||||
{
|
||||
item->setIcon(i, icons.at(i));
|
||||
}
|
||||
|
||||
QString themeDescription;
|
||||
if (theme.comment().isEmpty())
|
||||
{
|
||||
themeDescription = theme.text();
|
||||
}
|
||||
else
|
||||
{
|
||||
themeDescription = theme.text() % QStringLiteral(" (") % theme.comment() % QStringLiteral(")");
|
||||
}
|
||||
|
||||
item->setText(iconNamesN + 1, themeDescription);
|
||||
|
||||
items.append(item);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
iconThemeList->insertTopLevelItems(0, items);
|
||||
for (int i=0; i<iconThemeList->header()->count()-1; ++i)
|
||||
{
|
||||
iconThemeList->resizeColumnToContents(i);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void IconThemeConfig::initControls()
|
||||
{
|
||||
QString currentTheme = QIcon::themeName();
|
||||
QTreeWidgetItemIterator it(iconThemeList);
|
||||
while (*it) {
|
||||
if ((*it)->data(0, Qt::UserRole).toString() == currentTheme)
|
||||
{
|
||||
iconThemeList->setCurrentItem((*it));
|
||||
break;
|
||||
}
|
||||
++it;
|
||||
}
|
||||
|
||||
iconFollowColorSchemeCB->setChecked(m_settings->value("icon_follow_color_scheme", true).toBool());
|
||||
|
||||
update();
|
||||
}
|
||||
|
||||
|
||||
IconThemeConfig::~IconThemeConfig()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void IconThemeConfig::iconThemeSelected(QTreeWidgetItem *item, int column)
|
||||
{
|
||||
Q_UNUSED(column);
|
||||
const QString theme = item->data(0, Qt::UserRole).toString();
|
||||
if (!theme.isEmpty())
|
||||
{
|
||||
// Ensure that this widget also updates it's own icons
|
||||
QIcon::setThemeName(theme);
|
||||
|
||||
m_settings->setValue("icon_theme", theme);
|
||||
m_settings->sync();
|
||||
}
|
||||
}
|
@ -1,58 +0,0 @@
|
||||
/* BEGIN_COMMON_COPYRIGHT_HEADER
|
||||
* (c)LGPL2+
|
||||
*
|
||||
* LXQt - a lightweight, Qt based, desktop toolset
|
||||
* http://razor-qt.org
|
||||
*
|
||||
* Copyright: 2010-2011 Razor team
|
||||
* Authors:
|
||||
* Petr Vanek <petr@scribus.info>
|
||||
*
|
||||
* This program or 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
|
||||
*
|
||||
* END_COMMON_COPYRIGHT_HEADER */
|
||||
|
||||
#ifndef MAINWINDOW_H
|
||||
#define MAINWINDOW_H
|
||||
|
||||
#include "ui_iconthemeconfig.h"
|
||||
#include "iconthemeinfo.h"
|
||||
|
||||
namespace LXQt {
|
||||
class Settings;
|
||||
}
|
||||
|
||||
|
||||
class IconThemeConfig : public QWidget, public Ui::IconThemeConfig
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
IconThemeConfig(LXQt::Settings *settings, QWidget *parent = 0);
|
||||
~IconThemeConfig();
|
||||
|
||||
private:
|
||||
LXQt::Settings *m_settings;
|
||||
void initIconsThemes();
|
||||
|
||||
public slots:
|
||||
void initControls();
|
||||
|
||||
private slots:
|
||||
void iconThemeSelected(QTreeWidgetItem *item, int column);
|
||||
};
|
||||
|
||||
#endif
|
@ -1,98 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>IconThemeConfig</class>
|
||||
<widget class="QWidget" name="IconThemeConfig">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>450</width>
|
||||
<height>327</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>LXQt Appearance Configuration</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="font">
|
||||
<font>
|
||||
<weight>75</weight>
|
||||
<bold>true</bold>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Icons Theme</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QTreeWidget" name="iconThemeList">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="horizontalScrollBarPolicy">
|
||||
<enum>Qt::ScrollBarAlwaysOff</enum>
|
||||
</property>
|
||||
<property name="alternatingRowColors">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="iconSize">
|
||||
<size>
|
||||
<width>22</width>
|
||||
<height>22</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="rootIsDecorated">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="uniformRowHeights">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="columnCount">
|
||||
<number>4</number>
|
||||
</property>
|
||||
<attribute name="headerVisible">
|
||||
<bool>false</bool>
|
||||
</attribute>
|
||||
<column>
|
||||
<property name="text">
|
||||
<string notr="true">1</string>
|
||||
</property>
|
||||
</column>
|
||||
<column>
|
||||
<property name="text">
|
||||
<string notr="true">2</string>
|
||||
</property>
|
||||
</column>
|
||||
<column>
|
||||
<property name="text">
|
||||
<string notr="true">3</string>
|
||||
</property>
|
||||
</column>
|
||||
<column>
|
||||
<property name="text">
|
||||
<string notr="true">4</string>
|
||||
</property>
|
||||
</column>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="iconFollowColorSchemeCB">
|
||||
<property name="toolTip">
|
||||
<string>The KDE extension of XDG icon themes -> FollowsColorScheme</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Colorize icons based on widget style (palette)</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
@ -1,80 +0,0 @@
|
||||
/* BEGIN_COMMON_COPYRIGHT_HEADER
|
||||
* (c)LGPL2+
|
||||
*
|
||||
* LXQt - a lightweight, Qt based, desktop toolset
|
||||
* https://sourceforge.net/projects/lxde-qt/
|
||||
*
|
||||
* Copyright: 2010-2011 Razor team
|
||||
* Authors:
|
||||
* Alexander Sokoloff <sokoloff.a@gmail.com>
|
||||
* Luis Pereira <luis.artur.pereira@gmail.com>
|
||||
*
|
||||
* The directoryMatchesSize() and thedirectorySizeDistance() functions were
|
||||
* taken from Qt5 qtbase/src/gui/image/qiconloader.cpp
|
||||
* Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
|
||||
*
|
||||
* This program or 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
|
||||
*
|
||||
* END_COMMON_COPYRIGHT_HEADER */
|
||||
|
||||
#include "iconthemeinfo.h"
|
||||
|
||||
#define PREVIEW_ICON_SIZE 22
|
||||
|
||||
IconThemeInfo::IconThemeInfo(const QDir &dir):
|
||||
mValid(false),
|
||||
mHidden(false)
|
||||
{
|
||||
mName = dir.dirName();
|
||||
if (dir.exists(QStringLiteral("index.theme")))
|
||||
load(dir.absoluteFilePath(QStringLiteral("index.theme")));
|
||||
}
|
||||
|
||||
|
||||
void IconThemeInfo::load(const QString &fileName)
|
||||
{
|
||||
mFileName = fileName;
|
||||
mValid = false;
|
||||
QSettings file(mFileName, QSettings::IniFormat);
|
||||
if (file.status() != QSettings::NoError)
|
||||
return;
|
||||
|
||||
if (file.value(QStringLiteral("Icon Theme/Directories")).toStringList().join(QLatin1Char(' ')).isEmpty())
|
||||
return;
|
||||
|
||||
mHidden = file.value(QStringLiteral("Icon Theme/Hidden"), false).toBool();
|
||||
mText = file.value(QStringLiteral("Icon Theme/Name")).toString();
|
||||
mComment = file.value(QStringLiteral("Icon Theme/Comment")).toString();
|
||||
|
||||
mValid = true;
|
||||
}
|
||||
|
||||
|
||||
QVector<QIcon> IconThemeInfo::icons(const QStringList &iconNames) const
|
||||
{
|
||||
QVector<QIcon> icons;
|
||||
QString current_theme = QIcon::themeName();
|
||||
|
||||
QIcon::setThemeName(mName);
|
||||
for (const auto & i : iconNames)
|
||||
{
|
||||
icons.push_back({QIcon::fromTheme(i).pixmap({PREVIEW_ICON_SIZE, PREVIEW_ICON_SIZE})});
|
||||
}
|
||||
|
||||
QIcon::setThemeName(current_theme);
|
||||
|
||||
return icons;
|
||||
}
|
@ -1,65 +0,0 @@
|
||||
/* BEGIN_COMMON_COPYRIGHT_HEADER
|
||||
* (c)LGPL2+
|
||||
*
|
||||
* LXQt - a lightweight, Qt based, desktop toolset
|
||||
* https://sourceforge.net/projects/lxde-qt/
|
||||
*
|
||||
* Copyright: 2010-2011 Razor team
|
||||
* Authors:
|
||||
* Alexander Sokoloff <sokoloff.a@gmail.com>
|
||||
*
|
||||
* This program or 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
|
||||
*
|
||||
* END_COMMON_COPYRIGHT_HEADER */
|
||||
|
||||
#ifndef ICONTHEMEINFO_H
|
||||
#define ICONTHEMEINFO_H
|
||||
|
||||
#include <QObject>
|
||||
|
||||
#include <QIcon>
|
||||
#include <QDir>
|
||||
#include <QSettings>
|
||||
#include <QVector>
|
||||
|
||||
class IconThemeInfo
|
||||
{
|
||||
public:
|
||||
IconThemeInfo(const QDir &dir);
|
||||
|
||||
QString fileName() const { return mFileName; }
|
||||
QString name() const { return mName; }
|
||||
QString text() const { return mText; }
|
||||
QString comment() const { return mComment; }
|
||||
|
||||
bool isValid() const { return mValid; }
|
||||
bool isHidden() const { return mHidden; }
|
||||
QVector<QIcon> icons(const QStringList &iconNames) const;
|
||||
|
||||
private:
|
||||
QString mFileName;
|
||||
QString mName;
|
||||
QString mText;
|
||||
QString mComment;
|
||||
|
||||
bool mValid;
|
||||
bool mHidden;
|
||||
|
||||
void load(const QString &fileName);
|
||||
};
|
||||
|
||||
|
||||
#endif // ICONTHEMEINFO_H
|
@ -1,11 +0,0 @@
|
||||
[Desktop Entry]
|
||||
Type=Application
|
||||
Name=Appearance
|
||||
GenericName=Appearance settings
|
||||
Comment=Appearance settings for LXQt
|
||||
Exec=lxqt-config-appearance
|
||||
Icon=preferences-desktop-theme
|
||||
Categories=Settings;DesktopSettings;Qt;LXQt;
|
||||
OnlyShowIn=LXQt;
|
||||
|
||||
#TRANSLATIONS_DIR=translations
|
@ -1,152 +0,0 @@
|
||||
/* BEGIN_COMMON_COPYRIGHT_HEADER
|
||||
* (c)LGPL2+
|
||||
*
|
||||
* LXQt - a lightweight, Qt based, desktop toolset
|
||||
* http://razor-qt.org
|
||||
*
|
||||
* Copyright: 2012 Razor team
|
||||
* Authors:
|
||||
* Alexander Sokoloff <sokoloff.a@gmail.com>
|
||||
*
|
||||
* This program or 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
|
||||
*
|
||||
* END_COMMON_COPYRIGHT_HEADER */
|
||||
|
||||
#include "lxqtthemeconfig.h"
|
||||
#include "ui_lxqtthemeconfig.h"
|
||||
#include <QTreeWidget>
|
||||
#include <QStandardPaths>
|
||||
#include <QProcess>
|
||||
#include <QItemDelegate>
|
||||
#include <QPainter>
|
||||
|
||||
/*!
|
||||
* \brief Simple delegate to draw system background color below decoration/icon
|
||||
* (needed by System theme, which uses widget background and therefore provides semi-transparent preview)
|
||||
*/
|
||||
class ThemeDecorator : public QItemDelegate
|
||||
{
|
||||
public:
|
||||
using QItemDelegate::QItemDelegate;
|
||||
protected:
|
||||
virtual void drawDecoration(QPainter * painter, const QStyleOptionViewItem & option, const QRect & rect, const QPixmap & pixmap) const override
|
||||
{
|
||||
//Note: can't use QItemDelegate::drawDecoration, because it is ignoring pixmap,
|
||||
//if the icon is valid (and that is set in paint())
|
||||
if (pixmap.isNull() || !rect.isValid())
|
||||
return;
|
||||
|
||||
QPoint p = QStyle::alignedRect(option.direction, option.decorationAlignment, pixmap.size(), rect).topLeft();
|
||||
painter->fillRect(QRect{p, pixmap.size()}, QApplication::palette().color(QPalette::Window));
|
||||
painter->drawPixmap(p, pixmap);
|
||||
}
|
||||
};
|
||||
|
||||
/*!
|
||||
* \brief Check if currently configured wallpaper (read from pcmanfm-qt's
|
||||
* settings) is the same as \param themeWallpaper
|
||||
*/
|
||||
static bool isWallpaperChanged(const QString & themeWallpaper)
|
||||
{
|
||||
static const QString config_path = QStandardPaths::writableLocation(QStandardPaths::ConfigLocation)
|
||||
+ QStringLiteral("/pcmanfm-qt/lxqt/settings.conf");
|
||||
static const QString wallpaper_key = QStringLiteral("Desktop/Wallpaper");
|
||||
const QString current_wallpaper = QSettings{config_path, QSettings::IniFormat}.value(wallpaper_key).toString();
|
||||
return themeWallpaper != current_wallpaper;
|
||||
}
|
||||
|
||||
LXQtThemeConfig::LXQtThemeConfig(LXQt::Settings *settings, QWidget *parent) :
|
||||
QWidget(parent),
|
||||
ui(new Ui::LXQtThemeConfig),
|
||||
mSettings(settings)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
{
|
||||
QScopedPointer<QAbstractItemDelegate> p{ui->lxqtThemeList->itemDelegate()};
|
||||
ui->lxqtThemeList->setItemDelegate(new ThemeDecorator{this});
|
||||
}
|
||||
|
||||
connect(ui->lxqtThemeList, SIGNAL(itemClicked(QTreeWidgetItem*,int)),
|
||||
this, SLOT(lxqtThemeSelected(QTreeWidgetItem*,int)));
|
||||
connect(ui->wallpaperOverride, &QAbstractButton::toggled, [this] (bool checked) {
|
||||
if (checked)
|
||||
lxqtThemeSelected(ui->lxqtThemeList->currentItem(), 0/*not used*/);
|
||||
});
|
||||
|
||||
|
||||
const QList<LXQt::LXQtTheme> themes = LXQt::LXQtTheme::allThemes();
|
||||
foreach(const LXQt::LXQtTheme &theme, themes)
|
||||
{
|
||||
QString themeName = theme.name();
|
||||
themeName[0] = themeName[0].toTitleCase();
|
||||
QTreeWidgetItem *item = new QTreeWidgetItem(QStringList(themeName));
|
||||
if (!theme.previewImage().isEmpty())
|
||||
{
|
||||
item->setIcon(0, QIcon(theme.previewImage()));
|
||||
}
|
||||
item->setSizeHint(0, QSize(42,42)); // make icons non-cropped
|
||||
item->setData(0, Qt::UserRole, theme.name());
|
||||
ui->lxqtThemeList->addTopLevelItem(item);
|
||||
}
|
||||
|
||||
initControls();
|
||||
}
|
||||
|
||||
|
||||
LXQtThemeConfig::~LXQtThemeConfig()
|
||||
{
|
||||
delete ui;
|
||||
}
|
||||
|
||||
|
||||
void LXQtThemeConfig::initControls()
|
||||
{
|
||||
QString currentTheme = mSettings->value("theme").toString();
|
||||
|
||||
QTreeWidgetItemIterator it(ui->lxqtThemeList);
|
||||
while (*it) {
|
||||
if ((*it)->data(0, Qt::UserRole).toString() == currentTheme)
|
||||
{
|
||||
ui->lxqtThemeList->setCurrentItem((*it));
|
||||
break;
|
||||
}
|
||||
++it;
|
||||
}
|
||||
|
||||
update();
|
||||
}
|
||||
|
||||
|
||||
void LXQtThemeConfig::lxqtThemeSelected(QTreeWidgetItem* item, int column)
|
||||
{
|
||||
Q_UNUSED(column);
|
||||
if (!item)
|
||||
return;
|
||||
|
||||
LXQt::LXQtTheme currentTheme{mSettings->value("theme").toString()};
|
||||
QVariant themeName = item->data(0, Qt::UserRole);
|
||||
mSettings->setValue("theme", themeName);
|
||||
LXQt::LXQtTheme theme(themeName.toString());
|
||||
if(theme.isValid()) {
|
||||
QString wallpaper = theme.desktopBackground();
|
||||
if(!wallpaper.isEmpty() && (ui->wallpaperOverride->isChecked() || !isWallpaperChanged(currentTheme.desktopBackground()))) {
|
||||
// call pcmanfm-qt to update wallpaper
|
||||
QStringList args;
|
||||
args << "--set-wallpaper" << wallpaper;
|
||||
QProcess::startDetached("pcmanfm-qt", args);
|
||||
}
|
||||
}
|
||||
}
|
@ -1,59 +0,0 @@
|
||||
/* BEGIN_COMMON_COPYRIGHT_HEADER
|
||||
* (c)LGPL2+
|
||||
*
|
||||
* LXQt - a lightweight, Qt based, desktop toolset
|
||||
* http://razor-qt.org
|
||||
*
|
||||
* Copyright: 2012 Razor team
|
||||
* Authors:
|
||||
* Alexander Sokoloff <sokoloff.a@gmail.com>
|
||||
*
|
||||
* This program or 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
|
||||
*
|
||||
* END_COMMON_COPYRIGHT_HEADER */
|
||||
|
||||
#ifndef LXQTTHEMECONFIG_H
|
||||
#define LXQTTHEMECONFIG_H
|
||||
|
||||
#include <QWidget>
|
||||
#include <LXQt/Settings>
|
||||
|
||||
class QTreeWidgetItem;
|
||||
|
||||
namespace Ui {
|
||||
class LXQtThemeConfig;
|
||||
}
|
||||
|
||||
class LXQtThemeConfig : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit LXQtThemeConfig(LXQt::Settings *settings, QWidget *parent = 0);
|
||||
~LXQtThemeConfig();
|
||||
|
||||
public slots:
|
||||
void initControls();
|
||||
|
||||
private slots:
|
||||
void lxqtThemeSelected(QTreeWidgetItem* item, int column);
|
||||
|
||||
private:
|
||||
Ui::LXQtThemeConfig *ui;
|
||||
LXQt::Settings *mSettings;
|
||||
};
|
||||
|
||||
#endif // LXQTTHEMECONFIG_H
|
@ -1,65 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>LXQtThemeConfig</class>
|
||||
<widget class="QWidget" name="LXQtThemeConfig">
|
||||
<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="font">
|
||||
<font>
|
||||
<weight>75</weight>
|
||||
<bold>true</bold>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>LXQt Theme</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QTreeWidget" name="lxqtThemeList">
|
||||
<property name="alternatingRowColors">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="iconSize">
|
||||
<size>
|
||||
<width>100</width>
|
||||
<height>32</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="rootIsDecorated">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="uniformRowHeights">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<attribute name="headerVisible">
|
||||
<bool>false</bool>
|
||||
</attribute>
|
||||
<column>
|
||||
<property name="text">
|
||||
<string notr="true">1</string>
|
||||
</property>
|
||||
</column>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="wallpaperOverride">
|
||||
<property name="text">
|
||||
<string>Override user-defined wallpaper</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
@ -1,88 +0,0 @@
|
||||
/* BEGIN_COMMON_COPYRIGHT_HEADER
|
||||
* (c)LGPL2+
|
||||
*
|
||||
* LXQt - a lightweight, Qt based, desktop toolset
|
||||
* http://razor-qt.org
|
||||
*
|
||||
* Copyright: 2010-2011 Razor team
|
||||
* Authors:
|
||||
* Petr Vanek <petr@scribus.info>
|
||||
*
|
||||
* This program or 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
|
||||
*
|
||||
* END_COMMON_COPYRIGHT_HEADER */
|
||||
|
||||
#include <LXQt/SingleApplication>
|
||||
|
||||
#include <LXQt/Settings>
|
||||
#include <LXQt/ConfigDialog>
|
||||
#include <QCommandLineParser>
|
||||
#include "iconthemeconfig.h"
|
||||
#include "lxqtthemeconfig.h"
|
||||
#include "styleconfig.h"
|
||||
#include "fontsconfig.h"
|
||||
|
||||
#include "../liblxqt-config-cursor/selectwnd.h"
|
||||
|
||||
int main (int argc, char **argv)
|
||||
{
|
||||
LXQt::SingleApplication app(argc, argv);
|
||||
app.setAttribute(Qt::AA_UseHighDpiPixmaps, true);
|
||||
|
||||
QCommandLineParser parser;
|
||||
parser.setApplicationDescription(QStringLiteral("LXQt Config Appearance"));
|
||||
const QString VERINFO = QStringLiteral(LXQT_CONFIG_VERSION
|
||||
"\nliblxqt " LXQT_VERSION
|
||||
"\nQt " QT_VERSION_STR);
|
||||
app.setApplicationVersion(VERINFO);
|
||||
parser.addVersionOption();
|
||||
parser.addHelpOption();
|
||||
parser.process(app);
|
||||
|
||||
LXQt::Settings* settings = new LXQt::Settings("lxqt");
|
||||
LXQt::Settings* sessionSettings = new LXQt::Settings("session");
|
||||
LXQt::ConfigDialog* dialog = new LXQt::ConfigDialog(QObject::tr("LXQt Appearance Configuration"), settings);
|
||||
|
||||
app.setActivationWindow(dialog);
|
||||
|
||||
QSettings& qtSettings = *settings; // use lxqt config file for Qt settings in Qt5.
|
||||
StyleConfig* stylePage = new StyleConfig(settings, &qtSettings, dialog);
|
||||
dialog->addPage(stylePage, QObject::tr("Widget Style"), QStringList() << "preferences-desktop-theme" << "preferences-desktop");
|
||||
QObject::connect(dialog, SIGNAL(reset()), stylePage, SLOT(initControls()));
|
||||
|
||||
IconThemeConfig* iconPage = new IconThemeConfig(settings, dialog);
|
||||
dialog->addPage(iconPage, QObject::tr("Icons Theme"), QStringList() << "preferences-desktop-icons" << "preferences-desktop");
|
||||
QObject::connect(dialog, SIGNAL(reset()), iconPage, SLOT(initControls()));
|
||||
|
||||
LXQtThemeConfig* themePage = new LXQtThemeConfig(settings, dialog);
|
||||
dialog->addPage(themePage, QObject::tr("LXQt Theme"), QStringList() << "preferences-desktop-color" << "preferences-desktop");
|
||||
QObject::connect(dialog, SIGNAL(reset()), themePage, SLOT(initControls()));
|
||||
|
||||
FontsConfig* fontsPage = new FontsConfig(settings, &qtSettings, dialog);
|
||||
dialog->addPage(fontsPage, QObject::tr("Font"), QStringList() << "preferences-desktop-font" << "preferences-desktop");
|
||||
QObject::connect(dialog, SIGNAL(reset()), fontsPage, SLOT(initControls()));
|
||||
|
||||
SelectWnd* cursorPage = new SelectWnd(sessionSettings, dialog);
|
||||
cursorPage->setCurrent();
|
||||
dialog->addPage(cursorPage, QObject::tr("Cursor"), QStringList() << "input-mouse" << "preferences-desktop");
|
||||
|
||||
dialog->setAttribute(Qt::WA_DeleteOnClose);
|
||||
dialog->setWindowIcon(QIcon::fromTheme("preferences-desktop-theme"));
|
||||
dialog->show();
|
||||
|
||||
return app.exec();
|
||||
}
|
||||
|
@ -1,50 +0,0 @@
|
||||
.TH lxqt-config-appearance "1" "September 2012" "LXQt\ 0.7.0" "LXQt\ GUI settings"
|
||||
.SH NAME
|
||||
lxqt-config-appearance \- GUI appearance application of \fBLXQt\fR: the faster and lighter QT Desktop Environment
|
||||
.SH SYNOPSIS
|
||||
.B lxqt-config-appearance
|
||||
.br
|
||||
.SH DESCRIPTION
|
||||
With this application you can setting and configuring qt/lxqt gui appearance of programs.
|
||||
.P
|
||||
The GUI applications in linux depends of their respective subsystem, in lxqt the overal aspect of
|
||||
many apps relies on QT4 framework gui. The \fBlxqt-config-appearance\fR application its the configuration center
|
||||
to provide all aspects of setting \fBLXQt\fR desktop in session settings related programs.
|
||||
.P
|
||||
All remaining mayor aspect for lxqt appearance relies over qt4 config application (\fBqtconfig\-qt4\fR), due
|
||||
the \fBLXQt\fR DE are based on Qt framework.
|
||||
.P
|
||||
\fBLXQt\fR is an advanced, easy-to-use, and fast desktop environment based on Qt
|
||||
technologies, ships several core desktop components, all of which are optional:
|
||||
.P
|
||||
* Panel
|
||||
* Desktop
|
||||
* Application launcher
|
||||
* Settings center \fI(related to this)\fR
|
||||
* Session handler
|
||||
* Polkit handler
|
||||
* SSH pasword manager
|
||||
* Display manager handler
|
||||
* Power manager
|
||||
.P
|
||||
These components perform similar actions to those available in other desktop
|
||||
environments, and their name is self-descriptive. They are usually not launched
|
||||
by hand but automatically, when choosing a \fBLXQt\-qt\fR session in the Display
|
||||
Manager.
|
||||
.P
|
||||
.SH "REPORTING BUGS"
|
||||
Report bugs to https://github.com/lxde/lxqt/issues
|
||||
.SH "SEE ALSO"
|
||||
\fBLXQt\fR it has been tailored for users who value simplicity, speed, and
|
||||
an intuitive interface, also intended for less powerful machines. See also:
|
||||
.\" any module must refers to session app, for more info on start it
|
||||
.P
|
||||
\fBlxqt-session.1\fR LXQt module for manage LXQt complete environment.
|
||||
.P
|
||||
\fBlxqt-config.1\fR LXQt application for general config and settings.
|
||||
.P
|
||||
\fBqtconfig-qt4.1\fR Qt4 application for gui and appereance settings over all qt4 based software.
|
||||
.P
|
||||
.SH AUTHOR
|
||||
This manual page was created by \fBPICCORO Lenz McKAY\fR \fI<mckaygerhard@gmail.com>\fR
|
||||
for \fBLXQt\fR project and VENENUX GNU/Linux but can be used by others.
|
@ -1,142 +0,0 @@
|
||||
/* BEGIN_COMMON_COPYRIGHT_HEADER
|
||||
* (c)LGPL2+
|
||||
*
|
||||
* LXQt - a lightweight, Qt based, desktop toolset
|
||||
* http://lxde.org/
|
||||
*
|
||||
* Copyright: 2014 LXQt team
|
||||
* Authors:
|
||||
* Hong Jen Yee (PCMan) <pcman.tw@gmail.com>
|
||||
*
|
||||
* This program or 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
|
||||
*
|
||||
* END_COMMON_COPYRIGHT_HEADER */
|
||||
|
||||
#include "styleconfig.h"
|
||||
#include "ui_styleconfig.h"
|
||||
#include <QTreeWidget>
|
||||
#include <QDebug>
|
||||
#include <QStyleFactory>
|
||||
#include <QToolBar>
|
||||
#include <QSettings>
|
||||
#include <QMetaObject>
|
||||
#include <QMetaProperty>
|
||||
#include <QMetaEnum>
|
||||
#include <QToolBar>
|
||||
|
||||
#ifdef Q_WS_X11
|
||||
extern void qt_x11_apply_settings_in_all_apps();
|
||||
#endif
|
||||
|
||||
StyleConfig::StyleConfig(LXQt::Settings* settings, QSettings* qtSettings, QWidget* parent) :
|
||||
QWidget(parent),
|
||||
ui(new Ui::StyleConfig),
|
||||
mQtSettings(qtSettings),
|
||||
mSettings(settings)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
|
||||
connect(ui->styleList, SIGNAL(itemClicked(QTreeWidgetItem*,int)),
|
||||
this, SLOT(styleSelected(QTreeWidgetItem*,int)));
|
||||
|
||||
Q_FOREACH(const QString& name, QStyleFactory::keys())
|
||||
{
|
||||
QTreeWidgetItem *item = new QTreeWidgetItem(QStringList(name));
|
||||
ui->styleList->addTopLevelItem(item);
|
||||
}
|
||||
|
||||
initControls();
|
||||
|
||||
connect(ui->toolButtonStyle, SIGNAL(currentIndexChanged(int)), SLOT(toolButtonStyleSelected(int)));
|
||||
connect(ui->singleClickActivate, SIGNAL(toggled(bool)), SLOT(singleClickActivateToggled(bool)));
|
||||
}
|
||||
|
||||
|
||||
StyleConfig::~StyleConfig()
|
||||
{
|
||||
delete ui;
|
||||
}
|
||||
|
||||
|
||||
void StyleConfig::initControls()
|
||||
{
|
||||
// read Qt style settings from Qt Trolltech.conf config
|
||||
mQtSettings->beginGroup(QLatin1String("Qt"));
|
||||
QString currentTheme = mQtSettings->value("style").toString();
|
||||
mQtSettings->endGroup();
|
||||
|
||||
QTreeWidgetItemIterator it(ui->styleList);
|
||||
while (*it) {
|
||||
if ((*it)->data(0, Qt::DisplayRole).toString() == currentTheme)
|
||||
{
|
||||
ui->styleList->setCurrentItem((*it));
|
||||
break;
|
||||
}
|
||||
++it;
|
||||
}
|
||||
|
||||
// read other widget related settings form LXQt settings.
|
||||
QByteArray tb_style = mSettings->value("tool_button_style").toByteArray();
|
||||
// convert toolbar style name to value
|
||||
QMetaEnum me = QToolBar::staticMetaObject.property(QToolBar::staticMetaObject.indexOfProperty("toolButtonStyle")).enumerator();
|
||||
int val = me.keyToValue(tb_style.constData());
|
||||
if(val == -1)
|
||||
val = Qt::ToolButtonTextBesideIcon;
|
||||
ui->toolButtonStyle->setCurrentIndex(val);
|
||||
|
||||
// activate item views with single click
|
||||
ui->singleClickActivate->setChecked( mSettings->value("single_click_activate", false).toBool());
|
||||
|
||||
update();
|
||||
}
|
||||
|
||||
|
||||
void StyleConfig::styleSelected(QTreeWidgetItem* item, int column)
|
||||
{
|
||||
Q_UNUSED(column);
|
||||
if (!item)
|
||||
return;
|
||||
QVariant themeName = item->data(0, Qt::DisplayRole);
|
||||
mQtSettings->beginGroup(QLatin1String("Qt"));
|
||||
mQtSettings->setValue("style", themeName);
|
||||
mQtSettings->endGroup();
|
||||
mQtSettings->sync();
|
||||
|
||||
#ifdef Q_WS_X11
|
||||
qt_x11_apply_settings_in_all_apps();
|
||||
#endif
|
||||
}
|
||||
|
||||
void StyleConfig::toolButtonStyleSelected(int index)
|
||||
{
|
||||
// convert style value to string
|
||||
QMetaEnum me = QToolBar::staticMetaObject.property(QToolBar::staticMetaObject.indexOfProperty("toolButtonStyle")).enumerator();
|
||||
if(index == -1)
|
||||
index = Qt::ToolButtonTextBesideIcon;
|
||||
const char* str = me.valueToKey(index);
|
||||
if(str)
|
||||
{
|
||||
mSettings->setValue("tool_button_style", str);
|
||||
mSettings->sync();
|
||||
}
|
||||
}
|
||||
|
||||
void StyleConfig::singleClickActivateToggled(bool toggled)
|
||||
{
|
||||
mSettings->setValue("single_click_activate", toggled);
|
||||
mSettings->sync();
|
||||
}
|
||||
|
@ -1,63 +0,0 @@
|
||||
/* BEGIN_COMMON_COPYRIGHT_HEADER
|
||||
* (c)LGPL2+
|
||||
*
|
||||
* LXQt - a lightweight, Qt based, desktop toolset
|
||||
* http://razor-qt.org
|
||||
*
|
||||
* Copyright: 2012 Razor team
|
||||
* Authors:
|
||||
* Alexander Sokoloff <sokoloff.a@gmail.com>
|
||||
*
|
||||
* This program or 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
|
||||
*
|
||||
* END_COMMON_COPYRIGHT_HEADER */
|
||||
|
||||
#ifndef STYLECONFIG_H
|
||||
#define STYLECONFIG_H
|
||||
|
||||
#include <QWidget>
|
||||
#include <LXQt/Settings>
|
||||
|
||||
class QTreeWidgetItem;
|
||||
class QSettings;
|
||||
|
||||
namespace Ui {
|
||||
class StyleConfig;
|
||||
}
|
||||
|
||||
class StyleConfig : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit StyleConfig(LXQt::Settings *settings, QSettings *qtSettings, QWidget *parent = 0);
|
||||
~StyleConfig();
|
||||
|
||||
public slots:
|
||||
void initControls();
|
||||
|
||||
private slots:
|
||||
void styleSelected(QTreeWidgetItem* item, int column);
|
||||
void toolButtonStyleSelected(int index);
|
||||
void singleClickActivateToggled(bool toggled);
|
||||
|
||||
private:
|
||||
Ui::StyleConfig *ui;
|
||||
QSettings *mQtSettings;
|
||||
LXQt::Settings *mSettings;
|
||||
};
|
||||
|
||||
#endif // STYLECONFIG_H
|
@ -1,98 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>StyleConfig</class>
|
||||
<widget class="QWidget" name="StyleConfig">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>490</width>
|
||||
<height>363</height>
|
||||
</rect>
|
||||
</property>
|
||||
<layout class="QFormLayout" name="formLayout">
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="font">
|
||||
<font>
|
||||
<weight>75</weight>
|
||||
<bold>true</bold>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Widget Style</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0" colspan="2">
|
||||
<widget class="QTreeWidget" name="styleList">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>1</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="alternatingRowColors">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="rootIsDecorated">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<attribute name="headerVisible">
|
||||
<bool>false</bool>
|
||||
</attribute>
|
||||
<column>
|
||||
<property name="text">
|
||||
<string notr="true">1</string>
|
||||
</property>
|
||||
</column>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="label_2">
|
||||
<property name="text">
|
||||
<string>Toolbar button style:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QComboBox" name="toolButtonStyle">
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Only display the icon</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Only display the text</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>The text appears beside the icon</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>The text appears under the icon</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Default</string>
|
||||
</property>
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0" colspan="2">
|
||||
<widget class="QCheckBox" name="singleClickActivate">
|
||||
<property name="text">
|
||||
<string>Activate item on single click</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
@ -1,4 +0,0 @@
|
||||
# Translations
|
||||
Comment[ar]=إعدادات مظهر لكسكيوت
|
||||
GenericName[ar]=إعدادات المظهر
|
||||
Name[ar]=المظهر
|
@ -1,4 +0,0 @@
|
||||
# Translations
|
||||
Name[ca]=Aparença
|
||||
GenericName[ca]=Ajusts de l'aparença
|
||||
Comment[ca]=Ajusts de l'aparença per a LXQt
|
@ -1,4 +0,0 @@
|
||||
# Translations
|
||||
Comment[cs]=Nastavit vzhled pracovní plochy LXQt
|
||||
GenericName[cs]=Nastavení vzhledu
|
||||
Name[cs]=Nastavení vzhledu
|
@ -1,4 +0,0 @@
|
||||
# Translations
|
||||
Comment[cs_CZ]=Nastavit vzhled pracovní plochy LXQt
|
||||
GenericName[cs_CZ]=Nastavení vzhledu
|
||||
Name[cs_CZ]=Nastavení vzhledu
|
@ -1,4 +0,0 @@
|
||||
# Translations
|
||||
Name[da]=Udseende
|
||||
GenericName[da]=Udseendeindstillinger
|
||||
Comment[da]=Udseendeindstillinger for LXQt
|
@ -1,3 +0,0 @@
|
||||
Name[de]=Erscheinungsbild
|
||||
GenericName[de]=Erscheinungsbild Einstellungen
|
||||
Comment[de]=Einstellungen zum Aussehen der LXQt Arbeitsfläche
|
@ -1,4 +0,0 @@
|
||||
# Translations
|
||||
Comment[el]=Διαμόρφωση εμφάνισης της επιφάνειας εργασίας LXQt
|
||||
GenericName[el]=Διαμόρφωση εμφάνισης LXQt
|
||||
Name[el]=Διαμόρφωση εμφάνισης LXQt
|
@ -1,4 +0,0 @@
|
||||
# Translations
|
||||
Comment[eo]=Agordi aperon de LXQt-labortablo
|
||||
GenericName[eo]=Agordoj de apero de LXQt
|
||||
Name[eo]=Agordoj de apero de LXQt
|
@ -1,4 +0,0 @@
|
||||
# Translations
|
||||
Comment[es]=Configura el aspecto del escritorio LXQt
|
||||
GenericName[es]=Configuración de Aspecto LXQt
|
||||
Name[es]=Configuración de Aspecto LXQt
|
@ -1,4 +0,0 @@
|
||||
# Translations
|
||||
Comment[es_VE]=Configurar apariencia del escritorio LXQt
|
||||
GenericName[es_VE]=Configuración de apariencia de LXQt
|
||||
Name[es_VE]=Configuración de apariencia de LXQt
|
@ -1,4 +0,0 @@
|
||||
# Translations
|
||||
Comment[eu]=Konfiguratu LXQt mahaigainaren itxura
|
||||
GenericName[eu]=LXQt itxuraren konfigurazioa
|
||||
Name[eu]=LXQt itxuraren konfigurazioa
|
@ -1,4 +0,0 @@
|
||||
# Translations
|
||||
Comment[fi]=Hallitse LXQt-työpöydän ulkoasua
|
||||
GenericName[fi]=LXQtin ulkoasun hallinta
|
||||
Name[fi]=LXQtin ulkoasun hallinta
|
@ -1,4 +0,0 @@
|
||||
# Translations
|
||||
Name[fr]=Apparence
|
||||
GenericName[fr]=Configurer l'apparence
|
||||
Comment[fr]=Configurer l'apparence de LXQt
|
@ -1,4 +0,0 @@
|
||||
# Translations
|
||||
Comment[hu]=A LXQt asztal megjelenésének beállítása
|
||||
GenericName[hu]=LXQt megjelenésbeállító
|
||||
Name[hu]=LXQt megjelenésbeállító
|
@ -1 +0,0 @@
|
||||
# Translations
|
@ -1 +0,0 @@
|
||||
# Translations
|
@ -1,4 +0,0 @@
|
||||
# Translations
|
||||
GenericName[it]=Aspetto
|
||||
Name[it]=Aspetto
|
||||
Comment[it]=Configura l'aspetto di LXQt
|
@ -1,4 +0,0 @@
|
||||
# Translations
|
||||
Comment[ja]=LXQtデスクトップの外観を設定
|
||||
GenericName[ja]=LXQt外観の設定
|
||||
Name[ja]=LXQt外観の設定
|
@ -1 +0,0 @@
|
||||
# Translations
|
@ -1,4 +0,0 @@
|
||||
# Translations
|
||||
Comment[lt]=LXQt išvaizdos nustatymai
|
||||
GenericName[lt]=Išvaizdos nustatymai
|
||||
Name[lt]=Išvaizda
|
@ -1,4 +0,0 @@
|
||||
# Translations
|
||||
Comment[nl]=Configureer het uiterlijk van het LXQt bureaublad
|
||||
GenericName[nl]=LXQt Uiterlijk Configuratie
|
||||
Name[nl]=LXQt Uiterlijk Configuratie
|
@ -1,4 +0,0 @@
|
||||
# Translations
|
||||
Comment[pl_PL]=Konfiguruj wygląd pulpitu LXQt
|
||||
GenericName[pl_PL]=Konfiguracja wyglądu LXQt
|
||||
Name[pl_PL]=Konfiguracja wyglądu LXQt
|
@ -1,4 +0,0 @@
|
||||
# Translations
|
||||
Comment[pt]=Configurar o aspeto do LXQt
|
||||
GenericName[pt]=Configuração da aparência do LXQt
|
||||
Name[pt]=Configuração da aparência do LXQt
|
@ -1,4 +0,0 @@
|
||||
# Translations
|
||||
Comment[pt_BR]=Configure a aparência da área de trabalho LXQt
|
||||
GenericName[pt_BR]=Configuração da aparência do LXQt
|
||||
Name[pt_BR]=Configuração da aparência do LXQt
|
@ -1,4 +0,0 @@
|
||||
# Translations
|
||||
Comment[ro_RO]=Configurează aspectul desktopului LXQt
|
||||
GenericName[ro_RO]=Configurare aspect LXQt
|
||||
Name[ro_RO]=Configurare aspect LXQt
|
@ -1,4 +0,0 @@
|
||||
# Translations
|
||||
Comment[ru]=Настройки внешнего вида LXQt
|
||||
GenericName[ru]=Настройка внешнего вида
|
||||
Name[ru]=Внешний вид
|
@ -1,4 +0,0 @@
|
||||
# Translations
|
||||
Comment[sk]=Nastavenie vzhľadu prostredia LXQt
|
||||
GenericName[sk]=Nastavenie vzhľadu
|
||||
Name[sk]=Nastavenie vzhľadu
|
@ -1,4 +0,0 @@
|
||||
# Translations
|
||||
Comment[sl]=Nastavite videz namizja LXQt
|
||||
GenericName[sl]=Nastavitev videza
|
||||
Name[sl]=Nastavitev videza namizja LXQt
|
@ -1,4 +0,0 @@
|
||||
# Translations
|
||||
Comment[sr]=Подесите изглед Рејзорове радне површи
|
||||
GenericName[sr]=Подешавање изгледа
|
||||
Name[sr]=Подешавање изгледа Рејзора
|
@ -1,3 +0,0 @@
|
||||
Name[sr@ijekavian]=Подешавање изгледа Рејзора
|
||||
Comment[sr@ijekavian]=Подесите изглед Рејзорове радне површи
|
||||
GenericName[sr@ijekavian]=Подешавање изгледа
|
@ -1,3 +0,0 @@
|
||||
Name[sr@ijekavianlatin]=Podešavanje izgleda Rejzora
|
||||
Comment[sr@ijekavianlatin]=Podesite izgled Rejzorove radne površi
|
||||
GenericName[sr@ijekavianlatin]=Podešavanje izgleda
|
@ -1,4 +0,0 @@
|
||||
# Translations
|
||||
Comment[sr@latin]=Podesite izgled Rejzorove radne površi
|
||||
GenericName[sr@latin]=Podešavanje izgleda
|
||||
Name[sr@latin]=Podešavanje izgleda Rejzora
|
@ -1,4 +0,0 @@
|
||||
# Translations
|
||||
Comment[th_TH]=ตั้งค่ารูปลักษณ์ของเดสก์ท็อป LXQt
|
||||
GenericName[th_TH]=การตั้งค่ารูปลักษณ์ LXQt
|
||||
Name[th_TH]=การตั้งค่ารูปลักษณ์ LXQt
|
@ -1,4 +0,0 @@
|
||||
# Translations
|
||||
Comment[uk]=Налаштувати вигляд стільниці LXQt
|
||||
GenericName[uk]=Налаштування вигляду LXQt
|
||||
Name[uk]=Налаштування вигляду LXQt
|
@ -1 +0,0 @@
|
||||
# Translations
|
@ -1,4 +0,0 @@
|
||||
# Translations
|
||||
Comment[zh_CN]=配置 LXQt 桌面的外观
|
||||
GenericName[zh_CN]=LXQt 外观配置
|
||||
Name[zh_CN]=LXQt 外观配置
|
@ -1,4 +0,0 @@
|
||||
# Translations
|
||||
Comment[zh_TW]=自定LXQt桌面的外觀
|
||||
GenericName[zh_TW]=LXQt外觀設定
|
||||
Name[zh_TW]=LXQt外觀設定
|
@ -1,84 +0,0 @@
|
||||
project(lxqt-config-brightness)
|
||||
|
||||
find_package(Qt5Widgets REQUIRED QUIET)
|
||||
find_package(Qt5X11Extras REQUIRED QUIET)
|
||||
|
||||
find_package(XCB REQUIRED xcb xcb-randr)
|
||||
|
||||
set(QTX_LIBRARIES Qt5::Widgets Qt5::X11Extras)
|
||||
|
||||
|
||||
include_directories (
|
||||
${XCB_INCLUDE_DIRS}
|
||||
)
|
||||
|
||||
set(H_FILES
|
||||
brightnesssettings.h
|
||||
xrandrbrightness.h
|
||||
monitorinfo.h
|
||||
outputwidget.h
|
||||
)
|
||||
|
||||
set(CPP_FILES
|
||||
main.cpp
|
||||
brightnesssettings.cpp
|
||||
xrandrbrightness.cpp
|
||||
monitorinfo.cpp
|
||||
outputwidget.cpp
|
||||
)
|
||||
|
||||
set(UI_FILES
|
||||
brightnesssettings.ui
|
||||
outputwidget.ui
|
||||
)
|
||||
|
||||
qt5_wrap_ui(UI_HEADERS ${UI_FILES})
|
||||
|
||||
|
||||
# Translations **********************************
|
||||
lxqt_translate_ts(QM_FILES
|
||||
UPDATE_TRANSLATIONS
|
||||
${UPDATE_TRANSLATIONS}
|
||||
SOURCES
|
||||
${H_FILES}
|
||||
${CPP_FILES}
|
||||
${UI_FILES}
|
||||
INSTALL_DIR
|
||||
"${LXQT_TRANSLATIONS_DIR}/${PROJECT_NAME}"
|
||||
PULL_TRANSLATIONS
|
||||
${PULL_TRANSLATIONS}
|
||||
CLEAN_TRANSLATIONS
|
||||
${CLEAN_TRANSLATIONS}
|
||||
TRANSLATIONS_REPO
|
||||
${TRANSLATIONS_REPO}
|
||||
TRANSLATIONS_REFSPEC
|
||||
${TRANSLATIONS_REFSPEC}
|
||||
REPO_SUBDIR
|
||||
"lxqt-config/${PROJECT_NAME}"
|
||||
)
|
||||
|
||||
lxqt_app_translation_loader(QM_LOADER ${PROJECT_NAME})
|
||||
lxqt_translate_desktop(DESKTOP_FILES SOURCES "resources/${PROJECT_NAME}.desktop.in")
|
||||
|
||||
|
||||
add_executable(${PROJECT_NAME} ${CPP_FILES} ${UI_FILES} ${QM_FILES} ${DESKTOP_FILES} ${QM_LOADER})
|
||||
|
||||
target_link_libraries(
|
||||
${PROJECT_NAME}
|
||||
${QTX_LIBRARIES}
|
||||
${XCB_LIBRARIES}
|
||||
lxqt
|
||||
)
|
||||
|
||||
add_definitions(
|
||||
-DICON_DIR="${CMAKE_INSTALL_PREFIX}/share/icons/hicolor/48x48/apps"
|
||||
)
|
||||
|
||||
|
||||
install(TARGETS ${PROJECT_NAME} RUNTIME DESTINATION bin)
|
||||
install(FILES ${DESKTOP_FILES} DESTINATION ${CMAKE_INSTALL_PREFIX}/share/applications)
|
||||
install(
|
||||
FILES icons/brightnesssettings.svg
|
||||
DESTINATION "${CMAKE_INSTALL_PREFIX}/share/icons/hicolor/48x48/apps"
|
||||
)
|
||||
|
@ -1,4 +0,0 @@
|
||||
# brightness-settings
|
||||
|
||||
This tool changes brightness and gamma of your screen. It is a X11 tool. LibKScreen can not change brightness or gamma yet.
|
||||
|
@ -1,101 +0,0 @@
|
||||
/*
|
||||
Copyright (C) 2016 P.L. Lucas <selairi@gmail.com>
|
||||
|
||||
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
|
||||
*/
|
||||
|
||||
#include "brightnesssettings.h"
|
||||
#include "outputwidget.h"
|
||||
#include <QMessageBox>
|
||||
#include <QPushButton>
|
||||
|
||||
BrightnessSettings::BrightnessSettings(QWidget *parent):QDialog(parent)
|
||||
{
|
||||
ui = new Ui::BrightnessSettings();
|
||||
ui->setupUi(this);
|
||||
|
||||
mBrightness = new XRandrBrightness();
|
||||
mMonitors = mBrightness->getMonitorsInfo();
|
||||
|
||||
for(const MonitorInfo &monitor: mMonitors)
|
||||
{
|
||||
OutputWidget *output = new OutputWidget(monitor, this);
|
||||
ui->layout->addWidget(output);
|
||||
output->show();
|
||||
connect(output, SIGNAL(changed(MonitorInfo)), this, SLOT(monitorSettingsChanged(MonitorInfo)));
|
||||
connect(this, &BrightnessSettings::monitorReverted, output, &OutputWidget::setRevertedValues);
|
||||
}
|
||||
|
||||
mConfirmRequestTimer.setSingleShot(true);
|
||||
mConfirmRequestTimer.setInterval(1000);
|
||||
connect(&mConfirmRequestTimer, &QTimer::timeout, this, &BrightnessSettings::requestConfirmation);
|
||||
|
||||
}
|
||||
|
||||
void BrightnessSettings::monitorSettingsChanged(MonitorInfo monitor)
|
||||
{
|
||||
mBrightness->setMonitorsSettings(QList<MonitorInfo>{} << monitor);
|
||||
if (ui->confirmCB->isChecked())
|
||||
{
|
||||
mConfirmRequestTimer.start();
|
||||
} else
|
||||
{
|
||||
for (auto & m : mMonitors)
|
||||
{
|
||||
if (m.id() == monitor.id() && m.name() == monitor.name())
|
||||
{
|
||||
m.setBacklight(monitor.backlight());
|
||||
m.setBrightness(monitor.brightness());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void BrightnessSettings::requestConfirmation()
|
||||
{
|
||||
QMessageBox msg{QMessageBox::Question, tr("Brightness settings changed")
|
||||
, tr("Confirmation required. Are the settings correct?")
|
||||
, QMessageBox::Yes | QMessageBox::No};
|
||||
int timeout = 5; // seconds
|
||||
QString no_text = msg.button(QMessageBox::No)->text();
|
||||
no_text += QStringLiteral("(%1)");
|
||||
msg.setButtonText(QMessageBox::No, no_text.arg(timeout));
|
||||
msg.setDefaultButton(QMessageBox::No);
|
||||
|
||||
QTimer timeoutTimer;
|
||||
timeoutTimer.setSingleShot(false);
|
||||
timeoutTimer.setInterval(1000);
|
||||
connect(&timeoutTimer, &QTimer::timeout, [&] {
|
||||
msg.setButtonText(QMessageBox::No, no_text.arg(--timeout));
|
||||
if (timeout == 0)
|
||||
{
|
||||
timeoutTimer.stop();
|
||||
msg.reject();
|
||||
}
|
||||
});
|
||||
timeoutTimer.start();
|
||||
|
||||
if (QMessageBox::Yes == msg.exec())
|
||||
{
|
||||
// re-read current values
|
||||
mMonitors = mBrightness->getMonitorsInfo();
|
||||
} else
|
||||
{
|
||||
// revert the changes
|
||||
mBrightness->setMonitorsSettings(mMonitors);
|
||||
for (const auto & monitor : mMonitors)
|
||||
emit monitorReverted(monitor);
|
||||
}
|
||||
}
|
@ -1,53 +0,0 @@
|
||||
/*
|
||||
Copyright (C) 2016 P.L. Lucas <selairi@gmail.com>
|
||||
|
||||
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
|
||||
*/
|
||||
|
||||
#ifndef __BRIGHTNESS_SETTINGS_H__
|
||||
#define __BRIGHTNESS_SETTINGS_H__
|
||||
|
||||
#include <QDialog>
|
||||
#include <QTimer>
|
||||
#include "xrandrbrightness.h"
|
||||
#include "ui_brightnesssettings.h"
|
||||
|
||||
|
||||
class BrightnessSettings: public QDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
BrightnessSettings(QWidget *parent =0);
|
||||
|
||||
signals:
|
||||
void monitorReverted(const MonitorInfo & monitor);
|
||||
|
||||
public slots:
|
||||
void monitorSettingsChanged(MonitorInfo monitor);
|
||||
void requestConfirmation();
|
||||
|
||||
private:
|
||||
XRandrBrightness *mBrightness;
|
||||
QList<MonitorInfo> mMonitors;
|
||||
QTimer mConfirmRequestTimer;
|
||||
Ui::BrightnessSettings *ui;
|
||||
|
||||
|
||||
};
|
||||
|
||||
|
||||
#endif
|
||||
|
@ -1,89 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>BrightnessSettings</class>
|
||||
<widget class="QDialog" name="BrightnessSettings">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>406</width>
|
||||
<height>110</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Brightness Settings</string>
|
||||
</property>
|
||||
<property name="windowIcon">
|
||||
<iconset theme="system">
|
||||
<normaloff/>
|
||||
</iconset>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="text">
|
||||
<string><html><head/><body><p><span style=" font-weight:600;">Backlight and brightness settings:</span></p><p>Use arrow keys to change settings.</p></body></html></string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QVBoxLayout" name="layout"/>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="confirmCB">
|
||||
<property name="text">
|
||||
<string>Require confirmation after settings change</string>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QDialogButtonBox" name="buttonBox">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="standardButtons">
|
||||
<set>QDialogButtonBox::Close</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections>
|
||||
<connection>
|
||||
<sender>buttonBox</sender>
|
||||
<signal>accepted()</signal>
|
||||
<receiver>BrightnessSettings</receiver>
|
||||
<slot>accept()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>248</x>
|
||||
<y>254</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>157</x>
|
||||
<y>274</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>buttonBox</sender>
|
||||
<signal>rejected()</signal>
|
||||
<receiver>BrightnessSettings</receiver>
|
||||
<slot>reject()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>316</x>
|
||||
<y>260</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>286</x>
|
||||
<y>274</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
</connections>
|
||||
</ui>
|
Before Width: | Height: | Size: 4.7 KiB |
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in new issue