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