kf6-plasma-activities: vendor as full-fork recipe (path=source, patches baked)
This commit is contained in:
@@ -6,8 +6,13 @@ version = "6.7.2"
|
||||
# Provides Plasma::Activities and PlasmaActivitiesConfig.cmake.
|
||||
# Required by plasma-framework (KDE Plasma 6.x). Built from upstream tarball.
|
||||
[source]
|
||||
tar = "https://download.kde.org/stable/plasma/6.7.2/plasma-activities-6.7.2.tar.xz"
|
||||
blake3 = "0cc63d3e9eb0387c0da7b7051d82962352769285eb156ce009784b144d495655"
|
||||
# Vendored local fork (full-fork model): builds from the committed source/
|
||||
# tree (offline, reproducible). source/ = pristine upstream + the patches below
|
||||
# BAKED IN. .patch files kept tracked so a version bump can re-apply them via
|
||||
# sync-recipe-source.sh.
|
||||
# upstream: https://download.kde.org/stable/plasma/6.7.2/plasma-activities-6.7.2.tar.xz
|
||||
# blake3: 0cc63d3e9eb0387c0da7b7051d82962352769285eb156ce009784b144d495655
|
||||
path = "source"
|
||||
|
||||
[build]
|
||||
template = "custom"
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
#clang-format/tidy
|
||||
964b4dae478d9b7a03949718f18afa002286f433
|
||||
9b987f0e87a88896d549249577cce51ceb13a543
|
||||
e2abd678e4fc38552d3360759e4e47b02de0bf9d
|
||||
07a6b88bbd4c74d0bae94111770ba5020def0fef
|
||||
@@ -0,0 +1,25 @@
|
||||
.debug
|
||||
tags
|
||||
_tests
|
||||
.videproject/ctags
|
||||
*swp
|
||||
*~
|
||||
.kdev4
|
||||
.cmake-params
|
||||
.ycm_extra_conf.py
|
||||
.ycm_extra_conf.pyc
|
||||
.clang_complete
|
||||
kactivities.kdev4
|
||||
compile_commands.json
|
||||
/apidocs
|
||||
GPATH
|
||||
GRTAGS
|
||||
GSYMS
|
||||
GTAGS
|
||||
.cmake/
|
||||
/.clang-format
|
||||
/build*
|
||||
.idea
|
||||
.clangd
|
||||
/cmake-build*
|
||||
.cache
|
||||
@@ -0,0 +1,11 @@
|
||||
# SPDX-FileCopyrightText: 2020 Volker Krause <vkrause@kde.org>
|
||||
# SPDX-License-Identifier: CC0-1.0
|
||||
|
||||
include:
|
||||
- project: sysadmin/ci-utilities
|
||||
file:
|
||||
- /gitlab-templates/linux-qt6.yml
|
||||
- /gitlab-templates/freebsd-qt6.yml
|
||||
- /gitlab-templates/xml-lint.yml
|
||||
- /gitlab-templates/yaml-lint.yml
|
||||
- /gitlab-templates/linux-qt6-next.yml
|
||||
@@ -0,0 +1,11 @@
|
||||
Dependencies:
|
||||
- 'on': ['Linux', 'FreeBSD', 'Windows', 'macOS']
|
||||
'require':
|
||||
'frameworks/extra-cmake-modules': '@latest-kf6'
|
||||
'frameworks/kconfig': '@latest-kf6'
|
||||
'frameworks/kwindowsystem': '@latest-kf6'
|
||||
'frameworks/kcoreaddons': '@latest-kf6'
|
||||
|
||||
Options:
|
||||
test-before-installing: True
|
||||
require-passing-tests-on: ['Linux', 'FreeBSD']
|
||||
@@ -0,0 +1 @@
|
||||
plasma-activities-6.7.2.tar.xz
|
||||
@@ -0,0 +1,30 @@
|
||||
[Project]
|
||||
Name=KDE Activities
|
||||
Location=/opt/kde/src/libs/kactivities
|
||||
|
||||
MakeCommand='OBJ_REPLACEMENT="s:/opt/kde/src/core/libs/kactivities:/opt/kde/build-clang/core/libs/kactivities:" makeobj'
|
||||
|
||||
RunLocation=./
|
||||
RunCommand=./
|
||||
|
||||
[General]
|
||||
OverrideVimCommands=1
|
||||
AutoInsertModeOnOpen=0
|
||||
Tags=
|
||||
SourcePaths=.
|
||||
|
||||
[KeyBindings]
|
||||
SidePanelOpen='<C-A>'
|
||||
MakeProject='<F5>'
|
||||
RunProject='<F6>'
|
||||
|
||||
[Grep]
|
||||
Root=.
|
||||
|
||||
[Find]
|
||||
Root=.
|
||||
|
||||
[QuickBrowser]
|
||||
iNotifyEnabled=0
|
||||
Root=.
|
||||
TagsSystem=ctags
|
||||
@@ -0,0 +1,2 @@
|
||||
|
||||
set tags+=/opt/kde4trunk/ctags/libQt.tags
|
||||
@@ -0,0 +1,91 @@
|
||||
# vim:set softtabstop=3 shiftwidth=3 tabstop=3 expandtab:
|
||||
cmake_minimum_required(VERSION 3.16)
|
||||
|
||||
set(PROJECT_VERSION "6.7.2")
|
||||
project(PlasmaActivities VERSION ${PROJECT_VERSION})
|
||||
|
||||
set(QT_MIN_VERSION "6.10.0")
|
||||
set(KF6_MIN_VERSION "6.26.0")
|
||||
set(KDE_COMPILERSETTINGS_LEVEL "5.82")
|
||||
|
||||
set(CMAKE_CXX_STANDARD 20)
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||
|
||||
find_package(ECM ${KF6_MIN_VERSION} REQUIRED NO_MODULE)
|
||||
set(CMAKE_MODULE_PATH ${ECM_MODULE_PATH})
|
||||
|
||||
option (PLASMA_ACTIVITIES_LIBRARY_ONLY "If true, compiles only the PlasmaActivities library, without the QML imports." OFF)
|
||||
|
||||
set (PLASMA_ACTIVITIES_CURRENT_ROOT_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR})
|
||||
|
||||
include(FeatureSummary)
|
||||
include(KDEInstallDirs)
|
||||
include(KDECMakeSettings)
|
||||
include(KDEGitCommitHooks)
|
||||
include(KDECompilerSettings NO_POLICY_SCOPE)
|
||||
include(ECMGenerateExportHeader)
|
||||
include(ECMGenerateHeaders)
|
||||
include(ECMGeneratePkgConfigFile)
|
||||
include(ECMQtDeclareLoggingCategory)
|
||||
include(ECMMarkNonGuiExecutable)
|
||||
include(ECMDeprecationSettings)
|
||||
include(ECMQmlModule)
|
||||
include(ECMGenerateQDoc)
|
||||
include(KDEClangFormat)
|
||||
|
||||
find_package (Qt6 ${QT_MIN_VERSION} CONFIG REQUIRED COMPONENTS Core DBus)
|
||||
|
||||
include (CMakePackageConfigHelpers)
|
||||
include (ECMSetupVersion)
|
||||
|
||||
set(plasma_activities_version_header "${CMAKE_CURRENT_BINARY_DIR}/src/lib/plasma_activities_version.h")
|
||||
ecm_setup_version (
|
||||
PROJECT
|
||||
VARIABLE_PREFIX PLASMA_ACTIVITIES
|
||||
VERSION_HEADER "${plasma_activities_version_header}"
|
||||
PACKAGE_VERSION_FILE "${CMAKE_CURRENT_BINARY_DIR}/PlasmaActivitiesConfigVersion.cmake"
|
||||
SOVERSION 7
|
||||
)
|
||||
|
||||
ecm_set_disabled_deprecation_versions(
|
||||
QT 6.11.0
|
||||
KF 6.26.0
|
||||
)
|
||||
|
||||
add_subdirectory (src)
|
||||
if (BUILD_TESTING)
|
||||
add_subdirectory (autotests)
|
||||
add_subdirectory (tests)
|
||||
endif()
|
||||
|
||||
set (CMAKECONFIG_INSTALL_DIR "${KDE_INSTALL_CMAKEPACKAGEDIR}/PlasmaActivities")
|
||||
|
||||
install (
|
||||
EXPORT PlasmaActivitiesLibraryTargets
|
||||
DESTINATION "${CMAKECONFIG_INSTALL_DIR}"
|
||||
FILE PlasmaActivitiesLibraryTargets.cmake
|
||||
NAMESPACE Plasma::
|
||||
)
|
||||
|
||||
configure_package_config_file (
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/PlasmaActivitiesConfig.cmake.in"
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/PlasmaActivitiesConfig.cmake"
|
||||
INSTALL_DESTINATION ${CMAKECONFIG_INSTALL_DIR}
|
||||
)
|
||||
|
||||
install (
|
||||
FILES "${CMAKE_CURRENT_BINARY_DIR}/PlasmaActivitiesConfig.cmake"
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/PlasmaActivitiesConfigVersion.cmake"
|
||||
DESTINATION "${CMAKECONFIG_INSTALL_DIR}"
|
||||
COMPONENT Devel
|
||||
)
|
||||
|
||||
install (
|
||||
FILES ${plasma_activities_version_header}
|
||||
DESTINATION ${KDE_INSTALL_INCLUDEDIR}/PlasmaActivities COMPONENT Devel
|
||||
)
|
||||
|
||||
# Write out the features
|
||||
feature_summary (WHAT ALL FATAL_ON_MISSING_REQUIRED_PACKAGES)
|
||||
|
||||
kde_configure_git_pre_commit_hook(CHECKS CLANG_FORMAT)
|
||||
@@ -0,0 +1,121 @@
|
||||
Creative Commons Legal Code
|
||||
|
||||
CC0 1.0 Universal
|
||||
|
||||
CREATIVE COMMONS CORPORATION IS NOT A LAW FIRM AND DOES NOT PROVIDE
|
||||
LEGAL SERVICES. DISTRIBUTION OF THIS DOCUMENT DOES NOT CREATE AN
|
||||
ATTORNEY-CLIENT RELATIONSHIP. CREATIVE COMMONS PROVIDES THIS
|
||||
INFORMATION ON AN "AS-IS" BASIS. CREATIVE COMMONS MAKES NO WARRANTIES
|
||||
REGARDING THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS
|
||||
PROVIDED HEREUNDER, AND DISCLAIMS LIABILITY FOR DAMAGES RESULTING FROM
|
||||
THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS PROVIDED
|
||||
HEREUNDER.
|
||||
|
||||
Statement of Purpose
|
||||
|
||||
The laws of most jurisdictions throughout the world automatically confer
|
||||
exclusive Copyright and Related Rights (defined below) upon the creator
|
||||
and subsequent owner(s) (each and all, an "owner") of an original work of
|
||||
authorship and/or a database (each, a "Work").
|
||||
|
||||
Certain owners wish to permanently relinquish those rights to a Work for
|
||||
the purpose of contributing to a commons of creative, cultural and
|
||||
scientific works ("Commons") that the public can reliably and without fear
|
||||
of later claims of infringement build upon, modify, incorporate in other
|
||||
works, reuse and redistribute as freely as possible in any form whatsoever
|
||||
and for any purposes, including without limitation commercial purposes.
|
||||
These owners may contribute to the Commons to promote the ideal of a free
|
||||
culture and the further production of creative, cultural and scientific
|
||||
works, or to gain reputation or greater distribution for their Work in
|
||||
part through the use and efforts of others.
|
||||
|
||||
For these and/or other purposes and motivations, and without any
|
||||
expectation of additional consideration or compensation, the person
|
||||
associating CC0 with a Work (the "Affirmer"), to the extent that he or she
|
||||
is an owner of Copyright and Related Rights in the Work, voluntarily
|
||||
elects to apply CC0 to the Work and publicly distribute the Work under its
|
||||
terms, with knowledge of his or her Copyright and Related Rights in the
|
||||
Work and the meaning and intended legal effect of CC0 on those rights.
|
||||
|
||||
1. Copyright and Related Rights. A Work made available under CC0 may be
|
||||
protected by copyright and related or neighboring rights ("Copyright and
|
||||
Related Rights"). Copyright and Related Rights include, but are not
|
||||
limited to, the following:
|
||||
|
||||
i. the right to reproduce, adapt, distribute, perform, display,
|
||||
communicate, and translate a Work;
|
||||
ii. moral rights retained by the original author(s) and/or performer(s);
|
||||
iii. publicity and privacy rights pertaining to a person's image or
|
||||
likeness depicted in a Work;
|
||||
iv. rights protecting against unfair competition in regards to a Work,
|
||||
subject to the limitations in paragraph 4(a), below;
|
||||
v. rights protecting the extraction, dissemination, use and reuse of data
|
||||
in a Work;
|
||||
vi. database rights (such as those arising under Directive 96/9/EC of the
|
||||
European Parliament and of the Council of 11 March 1996 on the legal
|
||||
protection of databases, and under any national implementation
|
||||
thereof, including any amended or successor version of such
|
||||
directive); and
|
||||
vii. other similar, equivalent or corresponding rights throughout the
|
||||
world based on applicable law or treaty, and any national
|
||||
implementations thereof.
|
||||
|
||||
2. Waiver. To the greatest extent permitted by, but not in contravention
|
||||
of, applicable law, Affirmer hereby overtly, fully, permanently,
|
||||
irrevocably and unconditionally waives, abandons, and surrenders all of
|
||||
Affirmer's Copyright and Related Rights and associated claims and causes
|
||||
of action, whether now known or unknown (including existing as well as
|
||||
future claims and causes of action), in the Work (i) in all territories
|
||||
worldwide, (ii) for the maximum duration provided by applicable law or
|
||||
treaty (including future time extensions), (iii) in any current or future
|
||||
medium and for any number of copies, and (iv) for any purpose whatsoever,
|
||||
including without limitation commercial, advertising or promotional
|
||||
purposes (the "Waiver"). Affirmer makes the Waiver for the benefit of each
|
||||
member of the public at large and to the detriment of Affirmer's heirs and
|
||||
successors, fully intending that such Waiver shall not be subject to
|
||||
revocation, rescission, cancellation, termination, or any other legal or
|
||||
equitable action to disrupt the quiet enjoyment of the Work by the public
|
||||
as contemplated by Affirmer's express Statement of Purpose.
|
||||
|
||||
3. Public License Fallback. Should any part of the Waiver for any reason
|
||||
be judged legally invalid or ineffective under applicable law, then the
|
||||
Waiver shall be preserved to the maximum extent permitted taking into
|
||||
account Affirmer's express Statement of Purpose. In addition, to the
|
||||
extent the Waiver is so judged Affirmer hereby grants to each affected
|
||||
person a royalty-free, non transferable, non sublicensable, non exclusive,
|
||||
irrevocable and unconditional license to exercise Affirmer's Copyright and
|
||||
Related Rights in the Work (i) in all territories worldwide, (ii) for the
|
||||
maximum duration provided by applicable law or treaty (including future
|
||||
time extensions), (iii) in any current or future medium and for any number
|
||||
of copies, and (iv) for any purpose whatsoever, including without
|
||||
limitation commercial, advertising or promotional purposes (the
|
||||
"License"). The License shall be deemed effective as of the date CC0 was
|
||||
applied by Affirmer to the Work. Should any part of the License for any
|
||||
reason be judged legally invalid or ineffective under applicable law, such
|
||||
partial invalidity or ineffectiveness shall not invalidate the remainder
|
||||
of the License, and in such case Affirmer hereby affirms that he or she
|
||||
will not (i) exercise any of his or her remaining Copyright and Related
|
||||
Rights in the Work or (ii) assert any associated claims and causes of
|
||||
action with respect to the Work, in either case contrary to Affirmer's
|
||||
express Statement of Purpose.
|
||||
|
||||
4. Limitations and Disclaimers.
|
||||
|
||||
a. No trademark or patent rights held by Affirmer are waived, abandoned,
|
||||
surrendered, licensed or otherwise affected by this document.
|
||||
b. Affirmer offers the Work as-is and makes no representations or
|
||||
warranties of any kind concerning the Work, express, implied,
|
||||
statutory or otherwise, including without limitation warranties of
|
||||
title, merchantability, fitness for a particular purpose, non
|
||||
infringement, or the absence of latent or other defects, accuracy, or
|
||||
the present or absence of errors, whether or not discoverable, all to
|
||||
the greatest extent permissible under applicable law.
|
||||
c. Affirmer disclaims responsibility for clearing rights of other persons
|
||||
that may apply to the Work or any use thereof, including without
|
||||
limitation any person's Copyright and Related Rights in the Work.
|
||||
Further, Affirmer disclaims responsibility for obtaining any necessary
|
||||
consents, permissions or other rights required for any use of the
|
||||
Work.
|
||||
d. Affirmer understands and acknowledges that Creative Commons is not a
|
||||
party to this document and has no duty or obligation with respect to
|
||||
this CC0 or use of the Work.
|
||||
@@ -0,0 +1,319 @@
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
|
||||
Version 2, June 1991
|
||||
|
||||
Copyright (C) 1989, 1991 Free Software Foundation, Inc.
|
||||
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
|
||||
Everyone is permitted to copy and distribute verbatim copies of this license
|
||||
document, but changing it is not allowed.
|
||||
|
||||
Preamble
|
||||
|
||||
The licenses for most software are designed to take away your freedom to share
|
||||
and change it. By contrast, the GNU General Public License is intended to
|
||||
guarantee your freedom to share and change free software--to make sure the
|
||||
software is free for all its users. This General Public License applies to
|
||||
most of the Free Software Foundation's software and to any other program whose
|
||||
authors commit to using it. (Some other Free Software Foundation software
|
||||
is covered by the GNU Lesser General Public License instead.) You can apply
|
||||
it to your programs, too.
|
||||
|
||||
When we speak of free software, we are referring to freedom, not price. Our
|
||||
General Public Licenses are designed to make sure that you have the freedom
|
||||
to distribute copies of free software (and charge for this service if you
|
||||
wish), that you receive source code or can get it if you want it, that you
|
||||
can change the software or use pieces of it in new free programs; and that
|
||||
you know you can do these things.
|
||||
|
||||
To protect your rights, we need to make restrictions that forbid anyone to
|
||||
deny you these rights or to ask you to surrender the rights. These restrictions
|
||||
translate to certain responsibilities for you if you distribute copies of
|
||||
the software, or if you modify it.
|
||||
|
||||
For example, if you distribute copies of such a program, whether gratis or
|
||||
for a fee, you must give the recipients all the rights that you have. You
|
||||
must make sure that they, too, receive or can get the source code. And you
|
||||
must show them these terms so they know their rights.
|
||||
|
||||
We protect your rights with two steps: (1) copyright the software, and (2)
|
||||
offer you this license which gives you legal permission to copy, distribute
|
||||
and/or modify the software.
|
||||
|
||||
Also, for each author's protection and ours, we want to make certain that
|
||||
everyone understands that there is no warranty for this free software. If
|
||||
the software is modified by someone else and passed on, we want its recipients
|
||||
to know that what they have is not the original, so that any problems introduced
|
||||
by others will not reflect on the original authors' reputations.
|
||||
|
||||
Finally, any free program is threatened constantly by software patents. We
|
||||
wish to avoid the danger that redistributors of a free program will individually
|
||||
obtain patent licenses, in effect making the program proprietary. To prevent
|
||||
this, we have made it clear that any patent must be licensed for everyone's
|
||||
free use or not licensed at all.
|
||||
|
||||
The precise terms and conditions for copying, distribution and modification
|
||||
follow.
|
||||
|
||||
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||
|
||||
0. This License applies to any program or other work which contains a notice
|
||||
placed by the copyright holder saying it may be distributed under the terms
|
||||
of this General Public License. The "Program", below, refers to any such program
|
||||
or work, and a "work based on the Program" means either the Program or any
|
||||
derivative work under copyright law: that is to say, a work containing the
|
||||
Program or a portion of it, either verbatim or with modifications and/or translated
|
||||
into another language. (Hereinafter, translation is included without limitation
|
||||
in the term "modification".) Each licensee is addressed as "you".
|
||||
|
||||
Activities other than copying, distribution and modification are not covered
|
||||
by this License; they are outside its scope. The act of running the Program
|
||||
is not restricted, and the output from the Program is covered only if its
|
||||
contents constitute a work based on the Program (independent of having been
|
||||
made by running the Program). Whether that is true depends on what the Program
|
||||
does.
|
||||
|
||||
1. You may copy and distribute verbatim copies of the Program's source code
|
||||
as you receive it, in any medium, provided that you conspicuously and appropriately
|
||||
publish on each copy an appropriate copyright notice and disclaimer of warranty;
|
||||
keep intact all the notices that refer to this License and to the absence
|
||||
of any warranty; and give any other recipients of the Program a copy of this
|
||||
License along with the Program.
|
||||
|
||||
You may charge a fee for the physical act of transferring a copy, and you
|
||||
may at your option offer warranty protection in exchange for a fee.
|
||||
|
||||
2. You may modify your copy or copies of the Program or any portion of it,
|
||||
thus forming a work based on the Program, and copy and distribute such modifications
|
||||
or work under the terms of Section 1 above, provided that you also meet all
|
||||
of these conditions:
|
||||
|
||||
a) You must cause the modified files to carry prominent notices stating that
|
||||
you changed the files and the date of any change.
|
||||
|
||||
b) You must cause any work that you distribute or publish, that in whole or
|
||||
in part contains or is derived from the Program or any part thereof, to be
|
||||
licensed as a whole at no charge to all third parties under the terms of this
|
||||
License.
|
||||
|
||||
c) If the modified program normally reads commands interactively when run,
|
||||
you must cause it, when started running for such interactive use in the most
|
||||
ordinary way, to print or display an announcement including an appropriate
|
||||
copyright notice and a notice that there is no warranty (or else, saying that
|
||||
you provide a warranty) and that users may redistribute the program under
|
||||
these conditions, and telling the user how to view a copy of this License.
|
||||
(Exception: if the Program itself is interactive but does not normally print
|
||||
such an announcement, your work based on the Program is not required to print
|
||||
an announcement.)
|
||||
|
||||
These requirements apply to the modified work as a whole. If identifiable
|
||||
sections of that work are not derived from the Program, and can be reasonably
|
||||
considered independent and separate works in themselves, then this License,
|
||||
and its terms, do not apply to those sections when you distribute them as
|
||||
separate works. But when you distribute the same sections as part of a whole
|
||||
which is a work based on the Program, the distribution of the whole must be
|
||||
on the terms of this License, whose permissions for other licensees extend
|
||||
to the entire whole, and thus to each and every part regardless of who wrote
|
||||
it.
|
||||
|
||||
Thus, it is not the intent of this section to claim rights or contest your
|
||||
rights to work written entirely by you; rather, the intent is to exercise
|
||||
the right to control the distribution of derivative or collective works based
|
||||
on the Program.
|
||||
|
||||
In addition, mere aggregation of another work not based on the Program with
|
||||
the Program (or with a work based on the Program) on a volume of a storage
|
||||
or distribution medium does not bring the other work under the scope of this
|
||||
License.
|
||||
|
||||
3. You may copy and distribute the Program (or a work based on it, under Section
|
||||
2) in object code or executable form under the terms of Sections 1 and 2 above
|
||||
provided that you also do one of the following:
|
||||
|
||||
a) Accompany it with the complete corresponding machine-readable source code,
|
||||
which must be distributed under the terms of Sections 1 and 2 above on a medium
|
||||
customarily used for software interchange; or,
|
||||
|
||||
b) Accompany it with a written offer, valid for at least three years, to give
|
||||
any third party, for a charge no more than your cost of physically performing
|
||||
source distribution, a complete machine-readable copy of the corresponding
|
||||
source code, to be distributed under the terms of Sections 1 and 2 above on
|
||||
a medium customarily used for software interchange; or,
|
||||
|
||||
c) Accompany it with the information you received as to the offer to distribute
|
||||
corresponding source code. (This alternative is allowed only for noncommercial
|
||||
distribution and only if you received the program in object code or executable
|
||||
form with such an offer, in accord with Subsection b above.)
|
||||
|
||||
The source code for a work means the preferred form of the work for making
|
||||
modifications to it. For an executable work, complete source code means all
|
||||
the source code for all modules it contains, plus any associated interface
|
||||
definition files, plus the scripts used to control compilation and installation
|
||||
of the executable. However, as a special exception, the source code distributed
|
||||
need not include anything that is normally distributed (in either source or
|
||||
binary form) with the major components (compiler, kernel, and so on) of the
|
||||
operating system on which the executable runs, unless that component itself
|
||||
accompanies the executable.
|
||||
|
||||
If distribution of executable or object code is made by offering access to
|
||||
copy from a designated place, then offering equivalent access to copy the
|
||||
source code from the same place counts as distribution of the source code,
|
||||
even though third parties are not compelled to copy the source along with
|
||||
the object code.
|
||||
|
||||
4. You may not copy, modify, sublicense, or distribute the Program except
|
||||
as expressly provided under this License. Any attempt otherwise to copy, modify,
|
||||
sublicense or distribute the Program is void, and will automatically terminate
|
||||
your rights under this License. However, parties who have received copies,
|
||||
or rights, from you under this License will not have their licenses terminated
|
||||
so long as such parties remain in full compliance.
|
||||
|
||||
5. You are not required to accept this License, since you have not signed
|
||||
it. However, nothing else grants you permission to modify or distribute the
|
||||
Program or its derivative works. These actions are prohibited by law if you
|
||||
do not accept this License. Therefore, by modifying or distributing the Program
|
||||
(or any work based on the Program), you indicate your acceptance of this License
|
||||
to do so, and all its terms and conditions for copying, distributing or modifying
|
||||
the Program or works based on it.
|
||||
|
||||
6. Each time you redistribute the Program (or any work based on the Program),
|
||||
the recipient automatically receives a license from the original licensor
|
||||
to copy, distribute or modify the Program subject to these terms and conditions.
|
||||
You may not impose any further restrictions on the recipients' exercise of
|
||||
the rights granted herein. You are not responsible for enforcing compliance
|
||||
by third parties to this License.
|
||||
|
||||
7. If, as a consequence of a court judgment or allegation of patent infringement
|
||||
or for any other reason (not limited to patent issues), conditions are imposed
|
||||
on you (whether by court order, agreement or otherwise) that contradict the
|
||||
conditions of this License, they do not excuse you from the conditions of
|
||||
this License. If you cannot distribute so as to satisfy simultaneously your
|
||||
obligations under this License and any other pertinent obligations, then as
|
||||
a consequence you may not distribute the Program at all. For example, if a
|
||||
patent license would not permit royalty-free redistribution of the Program
|
||||
by all those who receive copies directly or indirectly through you, then the
|
||||
only way you could satisfy both it and this License would be to refrain entirely
|
||||
from distribution of the Program.
|
||||
|
||||
If any portion of this section is held invalid or unenforceable under any
|
||||
particular circumstance, the balance of the section is intended to apply and
|
||||
the section as a whole is intended to apply in other circumstances.
|
||||
|
||||
It is not the purpose of this section to induce you to infringe any patents
|
||||
or other property right claims or to contest validity of any such claims;
|
||||
this section has the sole purpose of protecting the integrity of the free
|
||||
software distribution system, which is implemented by public license practices.
|
||||
Many people have made generous contributions to the wide range of software
|
||||
distributed through that system in reliance on consistent application of that
|
||||
system; it is up to the author/donor to decide if he or she is willing to
|
||||
distribute software through any other system and a licensee cannot impose
|
||||
that choice.
|
||||
|
||||
This section is intended to make thoroughly clear what is believed to be a
|
||||
consequence of the rest of this License.
|
||||
|
||||
8. If the distribution and/or use of the Program is restricted in certain
|
||||
countries either by patents or by copyrighted interfaces, the original copyright
|
||||
holder who places the Program under this License may add an explicit geographical
|
||||
distribution limitation excluding those countries, so that distribution is
|
||||
permitted only in or among countries not thus excluded. In such case, this
|
||||
License incorporates the limitation as if written in the body of this License.
|
||||
|
||||
9. The Free Software Foundation may publish revised and/or new versions of
|
||||
the General Public License from time to time. Such new versions will be similar
|
||||
in spirit to the present version, but may differ in detail to address new
|
||||
problems or concerns.
|
||||
|
||||
Each version is given a distinguishing version number. If the Program specifies
|
||||
a version number of this License which applies to it and "any later version",
|
||||
you have the option of following the terms and conditions either of that version
|
||||
or of any later version published by the Free Software Foundation. If the
|
||||
Program does not specify a version number of this License, you may choose
|
||||
any version ever published by the Free Software Foundation.
|
||||
|
||||
10. If you wish to incorporate parts of the Program into other free programs
|
||||
whose distribution conditions are different, write to the author to ask for
|
||||
permission. For software which is copyrighted by the Free Software Foundation,
|
||||
write to the Free Software Foundation; we sometimes make exceptions for this.
|
||||
Our decision will be guided by the two goals of preserving the free status
|
||||
of all derivatives of our free software and of promoting the sharing and reuse
|
||||
of software generally.
|
||||
|
||||
NO WARRANTY
|
||||
|
||||
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR
|
||||
THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE
|
||||
STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM
|
||||
"AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
|
||||
BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE
|
||||
OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME
|
||||
THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
|
||||
|
||||
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
||||
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE
|
||||
THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
|
||||
GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE
|
||||
OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA
|
||||
OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES
|
||||
OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH
|
||||
HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
How to Apply These Terms to Your New Programs
|
||||
|
||||
If you develop a new program, and you want it to be of the greatest possible
|
||||
use to the public, the best way to achieve this is to make it free software
|
||||
which everyone can redistribute and change under these terms.
|
||||
|
||||
To do so, attach the following notices to the program. It is safest to attach
|
||||
them to the start of each source file to most effectively convey the exclusion
|
||||
of warranty; and each file should have at least the "copyright" line and a
|
||||
pointer to where the full notice is found.
|
||||
|
||||
<one line to give the program's name and an idea of what it does.>
|
||||
|
||||
Copyright (C) <yyyy> <name of author>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free Software
|
||||
Foundation; either version 2 of the License, or (at your option) any later
|
||||
version.
|
||||
|
||||
This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along with
|
||||
this program; if not, write to the Free Software Foundation, Inc., 51 Franklin
|
||||
Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
|
||||
Also add information on how to contact you by electronic and paper mail.
|
||||
|
||||
If the program is interactive, make it output a short notice like this when
|
||||
it starts in an interactive mode:
|
||||
|
||||
Gnomovision version 69, Copyright (C) year name of author Gnomovision comes
|
||||
with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software,
|
||||
and you are welcome to redistribute it under certain conditions; type `show
|
||||
c' for details.
|
||||
|
||||
The hypothetical commands `show w' and `show c' should show the appropriate
|
||||
parts of the General Public License. Of course, the commands you use may be
|
||||
called something other than `show w' and `show c'; they could even be mouse-clicks
|
||||
or menu items--whatever suits your program.
|
||||
|
||||
You should also get your employer (if you work as a programmer) or your school,
|
||||
if any, to sign a "copyright disclaimer" for the program, if necessary. Here
|
||||
is a sample; alter the names:
|
||||
|
||||
Yoyodyne, Inc., hereby disclaims all copyright interest in the program `Gnomovision'
|
||||
(which makes passes at compilers) written by James Hacker.
|
||||
|
||||
<signature of Ty Coon>, 1 April 1989 Ty Coon, President of Vice This General
|
||||
Public License does not permit incorporating your program into proprietary
|
||||
programs. If your program is a subroutine library, you may consider it more
|
||||
useful to permit linking proprietary applications with the library. If this
|
||||
is what you want to do, use the GNU Lesser General Public License instead
|
||||
of this License.
|
||||
@@ -0,0 +1,446 @@
|
||||
GNU LIBRARY GENERAL PUBLIC LICENSE
|
||||
|
||||
Version 2, June 1991 Copyright (C) 1991 Free Software Foundation, Inc.
|
||||
|
||||
51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
|
||||
Everyone is permitted to copy and distribute verbatim copies of this license
|
||||
document, but changing it is not allowed.
|
||||
|
||||
[This is the first released version of the library GPL. It is numbered 2 because
|
||||
it goes with version 2 of the ordinary GPL.]
|
||||
|
||||
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 Library General Public License, applies to some specially
|
||||
designated Free Software Foundation software, and to any other libraries whose
|
||||
authors decide to use it. You can use it for your libraries, too.
|
||||
|
||||
When we speak of free software, we are referring to freedom, not price. Our
|
||||
General Public Licenses are designed to make sure that you have the freedom
|
||||
to distribute copies of free software (and charge for this service if you
|
||||
wish), that you receive source code or can get it if you want it, that you
|
||||
can change the software or use pieces of it in new free programs; and that
|
||||
you know you can do these things.
|
||||
|
||||
To protect your rights, we need to make restrictions that forbid anyone to
|
||||
deny you these rights or to ask you to surrender the rights. These restrictions
|
||||
translate to certain responsibilities for you if you distribute copies of
|
||||
the 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
|
||||
a program 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.
|
||||
|
||||
Our method of protecting your rights has two steps: (1) copyright the library,
|
||||
and (2) offer you this license which gives you legal permission to copy, distribute
|
||||
and/or modify the library.
|
||||
|
||||
Also, for each distributor's protection, we want to make certain that everyone
|
||||
understands that there is no warranty for this free library. If the library
|
||||
is modified by someone else and passed on, we want its recipients to know
|
||||
that what they have is not the original version, so that any problems introduced
|
||||
by others will not reflect on the original authors' reputations.
|
||||
|
||||
Finally, any free program is threatened constantly by software patents. We
|
||||
wish to avoid the danger that companies distributing free software will individually
|
||||
obtain patent licenses, thus in effect transforming the program into proprietary
|
||||
software. To prevent this, we have made it clear that any patent must be licensed
|
||||
for everyone's free use or not licensed at all.
|
||||
|
||||
Most GNU software, including some libraries, is covered by the ordinary GNU
|
||||
General Public License, which was designed for utility programs. This license,
|
||||
the GNU Library General Public License, applies to certain designated libraries.
|
||||
This license is quite different from the ordinary one; be sure to read it
|
||||
in full, and don't assume that anything in it is the same as in the ordinary
|
||||
license.
|
||||
|
||||
The reason we have a separate public license for some libraries is that they
|
||||
blur the distinction we usually make between modifying or adding to a program
|
||||
and simply using it. Linking a program with a library, without changing the
|
||||
library, is in some sense simply using the library, and is analogous to running
|
||||
a utility program or application program. However, in a textual and legal
|
||||
sense, the linked executable is a combined work, a derivative of the original
|
||||
library, and the ordinary General Public License treats it as such.
|
||||
|
||||
Because of this blurred distinction, using the ordinary General Public License
|
||||
for libraries did not effectively promote software sharing, because most developers
|
||||
did not use the libraries. We concluded that weaker conditions might promote
|
||||
sharing better.
|
||||
|
||||
However, unrestricted linking of non-free programs would deprive the users
|
||||
of those programs of all benefit from the free status of the libraries themselves.
|
||||
This Library General Public License is intended to permit developers of non-free
|
||||
programs to use free libraries, while preserving your freedom as a user of
|
||||
such programs to change the free libraries that are incorporated in them.
|
||||
(We have not seen how to achieve this as regards changes in header files,
|
||||
but we have achieved it as regards changes in the actual functions of the
|
||||
Library.) The hope is that this will lead to faster development of free libraries.
|
||||
|
||||
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, while the latter only works together with the library.
|
||||
|
||||
Note that it is possible for a library to be covered by the ordinary General
|
||||
Public License rather than by this special one.
|
||||
|
||||
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||
|
||||
0. This License Agreement applies to any software library which contains a
|
||||
notice placed by the copyright holder or other authorized party saying it
|
||||
may be distributed under the terms of this Library 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 compile 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) 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.
|
||||
|
||||
c) 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.
|
||||
|
||||
d) 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 source code distributed need
|
||||
not include anything that is normally distributed (in either source or binary
|
||||
form) with the major components (compiler, kernel, and so on) of the operating
|
||||
system on which the executable runs, unless that component itself accompanies
|
||||
the executable.
|
||||
|
||||
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 to 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 Library General Public License from time to time. Such new versions will
|
||||
be similar in spirit to the present version, but may differ in detail to address
|
||||
new problems or concerns.
|
||||
|
||||
Each version is given a distinguishing version number. If the Library specifies
|
||||
a version number of this License which applies to it and "any later version",
|
||||
you have the option of following the terms and conditions either of that version
|
||||
or of any later version published by the Free Software Foundation. If the
|
||||
Library does not specify a license version number, you may choose any version
|
||||
ever published by the Free Software Foundation.
|
||||
|
||||
14. If you wish to incorporate parts of the Library into other free programs
|
||||
whose distribution conditions are incompatible with these, write to the author
|
||||
to ask for permission. For software which is copyrighted by the Free Software
|
||||
Foundation, write to the Free Software Foundation; we sometimes make exceptions
|
||||
for this. Our decision will be guided by the two goals of preserving the free
|
||||
status of all derivatives of our free software and of promoting the sharing
|
||||
and reuse of software generally.
|
||||
|
||||
NO WARRANTY
|
||||
|
||||
15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR
|
||||
THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE
|
||||
STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE LIBRARY
|
||||
"AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
|
||||
BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE
|
||||
OF THE LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
|
||||
THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
|
||||
|
||||
16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
||||
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE
|
||||
THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
|
||||
GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE
|
||||
OR INABILITY TO USE THE LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA
|
||||
OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES
|
||||
OR A FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF SUCH
|
||||
HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
How to Apply These Terms to Your New Libraries
|
||||
|
||||
If you develop a new library, and you want it to be of the greatest possible
|
||||
use to the public, we recommend making it free software that everyone can
|
||||
redistribute and change. You can do so by permitting redistribution under
|
||||
these terms (or, alternatively, under the terms of the ordinary General Public
|
||||
License).
|
||||
|
||||
To apply these terms, attach the following notices to the library. It is safest
|
||||
to attach them to the start of each source file to most effectively convey
|
||||
the exclusion of warranty; and each file should have at least the "copyright"
|
||||
line and a pointer to where the full notice is found.
|
||||
|
||||
one line to give the library's name and an idea of what it does.
|
||||
|
||||
Copyright (C) year name of author
|
||||
|
||||
This library is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU Library General Public License as published by the Free
|
||||
Software Foundation; either version 2 of the License, or (at your option)
|
||||
any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more
|
||||
details.
|
||||
|
||||
You should have received a copy of the GNU Library General Public License
|
||||
along with this library; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
|
||||
Also add information on how to contact you by electronic and paper mail.
|
||||
|
||||
You should also get your employer (if you work as a programmer) or your school,
|
||||
if any, to sign a "copyright disclaimer" for the library, if necessary. Here
|
||||
is a sample; alter the names:
|
||||
|
||||
Yoyodyne, Inc., hereby disclaims all copyright interest in
|
||||
|
||||
the library `Frob' (a library for tweaking knobs) written
|
||||
|
||||
by James Random Hacker.
|
||||
|
||||
signature of Ty Coon, 1 April 1990
|
||||
|
||||
Ty Coon, President of Vice
|
||||
|
||||
That's all there is to it!
|
||||
@@ -0,0 +1,467 @@
|
||||
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.
|
||||
|
||||
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||
|
||||
0. This License Agreement applies to any software library or other program
|
||||
which contains a notice placed by the copyright holder or other authorized
|
||||
party saying it may be distributed under the terms of this Lesser General
|
||||
Public License (also called "this License"). Each licensee is addressed as
|
||||
"you".
|
||||
|
||||
A "library" means a collection of software functions and/or data prepared
|
||||
so as to be conveniently linked with application programs (which use some
|
||||
of those functions and data) to form executables.
|
||||
|
||||
The "Library", below, refers to any such software library or work which has
|
||||
been distributed under these terms. A "work based on the Library" means either
|
||||
the Library or any derivative work under copyright law: that is to say, a
|
||||
work containing the Library or a portion of it, either verbatim or with modifications
|
||||
and/or translated straightforwardly into another language. (Hereinafter, translation
|
||||
is included without limitation in the term "modification".)
|
||||
|
||||
"Source code" for a work means the preferred form of the work for making modifications
|
||||
to it. For a library, complete source code means all the source code for all
|
||||
modules it contains, plus any associated interface definition files, plus
|
||||
the scripts used to control compilation and installation of the library.
|
||||
|
||||
Activities other than copying, distribution and modification are not covered
|
||||
by this License; they are outside its scope. The act of running a program
|
||||
using the Library is not restricted, and output from such a program is covered
|
||||
only if its contents constitute a work based on the Library (independent of
|
||||
the use of the Library in a tool for writing it). Whether that is true depends
|
||||
on what the Library does and what the program that uses the Library does.
|
||||
|
||||
1. You may copy and distribute verbatim copies of the Library's complete source
|
||||
code as you receive it, in any medium, provided that you conspicuously and
|
||||
appropriately publish on each copy an appropriate copyright notice and disclaimer
|
||||
of warranty; keep intact all the notices that refer to this License and to
|
||||
the absence of any warranty; and distribute a copy of this License along with
|
||||
the Library.
|
||||
|
||||
You may charge a fee for the physical act of transferring a copy, and you
|
||||
may at your option offer warranty protection in exchange for a fee.
|
||||
|
||||
2. You may modify your copy or copies of the Library or any portion of it,
|
||||
thus forming a work based on the Library, and copy and distribute such modifications
|
||||
or work under the terms of Section 1 above, provided that you also meet all
|
||||
of these conditions:
|
||||
|
||||
a) The modified work must itself be a software library.
|
||||
|
||||
b) You must cause the files modified to carry prominent notices stating that
|
||||
you changed the files and the date of any change.
|
||||
|
||||
c) You must cause the whole of the work to be licensed at no charge to all
|
||||
third parties under the terms of this License.
|
||||
|
||||
d) If a facility in the modified Library refers to a function or a table of
|
||||
data to be supplied by an application program that uses the facility, other
|
||||
than as an argument passed when the facility is invoked, then you must make
|
||||
a good faith effort to ensure that, in the event an application does not supply
|
||||
such function or table, the facility still operates, and performs whatever
|
||||
part of its purpose remains meaningful.
|
||||
|
||||
(For example, a function in a library to compute square roots has a purpose
|
||||
that is entirely well-defined independent of the application. Therefore, Subsection
|
||||
2d requires that any application-supplied function or table used by this function
|
||||
must be optional: if the application does not supply it, the square root function
|
||||
must still compute square roots.)
|
||||
|
||||
These requirements apply to the modified work as a whole. If identifiable
|
||||
sections of that work are not derived from the Library, and can be reasonably
|
||||
considered independent and separate works in themselves, then this License,
|
||||
and its terms, do not apply to those sections when you distribute them as
|
||||
separate works. But when you distribute the same sections as part of a whole
|
||||
which is a work based on the Library, the distribution of the whole must be
|
||||
on the terms of this License, whose permissions for other licensees extend
|
||||
to the entire whole, and thus to each and every part regardless of who wrote
|
||||
it.
|
||||
|
||||
Thus, it is not the intent of this section to claim rights or contest your
|
||||
rights to work written entirely by you; rather, the intent is to exercise
|
||||
the right to control the distribution of derivative or collective works based
|
||||
on the Library.
|
||||
|
||||
In addition, mere aggregation of another work not based on the Library with
|
||||
the Library (or with a work based on the Library) on a volume of a storage
|
||||
or distribution medium does not bring the other work under the scope of this
|
||||
License.
|
||||
|
||||
3. You may opt to apply the terms of the ordinary GNU General Public License
|
||||
instead of this License to a given copy of the Library. To do this, you must
|
||||
alter all the notices that refer to this License, so that they refer to the
|
||||
ordinary GNU General Public License, version 2, instead of to this License.
|
||||
(If a newer version than version 2 of the ordinary GNU General Public License
|
||||
has appeared, then you can specify that version instead if you wish.) Do not
|
||||
make any other change in these notices.
|
||||
|
||||
Once this change is made in a given copy, it is irreversible for that copy,
|
||||
so the ordinary GNU General Public License applies to all subsequent copies
|
||||
and derivative works made from that copy.
|
||||
|
||||
This option is useful when you wish to copy part of the code of the Library
|
||||
into a program that is not a library.
|
||||
|
||||
4. You may copy and distribute the Library (or a portion or derivative of
|
||||
it, under Section 2) in object code or executable form under the terms of
|
||||
Sections 1 and 2 above provided that you accompany it with the complete corresponding
|
||||
machine-readable source code, which must be distributed under the terms of
|
||||
Sections 1 and 2 above on a medium customarily used for software interchange.
|
||||
|
||||
If distribution of object code is made by offering access to copy from a designated
|
||||
place, then offering equivalent access to copy the source code from the same
|
||||
place satisfies the requirement to distribute the source code, even though
|
||||
third parties are not compelled to copy the source along with the object code.
|
||||
|
||||
5. A program that contains no derivative of any portion of the Library, but
|
||||
is designed to work with the Library by being compiled or linked with it,
|
||||
is called a "work that uses the Library". Such a work, in isolation, is not
|
||||
a derivative work of the Library, and therefore falls outside the scope of
|
||||
this License.
|
||||
|
||||
However, linking a "work that uses the Library" with the Library creates an
|
||||
executable that is a derivative of the Library (because it contains portions
|
||||
of the Library), rather than a "work that uses the library". The executable
|
||||
is therefore covered by this License. Section 6 states terms for distribution
|
||||
of such executables.
|
||||
|
||||
When a "work that uses the Library" uses material from a header file that
|
||||
is part of the Library, the object code for the work may be a derivative work
|
||||
of the Library even though the source code is not. Whether this is true is
|
||||
especially significant if the work can be linked without the Library, or if
|
||||
the work is itself a library. The threshold for this to be true is not precisely
|
||||
defined by law.
|
||||
|
||||
If such an object file uses only numerical parameters, data structure layouts
|
||||
and accessors, and small macros and small inline functions (ten lines or less
|
||||
in length), then the use of the object file is unrestricted, regardless of
|
||||
whether it is legally a derivative work. (Executables containing this object
|
||||
code plus portions of the Library will still fall under Section 6.)
|
||||
|
||||
Otherwise, if the work is a derivative of the Library, you may distribute
|
||||
the object code for the work under the terms of Section 6. Any executables
|
||||
containing that work also fall under Section 6, whether or not they are linked
|
||||
directly with the Library itself.
|
||||
|
||||
6. As an exception to the Sections above, you may also combine or link a "work
|
||||
that uses the Library" with the Library to produce a work containing portions
|
||||
of the Library, and distribute that work under terms of your choice, provided
|
||||
that the terms permit modification of the work for the customer's own use
|
||||
and reverse engineering for debugging such modifications.
|
||||
|
||||
You must give prominent notice with each copy of the work that the Library
|
||||
is used in it and that the Library and its use are covered by this License.
|
||||
You must supply a copy of this License. If the work during execution displays
|
||||
copyright notices, you must include the copyright notice for the Library among
|
||||
them, as well as a reference directing the user to the copy of this License.
|
||||
Also, you must do one of these things:
|
||||
|
||||
a) Accompany the work with the complete corresponding machine-readable source
|
||||
code for the Library including whatever changes were used in the work (which
|
||||
must be distributed under Sections 1 and 2 above); and, if the work is an
|
||||
executable linked with the Library, with the complete machine-readable "work
|
||||
that uses the Library", as object code and/or source code, so that the user
|
||||
can modify the Library and then relink to produce a modified executable containing
|
||||
the modified Library. (It is understood that the user who changes the contents
|
||||
of definitions files in the Library will not necessarily be able to recompile
|
||||
the application to use the modified definitions.)
|
||||
|
||||
b) Use a suitable shared library mechanism for linking with the Library. A
|
||||
suitable mechanism is one that (1) uses at run time a copy of the library
|
||||
already present on the user's computer system, rather than copying library
|
||||
functions into the executable, and (2) will operate properly with a modified
|
||||
version of the library, if the user installs one, as long as the modified
|
||||
version is interface-compatible with the version that the work was made with.
|
||||
|
||||
c) Accompany the work with a written offer, valid for at least three years,
|
||||
to give the same user the materials specified in Subsection 6a, above, for
|
||||
a charge no more than the cost of performing this distribution.
|
||||
|
||||
d) If distribution of the work is made by offering access to copy from a designated
|
||||
place, offer equivalent access to copy the above specified materials from
|
||||
the same place.
|
||||
|
||||
e) Verify that the user has already received a copy of these materials or
|
||||
that you have already sent this user a copy.
|
||||
|
||||
For an executable, the required form of the "work that uses the Library" must
|
||||
include any data and utility programs needed for reproducing the executable
|
||||
from it. However, as a special exception, the materials to be distributed
|
||||
need not include anything that is normally distributed (in either source or
|
||||
binary form) with the major components (compiler, kernel, and so on) of the
|
||||
operating system on which the executable runs, unless that component itself
|
||||
accompanies the executable.
|
||||
|
||||
It may happen that this requirement contradicts the license restrictions of
|
||||
other proprietary libraries that do not normally accompany the operating system.
|
||||
Such a contradiction means you cannot use both them and the Library together
|
||||
in an executable that you distribute.
|
||||
|
||||
7. You may place library facilities that are a work based on the Library side-by-side
|
||||
in a single library together with other library facilities not covered by
|
||||
this License, and distribute such a combined library, provided that the separate
|
||||
distribution of the work based on the Library and of the other library facilities
|
||||
is otherwise permitted, and provided that you do these two things:
|
||||
|
||||
a) Accompany the combined library with a copy of the same work based on the
|
||||
Library, uncombined with any other library facilities. This must be distributed
|
||||
under the terms of the Sections above.
|
||||
|
||||
b) Give prominent notice with the combined library of the fact that part of
|
||||
it is a work based on the Library, and explaining where to find the accompanying
|
||||
uncombined form of the same work.
|
||||
|
||||
8. You may not copy, modify, sublicense, link with, or distribute the Library
|
||||
except as expressly provided under this License. Any attempt otherwise to
|
||||
copy, modify, sublicense, link with, or distribute the Library is void, and
|
||||
will automatically terminate your rights under this License. However, parties
|
||||
who have received copies, or rights, from you under this License will not
|
||||
have their licenses terminated so long as such parties remain in full compliance.
|
||||
|
||||
9. You are not required to accept this License, since you have not signed
|
||||
it. However, nothing else grants you permission to modify or distribute the
|
||||
Library or its derivative works. These actions are prohibited by law if you
|
||||
do not accept this License. Therefore, by modifying or distributing the Library
|
||||
(or any work based on the Library), you indicate your acceptance of this License
|
||||
to do so, and all its terms and conditions for copying, distributing or modifying
|
||||
the Library or works based on it.
|
||||
|
||||
10. Each time you redistribute the Library (or any work based on the Library),
|
||||
the recipient automatically receives a license from the original licensor
|
||||
to copy, distribute, link with or modify the Library subject to these terms
|
||||
and conditions. You may not impose any further restrictions on the recipients'
|
||||
exercise of the rights granted herein. You are not responsible for enforcing
|
||||
compliance by third parties with this License.
|
||||
|
||||
11. If, as a consequence of a court judgment or allegation of patent infringement
|
||||
or for any other reason (not limited to patent issues), conditions are imposed
|
||||
on you (whether by court order, agreement or otherwise) that contradict the
|
||||
conditions of this License, they do not excuse you from the conditions of
|
||||
this License. If you cannot distribute so as to satisfy simultaneously your
|
||||
obligations under this License and any other pertinent obligations, then as
|
||||
a consequence you may not distribute the Library at all. For example, if a
|
||||
patent license would not permit royalty-free redistribution of the Library
|
||||
by all those who receive copies directly or indirectly through you, then the
|
||||
only way you could satisfy both it and this License would be to refrain entirely
|
||||
from distribution of the Library.
|
||||
|
||||
If any portion of this section is held invalid or unenforceable under any
|
||||
particular circumstance, the balance of the section is intended to apply,
|
||||
and the section as a whole is intended to apply in other circumstances.
|
||||
|
||||
It is not the purpose of this section to induce you to infringe any patents
|
||||
or other property right claims or to contest validity of any such claims;
|
||||
this section has the sole purpose of protecting the integrity of the free
|
||||
software distribution system which is implemented by public license practices.
|
||||
Many people have made generous contributions to the wide range of software
|
||||
distributed through that system in reliance on consistent application of that
|
||||
system; it is up to the author/donor to decide if he or she is willing to
|
||||
distribute software through any other system and a licensee cannot impose
|
||||
that choice.
|
||||
|
||||
This section is intended to make thoroughly clear what is believed to be a
|
||||
consequence of the rest of this License.
|
||||
|
||||
12. If the distribution and/or use of the Library is restricted in certain
|
||||
countries either by patents or by copyrighted interfaces, the original copyright
|
||||
holder who places the Library under this License may add an explicit geographical
|
||||
distribution limitation excluding those countries, so that distribution is
|
||||
permitted only in or among countries not thus excluded. In such case, this
|
||||
License incorporates the limitation as if written in the body of this License.
|
||||
|
||||
13. The Free Software Foundation may publish revised and/or new versions of
|
||||
the Lesser General Public License from time to time. Such new versions will
|
||||
be similar in spirit to the present version, but may differ in detail to address
|
||||
new problems or concerns.
|
||||
|
||||
Each version is given a distinguishing version number. If the Library specifies
|
||||
a version number of this License which applies to it and "any later version",
|
||||
you have the option of following the terms and conditions either of that version
|
||||
or of any later version published by the Free Software Foundation. If the
|
||||
Library does not specify a license version number, you may choose any version
|
||||
ever published by the Free Software Foundation.
|
||||
|
||||
14. If you wish to incorporate parts of the Library into other free programs
|
||||
whose distribution conditions are incompatible with these, write to the author
|
||||
to ask for permission. For software which is copyrighted by the Free Software
|
||||
Foundation, write to the Free Software Foundation; we sometimes make exceptions
|
||||
for this. Our decision will be guided by the two goals of preserving the free
|
||||
status of all derivatives of our free software and of promoting the sharing
|
||||
and reuse of software generally.
|
||||
|
||||
NO WARRANTY
|
||||
|
||||
15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR
|
||||
THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE
|
||||
STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE LIBRARY
|
||||
"AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
|
||||
BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE
|
||||
OF THE LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
|
||||
THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
|
||||
|
||||
16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
||||
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE
|
||||
THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
|
||||
GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE
|
||||
OR INABILITY TO USE THE LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA
|
||||
OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES
|
||||
OR A FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF SUCH
|
||||
HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
How to Apply These Terms to Your New Libraries
|
||||
|
||||
If you develop a new library, and you want it to be of the greatest possible
|
||||
use to the public, we recommend making it free software that everyone can
|
||||
redistribute and change. You can do so by permitting redistribution under
|
||||
these terms (or, alternatively, under the terms of the ordinary General Public
|
||||
License).
|
||||
|
||||
To apply these terms, attach the following notices to the library. It is safest
|
||||
to attach them to the start of each source file to most effectively convey
|
||||
the exclusion of warranty; and each file should have at least the "copyright"
|
||||
line and a pointer to where the full notice is found.
|
||||
|
||||
< one line to give the library's name and an idea of what it does. >
|
||||
|
||||
Copyright (C) < year > < name of author >
|
||||
|
||||
This library is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU Lesser General Public License as published by the Free
|
||||
Software Foundation; either version 2.1 of the License, or (at your option)
|
||||
any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
|
||||
details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License along
|
||||
with this library; if not, write to the Free Software Foundation, Inc., 51
|
||||
Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Also add information
|
||||
on how to contact you by electronic and paper mail.
|
||||
|
||||
You should also get your employer (if you work as a programmer) or your school,
|
||||
if any, to sign a "copyright disclaimer" for the library, if necessary. Here
|
||||
is a sample; alter the names:
|
||||
|
||||
Yoyodyne, Inc., hereby disclaims all copyright interest in
|
||||
|
||||
the library `Frob' (a library for tweaking knobs) written
|
||||
|
||||
by James Random Hacker.
|
||||
|
||||
< signature of Ty Coon > , 1 April 1990
|
||||
|
||||
Ty Coon, President of Vice
|
||||
|
||||
That's all there is to it!
|
||||
@@ -0,0 +1,163 @@
|
||||
GNU LESSER GENERAL PUBLIC LICENSE
|
||||
|
||||
Version 3, 29 June 2007
|
||||
|
||||
Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>
|
||||
|
||||
Everyone is permitted to copy and distribute verbatim copies of this license
|
||||
document, but changing it is not allowed.
|
||||
|
||||
This version of the GNU Lesser General Public License incorporates the terms
|
||||
and conditions of version 3 of the GNU General Public License, supplemented
|
||||
by the additional permissions listed below.
|
||||
|
||||
0. Additional Definitions.
|
||||
|
||||
|
||||
|
||||
As used herein, "this License" refers to version 3 of the GNU Lesser General
|
||||
Public License, and the "GNU GPL" refers to version 3 of the GNU General Public
|
||||
License.
|
||||
|
||||
|
||||
|
||||
"The Library" refers to a covered work governed by this License, other than
|
||||
an Application or a Combined Work as defined below.
|
||||
|
||||
|
||||
|
||||
An "Application" is any work that makes use of an interface provided by the
|
||||
Library, but which is not otherwise based on the Library. Defining a subclass
|
||||
of a class defined by the Library is deemed a mode of using an interface provided
|
||||
by the Library.
|
||||
|
||||
|
||||
|
||||
A "Combined Work" is a work produced by combining or linking an Application
|
||||
with the Library. The particular version of the Library with which the Combined
|
||||
Work was made is also called the "Linked Version".
|
||||
|
||||
|
||||
|
||||
The "Minimal Corresponding Source" for a Combined Work means the Corresponding
|
||||
Source for the Combined Work, excluding any source code for portions of the
|
||||
Combined Work that, considered in isolation, are based on the Application,
|
||||
and not on the Linked Version.
|
||||
|
||||
|
||||
|
||||
The "Corresponding Application Code" for a Combined Work means the object
|
||||
code and/or source code for the Application, including any data and utility
|
||||
programs needed for reproducing the Combined Work from the Application, but
|
||||
excluding the System Libraries of the Combined Work.
|
||||
|
||||
1. Exception to Section 3 of the GNU GPL.
|
||||
|
||||
You may convey a covered work under sections 3 and 4 of this License without
|
||||
being bound by section 3 of the GNU GPL.
|
||||
|
||||
2. Conveying Modified Versions.
|
||||
|
||||
If you modify a copy of the Library, and, in your modifications, a facility
|
||||
refers to a function or data to be supplied by an Application that uses the
|
||||
facility (other than as an argument passed when the facility is invoked),
|
||||
then you may convey a copy of the modified version:
|
||||
|
||||
a) under this License, provided that you make a good faith effort to ensure
|
||||
that, in the event an Application does not supply the function or data, the
|
||||
facility still operates, and performs whatever part of its purpose remains
|
||||
meaningful, or
|
||||
|
||||
b) under the GNU GPL, with none of the additional permissions of this License
|
||||
applicable to that copy.
|
||||
|
||||
3. Object Code Incorporating Material from Library Header Files.
|
||||
|
||||
The object code form of an Application may incorporate material from a header
|
||||
file that is part of the Library. You may convey such object code under terms
|
||||
of your choice, provided that, if the incorporated material is not limited
|
||||
to numerical parameters, data structure layouts and accessors, or small macros,
|
||||
inline functions and templates (ten or fewer lines in length), you do both
|
||||
of the following:
|
||||
|
||||
a) Give prominent notice with each copy of the object code that the Library
|
||||
is used in it and that the Library and its use are covered by this License.
|
||||
|
||||
b) Accompany the object code with a copy of the GNU GPL and this license document.
|
||||
|
||||
4. Combined Works.
|
||||
|
||||
You may convey a Combined Work under terms of your choice that, taken together,
|
||||
effectively do not restrict modification of the portions of the Library contained
|
||||
in the Combined Work and reverse engineering for debugging such modifications,
|
||||
if you also do each of the following:
|
||||
|
||||
a) Give prominent notice with each copy of the Combined Work that the Library
|
||||
is used in it and that the Library and its use are covered by this License.
|
||||
|
||||
b) Accompany the Combined Work with a copy of the GNU GPL and this license
|
||||
document.
|
||||
|
||||
c) For a Combined Work that displays copyright notices during execution, include
|
||||
the copyright notice for the Library among these notices, as well as a reference
|
||||
directing the user to the copies of the GNU GPL and this license document.
|
||||
|
||||
d) Do one of the following:
|
||||
|
||||
0) Convey the Minimal Corresponding Source under the terms of this License,
|
||||
and the Corresponding Application Code in a form suitable for, and under terms
|
||||
that permit, the user to recombine or relink the Application with a modified
|
||||
version of the Linked Version to produce a modified Combined Work, in the
|
||||
manner specified by section 6 of the GNU GPL for conveying Corresponding Source.
|
||||
|
||||
1) Use a suitable shared library mechanism for linking with the Library. A
|
||||
suitable mechanism is one that (a) uses at run time a copy of the Library
|
||||
already present on the user's computer system, and (b) will operate properly
|
||||
with a modified version of the Library that is interface-compatible with the
|
||||
Linked Version.
|
||||
|
||||
e) Provide Installation Information, but only if you would otherwise be required
|
||||
to provide such information under section 6 of the GNU GPL, and only to the
|
||||
extent that such information is necessary to install and execute a modified
|
||||
version of the Combined Work produced by recombining or relinking the Application
|
||||
with a modified version of the Linked Version. (If you use option 4d0, the
|
||||
Installation Information must accompany the Minimal Corresponding Source and
|
||||
Corresponding Application Code. If you use option 4d1, you must provide the
|
||||
Installation Information in the manner specified by section 6 of the GNU GPL
|
||||
for conveying Corresponding Source.)
|
||||
|
||||
5. Combined Libraries.
|
||||
|
||||
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 that are
|
||||
not Applications and are not covered by this License, and convey such a combined
|
||||
library under terms of your choice, if you do both of the following:
|
||||
|
||||
a) Accompany the combined library with a copy of the same work based on the
|
||||
Library, uncombined with any other library facilities, conveyed under the
|
||||
terms of this License.
|
||||
|
||||
b) Give prominent notice with the combined library that part of it is a work
|
||||
based on the Library, and explaining where to find the accompanying uncombined
|
||||
form of the same work.
|
||||
|
||||
6. Revised Versions of the GNU Lesser General Public License.
|
||||
|
||||
The Free Software Foundation may publish revised and/or new versions of the
|
||||
GNU 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 as you
|
||||
received it specifies that a certain numbered version of the GNU Lesser General
|
||||
Public License "or any later version" applies to it, you have the option of
|
||||
following the terms and conditions either of that published version or of
|
||||
any later version published by the Free Software Foundation. If the Library
|
||||
as you received it does not specify a version number of the GNU Lesser General
|
||||
Public License, you may choose any version of the GNU Lesser General Public
|
||||
License ever published by the Free Software Foundation.
|
||||
|
||||
If the Library as you received it specifies that a proxy can decide whether
|
||||
future versions of the GNU Lesser General Public License shall apply, that
|
||||
proxy's public statement of acceptance of any version is permanent authorization
|
||||
for you to choose that version for the Library.
|
||||
+12
@@ -0,0 +1,12 @@
|
||||
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 3 of the license or (at your option) any later version
|
||||
that is accepted by the membership of KDE e.V. (or its successor
|
||||
approved by the membership of KDE e.V.), which shall act as a
|
||||
proxy as defined in Section 6 of version 3 of the license.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
@@ -0,0 +1,19 @@
|
||||
MIT License Copyright (c) <year> <copyright holders>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is furnished
|
||||
to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice (including the next
|
||||
paragraph) shall be included in all copies or substantial portions of the
|
||||
Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS
|
||||
OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
|
||||
OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
@@ -0,0 +1,3 @@
|
||||
|
||||
Current kactivities maintainer is: Ivan Čukić <ivan.cukic@kde.org>
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
@PACKAGE_INIT@
|
||||
|
||||
include(CMakeFindDependencyMacro)
|
||||
find_dependency(Qt6Core @QT_MIN_VERSION@)
|
||||
|
||||
include("${CMAKE_CURRENT_LIST_DIR}/PlasmaActivitiesLibraryTargets.cmake")
|
||||
@PACKAGE_INCLUDE_QCHTARGETS@
|
||||
@@ -0,0 +1,6 @@
|
||||
See README.developers and README.packagers (the former is also for users).
|
||||
|
||||
In order to properly display the files, use the GNU man command.
|
||||
|
||||
man README.developers
|
||||
man README.packagers
|
||||
@@ -0,0 +1,87 @@
|
||||
|
||||
|
||||
.\" " " " " " " " " " " " " " " " " " " " " " " " " " " "
|
||||
.\" "
|
||||
.\" It is best to view this file with the man tool: "
|
||||
.\" man ./README.developers "
|
||||
.\" "
|
||||
.\" " " " " " " " " " " " " " " " " " " " " " " " " " " "
|
||||
|
||||
|
||||
.TH README KAMD 2012-08-29 "KDE" "KActivities Developers"
|
||||
|
||||
.SH COMMIT POLICY
|
||||
|
||||
Every non-trivial patch must go through the review before it goes into the
|
||||
master branch.
|
||||
|
||||
http://git.reviewboard.kde.org
|
||||
repository: kactivities
|
||||
groups: plasma
|
||||
people: Ivan Cukic
|
||||
|
||||
If you don't have an account for identity.kde.org, you can send smaller
|
||||
patches to the plasma-devel@kde.org mailing list, or (please don't) directly
|
||||
to the repository maintainer (see MAINTAINER file).
|
||||
|
||||
|
||||
.SH CODE POLICY
|
||||
|
||||
The code needs to follow KDElibs coding style in *all* parts of the project,
|
||||
not only the library. You can find more information about the style here:
|
||||
http://techbase.kde.org/Policies/Kdelibs_Coding_Style
|
||||
|
||||
Macros in CMakeLists.txt should be lowercase throughout the project,
|
||||
and indentation should be 4, with the closing parenthesis in the same level
|
||||
as the content.
|
||||
|
||||
.SH COMPILER COMPATIBILITY
|
||||
|
||||
The library (src/lib) needs to be compilable with these:
|
||||
- GCC 4.5
|
||||
- MSVC 2010
|
||||
- Clang 3.1
|
||||
(or newer)
|
||||
This is the same policy the KDE Frameworks have.
|
||||
|
||||
Other parts require modern compilers. You can (and should) use more modern
|
||||
C++ coding practices. Including auto, lambdas, smart pointers etc. You can
|
||||
use anything that GCC 4.7 can compile.
|
||||
|
||||
These are the compilers you need to test your patches against:
|
||||
- GCC 4.7
|
||||
- LLVM/Clang 3.1
|
||||
|
||||
When you set up different builds alongside the main one, you can use
|
||||
scripts/commit.sh to build them all before committing. The script
|
||||
calls git commit if all builds finished successfully. See the script
|
||||
for more info.
|
||||
|
||||
|
||||
.SH FILE NAMING
|
||||
|
||||
The library files are lower-case, apart from the "pretty" headers.
|
||||
The service, and the rest of the repository should be in camel-case
|
||||
(with the exception of source files that don't have corresponding
|
||||
headers, or vice-versa).
|
||||
|
||||
|
||||
.SH CONVENIENCE MACROS AND METHODS
|
||||
|
||||
There are some convenience macros and methods defined in the headers placed
|
||||
in the service/utils/ directory.
|
||||
|
||||
.TP
|
||||
.B D_PTR
|
||||
d_ptr.h and d_ptr_implementation.h define a smart pointer way of doing
|
||||
the d-ptr (aka pimpl) idiom.
|
||||
|
||||
.TP
|
||||
.B remove_if
|
||||
remove_if.h is a generic implementation of the erase-remove idiom
|
||||
|
||||
.TP
|
||||
.B for_each_assoc, find_if_assoc
|
||||
for_each_assoc.h and find_if_assoc.h define the for_each and find_if
|
||||
algorithms for associative containers. Works with both Qt and STL containers.
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
# KActivities
|
||||
|
||||
Core components for the KDE Activity concept
|
||||
|
||||
## Introduction
|
||||
|
||||
When a user is interacting with a computer, there are three main areas of
|
||||
contextual information that may affect the behaviour of the system: who the user
|
||||
is, where they are, and what they are doing.
|
||||
|
||||
*Activities* deal with the last one. An activity might be "developing a KDE
|
||||
application", "studying 19th century art", "composing music" or "watching funny
|
||||
videos". Each of these activities may involve multiple applications, and a single
|
||||
application may be used in multiple activities (for example, most activities are
|
||||
likely to involve using a web browser, but different activities will probably
|
||||
involve different websites).
|
||||
|
||||
KActivities provides the infrastructure needed to manage a user's activities,
|
||||
allowing them to switch between tasks, and for applications to update their
|
||||
state to match the user's current activity. This includes a daemon, a library
|
||||
for interacting with that daemon, and plugins for integration with other
|
||||
frameworks.
|
||||
|
||||
## Usage
|
||||
|
||||
Most applications that wish to be activity-aware will want to use
|
||||
KActivities::Consumer to keep track of the user's current activity, and
|
||||
KActivities::ResourceInstance to notify the activity manager of resources the
|
||||
user has accessed (this is not necessary for resources accessed via KIO, as a
|
||||
plugin is provided to do that automatically).
|
||||
|
||||
The other classes available in the API are primarily intended for use by the
|
||||
workspace to allow the user to view and manage available activities.
|
||||
@@ -0,0 +1,23 @@
|
||||
|
||||
|
||||
.\" " " " " " " " " " " " " " " " " " " " " " " " " " " "
|
||||
.\" "
|
||||
.\" It is best to view this file with the man tool: "
|
||||
.\" man ./README.packagers "
|
||||
.\" "
|
||||
.\" " " " " " " " " " " " " " " " " " " " " " " " " " " "
|
||||
|
||||
|
||||
.\" Best to view this file with the man tool
|
||||
.TH README KAMD 2012-08-29 "KDE" "KActivities Packagers"
|
||||
|
||||
.SH LIBRARY
|
||||
|
||||
The library can be used even if the service is not running nor installed.
|
||||
The dependencies are minimal since it is only a thin wrapper for the d-bus
|
||||
service.
|
||||
|
||||
.SH SERVICE
|
||||
|
||||
.TP
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
src/lib/resourceinstance.cpp:149:
|
||||
TODO: update the service info
|
||||
src/lib/resourceinstance.cpp:161:
|
||||
TODO: update the service info
|
||||
|
||||
src/imports/resourcemodel.cpp:103:
|
||||
NOTE: What to do if the file does not exist?
|
||||
Ignoring that case since the daemon creates it on startup.
|
||||
Is it plausible that somebody will instantiate the ResourceModel
|
||||
before the daemon is started?
|
||||
src/imports/resourcemodel.cpp:133:
|
||||
TODO: Database connection naming could be smarter (thread-id-based,
|
||||
reusing connections...?)
|
||||
src/imports/resourcemodel.cpp:335:
|
||||
TODO: Will probably need some more special handling -
|
||||
for application:/ and a few more
|
||||
src/imports/resourcemodel.cpp:551:
|
||||
TODO: This might be smarter possibly, but might collide
|
||||
with the SQL model. Implement a custom model with internal
|
||||
cache instead of basing it on QSqlModel.
|
||||
|
||||
src/imports/activitiesextensionplugin.cpp:30:
|
||||
TODO: Clean up unused classes from the imports module
|
||||
src/imports/activitiesextensionplugin.cpp:32:
|
||||
TODO: Since plasma is now dealing with activity model wallpapers,
|
||||
replace ActivityModel with the KActivities::ActivitiesModel
|
||||
(but keep the name)
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
# vim:set softtabstop=3 shiftwidth=3 tabstop=3 expandtab:
|
||||
|
||||
add_subdirectory (core)
|
||||
|
||||
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
SPDX-FileCopyrightText: 2013, 2014, 2015 Ivan Cukic <ivan.cukic(at)kde.org>
|
||||
|
||||
SPDX-License-Identifier: GPL-2.0-or-later
|
||||
*/
|
||||
|
||||
#include "test.h"
|
||||
|
||||
#include <QDBusConnection>
|
||||
#include <QDBusConnectionInterface>
|
||||
|
||||
#include "common/dbus/common.h"
|
||||
|
||||
Test::Test(QObject *parent)
|
||||
: QObject(parent)
|
||||
{
|
||||
}
|
||||
|
||||
bool Test::inEmptySession()
|
||||
{
|
||||
const QStringList services = QDBusConnection::sessionBus().interface()->registeredServiceNames();
|
||||
|
||||
for (const QString &service : services) {
|
||||
bool kdeServiceAndNotKAMD = service.startsWith(QLatin1String("org.kde")) && service != KAMD_DBUS_SERVICE;
|
||||
|
||||
if (kdeServiceAndNotKAMD) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Test::isActivityManagerRunning()
|
||||
{
|
||||
return QDBusConnection::sessionBus().interface()->isServiceRegistered(KAMD_DBUS_SERVICE);
|
||||
}
|
||||
|
||||
#include "moc_test.cpp"
|
||||
@@ -0,0 +1,134 @@
|
||||
/*
|
||||
SPDX-FileCopyrightText: 2013, 2014, 2015 Ivan Cukic <ivan.cukic(at)kde.org>
|
||||
|
||||
SPDX-License-Identifier: GPL-2.0-or-later
|
||||
*/
|
||||
|
||||
#ifndef COMMON_TEST_H
|
||||
#define COMMON_TEST_H
|
||||
|
||||
#include <QCoreApplication>
|
||||
#include <QFuture>
|
||||
#include <QFutureWatcher>
|
||||
#include <QObject>
|
||||
#include <QTest>
|
||||
|
||||
class Test : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
Test(QObject *parent = nullptr);
|
||||
|
||||
protected:
|
||||
enum WhenToFail {
|
||||
DontFail = 0,
|
||||
FailIfTrue = 1,
|
||||
FailIfFalse = 2,
|
||||
};
|
||||
|
||||
template<typename _ReturnType, typename _Continuation>
|
||||
void continue_future(const QFuture<_ReturnType> &future, _Continuation &&continuation)
|
||||
{
|
||||
if (!future.isFinished()) {
|
||||
auto watcher = new QFutureWatcher<decltype(future.result())>();
|
||||
QObject::connect(
|
||||
watcher,
|
||||
&QFutureWatcherBase::finished,
|
||||
watcher,
|
||||
[=] {
|
||||
continuation(watcher->result());
|
||||
watcher->deleteLater();
|
||||
},
|
||||
Qt::QueuedConnection);
|
||||
|
||||
watcher->setFuture(future);
|
||||
|
||||
} else {
|
||||
continuation(future.result());
|
||||
}
|
||||
}
|
||||
|
||||
template<typename _Continuation>
|
||||
void continue_future(const QFuture<void> &future, _Continuation &&continuation)
|
||||
{
|
||||
if (!future.isFinished()) {
|
||||
auto watcher = new QFutureWatcher<void>();
|
||||
QObject::connect(
|
||||
watcher,
|
||||
&QFutureWatcherBase::finished,
|
||||
watcher,
|
||||
[=] {
|
||||
continuation();
|
||||
watcher->deleteLater();
|
||||
},
|
||||
Qt::QueuedConnection);
|
||||
|
||||
watcher->setFuture(future);
|
||||
|
||||
} else {
|
||||
continuation();
|
||||
}
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
static inline void wait_until(T condition, const char *msg, int msecs = 300)
|
||||
{
|
||||
auto start = QTime::currentTime();
|
||||
|
||||
while (!condition()) {
|
||||
QCoreApplication::processEvents();
|
||||
|
||||
auto now = QTime::currentTime();
|
||||
QVERIFY2(start.msecsTo(now) < msecs, msg);
|
||||
if (start.msecsTo(now) >= msecs)
|
||||
break;
|
||||
}
|
||||
}
|
||||
// clang-format off
|
||||
#define TEST_WAIT_UNTIL(C) \
|
||||
wait_until([&] () -> bool { return C; }, "Timeout waiting for: " #C);
|
||||
#define TEST_WAIT_UNTIL_WITH_TIMEOUT(C, T) \
|
||||
wait_until([&] () ->bool { return C; }, "Timeout waiting for: " #C, T);
|
||||
// clang-format on
|
||||
|
||||
template<typename T>
|
||||
static bool check(T what, WhenToFail wtf = DontFail, const char *msg = nullptr)
|
||||
{
|
||||
bool result = what();
|
||||
|
||||
if ((wtf == FailIfTrue && result) || (wtf == FailIfFalse && !result)) {
|
||||
qFatal(
|
||||
"\n"
|
||||
"\n"
|
||||
"!!! > \n"
|
||||
"!!! > %s\n"
|
||||
"!!! > \n",
|
||||
msg);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static bool inEmptySession();
|
||||
static bool isActivityManagerRunning();
|
||||
|
||||
Q_SIGNALS:
|
||||
void testFinished();
|
||||
};
|
||||
|
||||
#define CHECK_CONDITION(A, B) check(A, B, #A " raised " #B)
|
||||
|
||||
// Pretty print
|
||||
#include <iostream>
|
||||
|
||||
#if defined(Q_NO_DEBUG) || !defined(Q_OS_LINUX)
|
||||
#define TEST_CHUNK(Name)
|
||||
#else
|
||||
inline void _test_chunk(const QString &message)
|
||||
{
|
||||
std::cerr << '\n' << message.toStdString() << "\n" << std::string(message.length(), '-') << '\n';
|
||||
}
|
||||
#define TEST_CHUNK(Name) _test_chunk(Name);
|
||||
#endif
|
||||
|
||||
#endif /* TEST_H */
|
||||
@@ -0,0 +1,41 @@
|
||||
# vim:set softtabstop=3 shiftwidth=3 tabstop=3 expandtab:
|
||||
project (PlasmaActivitiesTest)
|
||||
|
||||
find_package (Qt6 REQUIRED NO_MODULE COMPONENTS Test Core DBus)
|
||||
|
||||
if (NOT WIN32)
|
||||
|
||||
add_executable(PlasmaActivitiesTest)
|
||||
|
||||
target_include_directories(PlasmaActivitiesTest PRIVATE
|
||||
${PLASMA_ACTIVITIES_CURRENT_ROOT_SOURCE_DIR}/src/
|
||||
${PLASMA_ACTIVITIES_CURRENT_ROOT_SOURCE_DIR}/tests/
|
||||
${PLASMA_ACTIVITIES_CURRENT_ROOT_SOURCE_DIR}/autotests/
|
||||
${CMAKE_BINARY_DIR}/src/
|
||||
)
|
||||
|
||||
target_sources(PlasmaActivitiesTest PRIVATE
|
||||
main.cpp
|
||||
Process.cpp
|
||||
OfflineTest.cpp
|
||||
CleanOnlineTest.cpp
|
||||
Process.h
|
||||
OfflineTest.h
|
||||
CleanOnlineTest.h
|
||||
${PLASMA_ACTIVITIES_CURRENT_ROOT_SOURCE_DIR}/autotests/common/test.cpp
|
||||
)
|
||||
|
||||
target_link_libraries(PlasmaActivitiesTest
|
||||
PRIVATE
|
||||
Qt6::Core
|
||||
Qt6::Test
|
||||
Qt6::DBus
|
||||
Plasma::Activities
|
||||
)
|
||||
|
||||
endif ()
|
||||
|
||||
add_executable(QFlatSetTest QFlatSetTest.cpp)
|
||||
target_link_libraries(QFlatSetTest PRIVATE Qt6::Core Qt6::Test)
|
||||
target_include_directories(QFlatSetTest PRIVATE ${PLASMA_ACTIVITIES_CURRENT_ROOT_SOURCE_DIR}/src/)
|
||||
add_test(NAME QFlatSetTest COMMAND QFlatSetTest)
|
||||
@@ -0,0 +1,110 @@
|
||||
/*
|
||||
SPDX-FileCopyrightText: 2013 Ivan Cukic <ivan.cukic(at)kde.org>
|
||||
|
||||
SPDX-License-Identifier: GPL-2.0-or-later
|
||||
*/
|
||||
|
||||
#include "CleanOnlineTest.h"
|
||||
|
||||
#include <QDBusConnection>
|
||||
#include <QDBusConnectionInterface>
|
||||
#include <QDebug>
|
||||
#include <QString>
|
||||
#include <QTest>
|
||||
|
||||
QString CleanOnlineSetup::id1;
|
||||
QString CleanOnlineSetup::id2;
|
||||
|
||||
CleanOnlineTest::CleanOnlineTest(QObject *parent)
|
||||
: Test(parent)
|
||||
{
|
||||
activities.reset(new KActivities::Controller());
|
||||
}
|
||||
|
||||
CleanOnlineSetup::CleanOnlineSetup(QObject *parent)
|
||||
: Test(parent)
|
||||
{
|
||||
activities.reset(new KActivities::Controller());
|
||||
}
|
||||
|
||||
OnlineTest::OnlineTest(QObject *parent)
|
||||
: Test(parent)
|
||||
{
|
||||
activities.reset(new KActivities::Controller());
|
||||
}
|
||||
|
||||
void CleanOnlineTest::testCleanOnlineActivityListing()
|
||||
{
|
||||
// Waiting for the service to start, and for us to sync
|
||||
TEST_WAIT_UNTIL(activities->serviceStatus() == KActivities::Consumer::Running);
|
||||
|
||||
QCOMPARE(activities->activities(), QStringList());
|
||||
QCOMPARE(activities->serviceStatus(), KActivities::Consumer::Running);
|
||||
QCOMPARE(activities->currentActivity(), QString());
|
||||
|
||||
QCOMPARE(activities->activities(), QStringList());
|
||||
}
|
||||
|
||||
void CleanOnlineSetup::testCleanOnlineActivityControl()
|
||||
{
|
||||
// Waiting for the service to start, and for us to sync
|
||||
TEST_WAIT_UNTIL(activities->serviceStatus() == KActivities::Consumer::Running);
|
||||
|
||||
auto activity1 = activities->addActivity(QStringLiteral("The first one"));
|
||||
TEST_WAIT_UNTIL(activity1.isFinished());
|
||||
id1 = activity1.result();
|
||||
|
||||
auto activity2 = activities->addActivity(QStringLiteral("The second one"));
|
||||
TEST_WAIT_UNTIL(activity2.isFinished());
|
||||
id2 = activity2.result();
|
||||
|
||||
TEST_WAIT_UNTIL(activities->currentActivity() == id1);
|
||||
|
||||
auto f1 = activities->setCurrentActivity(activity2.result());
|
||||
TEST_WAIT_UNTIL(f1.isFinished());
|
||||
TEST_WAIT_UNTIL(activities->currentActivity() == id2);
|
||||
|
||||
auto f2 = activities->setCurrentActivity(id1);
|
||||
TEST_WAIT_UNTIL(f2.isFinished());
|
||||
TEST_WAIT_UNTIL(activities->currentActivity() == id1);
|
||||
|
||||
auto f3 = activities->setActivityName(id1, QStringLiteral("Renamed activity"));
|
||||
TEST_WAIT_UNTIL(f3.isFinished());
|
||||
|
||||
KActivities::Info ac(id1);
|
||||
TEST_WAIT_UNTIL(ac.name() == QLatin1String("Renamed activity"));
|
||||
|
||||
TEST_WAIT_UNTIL(activities->activities().size() == 2);
|
||||
}
|
||||
|
||||
void OnlineTest::testOnlineActivityListing()
|
||||
{
|
||||
// Waiting for the service to start, and for us to sync
|
||||
TEST_WAIT_UNTIL(activities->serviceStatus() == KActivities::Consumer::Running);
|
||||
|
||||
KActivities::Info i1(CleanOnlineSetup::id1);
|
||||
KActivities::Info i2(CleanOnlineSetup::id2);
|
||||
|
||||
TEST_WAIT_UNTIL(i1.name() == QLatin1String("Renamed activity"));
|
||||
TEST_WAIT_UNTIL(i2.name() == QLatin1String("The second one"));
|
||||
|
||||
qDebug() << CleanOnlineSetup::id1 << i1.name();
|
||||
qDebug() << CleanOnlineSetup::id2 << i2.name();
|
||||
}
|
||||
|
||||
void CleanOnlineTest::cleanupTestCase()
|
||||
{
|
||||
Q_EMIT testFinished();
|
||||
}
|
||||
|
||||
void CleanOnlineSetup::cleanupTestCase()
|
||||
{
|
||||
Q_EMIT testFinished();
|
||||
}
|
||||
|
||||
void OnlineTest::cleanupTestCase()
|
||||
{
|
||||
Q_EMIT testFinished();
|
||||
}
|
||||
|
||||
#include "moc_CleanOnlineTest.cpp"
|
||||
@@ -0,0 +1,67 @@
|
||||
/*
|
||||
SPDX-FileCopyrightText: 2013 Ivan Cukic <ivan.cukic(at)kde.org>
|
||||
|
||||
SPDX-License-Identifier: GPL-2.0-or-later
|
||||
*/
|
||||
|
||||
#ifndef CLEANONLINETEST_H
|
||||
#define CLEANONLINETEST_H
|
||||
|
||||
#include <common/test.h>
|
||||
|
||||
#include <controller.h>
|
||||
|
||||
#include <QScopedPointer>
|
||||
|
||||
class CleanOnlineTest : public Test
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
CleanOnlineTest(QObject *parent = nullptr);
|
||||
|
||||
private Q_SLOTS:
|
||||
void testCleanOnlineActivityListing();
|
||||
|
||||
void cleanupTestCase();
|
||||
|
||||
private:
|
||||
QScopedPointer<KActivities::Controller> activities;
|
||||
QString id1;
|
||||
QString id2;
|
||||
};
|
||||
|
||||
class CleanOnlineSetup : public Test
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit CleanOnlineSetup(QObject *parent = nullptr);
|
||||
|
||||
private Q_SLOTS:
|
||||
void testCleanOnlineActivityControl();
|
||||
|
||||
void cleanupTestCase();
|
||||
|
||||
private:
|
||||
QScopedPointer<KActivities::Controller> activities;
|
||||
|
||||
public:
|
||||
static QString id1;
|
||||
static QString id2;
|
||||
};
|
||||
|
||||
class OnlineTest : public Test
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit OnlineTest(QObject *parent = nullptr);
|
||||
|
||||
private Q_SLOTS:
|
||||
void testOnlineActivityListing();
|
||||
|
||||
void cleanupTestCase();
|
||||
|
||||
private:
|
||||
QScopedPointer<KActivities::Controller> activities;
|
||||
};
|
||||
|
||||
#endif /* CLEANONLINETEST_H */
|
||||
@@ -0,0 +1,73 @@
|
||||
/*
|
||||
SPDX-FileCopyrightText: 2013 Ivan Cukic <ivan.cukic(at)kde.org>
|
||||
|
||||
SPDX-License-Identifier: GPL-2.0-or-later
|
||||
*/
|
||||
|
||||
#include "OfflineTest.h"
|
||||
|
||||
#include <QDBusConnection>
|
||||
#include <QDBusConnectionInterface>
|
||||
#include <QString>
|
||||
#include <QTest>
|
||||
|
||||
QString nulluuid = QStringLiteral("00000000-0000-0000-0000-000000000000");
|
||||
|
||||
OfflineTest::OfflineTest(QObject *parent)
|
||||
: Test(parent)
|
||||
{
|
||||
QCoreApplication::instance()->setProperty("org.kde.KActivities.core.disableAutostart", true);
|
||||
|
||||
activities.reset(new KActivities::Controller());
|
||||
}
|
||||
|
||||
void OfflineTest::testOfflineActivityListing()
|
||||
{
|
||||
// The service is not running
|
||||
|
||||
TEST_WAIT_UNTIL(activities->serviceStatus() == KActivities::Consumer::NotRunning);
|
||||
QCOMPARE(activities->currentActivity(), nulluuid);
|
||||
|
||||
QCOMPARE(activities->activities(), QStringList() << nulluuid);
|
||||
}
|
||||
|
||||
void OfflineTest::testOfflineActivityControl()
|
||||
{
|
||||
continue_future(activities->addActivity(QStringLiteral("Activity")), [](const QString &newid) {
|
||||
QCOMPARE(newid, QString());
|
||||
});
|
||||
|
||||
continue_future(activities->setCurrentActivity(QStringLiteral("Activity")), [](bool success) {
|
||||
QCOMPARE(success, false);
|
||||
});
|
||||
|
||||
// Test whether the responses are immediate
|
||||
static bool inMethod = false;
|
||||
|
||||
inMethod = true;
|
||||
|
||||
continue_future(activities->setActivityName(QStringLiteral("Activity"), QStringLiteral("Activity")), []() {
|
||||
QCOMPARE(inMethod, true);
|
||||
});
|
||||
continue_future(activities->setActivityIcon(QStringLiteral("Activity"), QStringLiteral("Activity")), []() {
|
||||
QCOMPARE(inMethod, true);
|
||||
});
|
||||
continue_future(activities->removeActivity(QStringLiteral("Activity")), []() {
|
||||
QCOMPARE(inMethod, true);
|
||||
});
|
||||
|
||||
inMethod = false;
|
||||
}
|
||||
|
||||
void OfflineTest::initTestCase()
|
||||
{
|
||||
CHECK_CONDITION(inEmptySession, FailIfFalse);
|
||||
CHECK_CONDITION(isActivityManagerRunning, FailIfTrue);
|
||||
}
|
||||
|
||||
void OfflineTest::cleanupTestCase()
|
||||
{
|
||||
Q_EMIT testFinished();
|
||||
}
|
||||
|
||||
#include "moc_OfflineTest.cpp"
|
||||
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
SPDX-FileCopyrightText: 2013 Ivan Cukic <ivan.cukic(at)kde.org>
|
||||
|
||||
SPDX-License-Identifier: GPL-2.0-or-later
|
||||
*/
|
||||
|
||||
#ifndef OFFLINETEST_H
|
||||
#define OFFLINETEST_H
|
||||
|
||||
#include <common/test.h>
|
||||
|
||||
#include <controller.h>
|
||||
|
||||
#include <QScopedPointer>
|
||||
|
||||
class OfflineTest : public Test
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit OfflineTest(QObject *parent = nullptr);
|
||||
|
||||
private Q_SLOTS:
|
||||
void initTestCase();
|
||||
|
||||
void testOfflineActivityListing();
|
||||
void testOfflineActivityControl();
|
||||
|
||||
void cleanupTestCase();
|
||||
|
||||
private:
|
||||
QScopedPointer<KActivities::Controller> activities;
|
||||
};
|
||||
|
||||
#endif /* OFFLINETEST_H */
|
||||
@@ -0,0 +1,146 @@
|
||||
/*
|
||||
SPDX-FileCopyrightText: 2013 Ivan Cukic <ivan.cukic(at)kde.org>
|
||||
|
||||
SPDX-License-Identifier: GPL-2.0-or-later
|
||||
*/
|
||||
|
||||
#include "Process.h"
|
||||
|
||||
#include <QDBusConnection>
|
||||
#include <QDBusConnectionInterface>
|
||||
#include <QDebug>
|
||||
#include <QProcess>
|
||||
#include <QRegularExpression>
|
||||
#include <QStandardPaths>
|
||||
#include <QString>
|
||||
#include <QTemporaryDir>
|
||||
#include <QTest>
|
||||
|
||||
#include <signal.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#include "common/dbus/common.h"
|
||||
|
||||
namespace Process
|
||||
{
|
||||
QProcess *Modifier::s_process = nullptr;
|
||||
QTemporaryDir *Modifier::s_tempDir = nullptr;
|
||||
QString nulluuid = QStringLiteral("00000000-0000-0000-0000-000000000000");
|
||||
|
||||
Modifier::Modifier(Action action)
|
||||
: Test()
|
||||
, m_action(action)
|
||||
{
|
||||
if (!s_process) {
|
||||
s_process = new QProcess();
|
||||
s_tempDir = new QTemporaryDir();
|
||||
|
||||
if (!s_tempDir->isValid()) {
|
||||
qFatal("Can not create a temporary dir");
|
||||
}
|
||||
|
||||
qDebug() << "Running KAMD in " << s_tempDir->path();
|
||||
s_process->setProcessChannelMode(QProcess::ForwardedChannels);
|
||||
}
|
||||
}
|
||||
|
||||
void Modifier::initTestCase()
|
||||
{
|
||||
const auto state = s_process->state();
|
||||
|
||||
if (state != QProcess::NotRunning && m_action == Start) {
|
||||
qFatal("Already running");
|
||||
}
|
||||
|
||||
switch (m_action) {
|
||||
case Start: {
|
||||
qDebug() << "Starting...";
|
||||
|
||||
QRegularExpression nonxdg(QStringLiteral("^[^X][^D][^G].*$"));
|
||||
|
||||
auto env = QProcessEnvironment::systemEnvironment().toStringList().filter(nonxdg)
|
||||
<< QStringLiteral("XDG_DATA_HOME=") + s_tempDir->path() + QStringLiteral("/")
|
||||
<< QStringLiteral("XDG_CONFIG_HOME=") + s_tempDir->path() + QStringLiteral("/")
|
||||
<< QStringLiteral("XDG_CACHE_HOME=") + s_tempDir->path() + QStringLiteral("/");
|
||||
|
||||
// qDebug() << env;
|
||||
|
||||
s_process->setEnvironment(env);
|
||||
const QString exec = QStandardPaths::findExecutable(QStringLiteral("kactivitymanagerd"));
|
||||
QVERIFY(!exec.isEmpty());
|
||||
s_process->start(exec, QStringList());
|
||||
s_process->waitForStarted();
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case Stop:
|
||||
case Kill:
|
||||
case Crash: {
|
||||
qDebug() << "Stopping...";
|
||||
|
||||
const auto dbus = QDBusConnection::sessionBus().interface();
|
||||
const auto kamd = KAMD_DBUS_SERVICE;
|
||||
|
||||
if (!dbus->isServiceRegistered(kamd)) {
|
||||
break;
|
||||
}
|
||||
|
||||
uint pid = dbus->servicePid(kamd);
|
||||
// clang-format off
|
||||
::kill(pid,
|
||||
m_action == Stop ? SIGQUIT :
|
||||
m_action == Kill ? SIGKILL :
|
||||
/* else */ SIGSEGV
|
||||
);
|
||||
// clang-format on
|
||||
|
||||
while (Test::isActivityManagerRunning()) {
|
||||
QCoreApplication::processEvents();
|
||||
}
|
||||
|
||||
if (s_process->state() == QProcess::Running) {
|
||||
s_process->terminate();
|
||||
s_process->waitForFinished();
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Modifier::testProcess()
|
||||
{
|
||||
const auto state = s_process->state();
|
||||
|
||||
switch (m_action) {
|
||||
case Start:
|
||||
QCOMPARE(state, QProcess::Running);
|
||||
break;
|
||||
|
||||
case Stop:
|
||||
QCOMPARE(state, QProcess::NotRunning);
|
||||
break;
|
||||
|
||||
case Kill:
|
||||
QCOMPARE(state, QProcess::NotRunning);
|
||||
break;
|
||||
|
||||
case Crash:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void Modifier::cleanupTestCase()
|
||||
{
|
||||
Q_EMIT testFinished();
|
||||
}
|
||||
|
||||
Modifier *exec(Action action)
|
||||
{
|
||||
return new Modifier(action);
|
||||
}
|
||||
|
||||
} // namespace Process
|
||||
|
||||
#include "moc_Process.cpp"
|
||||
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
SPDX-FileCopyrightText: 2013 Ivan Cukic <ivan.cukic(at)kde.org>
|
||||
|
||||
SPDX-License-Identifier: GPL-2.0-or-later
|
||||
*/
|
||||
|
||||
#ifndef PROCESS_H
|
||||
#define PROCESS_H
|
||||
|
||||
#include <common/test.h>
|
||||
|
||||
#include <controller.h>
|
||||
|
||||
class QProcess;
|
||||
class QTemporaryDir;
|
||||
|
||||
namespace Process
|
||||
{
|
||||
enum Action {
|
||||
Start,
|
||||
Stop,
|
||||
Kill,
|
||||
Crash,
|
||||
};
|
||||
|
||||
class Modifier : public Test
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
Modifier(Action action);
|
||||
|
||||
private Q_SLOTS:
|
||||
void initTestCase();
|
||||
void testProcess();
|
||||
void cleanupTestCase();
|
||||
|
||||
private:
|
||||
Action m_action;
|
||||
static QProcess *s_process;
|
||||
static QTemporaryDir *s_tempDir;
|
||||
};
|
||||
|
||||
Modifier *exec(Action action);
|
||||
|
||||
} // namespace Process
|
||||
|
||||
#endif /* PROCESS_H */
|
||||
@@ -0,0 +1,54 @@
|
||||
#include <utils/qflatset.h>
|
||||
|
||||
#include <QTest>
|
||||
|
||||
class QFlatSetTest : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
private Q_SLOTS:
|
||||
void test1();
|
||||
};
|
||||
|
||||
void QFlatSetTest::test1()
|
||||
{
|
||||
KActivities::QFlatSet<int, std::less<int>> set;
|
||||
set.insert(5);
|
||||
set.insert(4);
|
||||
set.insert(3);
|
||||
|
||||
// Expect sorted
|
||||
auto expected = QList<int>{3, 4, 5};
|
||||
QCOMPARE(set, expected);
|
||||
|
||||
{
|
||||
// try inserting a dupe, expect no change
|
||||
const auto [insertedIt, insertedIndex, didInsert] = set.insert(3);
|
||||
QCOMPARE(didInsert, false);
|
||||
QCOMPARE(insertedIndex, 0);
|
||||
QCOMPARE(insertedIt, set.begin());
|
||||
QCOMPARE(set, expected);
|
||||
}
|
||||
|
||||
// try inserting something at the beginning, expect it to be inserted and have a valid iterator
|
||||
{
|
||||
const auto [insertedIt, insertedIndex, didInsert] = set.insert(0);
|
||||
QVERIFY(didInsert);
|
||||
QCOMPARE(insertedIt, set.begin());
|
||||
QCOMPARE(insertedIndex, (insertedIt - set.begin()));
|
||||
}
|
||||
|
||||
set.clear();
|
||||
set.squeeze();
|
||||
QCOMPARE(set.capacity(), 0);
|
||||
|
||||
for (int i = 0; i < 50; i++) {
|
||||
const auto [insertedIt, insertedIndex, didInsert] = set.insert(i);
|
||||
QVERIFY(didInsert);
|
||||
QCOMPARE(insertedIndex, (insertedIt - set.begin()));
|
||||
QCOMPARE(insertedIt, set.begin() + i);
|
||||
}
|
||||
}
|
||||
|
||||
QTEST_MAIN(QFlatSetTest)
|
||||
|
||||
#include "QFlatSetTest.moc"
|
||||
@@ -0,0 +1,103 @@
|
||||
/*
|
||||
SPDX-FileCopyrightText: 2013 Ivan Cukic <ivan.cukic(at)kde.org>
|
||||
|
||||
SPDX-License-Identifier: GPL-2.0-or-later
|
||||
*/
|
||||
|
||||
#include <QCoreApplication>
|
||||
#include <QList>
|
||||
|
||||
#include <common/test.h>
|
||||
|
||||
#include "CleanOnlineTest.h"
|
||||
#include "OfflineTest.h"
|
||||
#include "Process.h"
|
||||
|
||||
class TestRunner : public QObject
|
||||
{
|
||||
public:
|
||||
TestRunner()
|
||||
: m_nextToStart(0)
|
||||
{
|
||||
}
|
||||
|
||||
TestRunner &addTest(Test *test)
|
||||
{
|
||||
if (m_nextToStart == 0) {
|
||||
m_tests << test;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
TestRunner &operator<<(Test *test)
|
||||
{
|
||||
addTest(test);
|
||||
return *this;
|
||||
}
|
||||
|
||||
void start()
|
||||
{
|
||||
if (m_nextToStart) {
|
||||
return;
|
||||
}
|
||||
|
||||
next();
|
||||
}
|
||||
|
||||
private:
|
||||
void next()
|
||||
{
|
||||
if (m_nextToStart >= m_tests.size()) {
|
||||
QCoreApplication::exit(0);
|
||||
return;
|
||||
}
|
||||
|
||||
Test *test = m_tests[m_nextToStart++];
|
||||
|
||||
QObject::connect(test, &Test::testFinished, this, &TestRunner::next, Qt::QueuedConnection);
|
||||
|
||||
QTest::qExec(test);
|
||||
}
|
||||
|
||||
private:
|
||||
QList<Test *> m_tests;
|
||||
int m_nextToStart;
|
||||
};
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
QCoreApplication app(argc, argv);
|
||||
|
||||
TestRunner &runner = *(new TestRunner());
|
||||
|
||||
(runner << Process::exec(Process::Kill)
|
||||
|
||||
// Running the tests for when the service is offline
|
||||
<< new OfflineTest()
|
||||
|
||||
// Running the offline tests again so that we are sure
|
||||
// nothing has changed -- no activities created, changed etc.
|
||||
<< new OfflineTest()
|
||||
|
||||
// Starting the manager
|
||||
<< Process::exec(Process::Start)
|
||||
|
||||
// Starting the online tests
|
||||
<< new CleanOnlineTest() << new CleanOnlineSetup()
|
||||
<< new OnlineTest()
|
||||
|
||||
// Starting the manager
|
||||
<< Process::exec(Process::Stop)
|
||||
|
||||
<< new OfflineTest() << new OfflineTest()
|
||||
|
||||
<< Process::exec(Process::Start) << new OnlineTest()
|
||||
|
||||
<< Process::exec(Process::Stop)
|
||||
|
||||
)
|
||||
.start();
|
||||
|
||||
return app.exec();
|
||||
// QTest::qExec(&tc, argc, argv);
|
||||
}
|
||||
+30
@@ -0,0 +1,30 @@
|
||||
#! /bin/bash
|
||||
#
|
||||
# next-activity.sh
|
||||
# SPDX-FileCopyrightText: 2016 Ivan Čukić <ivan.cukic(at)kde.org>
|
||||
#
|
||||
# SPDX-License-Identifier: MIT
|
||||
#
|
||||
|
||||
current_activity=($(qdbus org.kde.ActivityManager /ActivityManager/Activities CurrentActivity))
|
||||
activities=($(qdbus org.kde.ActivityManager /ActivityManager/Activities ListActivities))
|
||||
found="0"
|
||||
|
||||
for ((i=0; i < ${#activities[@]}; ++i)); do
|
||||
if [ "$current_activity" = "${activities[$i]}" ]; then
|
||||
found="1"
|
||||
else
|
||||
if [ "$found" == "1" ]; then
|
||||
echo "Switching to ${activities[$i]}"
|
||||
qdbus org.kde.ActivityManager /ActivityManager/Activities SetCurrentActivity ${activities[$i]}
|
||||
found="0"
|
||||
fi
|
||||
fi
|
||||
done
|
||||
|
||||
if [ "$found" == "1" ]; then
|
||||
echo "Switching to ${activities[0]}"
|
||||
qdbus org.kde.ActivityManager /ActivityManager/Activities SetCurrentActivity ${activities[0]}
|
||||
fi
|
||||
|
||||
|
||||
+30
@@ -0,0 +1,30 @@
|
||||
#! /bin/bash
|
||||
#
|
||||
# next-activity.sh
|
||||
# SPDX-FileCopyrightText: 2016 Ivan Čukić <ivan.cukic(at)kde.org>
|
||||
#
|
||||
# SPDX-License-Identifier: MIT
|
||||
#
|
||||
|
||||
current_activity=($(qdbus org.kde.ActivityManager /ActivityManager/Activities CurrentActivity))
|
||||
activities=($(qdbus org.kde.ActivityManager /ActivityManager/Activities ListActivities))
|
||||
found="0"
|
||||
|
||||
previous_activity=""
|
||||
|
||||
for ((i=0; i < ${#activities[@]}; ++i)); do
|
||||
if [ "$current_activity" = "${activities[$i]}" ]; then
|
||||
if [ "$previous_activity" != "" ]; then
|
||||
echo "Switching to $previous_activity"
|
||||
qdbus org.kde.ActivityManager /ActivityManager/Activities SetCurrentActivity $previous_activity
|
||||
exit
|
||||
else
|
||||
echo "Switching to ${activities[-1]}"
|
||||
qdbus org.kde.ActivityManager /ActivityManager/Activities SetCurrentActivity ${activities[-1]}
|
||||
exit
|
||||
fi
|
||||
else
|
||||
previous_activity="${activities[$i]}"
|
||||
fi
|
||||
done
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
#!/bin/bash
|
||||
|
||||
# The script finds build directories for the current
|
||||
# src directory and builds them
|
||||
#
|
||||
# For example, for the source dir:
|
||||
# /some/path/kde/src/project/whatever
|
||||
# It finds:
|
||||
# /some/path/kde/build*/project/whatever
|
||||
|
||||
current_dir=`pwd`
|
||||
|
||||
all_root_dir=`pwd | sed 's#/src/.*##'`
|
||||
src_root_dir=$all_root_dir/src
|
||||
|
||||
echo "src: $src_root_dir"
|
||||
|
||||
for build_root_dir in $all_root_dir/build*; do
|
||||
echo "building in $build_root_dir"
|
||||
|
||||
cd $current_dir
|
||||
current_dir_log=`OBJ_REPLACEMENT=s#$src_root_dir#$build_root_dir# makeobj`
|
||||
if [ "$?" = "0" ]
|
||||
then
|
||||
echo "... success"
|
||||
else
|
||||
echo "... FAILED"
|
||||
echo $current_dir_log
|
||||
exit
|
||||
fi
|
||||
|
||||
done
|
||||
|
||||
git commit
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
#!/bin/bash
|
||||
|
||||
if [ ! -f "contrib/run-krazy.sh" ];
|
||||
then
|
||||
echo "This script needs to be started from KAMD's root directory"
|
||||
exit
|
||||
fi
|
||||
|
||||
DIRS=$1
|
||||
|
||||
if [ ! -n "$1" ];
|
||||
then
|
||||
DIRS="lib service utils workspace"
|
||||
fi
|
||||
|
||||
|
||||
|
||||
echo $DIRS
|
||||
CURRENT_DIRECTORY=$PWD
|
||||
|
||||
for dir in $DIRS;
|
||||
do
|
||||
echo "Running krazy2 on $dir ..."
|
||||
cd $CURRENT_DIRECTORY/src/$dir && krazy2all --exclude license > /tmp/$dir.krazy
|
||||
done
|
||||
@@ -0,0 +1,115 @@
|
||||
#! /usr/bin/env runhaskell
|
||||
|
||||
{-# LANGUAGE LambdaCase #-}
|
||||
|
||||
import System.Directory (doesFileExist, getDirectoryContents)
|
||||
import System.FilePath ((</>))
|
||||
|
||||
import Data.String.Utils
|
||||
import Data.List
|
||||
|
||||
|
||||
-- Util methods
|
||||
|
||||
mapSnd :: (a -> b) -> [(c, a)] -> [(c, b)]
|
||||
mapSnd f xys = map ( \case (x, y) -> (x, f y) ) xys
|
||||
|
||||
mapDir :: (FilePath -> IO ()) -> FilePath -> IO ()
|
||||
mapDir proc fp = do
|
||||
isFile <- doesFileExist fp -- is a file of fp
|
||||
if isFile then proc fp -- process the file
|
||||
else getDirectoryContents fp >>=
|
||||
mapM_ (mapDir proc . (fp </>)) . filter (`notElem` [".", ".."])
|
||||
|
||||
printTitle :: String -> IO()
|
||||
printTitle title = do
|
||||
putStrLn ""
|
||||
putStrLn title
|
||||
putStrLn $ map (\_ -> '=') title
|
||||
|
||||
main :: IO ()
|
||||
main = do
|
||||
printTitle "libKActivities"
|
||||
mapDir process "src/lib/core"
|
||||
|
||||
printTitle "libKActivitiesStats"
|
||||
mapDir process "src/lib/stats"
|
||||
|
||||
printTitle "KActivityManagerD"
|
||||
mapDir process "src/service"
|
||||
|
||||
printTitle "QML imports"
|
||||
mapDir process "src/imports"
|
||||
|
||||
printTitle "Workspace plugins"
|
||||
mapDir process "src/workspace"
|
||||
|
||||
printTitle "Other"
|
||||
mapDir process "src/common"
|
||||
mapDir process "src/utils"
|
||||
|
||||
-- Parsing methods
|
||||
|
||||
extractBlock :: [String] -> [String]
|
||||
extractBlock =
|
||||
takeWhile (startswith "//")
|
||||
|
||||
isTodoBlock :: (Integer, [String]) -> Bool
|
||||
isTodoBlock (_, block) =
|
||||
(not $ null block) && (
|
||||
(startswith "// TODO: " $ head block) ||
|
||||
(startswith "// FIXME: " $ head block) ||
|
||||
(startswith "// NOTE: " $ head block)
|
||||
)
|
||||
|
||||
joinBlock :: [String] -> String
|
||||
joinBlock block =
|
||||
unlines $
|
||||
map ( \line ->
|
||||
( dropWhile (== '/') line )
|
||||
) $
|
||||
block
|
||||
|
||||
|
||||
-- File processing
|
||||
|
||||
process :: FilePath -> IO ()
|
||||
process filename = do
|
||||
-- Getting the file contents
|
||||
content <- readFile filename
|
||||
|
||||
-- Items with line numbers
|
||||
let items :: [(Integer, [String])]
|
||||
items =
|
||||
zip [1..] $
|
||||
tails $
|
||||
map strip $
|
||||
lines content
|
||||
|
||||
-- Only those starting with TODO
|
||||
let todoBlocks :: [(Integer, [String])]
|
||||
todoBlocks =
|
||||
-- Getting only the comment block
|
||||
mapSnd extractBlock $
|
||||
-- Getting comment blocks that define a todo item
|
||||
filter isTodoBlock $
|
||||
items
|
||||
|
||||
-- Todo items
|
||||
let todoItems :: [(Integer, String)]
|
||||
todoItems =
|
||||
-- Getting the item blocks into actual items
|
||||
mapSnd joinBlock todoBlocks
|
||||
|
||||
|
||||
if (not $ null todoItems)
|
||||
then
|
||||
putStrLn $
|
||||
concat $
|
||||
map (\case (lineNo, todoItem) ->
|
||||
filename ++ ":" ++ (show lineNo) ++ ":\n" ++ todoItem
|
||||
) todoItems
|
||||
else
|
||||
return ()
|
||||
|
||||
|
||||
@@ -0,0 +1,141 @@
|
||||
# Module: KDE Aliases
|
||||
# Priority: 10
|
||||
|
||||
autoload -U colors
|
||||
colors
|
||||
|
||||
# Defining aliases for common kamd dbus objects
|
||||
alias kamd_dbus="qdbus org.kde.ActivityManager"
|
||||
|
||||
alias kamd_activities="qdbus org.kde.ActivityManager /ActivityManager/Activities"
|
||||
alias kamd_resources="qdbus org.kde.ActivityManager /ActivityManager/Resources"
|
||||
alias kamd_resources_linking="qdbus org.kde.ActivityManager /ActivityManager/Resources/Linking"
|
||||
alias kamd_features="qdbus org.kde.ActivityManager /ActivityManager/Features"
|
||||
|
||||
alias kamd_addactivity="qdbus org.kde.ActivityManager /ActivityManager/Activities AddActivity"
|
||||
alias kamd_removeactivity="qdbus org.kde.ActivityManager /ActivityManager/Activities RemoveActivity"
|
||||
|
||||
# Open the KAMD database
|
||||
alias kamd_database="sqlite3 ~/.local/share/kactivitymanagerd/resources/database"
|
||||
|
||||
# Lists the existing activities, along with their state
|
||||
function kamd_listactivities() {
|
||||
echo -n "Service version: "
|
||||
qdbus org.kde.ActivityManager /ActivityManager serviceVersion
|
||||
|
||||
CURRENT_ACTIVITY=`qdbus org.kde.ActivityManager /ActivityManager/Activities CurrentActivity`
|
||||
|
||||
for activity in `qdbus org.kde.ActivityManager /ActivityManager/Activities ListActivities`; do
|
||||
|
||||
STATE=""
|
||||
|
||||
if [ "$CURRENT_ACTIVITY" = "$activity" ]; then
|
||||
STATE="$fg[green][CURRENT]"
|
||||
|
||||
else
|
||||
STATE=`qdbus org.kde.ActivityManager /ActivityManager/Activities ActivityState $activity`
|
||||
|
||||
case "state$STATE" in
|
||||
state0)
|
||||
STATE="$fg[red]$bg[black][INVALID]"
|
||||
;;
|
||||
state2)
|
||||
STATE="$fg[blue][RUNNING]"
|
||||
;;
|
||||
state3)
|
||||
STATE="$fg[red]$bg[black][STARTING]"
|
||||
;;
|
||||
state4)
|
||||
STATE="$fg[black][STOPPED]"
|
||||
;;
|
||||
state5)
|
||||
STATE="$fg[red]$bg[black][STOPPING]"
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
|
||||
echo -n "$STATE$reset_color $activity "
|
||||
|
||||
ACTIVITY_NAME=`qdbus org.kde.ActivityManager /ActivityManager/Activities ActivityName $activity`
|
||||
ACTIVITY_DESC=`qdbus org.kde.ActivityManager /ActivityManager/Activities ActivityDescription $activity`
|
||||
ACTIVITY_ICON=`qdbus org.kde.ActivityManager /ActivityManager/Activities ActivityIcon $activity`
|
||||
|
||||
if [ -n "$ACTIVITY_DESC" ]; then
|
||||
echo "$ACTIVITY_NAME ($ACTIVITY_DESC, $ACTIVITY_ICON)"
|
||||
else
|
||||
echo "$ACTIVITY_NAME ($ACTIVITY_ICON)"
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
# Shows the information about the current activity
|
||||
function kamd_currentactivity() {
|
||||
for activity in `qdbus org.kde.ActivityManager /ActivityManager/Activities CurrentActivity`; do
|
||||
STATE=`qdbus org.kde.ActivityManager /ActivityManager/Activities ActivityState $activity`
|
||||
|
||||
case "state$STATE" in
|
||||
state0)
|
||||
STATE="[INVALID] "
|
||||
;;
|
||||
state2)
|
||||
STATE="[RUNNING] "
|
||||
;;
|
||||
state3)
|
||||
STATE="[STARTING]"
|
||||
;;
|
||||
state4)
|
||||
STATE="[STOPPED] "
|
||||
;;
|
||||
state5)
|
||||
STATE="[STOPPING]"
|
||||
;;
|
||||
esac
|
||||
|
||||
echo -n "$STATE $activity "
|
||||
qdbus org.kde.ActivityManager /ActivityManager/Activities ActivityName $activity
|
||||
done
|
||||
}
|
||||
|
||||
# Returns the current activity ID
|
||||
function kamd_get_currentactivity_id() {
|
||||
qdbus org.kde.ActivityManager /ActivityManager/Activities CurrentActivity
|
||||
}
|
||||
|
||||
# Returns the current activity name
|
||||
function kamd_get_currentactivity_name() {
|
||||
CURRENT_ACTIVITY_ID=$(kamd_get_currentactivity_id)
|
||||
qdbus org.kde.ActivityManager /ActivityManager/Activities ActivityName $CURRENT_ACTIVITY_ID
|
||||
}
|
||||
|
||||
# Returns the current activity name
|
||||
function kamd_get_currentactivity_name_normalized() {
|
||||
CURRENT_ACTIVITY_NAME=$(kamd_get_currentactivity_name)
|
||||
echo $CURRENT_ACTIVITY_NAME | tr '[:upper:] ' '[:lower:]-'
|
||||
}
|
||||
|
||||
# Returns the current activity ID
|
||||
function kamd_STOP_ALL_BUT_CURRENT() {
|
||||
CURRENT_ACTIVITY_ID=$(kamd_get_currentactivity_id)
|
||||
|
||||
for activity in `qdbus org.kde.ActivityManager /ActivityManager/Activities ListActivities`; do
|
||||
if [ "$activity" != "$CURRENT_ACTIVITY_ID" ]; then
|
||||
echo "Stop: $activity"
|
||||
qdbus org.kde.ActivityManager /ActivityManager/Activities StopActivity $activity
|
||||
sleep 1
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
# Returns the current activity ID
|
||||
function kamd_REMOVE_ALL_BUT_CURRENT() {
|
||||
CURRENT_ACTIVITY_ID=$(kamd_get_currentactivity_id)
|
||||
|
||||
for activity in `qdbus org.kde.ActivityManager /ActivityManager/Activities ListActivities`; do
|
||||
if [ "$activity" != "$CURRENT_ACTIVITY_ID" ]; then
|
||||
echo "Remove: $activity"
|
||||
qdbus org.kde.ActivityManager /ActivityManager/Activities RemoveActivity $activity
|
||||
sleep 1
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
EXCLUDE_PATTERNS += */service/* */scripts/* */workspace/*
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 10 KiB |
@@ -0,0 +1,13 @@
|
||||
description: Activities Libary
|
||||
platforms:
|
||||
- name: Linux
|
||||
- name: FreeBSD
|
||||
portingAid: false
|
||||
deprecated: false
|
||||
release: true
|
||||
libraries:
|
||||
- cmake: Plasma::Activities
|
||||
cmakename: PlasmaActivities
|
||||
|
||||
public_lib: true
|
||||
group: Plasma
|
||||
@@ -0,0 +1,23 @@
|
||||
# vim:set softtabstop=3 shiftwidth=3 tabstop=3 expandtab:
|
||||
|
||||
# =======================================================
|
||||
# Starting the actual project definition
|
||||
|
||||
# The libraries do not depend on any compile-time features
|
||||
add_subdirectory (lib)
|
||||
|
||||
if (NOT PLASMA_ACTIVITIES_LIBRARY_ONLY)
|
||||
include_directories (
|
||||
${CMAKE_CURRENT_BINARY_DIR}
|
||||
${CMAKE_CURRENT_SOURCE_DIR}
|
||||
)
|
||||
add_subdirectory (imports)
|
||||
endif ()
|
||||
|
||||
add_subdirectory (cli)
|
||||
|
||||
ecm_qt_install_logging_categories(
|
||||
EXPORT PLASMA_ACTIVITIES
|
||||
FILE plasma-activities.categories
|
||||
DESTINATION ${KDE_INSTALL_LOGGINGCATEGORIESDIR}
|
||||
)
|
||||
@@ -0,0 +1,26 @@
|
||||
# vim:set softtabstop=3 shiftwidth=3 tabstop=3 expandtab:
|
||||
project (PlasmaActivitiesCLI)
|
||||
|
||||
find_package (Qt6 REQUIRED NO_MODULE COMPONENTS Core Gui Widgets)
|
||||
|
||||
add_executable(plasma-activities-cli6)
|
||||
ecm_mark_nongui_executable(plasma-activities-cli6)
|
||||
|
||||
target_include_directories(plasma-activities-cli6 PRIVATE
|
||||
${PLASMA_ACTIVITIES_CURRENT_ROOT_SOURCE_DIR}/src/
|
||||
${PLASMA_ACTIVITIES_CURRENT_ROOT_SOURCE_DIR}/autotests/
|
||||
)
|
||||
|
||||
target_sources(plasma-activities-cli6 PRIVATE
|
||||
main.cpp
|
||||
)
|
||||
|
||||
target_link_libraries(plasma-activities-cli6
|
||||
Qt6::Core
|
||||
Plasma::Activities
|
||||
)
|
||||
|
||||
install (TARGETS
|
||||
plasma-activities-cli6
|
||||
${KF_INSTALL_TARGETS_DEFAULT_ARGS}
|
||||
)
|
||||
@@ -0,0 +1,230 @@
|
||||
/*
|
||||
SPDX-FileCopyrightText: 2016 Ivan Cukic <ivan.cukic(at)kde.org>
|
||||
|
||||
SPDX-License-Identifier: GPL-2.0-or-later
|
||||
*/
|
||||
|
||||
#include <QCoreApplication>
|
||||
#include <QDebug>
|
||||
#include <QTimer>
|
||||
|
||||
#include <PlasmaActivities/Controller>
|
||||
|
||||
#include "utils.h"
|
||||
|
||||
// Output modifiers
|
||||
|
||||
DEFINE_COMMAND(bare, 0)
|
||||
{
|
||||
flags.bare = true;
|
||||
return 0;
|
||||
}
|
||||
|
||||
DEFINE_COMMAND(noBare, 0)
|
||||
{
|
||||
flags.bare = false;
|
||||
return 0;
|
||||
}
|
||||
|
||||
DEFINE_COMMAND(color, 0)
|
||||
{
|
||||
flags.color = true;
|
||||
return 0;
|
||||
}
|
||||
|
||||
DEFINE_COMMAND(noColor, 0)
|
||||
{
|
||||
flags.color = false;
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Activity management
|
||||
|
||||
DEFINE_COMMAND(createActivity, 1)
|
||||
{
|
||||
auto result = awaitFuture(controller->addActivity(args(1)));
|
||||
|
||||
qDebug().noquote() << result;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
DEFINE_COMMAND(removeActivity, 1)
|
||||
{
|
||||
awaitFuture(controller->removeActivity(args(1)));
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
DEFINE_COMMAND(listActivities, 0)
|
||||
{
|
||||
for (const auto &activity : controller->activities()) {
|
||||
printActivity(activity);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
DEFINE_COMMAND(currentActivity, 0)
|
||||
{
|
||||
printActivity(controller->currentActivity());
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
DEFINE_COMMAND(setActivityProperty, 3)
|
||||
{
|
||||
const auto what = args(1);
|
||||
const auto id = args(2);
|
||||
const auto value = args(3);
|
||||
|
||||
// clang-format off
|
||||
awaitFuture(
|
||||
what == QLatin1String("name") ? controller->setActivityName(id, value) :
|
||||
what == QLatin1String("description") ? controller->setActivityDescription(id, value) :
|
||||
what == QLatin1String("icon") ? controller->setActivityIcon(id, value) :
|
||||
QFuture<void>()
|
||||
);
|
||||
// clang-format on
|
||||
|
||||
return 3;
|
||||
}
|
||||
|
||||
DEFINE_COMMAND(activityProperty, 2)
|
||||
{
|
||||
const auto what = args(1);
|
||||
const auto id = args(2);
|
||||
|
||||
KActivities::Info info(id);
|
||||
// clang-format off
|
||||
out << (
|
||||
what == QLatin1String("name") ? info.name() :
|
||||
what == QLatin1String("description") ? info.description() :
|
||||
what == QLatin1String("icon") ? info.icon() :
|
||||
QString()
|
||||
) << "\n";
|
||||
// clang-format on
|
||||
return 2;
|
||||
}
|
||||
|
||||
// Activity switching
|
||||
|
||||
DEFINE_COMMAND(setCurrentActivity, 1)
|
||||
{
|
||||
switchToActivity(args(1));
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
DEFINE_COMMAND(nextActivity, 0)
|
||||
{
|
||||
controller->nextActivity();
|
||||
return 0;
|
||||
}
|
||||
|
||||
DEFINE_COMMAND(previousActivity, 0)
|
||||
{
|
||||
controller->previousActivity();
|
||||
return 0;
|
||||
}
|
||||
|
||||
void printHelp()
|
||||
{
|
||||
if (!flags.bare) {
|
||||
qDebug() << "\nModifiers (applied only to trailing commands):"
|
||||
<< "\n --bare, --no-bare - show minimal info vs show everything"
|
||||
<< "\n --color, --no-color - make the output pretty"
|
||||
|
||||
<< "\n\nCommands:"
|
||||
<< "\n --list-activities - lists all activities"
|
||||
<< "\n --create-activity Name - creates a new activity with the specified name"
|
||||
<< "\n --remove-activity ID - removes the activity with the specified id"
|
||||
|
||||
<< "\n --current-activity - show the current activity"
|
||||
<< "\n --set-current-activity - sets the current activity"
|
||||
<< "\n --next-activity - switches to the next activity (in list-activities order)"
|
||||
<< "\n --previous-activity - switches to the previous activity (in list-activities order)"
|
||||
|
||||
<< "\n --activity-property What ID"
|
||||
<< "\n - gets activity name, icon or description"
|
||||
<< "\n --set-activity-property What ID Value"
|
||||
<< "\n - changes activity name, icon or description";
|
||||
|
||||
} else {
|
||||
qDebug() << "\n--bare"
|
||||
<< "\n--no-bare"
|
||||
<< "\n--color"
|
||||
<< "\n--no-color"
|
||||
<< "\n--list-activities"
|
||||
<< "\n--create-activity NAME"
|
||||
<< "\n--remove-activity ID"
|
||||
|
||||
<< "\n--current-activity"
|
||||
<< "\n--set-current-activity"
|
||||
<< "\n--next-activity"
|
||||
<< "\n--previous-activity";
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
QCoreApplication app(argc, argv);
|
||||
|
||||
QTimer::singleShot(0, &app, [] {
|
||||
const auto args = QCoreApplication::arguments();
|
||||
|
||||
controller = new KActivities::Controller();
|
||||
|
||||
while (controller->serviceStatus() != KActivities::Controller::Running) {
|
||||
QCoreApplication::processEvents();
|
||||
}
|
||||
|
||||
// clang-format off
|
||||
#define MATCH_COMMAND(Command) \
|
||||
else if (args[argId] == QLatin1String("--") + toDashes(QStringLiteral(#Command))) \
|
||||
{ \
|
||||
argId += 1 + Command##_command({ args, argId })(); \
|
||||
}
|
||||
// clang-format on
|
||||
if (args.count() <= 1) {
|
||||
printHelp();
|
||||
|
||||
} else {
|
||||
for (int argId = 1; argId < args.count();) {
|
||||
if (args[argId] == QLatin1String("--help")) {
|
||||
printHelp();
|
||||
argId++;
|
||||
}
|
||||
|
||||
MATCH_COMMAND(bare)
|
||||
MATCH_COMMAND(noBare)
|
||||
MATCH_COMMAND(color)
|
||||
MATCH_COMMAND(noColor)
|
||||
|
||||
MATCH_COMMAND(listActivities)
|
||||
|
||||
MATCH_COMMAND(currentActivity)
|
||||
MATCH_COMMAND(setCurrentActivity)
|
||||
MATCH_COMMAND(activityProperty)
|
||||
MATCH_COMMAND(setActivityProperty)
|
||||
MATCH_COMMAND(nextActivity)
|
||||
MATCH_COMMAND(previousActivity)
|
||||
|
||||
MATCH_COMMAND(createActivity)
|
||||
MATCH_COMMAND(removeActivity)
|
||||
|
||||
else
|
||||
{
|
||||
qDebug() << "Skipping unknown argument" << args[argId];
|
||||
argId++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
delete controller;
|
||||
|
||||
QCoreApplication::quit();
|
||||
});
|
||||
|
||||
return app.exec();
|
||||
}
|
||||
@@ -0,0 +1,138 @@
|
||||
/*
|
||||
SPDX-FileCopyrightText: 2016 Ivan Čukić <ivan.cukic(at)kde.org>
|
||||
|
||||
SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
|
||||
*/
|
||||
|
||||
#ifndef KACTIVITIES_UTILS_H
|
||||
#define KACTIVITIES_UTILS_H
|
||||
|
||||
QTextStream out(stdout);
|
||||
|
||||
class StringListView
|
||||
{
|
||||
public:
|
||||
StringListView(const QStringList &list, int start, int end = -1)
|
||||
: m_list(list)
|
||||
, m_start(start)
|
||||
, m_size((end == -1 ? list.count() : end) - start)
|
||||
{
|
||||
}
|
||||
|
||||
const QString &operator()(int index) const
|
||||
{
|
||||
return m_list[m_start + index];
|
||||
}
|
||||
|
||||
int count() const
|
||||
{
|
||||
return m_size;
|
||||
}
|
||||
|
||||
private:
|
||||
const QStringList &m_list;
|
||||
int m_start;
|
||||
int m_size;
|
||||
};
|
||||
|
||||
KActivities::Controller *controller = nullptr;
|
||||
|
||||
class Flags
|
||||
{
|
||||
public:
|
||||
Flags()
|
||||
: bare(false)
|
||||
, color(true)
|
||||
{
|
||||
}
|
||||
|
||||
bool bare;
|
||||
bool color;
|
||||
|
||||
} flags;
|
||||
|
||||
QString toDashes(const QString &command)
|
||||
{
|
||||
QString result(command);
|
||||
|
||||
for (int i = 0; i < result.size() - 1; ++i) {
|
||||
if (result[i].isLower() && result[i + 1].isUpper()) {
|
||||
result[i + 1] = result[i + 1].toLower();
|
||||
result.insert(i + 1, QStringLiteral("-"));
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void printActivity(const QString &id)
|
||||
{
|
||||
// clang-format off
|
||||
if (flags.bare) {
|
||||
out << id << "\n";
|
||||
|
||||
} else {
|
||||
using namespace KActivities;
|
||||
Info info(id);
|
||||
|
||||
out
|
||||
<< info.id()
|
||||
<< " "
|
||||
<< info.name()
|
||||
<< " ("
|
||||
<< info.icon()
|
||||
<< ")\n"
|
||||
;
|
||||
}
|
||||
// clang-format on
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
T awaitFuture(const QFuture<T> &future)
|
||||
{
|
||||
while (!future.isFinished()) {
|
||||
QCoreApplication::processEvents();
|
||||
}
|
||||
|
||||
return future.result();
|
||||
}
|
||||
|
||||
void awaitFuture(const QFuture<void> &future)
|
||||
{
|
||||
while (!future.isFinished()) {
|
||||
QCoreApplication::processEvents();
|
||||
}
|
||||
}
|
||||
|
||||
void switchToActivity(const QString &id)
|
||||
{
|
||||
auto result = awaitFuture(controller->setCurrentActivity(id));
|
||||
|
||||
if (!flags.bare) {
|
||||
if (result) {
|
||||
qDebug() << "Current activity is" << id;
|
||||
} else {
|
||||
qDebug() << "Failed to change the activity";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// clang-format off
|
||||
#define DEFINE_COMMAND(Command, MinArgCount) \
|
||||
struct Command##_command { \
|
||||
const StringListView &args; \
|
||||
Command##_command(const StringListView &args) \
|
||||
: args(args) \
|
||||
{ \
|
||||
if (args.count() < MinArgCount + 1) { \
|
||||
qFatal("not enough arguments for " #Command); \
|
||||
} \
|
||||
} \
|
||||
\
|
||||
int operator()(); \
|
||||
}; \
|
||||
\
|
||||
int Command##_command::operator()()
|
||||
|
||||
#endif
|
||||
// clang-format on
|
||||
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
SPDX-FileCopyrightText: 2010-2016 Ivan Cukic <ivan.cukic(at)kde.org>
|
||||
|
||||
SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
|
||||
*/
|
||||
|
||||
#ifndef DBUS_COMMON_H
|
||||
#define DBUS_COMMON_H
|
||||
|
||||
#include <QDBusConnection>
|
||||
#include <QDBusInterface>
|
||||
|
||||
// clang-format off
|
||||
|
||||
#define KAMD_DBUS_SERVICE \
|
||||
QStringLiteral("org.kde.ActivityManager")
|
||||
|
||||
#define KAMD_DBUS_OBJECT_PATH(A) \
|
||||
(sizeof(A) > 2 ? QLatin1String("/ActivityManager/" A) \
|
||||
: QLatin1String("/ActivityManager"))
|
||||
|
||||
#define KAMD_DBUS_OBJECT(A) \
|
||||
QLatin1String("org.kde.ActivityManager." A)
|
||||
|
||||
#define KAMD_DBUS_INTERFACE(OBJECT_PATH, OBJECT, PARENT) \
|
||||
QDBusInterface(KAMD_DBUS_SERVICE, \
|
||||
KAMD_DBUS_OBJECT_PATH(OBJECT_PATH), \
|
||||
KAMD_DBUS_OBJECT(OBJECT), \
|
||||
QDBusConnection::sessionBus(), \
|
||||
PARENT)
|
||||
|
||||
#define KAMD_DBUS_DECL_INTERFACE(VAR, OBJECT_PATH, OBJECT) \
|
||||
QDBusInterface VAR(KAMD_DBUS_SERVICE, \
|
||||
KAMD_DBUS_OBJECT_PATH(OBJECT_PATH), \
|
||||
KAMD_DBUS_OBJECT(OBJECT), \
|
||||
QDBusConnection::sessionBus(), \
|
||||
nullptr)
|
||||
|
||||
#define KAMD_DBUS_CLASS_INTERFACE(OBJECT_PATH, OBJECT, PARENT) \
|
||||
org::kde::ActivityManager::OBJECT( \
|
||||
KAMD_DBUS_SERVICE, \
|
||||
KAMD_DBUS_OBJECT_PATH(OBJECT_PATH), \
|
||||
QDBusConnection::sessionBus(), \
|
||||
PARENT)
|
||||
|
||||
#endif // DBUS_COMMON_H
|
||||
|
||||
+64
@@ -0,0 +1,64 @@
|
||||
/*
|
||||
SPDX-FileCopyrightText: 2010-2016 Ivan Cukic <ivan.cukic(at)kde.org>
|
||||
|
||||
SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
|
||||
*/
|
||||
|
||||
#include "org.kde.ActivityManager.Activities.h"
|
||||
|
||||
#include <QDBusMetaType>
|
||||
#include <QMetaType>
|
||||
|
||||
namespace details
|
||||
{
|
||||
class ActivityInfoStaticInit
|
||||
{
|
||||
public:
|
||||
ActivityInfoStaticInit()
|
||||
{
|
||||
qDBusRegisterMetaType<ActivityInfo>();
|
||||
qDBusRegisterMetaType<ActivityInfoList>();
|
||||
}
|
||||
|
||||
static ActivityInfoStaticInit _instance;
|
||||
};
|
||||
|
||||
ActivityInfoStaticInit ActivityInfoStaticInit::_instance;
|
||||
|
||||
} // namespace details
|
||||
|
||||
QDBusArgument &operator<<(QDBusArgument &arg, const ActivityInfo r)
|
||||
{
|
||||
arg.beginStructure();
|
||||
|
||||
arg << r.id;
|
||||
arg << r.name;
|
||||
arg << r.description;
|
||||
arg << r.icon;
|
||||
arg << r.state;
|
||||
|
||||
arg.endStructure();
|
||||
|
||||
return arg;
|
||||
}
|
||||
|
||||
const QDBusArgument &operator>>(const QDBusArgument &arg, ActivityInfo &r)
|
||||
{
|
||||
arg.beginStructure();
|
||||
|
||||
arg >> r.id;
|
||||
arg >> r.name;
|
||||
arg >> r.description;
|
||||
arg >> r.icon;
|
||||
arg >> r.state;
|
||||
|
||||
arg.endStructure();
|
||||
|
||||
return arg;
|
||||
}
|
||||
|
||||
QDebug operator<<(QDebug dbg, const ActivityInfo &r)
|
||||
{
|
||||
dbg << "ActivityInfo(" << r.id << r.name << ")";
|
||||
return dbg.space();
|
||||
}
|
||||
+46
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
SPDX-FileCopyrightText: 2010-2016 Ivan Cukic <ivan.cukic(at)kde.org>
|
||||
|
||||
SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
|
||||
*/
|
||||
|
||||
#ifndef KAMD_ORG_KDE_ACTIVITYMANAGER_ACTIVITIES_H
|
||||
#define KAMD_ORG_KDE_ACTIVITYMANAGER_ACTIVITIES_H
|
||||
|
||||
#include <QDBusArgument>
|
||||
#include <QDebug>
|
||||
#include <QList>
|
||||
#include <QString>
|
||||
|
||||
struct ActivityInfo {
|
||||
QString id;
|
||||
QString name;
|
||||
QString description;
|
||||
QString icon;
|
||||
int state;
|
||||
|
||||
ActivityInfo(const QString &id = QString(),
|
||||
const QString &name = QString(),
|
||||
const QString &description = QString(),
|
||||
const QString &icon = QString(),
|
||||
int state = 0)
|
||||
: id(id)
|
||||
, name(name)
|
||||
, description(description)
|
||||
, icon(icon)
|
||||
, state(state)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
typedef QList<ActivityInfo> ActivityInfoList;
|
||||
|
||||
Q_DECLARE_METATYPE(ActivityInfo)
|
||||
Q_DECLARE_METATYPE(ActivityInfoList)
|
||||
|
||||
QDBusArgument &operator<<(QDBusArgument &arg, const ActivityInfo);
|
||||
const QDBusArgument &operator>>(const QDBusArgument &arg, ActivityInfo &rec);
|
||||
|
||||
QDebug operator<<(QDebug dbg, const ActivityInfo &r);
|
||||
|
||||
#endif // KAMD_ORG_KDE_ACTIVITYMANAGER_ACTIVITIES_H
|
||||
+115
@@ -0,0 +1,115 @@
|
||||
<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN" "http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd">
|
||||
<node>
|
||||
<interface name="org.kde.ActivityManager.Activities">
|
||||
|
||||
<method name="CurrentActivity">
|
||||
<arg type="s" direction="out"/>
|
||||
</method>
|
||||
<method name="SetCurrentActivity">
|
||||
<arg type="b" direction="out"/>
|
||||
<arg name="activity" type="s" direction="in"/>
|
||||
</method>
|
||||
|
||||
<method name="AddActivity">
|
||||
<arg type="s" direction="out"/>
|
||||
<arg name="name" type="s" direction="in"/>
|
||||
</method>
|
||||
<method name="StartActivity">
|
||||
<arg name="activity" type="s" direction="in"/>
|
||||
</method>
|
||||
<method name="StopActivity">
|
||||
<arg name="activity" type="s" direction="in"/>
|
||||
</method>
|
||||
<method name="ActivityState">
|
||||
<arg type="i" direction="out"/>
|
||||
<arg name="activity" type="s" direction="in"/>
|
||||
</method>
|
||||
<method name="RemoveActivity">
|
||||
<arg name="activity" type="s" direction="in"/>
|
||||
</method>
|
||||
|
||||
<method name="ListActivities">
|
||||
<arg type="as" direction="out"/>
|
||||
</method>
|
||||
<method name="ListActivities">
|
||||
<arg type="as" direction="out"/>
|
||||
<arg name="state" type="i" direction="in"/>
|
||||
</method>
|
||||
|
||||
<method name="ListActivitiesWithInformation">
|
||||
<arg type="a(ssssi)" direction="out"/>
|
||||
<annotation name="org.qtproject.QtDBus.QtTypeName.Out0" value="ActivityInfoList" />
|
||||
<annotation name="org.qtproject.QtDBus.QtTypeName.Out0" value="ActivityInfoList" />
|
||||
</method>
|
||||
<method name="ActivityInformation">
|
||||
<arg type="(ssssi)" direction="out"/>
|
||||
<annotation name="org.qtproject.QtDBus.QtTypeName.Out0" value="ActivityInfo" />
|
||||
<annotation name="org.qtproject.QtDBus.QtTypeName.Out0" value="ActivityInfo" />
|
||||
<arg name="activity" type="s" direction="in"/>
|
||||
</method>
|
||||
|
||||
<method name="ActivityName">
|
||||
<arg type="s" direction="out"/>
|
||||
<arg name="activity" type="s" direction="in"/>
|
||||
</method>
|
||||
<method name="SetActivityName">
|
||||
<arg name="activity" type="s" direction="in"/>
|
||||
<arg name="name" type="s" direction="in"/>
|
||||
</method>
|
||||
|
||||
<method name="ActivityDescription">
|
||||
<arg type="s" direction="out"/>
|
||||
<arg name="activity" type="s" direction="in"/>
|
||||
</method>
|
||||
<method name="SetActivityDescription">
|
||||
<arg name="activity" type="s" direction="in"/>
|
||||
<arg name="description" type="s" direction="in"/>
|
||||
</method>
|
||||
|
||||
<method name="ActivityIcon">
|
||||
<arg type="s" direction="out"/>
|
||||
<arg name="activity" type="s" direction="in"/>
|
||||
</method>
|
||||
<method name="SetActivityIcon">
|
||||
<arg name="activity" type="s" direction="in"/>
|
||||
<arg name="icon" type="s" direction="in"/>
|
||||
</method>
|
||||
|
||||
<signal name="CurrentActivityChanged">
|
||||
<arg name="activity" type="s" direction="out"/>
|
||||
</signal>
|
||||
|
||||
<signal name="ActivityAdded">
|
||||
<arg name="activity" type="s" direction="out"/>
|
||||
</signal>
|
||||
<signal name="ActivityStarted">
|
||||
<arg name="activity" type="s" direction="out"/>
|
||||
</signal>
|
||||
<signal name="ActivityStopped">
|
||||
<arg name="activity" type="s" direction="out"/>
|
||||
</signal>
|
||||
<signal name="ActivityRemoved">
|
||||
<arg name="activity" type="s" direction="out"/>
|
||||
</signal>
|
||||
<signal name="ActivityChanged">
|
||||
<arg name="activity" type="s" direction="out"/>
|
||||
</signal>
|
||||
<signal name="ActivityNameChanged">
|
||||
<arg name="activity" type="s" direction="out"/>
|
||||
<arg name="name" type="s" direction="out"/>
|
||||
</signal>
|
||||
<signal name="ActivityDescriptionChanged">
|
||||
<arg name="activity" type="s" direction="out"/>
|
||||
<arg name="description" type="s" direction="out"/>
|
||||
</signal>
|
||||
<signal name="ActivityIconChanged">
|
||||
<arg name="activity" type="s" direction="out"/>
|
||||
<arg name="icon" type="s" direction="out"/>
|
||||
</signal>
|
||||
<signal name="ActivityStateChanged">
|
||||
<arg name="activity" type="s" direction="out"/>
|
||||
<arg name="state" type="i" direction="out"/>
|
||||
</signal>
|
||||
|
||||
</interface>
|
||||
</node>
|
||||
+14
@@ -0,0 +1,14 @@
|
||||
<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN" "http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd">
|
||||
<node>
|
||||
<interface name="org.kde.ActivityManager.Application">
|
||||
<method name="quit">
|
||||
</method>
|
||||
<method name="serviceVersion">
|
||||
<arg type="s" direction="out"/>
|
||||
</method>
|
||||
<method name="loadPlugin">
|
||||
<arg type="b" direction="out"/>
|
||||
<arg name="plugin" type="s" direction="in"/>
|
||||
</method>
|
||||
</interface>
|
||||
</node>
|
||||
+21
@@ -0,0 +1,21 @@
|
||||
<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN" "http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd">
|
||||
<node>
|
||||
<interface name="org.kde.ActivityManager.Features">
|
||||
<method name="IsFeatureOperational">
|
||||
<arg type="b" direction="out"/>
|
||||
<arg name="feature" type="s" direction="in"/>
|
||||
</method>
|
||||
<method name="ListFeatures">
|
||||
<arg type="as" direction="out"/>
|
||||
<arg name="module" type="s" direction="in"/>
|
||||
</method>
|
||||
<method name="GetValue">
|
||||
<arg type="v" direction="out"/>
|
||||
<arg name="property" type="s" direction="in"/>
|
||||
</method>
|
||||
<method name="SetValue">
|
||||
<arg name="property" type="s" direction="in"/>
|
||||
<arg name="value" type="v" direction="in"/>
|
||||
</method>
|
||||
</interface>
|
||||
</node>
|
||||
+23
@@ -0,0 +1,23 @@
|
||||
<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN" "http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd">
|
||||
<node>
|
||||
<interface name="org.kde.ActivityManager.Resources">
|
||||
|
||||
<method name="RegisterResourceEvent">
|
||||
<arg name="application" type="s" direction="in"/>
|
||||
<arg name="windowId" type="u" direction="in"/>
|
||||
<arg name="uri" type="s" direction="in"/>
|
||||
<arg name="event" type="u" direction="in"/>
|
||||
</method>
|
||||
|
||||
<method name="RegisterResourceMimetype">
|
||||
<arg name="uri" type="s" direction="in"/>
|
||||
<arg name="mimetype" type="s" direction="in"/>
|
||||
</method>
|
||||
|
||||
<method name="RegisterResourceTitle">
|
||||
<arg name="uri" type="s" direction="in"/>
|
||||
<arg name="title" type="s" direction="in"/>
|
||||
</method>
|
||||
|
||||
</interface>
|
||||
</node>
|
||||
+49
@@ -0,0 +1,49 @@
|
||||
<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN" "http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd">
|
||||
<node>
|
||||
<interface name="org.kde.ActivityManager.ResourcesLinking">
|
||||
|
||||
<method name="LinkResourceToActivity">
|
||||
<arg name="agent" type="s" direction="in"/>
|
||||
<arg name="resource" type="s" direction="in"/>
|
||||
<arg name="activity" type="s" direction="in"/>
|
||||
</method>
|
||||
<method name="LinkResourceToActivity">
|
||||
<arg name="agent" type="s" direction="in"/>
|
||||
<arg name="resource" type="s" direction="in"/>
|
||||
</method>
|
||||
|
||||
<method name="UnlinkResourceFromActivity">
|
||||
<arg name="agent" type="s" direction="in"/>
|
||||
<arg name="resource" type="s" direction="in"/>
|
||||
<arg name="activity" type="s" direction="in"/>
|
||||
</method>
|
||||
<method name="UnlinkResourceFromActivity">
|
||||
<arg name="agent" type="s" direction="in"/>
|
||||
<arg name="resource" type="s" direction="in"/>
|
||||
</method>
|
||||
|
||||
<method name="IsResourceLinkedToActivity">
|
||||
<arg name="agent" type="s" direction="in"/>
|
||||
<arg name="resource" type="s" direction="in"/>
|
||||
<arg name="activity" type="s" direction="in"/>
|
||||
<arg type="b" direction="out"/>
|
||||
</method>
|
||||
<method name="IsResourceLinkedToActivity">
|
||||
<arg name="agent" type="s" direction="in"/>
|
||||
<arg name="resource" type="s" direction="in"/>
|
||||
<arg type="b" direction="out"/>
|
||||
</method>
|
||||
|
||||
<signal name="ResourceLinkedToActivity">
|
||||
<arg name="agent" type="s" direction="out"/>
|
||||
<arg name="resource" type="s" direction="out"/>
|
||||
<arg name="activity" type="s" direction="out"/>
|
||||
</signal>
|
||||
<signal name="ResourceUnlinkedFromActivity">
|
||||
<arg name="agent" type="s" direction="out"/>
|
||||
<arg name="resource" type="s" direction="out"/>
|
||||
<arg name="activity" type="s" direction="out"/>
|
||||
</signal>
|
||||
|
||||
</interface>
|
||||
</node>
|
||||
+45
@@ -0,0 +1,45 @@
|
||||
<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN" "http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd">
|
||||
<node>
|
||||
<interface name="org.kde.ActivityManager.ResourcesScoring">
|
||||
|
||||
<signal name="ResourceScoreUpdated">
|
||||
<arg name="activity" type="s" direction="out"/>
|
||||
<arg name="client" type="s" direction="out"/>
|
||||
<arg name="resource" type="s" direction="out"/>
|
||||
<arg name="score" type="d" direction="out"/>
|
||||
<arg name="lastUpdate" type="u" direction="out"/>
|
||||
<arg name="firstUpdate" type="u" direction="out"/>
|
||||
</signal>
|
||||
<signal name="ResourceScoreDeleted">
|
||||
<arg name="activity" type="s" direction="out"/>
|
||||
<arg name="client" type="s" direction="out"/>
|
||||
<arg name="resource" type="s" direction="out"/>
|
||||
</signal>
|
||||
|
||||
<signal name="RecentStatsDeleted">
|
||||
<arg name="activity" type="s" direction="out"/>
|
||||
<arg name="count" type="i" direction="out"/>
|
||||
<arg name="what" type="s" direction="out"/>
|
||||
</signal>
|
||||
<signal name="EarlierStatsDeleted">
|
||||
<arg name="activity" type="s" direction="out"/>
|
||||
<arg name="months" type="i" direction="out"/>
|
||||
</signal>
|
||||
|
||||
<method name="DeleteStatsForResource">
|
||||
<arg name="activity" type="s" direction="in"/>
|
||||
<arg name="client" type="s" direction="in"/>
|
||||
<arg name="resource" type="s" direction="in"/>
|
||||
</method>
|
||||
<method name="DeleteRecentStats">
|
||||
<arg name="activity" type="s" direction="in"/>
|
||||
<arg name="count" type="i" direction="in"/>
|
||||
<arg name="what" type="s" direction="in"/>
|
||||
</method>
|
||||
<method name="DeleteEarlierStats">
|
||||
<arg name="activity" type="s" direction="in"/>
|
||||
<arg name="months" type="i" direction="in"/>
|
||||
</method>
|
||||
|
||||
</interface>
|
||||
</node>
|
||||
@@ -0,0 +1,35 @@
|
||||
# vim:set softtabstop=3 shiftwidth=3 tabstop=3 expandtab:
|
||||
|
||||
project (plasmaactivities-imports)
|
||||
|
||||
find_package (Qt6 REQUIRED NO_MODULE COMPONENTS Gui Qml Quick Sql)
|
||||
find_package (KF6Config ${KF6_MIN_VERSION} CONFIG REQUIRED)
|
||||
find_package (KF6CoreAddons ${KF6_MIN_VERSION} CONFIG REQUIRED)
|
||||
|
||||
ecm_add_qml_module(plasmaactivitiesextensionplugin URI "org.kde.activities" VERSION 0.1 GENERATE_PLUGIN_SOURCE DEPENDENCIES QtCore)
|
||||
|
||||
target_sources(plasmaactivitiesextensionplugin PRIVATE
|
||||
activitymodel.cpp
|
||||
activitymodel.h
|
||||
activityinfo.cpp
|
||||
activityinfo.h
|
||||
|
||||
${PLASMA_ACTIVITIES_CURRENT_ROOT_SOURCE_DIR}/src/utils/dbusfuture_p.cpp
|
||||
)
|
||||
|
||||
target_link_libraries(
|
||||
plasmaactivitiesextensionplugin PRIVATE
|
||||
Qt6::Core
|
||||
Qt6::DBus
|
||||
Qt6::Gui
|
||||
Qt6::Qml
|
||||
Qt6::Quick
|
||||
Qt6::Sql
|
||||
Plasma::Activities
|
||||
KF6::ConfigCore
|
||||
KF6::CoreAddons
|
||||
)
|
||||
|
||||
ecm_finalize_qml_module(plasmaactivitiesextensionplugin DESTINATION ${KDE_INSTALL_QMLDIR})
|
||||
|
||||
ecm_generate_qdoc(plasmaactivitiesextensionplugin plasmaactivitiesqml.qdocconf)
|
||||
@@ -0,0 +1,7 @@
|
||||
org.kde.activities namespace does not guarantee a
|
||||
stable api.
|
||||
|
||||
If you want to use components from it, make sure
|
||||
you follow the further developments closely.
|
||||
|
||||
|
||||
@@ -0,0 +1,93 @@
|
||||
/*
|
||||
SPDX-FileCopyrightText: 2012, 2013, 2014, 2015 Ivan Cukic <ivan.cukic(at)kde.org>
|
||||
|
||||
SPDX-License-Identifier: GPL-2.0-or-later
|
||||
*/
|
||||
|
||||
// Self
|
||||
#include "activityinfo.h"
|
||||
|
||||
namespace KActivities
|
||||
{
|
||||
namespace Imports
|
||||
{
|
||||
ActivityInfo::ActivityInfo(QObject *parent)
|
||||
: QObject(parent)
|
||||
, m_showCurrentActivity(false)
|
||||
{
|
||||
connect(&m_service, &KActivities::Controller::currentActivityChanged, this, &ActivityInfo::setCurrentActivity);
|
||||
}
|
||||
|
||||
ActivityInfo::~ActivityInfo()
|
||||
{
|
||||
}
|
||||
|
||||
void ActivityInfo::setCurrentActivity(const QString &id)
|
||||
{
|
||||
if (!m_showCurrentActivity) {
|
||||
return;
|
||||
}
|
||||
|
||||
setIdInternal(id);
|
||||
|
||||
Q_EMIT nameChanged(m_info->name());
|
||||
Q_EMIT descriptionChanged(m_info->description());
|
||||
Q_EMIT iconChanged(m_info->icon());
|
||||
}
|
||||
|
||||
void ActivityInfo::setActivityId(const QString &id)
|
||||
{
|
||||
m_showCurrentActivity = (id == QLatin1String(":current"));
|
||||
|
||||
setIdInternal(m_showCurrentActivity ? m_service.currentActivity() : id);
|
||||
}
|
||||
|
||||
void ActivityInfo::setIdInternal(const QString &id)
|
||||
{
|
||||
using namespace KActivities;
|
||||
|
||||
// We are killing the old info object, if any
|
||||
m_info.reset(new KActivities::Info(id));
|
||||
|
||||
auto ptr = m_info.get();
|
||||
|
||||
connect(ptr, &Info::nameChanged, this, &ActivityInfo::nameChanged);
|
||||
connect(ptr, &Info::descriptionChanged, this, &ActivityInfo::descriptionChanged);
|
||||
connect(ptr, &Info::iconChanged, this, &ActivityInfo::iconChanged);
|
||||
}
|
||||
// clang-format off
|
||||
#define CREATE_GETTER_AND_SETTER(WHAT, What) \
|
||||
QString ActivityInfo::What() const \
|
||||
{ \
|
||||
return m_info ? m_info->What() : QString(); \
|
||||
} \
|
||||
\
|
||||
void ActivityInfo::set##WHAT(const QString &value) \
|
||||
{ \
|
||||
if (!m_info) \
|
||||
return; \
|
||||
\
|
||||
m_service.setActivity##WHAT(m_info->id(), value); \
|
||||
}
|
||||
// clang-format on
|
||||
|
||||
CREATE_GETTER_AND_SETTER(Name, name)
|
||||
CREATE_GETTER_AND_SETTER(Description, description)
|
||||
CREATE_GETTER_AND_SETTER(Icon, icon)
|
||||
|
||||
#undef CREATE_GETTER_AND_SETTER
|
||||
|
||||
QString ActivityInfo::activityId() const
|
||||
{
|
||||
return m_info ? m_info->id() : QString();
|
||||
}
|
||||
|
||||
bool ActivityInfo::valid() const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace Imports
|
||||
} // namespace KActivities
|
||||
|
||||
#include "moc_activityinfo.cpp"
|
||||
@@ -0,0 +1,114 @@
|
||||
/*
|
||||
SPDX-FileCopyrightText: 2012, 2013, 2014, 2015 Ivan Cukic <ivan.cukic(at)kde.org>
|
||||
|
||||
SPDX-License-Identifier: GPL-2.0-or-later
|
||||
*/
|
||||
|
||||
#ifndef KACTIVITIES_IMPORTS_ACTIVITY_INFO_H
|
||||
#define KACTIVITIES_IMPORTS_ACTIVITY_INFO_H
|
||||
|
||||
// Qt
|
||||
#include <QObject>
|
||||
#include <qqmlregistration.h>
|
||||
|
||||
// STL
|
||||
#include <memory>
|
||||
|
||||
// Local
|
||||
#include <lib/controller.h>
|
||||
#include <lib/info.h>
|
||||
|
||||
namespace KActivities
|
||||
{
|
||||
namespace Imports
|
||||
{
|
||||
|
||||
/*!
|
||||
* \qmltype ActivityInfo
|
||||
* \inqmlmodule org.kde.activities
|
||||
*
|
||||
* \brief Activity info.
|
||||
*/
|
||||
class ActivityInfo : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
QML_ELEMENT
|
||||
|
||||
/*!
|
||||
* \qmlproperty string ActivityInfo::activityId
|
||||
*
|
||||
* Unique identifier of the activity
|
||||
*/
|
||||
Q_PROPERTY(QString activityId READ activityId WRITE setActivityId NOTIFY activityIdChanged)
|
||||
|
||||
/*!
|
||||
* \qmlproperty string ActivityInfo::name
|
||||
*
|
||||
* Name of the activity
|
||||
*/
|
||||
Q_PROPERTY(QString name READ name WRITE setName NOTIFY nameChanged)
|
||||
|
||||
/*!
|
||||
* \qmlproperty string ActivityInfo::description
|
||||
*
|
||||
* Name of the activity
|
||||
*/
|
||||
Q_PROPERTY(QString description READ description WRITE setDescription NOTIFY descriptionChanged)
|
||||
|
||||
/*!
|
||||
* \qmlproperty string ActivityInfo::icon
|
||||
*
|
||||
* Activity icon
|
||||
*/
|
||||
Q_PROPERTY(QString icon READ icon WRITE setIcon NOTIFY iconChanged)
|
||||
|
||||
/*!
|
||||
* \qmlproperty bool ActivityInfo::valid
|
||||
*
|
||||
* \readonly
|
||||
*
|
||||
* Is the activity a valid one - does it exist?
|
||||
*/
|
||||
Q_PROPERTY(bool valid READ valid NOTIFY validChanged)
|
||||
|
||||
public:
|
||||
explicit ActivityInfo(QObject *parent = nullptr);
|
||||
~ActivityInfo() override;
|
||||
|
||||
public Q_SLOTS:
|
||||
void setActivityId(const QString &id);
|
||||
QString activityId() const;
|
||||
|
||||
void setName(const QString &name);
|
||||
QString name() const;
|
||||
|
||||
void setDescription(const QString &description);
|
||||
QString description() const;
|
||||
|
||||
void setIcon(const QString &icon);
|
||||
QString icon() const;
|
||||
|
||||
bool valid() const;
|
||||
|
||||
Q_SIGNALS:
|
||||
void activityIdChanged(const QString &id);
|
||||
void nameChanged(const QString &name);
|
||||
void descriptionChanged(const QString &description);
|
||||
void iconChanged(const QString &icon);
|
||||
void validChanged(bool valid);
|
||||
|
||||
private Q_SLOTS:
|
||||
void setCurrentActivity(const QString &id);
|
||||
|
||||
private:
|
||||
void setIdInternal(const QString &id);
|
||||
|
||||
KActivities::Controller m_service;
|
||||
std::unique_ptr<KActivities::Info> m_info;
|
||||
bool m_showCurrentActivity;
|
||||
};
|
||||
|
||||
} // namespace Imports
|
||||
} // namespace KActivities
|
||||
|
||||
#endif // KACTIVITIES_IMPORTS_ACTIVITY_INFO_H
|
||||
@@ -0,0 +1,511 @@
|
||||
/*
|
||||
SPDX-FileCopyrightText: 2012, 2013, 2014, 2015 Ivan Cukic <ivan.cukic(at)kde.org>
|
||||
|
||||
SPDX-License-Identifier: GPL-2.0-or-later
|
||||
*/
|
||||
|
||||
// Self
|
||||
#include "activitymodel.h"
|
||||
|
||||
// Qt
|
||||
#include <QByteArray>
|
||||
#include <QDBusPendingCall>
|
||||
#include <QDBusPendingCallWatcher>
|
||||
#include <QDebug>
|
||||
#include <QFutureWatcher>
|
||||
#include <QHash>
|
||||
#include <QIcon>
|
||||
#include <QList>
|
||||
#include <QModelIndex>
|
||||
|
||||
// KDE
|
||||
#include <KConfig>
|
||||
#include <KConfigGroup>
|
||||
#include <KDirWatch>
|
||||
|
||||
#include <optional>
|
||||
|
||||
// Local
|
||||
#define ENABLE_QJSVALUE_CONTINUATION
|
||||
#include "utils/continue_with.h"
|
||||
#include "utils/model_updaters.h"
|
||||
|
||||
using kamd::utils::continue_with;
|
||||
|
||||
namespace KActivities
|
||||
{
|
||||
namespace Imports
|
||||
{
|
||||
class ActivityModel::Private
|
||||
{
|
||||
public:
|
||||
DECLARE_RAII_MODEL_UPDATERS(ActivityModel)
|
||||
|
||||
/**
|
||||
* Searches for the activity.
|
||||
* Returns an option(index, iterator) for the found activity.
|
||||
*/
|
||||
template<typename _Container>
|
||||
static inline std::optional<std::pair<unsigned int, typename _Container::const_iterator>> activityPosition(const _Container &container,
|
||||
const QString &activityId)
|
||||
{
|
||||
using ActivityPosition = decltype(activityPosition(container, activityId));
|
||||
using ContainerElement = typename _Container::value_type;
|
||||
|
||||
auto position = std::find_if(container.begin(), container.end(), [&](const ContainerElement &activity) {
|
||||
return activity->id() == activityId;
|
||||
});
|
||||
|
||||
return (position != container.end()) ? ActivityPosition(std::make_pair(position - container.begin(), position)) : ActivityPosition();
|
||||
}
|
||||
|
||||
/**
|
||||
* Notifies the model that an activity was updated
|
||||
*/
|
||||
template<typename _Model, typename _Container>
|
||||
static inline void emitActivityUpdated(_Model *model, const _Container &container, QObject *activityInfo, int role)
|
||||
{
|
||||
const auto activity = static_cast<Info *>(activityInfo);
|
||||
emitActivityUpdated(model, container, activity->id(), role);
|
||||
}
|
||||
|
||||
/**
|
||||
* Notifies the model that an activity was updated
|
||||
*/
|
||||
template<typename _Model, typename _Container>
|
||||
static inline void emitActivityUpdated(_Model *model, const _Container &container, const QString &activity, int role)
|
||||
{
|
||||
auto position = Private::activityPosition(container, activity);
|
||||
|
||||
if (position) {
|
||||
Q_EMIT model->dataChanged(model->index(position->first),
|
||||
model->index(position->first),
|
||||
role == Qt::DecorationRole ? QList<int>{role, ActivityModel::ActivityIcon} : QList<int>{role});
|
||||
}
|
||||
}
|
||||
|
||||
class BackgroundCache
|
||||
{
|
||||
public:
|
||||
BackgroundCache()
|
||||
: initialized(false)
|
||||
, plasmaConfig(QStringLiteral("plasma-org.kde.plasma.desktop-appletsrc"))
|
||||
{
|
||||
using namespace std::placeholders;
|
||||
|
||||
const QString configFile = QStandardPaths::writableLocation(QStandardPaths::GenericConfigLocation) + QLatin1Char('/') + plasmaConfig.name();
|
||||
|
||||
KDirWatch::self()->addFile(configFile);
|
||||
|
||||
connect(KDirWatch::self(), &KDirWatch::dirty, std::bind(&BackgroundCache::settingsFileChanged, this, _1));
|
||||
connect(KDirWatch::self(), &KDirWatch::created, std::bind(&BackgroundCache::settingsFileChanged, this, _1));
|
||||
}
|
||||
|
||||
void settingsFileChanged(const QString &file)
|
||||
{
|
||||
if (!file.endsWith(plasmaConfig.name())) {
|
||||
return;
|
||||
}
|
||||
|
||||
plasmaConfig.reparseConfiguration();
|
||||
|
||||
if (initialized) {
|
||||
reload(false);
|
||||
}
|
||||
}
|
||||
|
||||
void subscribe(ActivityModel *model)
|
||||
{
|
||||
if (!initialized) {
|
||||
reload(true);
|
||||
}
|
||||
|
||||
models << model;
|
||||
}
|
||||
|
||||
void unsubscribe(ActivityModel *model)
|
||||
{
|
||||
models.removeAll(model);
|
||||
|
||||
if (models.isEmpty()) {
|
||||
initialized = false;
|
||||
forActivity.clear();
|
||||
}
|
||||
}
|
||||
|
||||
QString backgroundFromConfig(const KConfigGroup &config) const
|
||||
{
|
||||
auto wallpaperPlugin = config.readEntry("wallpaperplugin");
|
||||
auto wallpaperConfig = config.group(QStringLiteral("Wallpaper")).group(wallpaperPlugin).group(QStringLiteral("General"));
|
||||
|
||||
if (wallpaperConfig.hasKey("Image")) {
|
||||
// Trying for the wallpaper
|
||||
auto wallpaper = wallpaperConfig.readEntry("Image", QString());
|
||||
if (!wallpaper.isEmpty()) {
|
||||
return wallpaper;
|
||||
}
|
||||
}
|
||||
if (wallpaperConfig.hasKey("Color")) {
|
||||
auto backgroundColor = wallpaperConfig.readEntry("Color", QColor(0, 0, 0));
|
||||
return backgroundColor.name();
|
||||
}
|
||||
|
||||
return QString();
|
||||
}
|
||||
|
||||
void reload(bool fullReload)
|
||||
{
|
||||
QHash<QString, QString> newBackgrounds;
|
||||
|
||||
if (fullReload) {
|
||||
forActivity.clear();
|
||||
}
|
||||
|
||||
QStringList changedBackgrounds;
|
||||
|
||||
for (const auto &cont : plasmaConfigContainments().groupList()) {
|
||||
auto config = plasmaConfigContainments().group(cont);
|
||||
auto activityId = config.readEntry("activityId", QString());
|
||||
|
||||
// Ignore if it has no assigned activity
|
||||
if (activityId.isEmpty()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Ignore if we have already found the background
|
||||
if (newBackgrounds.contains(activityId) && newBackgrounds[activityId][0] != QLatin1Char('#')) {
|
||||
continue;
|
||||
}
|
||||
|
||||
auto newBackground = backgroundFromConfig(config);
|
||||
|
||||
if (forActivity[activityId] != newBackground) {
|
||||
changedBackgrounds << activityId;
|
||||
if (!newBackground.isEmpty()) {
|
||||
newBackgrounds[activityId] = newBackground;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
initialized = true;
|
||||
|
||||
if (!changedBackgrounds.isEmpty()) {
|
||||
forActivity = newBackgrounds;
|
||||
|
||||
for (auto model : models) {
|
||||
model->backgroundsUpdated(changedBackgrounds);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
KConfigGroup plasmaConfigContainments()
|
||||
{
|
||||
return plasmaConfig.group(QStringLiteral("Containments"));
|
||||
}
|
||||
|
||||
QHash<QString, QString> forActivity;
|
||||
QList<ActivityModel *> models;
|
||||
|
||||
bool initialized;
|
||||
KConfig plasmaConfig;
|
||||
};
|
||||
|
||||
static BackgroundCache &backgrounds()
|
||||
{
|
||||
// If you convert this to a shared pointer,
|
||||
// fix the connections to KDirWatcher
|
||||
static BackgroundCache cache;
|
||||
return cache;
|
||||
}
|
||||
};
|
||||
|
||||
ActivityModel::ActivityModel(QObject *parent)
|
||||
: QAbstractListModel(parent)
|
||||
{
|
||||
// Initializing role names for qml
|
||||
connect(&m_service, &Consumer::serviceStatusChanged, this, &ActivityModel::setServiceStatus);
|
||||
|
||||
connect(&m_service, &KActivities::Consumer::activityAdded, this, [this](const QString &id) {
|
||||
onActivityAdded(id);
|
||||
});
|
||||
connect(&m_service, &KActivities::Consumer::activityRemoved, this, &ActivityModel::onActivityRemoved);
|
||||
connect(&m_service, &KActivities::Consumer::currentActivityChanged, this, &ActivityModel::onCurrentActivityChanged);
|
||||
|
||||
setServiceStatus(m_service.serviceStatus());
|
||||
|
||||
Private::backgrounds().subscribe(this);
|
||||
}
|
||||
|
||||
ActivityModel::~ActivityModel()
|
||||
{
|
||||
Private::backgrounds().unsubscribe(this);
|
||||
}
|
||||
|
||||
QHash<int, QByteArray> ActivityModel::roleNames() const
|
||||
{
|
||||
return {{Qt::DisplayRole, "name"},
|
||||
{Qt::DecorationRole, "icon"},
|
||||
|
||||
{ActivityId, "id"},
|
||||
{ActivityIcon, "iconSource"},
|
||||
{ActivityDescription, "description"},
|
||||
{ActivityBackground, "background"},
|
||||
{ActivityCurrent, "current"}};
|
||||
}
|
||||
|
||||
void ActivityModel::setServiceStatus(Consumer::ServiceStatus)
|
||||
{
|
||||
replaceActivities(m_service.activities());
|
||||
}
|
||||
|
||||
void ActivityModel::replaceActivities(const QStringList &activities)
|
||||
{
|
||||
// qDebug() << m_shownStatesString << "New list of activities: "
|
||||
// << activities;
|
||||
// qDebug() << m_shownStatesString << " -- RESET MODEL -- ";
|
||||
|
||||
Private::model_reset m(this);
|
||||
|
||||
m_knownActivities.clear();
|
||||
m_shownActivities.clear();
|
||||
|
||||
for (const QString &activity : activities) {
|
||||
onActivityAdded(activity, false);
|
||||
}
|
||||
}
|
||||
|
||||
void ActivityModel::onActivityAdded(const QString &id, bool notifyClients)
|
||||
{
|
||||
auto info = registerActivity(id);
|
||||
|
||||
// qDebug() << m_shownStatesString << "Added a new activity:" << info->id()
|
||||
// << " " << info->name();
|
||||
|
||||
showActivity(info, notifyClients);
|
||||
}
|
||||
|
||||
void ActivityModel::onActivityRemoved(const QString &id)
|
||||
{
|
||||
// qDebug() << m_shownStatesString << "Removed an activity:" << id;
|
||||
|
||||
hideActivity(id);
|
||||
unregisterActivity(id);
|
||||
}
|
||||
|
||||
void ActivityModel::onCurrentActivityChanged(const QString &id)
|
||||
{
|
||||
Q_UNUSED(id);
|
||||
|
||||
for (const auto &activity : m_shownActivities) {
|
||||
Private::emitActivityUpdated(this, m_shownActivities, activity->id(), ActivityCurrent);
|
||||
}
|
||||
}
|
||||
|
||||
ActivityModel::InfoPtr ActivityModel::registerActivity(const QString &id)
|
||||
{
|
||||
auto position = Private::activityPosition(m_knownActivities, id);
|
||||
|
||||
// qDebug() << m_shownStatesString << "Registering activity: " << id
|
||||
// << " new? not " << (bool)position;
|
||||
|
||||
if (position) {
|
||||
return *(position->second);
|
||||
|
||||
} else {
|
||||
auto activityInfo = std::make_shared<Info>(id);
|
||||
|
||||
auto ptr = activityInfo.get();
|
||||
|
||||
connect(ptr, &Info::nameChanged, this, &ActivityModel::onActivityNameChanged);
|
||||
connect(ptr, &Info::descriptionChanged, this, &ActivityModel::onActivityDescriptionChanged);
|
||||
connect(ptr, &Info::iconChanged, this, &ActivityModel::onActivityIconChanged);
|
||||
|
||||
m_knownActivities.insert(InfoPtr(activityInfo));
|
||||
|
||||
return activityInfo;
|
||||
}
|
||||
}
|
||||
|
||||
void ActivityModel::unregisterActivity(const QString &id)
|
||||
{
|
||||
// qDebug() << m_shownStatesString << "Deregistering activity: " << id;
|
||||
|
||||
auto position = Private::activityPosition(m_knownActivities, id);
|
||||
|
||||
if (position) {
|
||||
if (auto shown = Private::activityPosition(m_shownActivities, id)) {
|
||||
Private::model_remove(this, QModelIndex(), shown->first, shown->first);
|
||||
m_shownActivities.erase(shown->second);
|
||||
}
|
||||
|
||||
m_knownActivities.erase(position->second);
|
||||
}
|
||||
}
|
||||
|
||||
void ActivityModel::showActivity(InfoPtr activityInfo, bool notifyClients)
|
||||
{
|
||||
// Is it already shown?
|
||||
if (std::binary_search(m_shownActivities.begin(), m_shownActivities.end(), activityInfo, InfoPtrComparator())) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto registeredPosition = Private::activityPosition(m_knownActivities, activityInfo->id());
|
||||
|
||||
if (!registeredPosition) {
|
||||
qDebug() << "Got a request to show an unknown activity, ignoring";
|
||||
return;
|
||||
}
|
||||
|
||||
auto activityInfoPtr = *(registeredPosition->second);
|
||||
|
||||
// qDebug() << m_shownStatesString << "Setting activity visibility to true:"
|
||||
// << activityInfoPtr->id() << activityInfoPtr->name();
|
||||
|
||||
auto [insertedIt, _, didInsert] = m_shownActivities.insert(activityInfoPtr);
|
||||
|
||||
if (notifyClients) {
|
||||
unsigned int index = (didInsert ? insertedIt : m_shownActivities.end()) - m_shownActivities.begin();
|
||||
|
||||
// qDebug() << m_shownStatesString << " -- MODEL INSERT -- " << index;
|
||||
Private::model_insert(this, QModelIndex(), index, index);
|
||||
}
|
||||
}
|
||||
|
||||
void ActivityModel::hideActivity(const QString &id)
|
||||
{
|
||||
auto position = Private::activityPosition(m_shownActivities, id);
|
||||
|
||||
// qDebug() << m_shownStatesString
|
||||
// << "Setting activity visibility to false: " << id;
|
||||
|
||||
if (position) {
|
||||
// qDebug() << m_shownStatesString << " -- MODEL REMOVE -- "
|
||||
// << position->first;
|
||||
Private::model_remove(this, QModelIndex(), position->first, position->first);
|
||||
m_shownActivities.erase(position->second);
|
||||
}
|
||||
}
|
||||
// clang-format off
|
||||
#define CREATE_SIGNAL_EMITTER(What,Role) \
|
||||
void ActivityModel::onActivity##What##Changed(const QString &) \
|
||||
{ \
|
||||
Private::emitActivityUpdated(this, m_shownActivities, sender(), Role); \
|
||||
}
|
||||
// clang-format on
|
||||
|
||||
CREATE_SIGNAL_EMITTER(Name, Qt::DisplayRole)
|
||||
CREATE_SIGNAL_EMITTER(Description, ActivityDescription)
|
||||
CREATE_SIGNAL_EMITTER(Icon, Qt::DecorationRole)
|
||||
|
||||
#undef CREATE_SIGNAL_EMITTER
|
||||
|
||||
void ActivityModel::backgroundsUpdated(const QStringList &activities)
|
||||
{
|
||||
for (const auto &activity : activities) {
|
||||
Private::emitActivityUpdated(this, m_shownActivities, activity, ActivityBackground);
|
||||
}
|
||||
}
|
||||
|
||||
int ActivityModel::rowCount(const QModelIndex &parent) const
|
||||
{
|
||||
Q_UNUSED(parent);
|
||||
|
||||
return m_shownActivities.size();
|
||||
}
|
||||
|
||||
QVariant ActivityModel::data(const QModelIndex &index, int role) const
|
||||
{
|
||||
const int row = index.row();
|
||||
const auto &item = *(m_shownActivities.cbegin() + row);
|
||||
|
||||
switch (role) {
|
||||
case Qt::DisplayRole:
|
||||
return item->name();
|
||||
|
||||
case Qt::DecorationRole:
|
||||
return QIcon::fromTheme(data(index, ActivityIcon).toString());
|
||||
|
||||
case ActivityId:
|
||||
return item->id();
|
||||
|
||||
case ActivityIcon: {
|
||||
const QString &icon = item->icon();
|
||||
|
||||
// We need a default icon for activities
|
||||
return icon.isEmpty() ? QStringLiteral("activities") : icon;
|
||||
}
|
||||
|
||||
case ActivityDescription:
|
||||
return item->description();
|
||||
|
||||
case ActivityCurrent:
|
||||
return m_service.currentActivity() == item->id();
|
||||
|
||||
case ActivityBackground:
|
||||
return Private::backgrounds().forActivity[item->id()];
|
||||
|
||||
default:
|
||||
return QVariant();
|
||||
}
|
||||
}
|
||||
|
||||
QVariant ActivityModel::headerData(int section, Qt::Orientation orientation, int role) const
|
||||
{
|
||||
Q_UNUSED(section);
|
||||
Q_UNUSED(orientation);
|
||||
Q_UNUSED(role);
|
||||
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
ActivityModel::InfoPtr ActivityModel::findActivity(QObject *ptr) const
|
||||
{
|
||||
auto info = std::find_if(m_knownActivities.begin(), m_knownActivities.end(), [ptr](const InfoPtr &info) {
|
||||
return ptr == info.get();
|
||||
});
|
||||
|
||||
if (info == m_knownActivities.end()) {
|
||||
return nullptr;
|
||||
} else {
|
||||
return *info;
|
||||
}
|
||||
}
|
||||
|
||||
// clang-format off
|
||||
// QFuture<void> Controller::setActivityWhat(id, value)
|
||||
#define CREATE_SETTER(What) \
|
||||
void ActivityModel::setActivity##What( \
|
||||
const QString &id, const QString &value, const QJSValue &callback) \
|
||||
{ \
|
||||
continue_with(m_service.setActivity##What(id, value), callback); \
|
||||
}
|
||||
// clang-format on
|
||||
|
||||
CREATE_SETTER(Name)
|
||||
CREATE_SETTER(Description)
|
||||
CREATE_SETTER(Icon)
|
||||
|
||||
#undef CREATE_SETTER
|
||||
|
||||
// QFuture<bool> Controller::setCurrentActivity(id)
|
||||
void ActivityModel::setCurrentActivity(const QString &id, const QJSValue &callback)
|
||||
{
|
||||
continue_with(m_service.setCurrentActivity(id), callback);
|
||||
}
|
||||
|
||||
// QFuture<QString> Controller::addActivity(name)
|
||||
void ActivityModel::addActivity(const QString &name, const QJSValue &callback)
|
||||
{
|
||||
continue_with(m_service.addActivity(name), callback);
|
||||
}
|
||||
|
||||
// QFuture<void> Controller::removeActivity(id)
|
||||
void ActivityModel::removeActivity(const QString &id, const QJSValue &callback)
|
||||
{
|
||||
continue_with(m_service.removeActivity(id), callback);
|
||||
}
|
||||
|
||||
} // namespace Imports
|
||||
} // namespace KActivities
|
||||
|
||||
#include "moc_activitymodel.cpp"
|
||||
@@ -0,0 +1,164 @@
|
||||
/*
|
||||
SPDX-FileCopyrightText: 2012, 2013, 2014 Ivan Cukic <ivan.cukic(at)kde.org>
|
||||
|
||||
SPDX-License-Identifier: GPL-2.0-or-later
|
||||
*/
|
||||
|
||||
#ifndef KACTIVITIES_IMPORTS_ACTIVITY_MODEL_H
|
||||
#define KACTIVITIES_IMPORTS_ACTIVITY_MODEL_H
|
||||
|
||||
// Qt
|
||||
#include <QAbstractListModel>
|
||||
#include <QCollator>
|
||||
#include <QJSValue>
|
||||
#include <QObject>
|
||||
#include <qqmlregistration.h>
|
||||
|
||||
// STL
|
||||
#include <memory>
|
||||
|
||||
// Local
|
||||
#include "utils/qflatset.h"
|
||||
#include <lib/consumer.h>
|
||||
#include <lib/controller.h>
|
||||
#include <lib/info.h>
|
||||
|
||||
class QModelIndex;
|
||||
class QDBusPendingCallWatcher;
|
||||
|
||||
namespace KActivities
|
||||
{
|
||||
namespace Imports
|
||||
{
|
||||
|
||||
/*!
|
||||
* \qmltype ActivityModel
|
||||
* \inqmlmodule org.kde.activities
|
||||
*
|
||||
* \brief Activities model.
|
||||
*
|
||||
* This model provides the following roles:
|
||||
* \list
|
||||
* \li name (string)
|
||||
* \li icon (QIcon)
|
||||
* \li id (string)
|
||||
* \li iconSource (string)
|
||||
* \li description (string)
|
||||
* \li background (string)
|
||||
* \li current (bool)
|
||||
* \endlist
|
||||
*/
|
||||
class ActivityModel : public QAbstractListModel
|
||||
{
|
||||
Q_OBJECT
|
||||
QML_ELEMENT
|
||||
|
||||
public:
|
||||
explicit ActivityModel(QObject *parent = nullptr);
|
||||
~ActivityModel() override;
|
||||
|
||||
int rowCount(const QModelIndex &parent = QModelIndex()) const override;
|
||||
|
||||
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
|
||||
|
||||
QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override;
|
||||
|
||||
QHash<int, QByteArray> roleNames() const override;
|
||||
|
||||
enum Roles {
|
||||
ActivityId = Qt::UserRole,
|
||||
ActivityDescription = Qt::UserRole + 1,
|
||||
ActivityIcon = Qt::UserRole + 2,
|
||||
ActivityBackground = Qt::UserRole + 4,
|
||||
ActivityCurrent = Qt::UserRole + 5,
|
||||
};
|
||||
|
||||
public Q_SLOTS:
|
||||
// Activity control methods
|
||||
|
||||
/*!
|
||||
* \qmlmethod void ActivityModel::setActivityName(string id, string name, var callback)
|
||||
*/
|
||||
void setActivityName(const QString &id, const QString &name, const QJSValue &callback);
|
||||
|
||||
/*!
|
||||
* \qmlmethod void ActivityModel::setActivityDescription(string id, string description, var callback)
|
||||
*/
|
||||
void setActivityDescription(const QString &id, const QString &description, const QJSValue &callback);
|
||||
|
||||
/*!
|
||||
* \qmlmethod void ActivityModel::setActivityIcon(string id, string icon, var callback)
|
||||
*/
|
||||
void setActivityIcon(const QString &id, const QString &icon, const QJSValue &callback);
|
||||
|
||||
/*!
|
||||
* \qmlmethod void ActivityModel::setCurrentActivity(string id, var callback)
|
||||
*/
|
||||
void setCurrentActivity(const QString &id, const QJSValue &callback);
|
||||
|
||||
/*!
|
||||
* \qmlmethod void ActivityModel::addActivity(string name, var callback)
|
||||
*/
|
||||
void addActivity(const QString &name, const QJSValue &callback);
|
||||
|
||||
/*!
|
||||
* \qmlmethod void ActivityModel::removeActivity(string id, var callback)
|
||||
*/
|
||||
void removeActivity(const QString &id, const QJSValue &callback);
|
||||
|
||||
Q_SIGNALS:
|
||||
/*!
|
||||
* \qmlsignal ActivityModel::shownStatesChanged(string state)
|
||||
*/
|
||||
void shownStatesChanged(const QString &state);
|
||||
|
||||
private Q_SLOTS:
|
||||
void onActivityNameChanged(const QString &name);
|
||||
void onActivityDescriptionChanged(const QString &description);
|
||||
void onActivityIconChanged(const QString &icon);
|
||||
|
||||
void replaceActivities(const QStringList &activities);
|
||||
void onActivityAdded(const QString &id, bool notifyClients = true);
|
||||
void onActivityRemoved(const QString &id);
|
||||
void onCurrentActivityChanged(const QString &id);
|
||||
|
||||
void setServiceStatus(KActivities::Consumer::ServiceStatus status);
|
||||
|
||||
private:
|
||||
KActivities::Controller m_service;
|
||||
|
||||
typedef std::shared_ptr<Info> InfoPtr;
|
||||
|
||||
struct InfoPtrComparator {
|
||||
bool operator()(const InfoPtr &left, const InfoPtr &right) const
|
||||
{
|
||||
QCollator c;
|
||||
c.setCaseSensitivity(Qt::CaseInsensitive);
|
||||
c.setNumericMode(true);
|
||||
int rc = c.compare(left->name(), right->name());
|
||||
if (rc == 0) {
|
||||
return left->id() < right->id();
|
||||
}
|
||||
return rc < 0;
|
||||
}
|
||||
};
|
||||
|
||||
QFlatSet<InfoPtr, InfoPtrComparator> m_knownActivities;
|
||||
QFlatSet<InfoPtr, InfoPtrComparator> m_shownActivities;
|
||||
|
||||
InfoPtr registerActivity(const QString &id);
|
||||
void unregisterActivity(const QString &id);
|
||||
void showActivity(InfoPtr activityInfo, bool notifyClients);
|
||||
void hideActivity(const QString &id);
|
||||
void backgroundsUpdated(const QStringList &activities);
|
||||
|
||||
InfoPtr findActivity(QObject *ptr) const;
|
||||
|
||||
class Private;
|
||||
friend class Private;
|
||||
};
|
||||
|
||||
} // namespace Imports
|
||||
} // namespace KActivities
|
||||
|
||||
#endif // KACTIVITIES_IMPORTS_ACTIVITY_MODEL_H
|
||||
@@ -0,0 +1,6 @@
|
||||
/*!
|
||||
\qmlmodule org.kde.activities
|
||||
\title Plasma Activities QML Types
|
||||
\ingroup qmlmodules
|
||||
\brief QML API for Plasma Activities
|
||||
*/
|
||||
+35
@@ -0,0 +1,35 @@
|
||||
include($KDE_DOCS/global/qt-module-defaults.qdocconf)
|
||||
|
||||
project = PlasmaActivitiesQml
|
||||
description = QML API for Plasma Activities
|
||||
|
||||
documentationinheaders = true
|
||||
|
||||
headerdirs += .
|
||||
sourcedirs += .
|
||||
|
||||
outputformats = HTML
|
||||
|
||||
depends += \
|
||||
kde \
|
||||
qtcore \
|
||||
qtqml \
|
||||
plasmaactivities
|
||||
|
||||
navigation.landingpage = "PlasmaActivities"
|
||||
|
||||
qhp.projects = PlasmaActivitiesQml
|
||||
|
||||
qhp.PlasmaActivitiesQml.file = plasmaactivitiesqml.qhp
|
||||
qhp.PlasmaActivitiesQml.namespace = org.kde.plasmaactivitiesqml.$QT_VERSION_TAG
|
||||
qhp.PlasmaActivitiesQml.virtualFolder = plasmaactivitiesqml
|
||||
qhp.PlasmaActivitiesQml.indexTitle = Plasma Activities QML
|
||||
qhp.PlasmaActivitiesQml.indexRoot =
|
||||
|
||||
qhp.PlasmaActivitiesQml.subprojects = qmltypes
|
||||
qhp.PlasmaActivitiesQml.subprojects.qmltypes.title = QML Types
|
||||
qhp.PlasmaActivitiesQml.subprojects.qmltypes.indexTitle = Plasma Activities QML Types
|
||||
qhp.PlasmaActivitiesQml.subprojects.qmltypes.selectors = qmlmodule:org.kde.coreaddons
|
||||
qhp.PlasmaActivitiesQml.subprojects.qmltypes.sortPages = true
|
||||
|
||||
tagfile = plasmaactivitiesqml.tags
|
||||
@@ -0,0 +1,17 @@
|
||||
#ifndef CONFIG_FEATURES_H_
|
||||
#define CONFIG_FEATURES_H_
|
||||
|
||||
#cmakedefine KAMD_DATA_DIR "@KAMD_DATA_DIR@"
|
||||
|
||||
#cmakedefine KAMD_PLUGIN_DIR "@KAMD_PLUGIN_DIR@"
|
||||
#cmakedefine KAMD_FULL_PLUGIN_DIR "@KAMD_FULL_PLUGIN_DIR@"
|
||||
|
||||
#cmakedefine KAMD_INSTALL_PREFIX "@KAMD_INSTALL_PREFIX@"
|
||||
|
||||
#cmakedefine01 HAVE_CXX11_AUTO
|
||||
#cmakedefine01 HAVE_CXX11_NULLPTR
|
||||
#cmakedefine01 HAVE_CXX11_LAMBDA
|
||||
#cmakedefine01 HAVE_CXX11_OVERRIDE
|
||||
#cmakedefine01 HAVE_CXX_OVERRIDE_ATTR
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,149 @@
|
||||
# vim:set softtabstop=3 shiftwidth=3 tabstop=3 expandtab:
|
||||
|
||||
# =======================================================
|
||||
# Now that we finished with the boilerplate, start
|
||||
# with the library definition
|
||||
|
||||
add_library(PlasmaActivities)
|
||||
add_library(Plasma::Activities ALIAS PlasmaActivities)
|
||||
|
||||
set_target_properties(PlasmaActivities PROPERTIES
|
||||
VERSION ${PLASMA_ACTIVITIES_VERSION}
|
||||
SOVERSION ${PLASMA_ACTIVITIES_SOVERSION}
|
||||
EXPORT_NAME Activities
|
||||
)
|
||||
|
||||
target_sources(PlasmaActivities PRIVATE
|
||||
${PLASMA_ACTIVITIES_CURRENT_ROOT_SOURCE_DIR}/src/common/dbus/org.kde.ActivityManager.Activities.cpp
|
||||
|
||||
consumer.cpp
|
||||
consumer.h
|
||||
controller.cpp
|
||||
controller.h
|
||||
info.cpp
|
||||
info.h
|
||||
resourceinstance.cpp
|
||||
resourceinstance.h
|
||||
activitiesmodel.cpp
|
||||
activitiesmodel.h
|
||||
|
||||
mainthreadexecutor_p.cpp
|
||||
mainthreadexecutor_p.h
|
||||
manager_p.cpp
|
||||
manager_p.h
|
||||
activitiescache_p.cpp
|
||||
activitiescache_p.h
|
||||
|
||||
${PLASMA_ACTIVITIES_CURRENT_ROOT_SOURCE_DIR}/src/utils/dbusfuture_p.cpp
|
||||
|
||||
version.cpp
|
||||
version.h
|
||||
)
|
||||
|
||||
set_source_files_properties (
|
||||
${PLASMA_ACTIVITIES_CURRENT_ROOT_SOURCE_DIR}/src/common/dbus/org.kde.ActivityManager.Activities.xml
|
||||
PROPERTIES
|
||||
INCLUDE ../common/dbus/org.kde.ActivityManager.Activities.h
|
||||
)
|
||||
|
||||
set(PlasmaActivities_DBus_SRCS)
|
||||
qt6_add_dbus_interface(PlasmaActivities_DBus_SRCS
|
||||
${PLASMA_ACTIVITIES_CURRENT_ROOT_SOURCE_DIR}/src/common/dbus/org.kde.ActivityManager.Activities.xml
|
||||
activities_interface
|
||||
)
|
||||
qt6_add_dbus_interface(PlasmaActivities_DBus_SRCS
|
||||
${PLASMA_ACTIVITIES_CURRENT_ROOT_SOURCE_DIR}/src/common/dbus/org.kde.ActivityManager.Resources.xml
|
||||
resources_interface
|
||||
)
|
||||
qt6_add_dbus_interface(PlasmaActivities_DBus_SRCS
|
||||
${PLASMA_ACTIVITIES_CURRENT_ROOT_SOURCE_DIR}/src/common/dbus/org.kde.ActivityManager.Features.xml
|
||||
features_interface
|
||||
)
|
||||
qt6_add_dbus_interface(PlasmaActivities_DBus_SRCS
|
||||
${PLASMA_ACTIVITIES_CURRENT_ROOT_SOURCE_DIR}/src/common/dbus/org.kde.ActivityManager.ResourcesLinking.xml
|
||||
resources_linking_interface
|
||||
)
|
||||
qt6_add_dbus_interface(PlasmaActivities_DBus_SRCS
|
||||
${PLASMA_ACTIVITIES_CURRENT_ROOT_SOURCE_DIR}/src/common/dbus/org.kde.ActivityManager.Application.xml
|
||||
application_interface
|
||||
)
|
||||
target_sources(PlasmaActivities PRIVATE
|
||||
${PlasmaActivities_DBus_SRCS}
|
||||
)
|
||||
|
||||
ecm_qt_declare_logging_category(PlasmaActivities
|
||||
HEADER debug_p.h
|
||||
IDENTIFIER KAMD_CORELIB
|
||||
CATEGORY_NAME kde.plasma.activities
|
||||
OLD_CATEGORY_NAMES org.kde.kactivities.lib.core
|
||||
DESCRIPTION "Plasma Activities core lib"
|
||||
EXPORT PLASMA_ACTIVITIES
|
||||
)
|
||||
|
||||
target_link_libraries(PlasmaActivities
|
||||
PUBLIC
|
||||
Qt6::Core
|
||||
PRIVATE
|
||||
Qt6::DBus
|
||||
)
|
||||
|
||||
set(PLASMA_ACTIVITIES_BUILD_INCLUDE_DIRS
|
||||
${PLASMA_ACTIVITIES_CURRENT_ROOT_SOURCE_DIR}/src
|
||||
${CMAKE_BINARY_DIR}/
|
||||
)
|
||||
|
||||
target_include_directories(PlasmaActivities
|
||||
INTERFACE "$<INSTALL_INTERFACE:${KDE_INSTALL_INCLUDEDIR}/PlasmaActivities>"
|
||||
PRIVATE ${PLASMA_ACTIVITIES_BUILD_INCLUDE_DIRS}
|
||||
)
|
||||
|
||||
# install
|
||||
ecm_generate_export_header (PlasmaActivities
|
||||
BASE_NAME Plasma_Activities
|
||||
VERSION ${PROJECT_VERSION}
|
||||
USE_VERSION_HEADER plasma_activities_version.h
|
||||
DEPRECATED_BASE_VERSION 0
|
||||
)
|
||||
|
||||
ecm_generate_qdoc(PlasmaActivities plasmaactivities.qdocconf)
|
||||
|
||||
ecm_generate_headers (
|
||||
PlasmaActivities_CamelCase_HEADERS
|
||||
HEADER_NAMES
|
||||
Consumer
|
||||
Controller
|
||||
Info
|
||||
ResourceInstance
|
||||
ActivitiesModel
|
||||
Version
|
||||
PREFIX PlasmaActivities
|
||||
REQUIRED_HEADERS PlasmaActivities_HEADERS
|
||||
)
|
||||
install (
|
||||
FILES ${PlasmaActivities_CamelCase_HEADERS}
|
||||
DESTINATION ${KDE_INSTALL_INCLUDEDIR}/PlasmaActivities/PlasmaActivities
|
||||
COMPONENT Devel
|
||||
)
|
||||
|
||||
install (
|
||||
FILES ${PlasmaActivities_HEADERS} ${CMAKE_CURRENT_BINARY_DIR}/plasma_activities_export.h
|
||||
DESTINATION ${KDE_INSTALL_INCLUDEDIR}/PlasmaActivities/plasmaactivities
|
||||
COMPONENT Devel
|
||||
)
|
||||
|
||||
install (
|
||||
TARGETS PlasmaActivities
|
||||
EXPORT PlasmaActivitiesLibraryTargets
|
||||
${KDE_INSTALL_TARGETS_DEFAULT_ARGS}
|
||||
)
|
||||
|
||||
if (NOT WIN32)
|
||||
ecm_generate_pkgconfig_file(BASE_NAME PlasmaActivities
|
||||
LIB_NAME PlasmaActivities
|
||||
INCLUDE_INSTALL_DIR ${KDE_INSTALL_INCLUDEDIR}/PlasmaActivities
|
||||
DEPS Qt6Core
|
||||
DESCRIPTION "Plasma Activities is a C++ library for using Plasma's activities"
|
||||
INSTALL
|
||||
)
|
||||
endif ()
|
||||
|
||||
@@ -0,0 +1,258 @@
|
||||
/*
|
||||
SPDX-FileCopyrightText: 2013-2016 Ivan Cukic <ivan.cukic(at)kde.org>
|
||||
|
||||
SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
|
||||
*/
|
||||
|
||||
#include "activitiescache_p.h"
|
||||
#include "manager_p.h"
|
||||
|
||||
#include <mutex>
|
||||
|
||||
#include <QString>
|
||||
|
||||
#include "mainthreadexecutor_p.h"
|
||||
|
||||
namespace KActivities
|
||||
{
|
||||
static QString nulluuid = QStringLiteral("00000000-0000-0000-0000-000000000000");
|
||||
|
||||
using kamd::utils::Mutable;
|
||||
|
||||
std::shared_ptr<ActivitiesCache> ActivitiesCache::self()
|
||||
{
|
||||
static std::weak_ptr<ActivitiesCache> s_instance;
|
||||
static std::mutex singleton;
|
||||
std::lock_guard<std::mutex> singleton_lock(singleton);
|
||||
|
||||
auto result = s_instance.lock();
|
||||
|
||||
if (s_instance.expired()) {
|
||||
runInMainThread([&result] {
|
||||
result.reset(new ActivitiesCache());
|
||||
s_instance = result;
|
||||
});
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
ActivitiesCache::ActivitiesCache()
|
||||
: m_status(Consumer::NotRunning)
|
||||
{
|
||||
// qDebug() << "ActivitiesCache: Creating a new instance";
|
||||
using org::kde::ActivityManager::Activities;
|
||||
|
||||
auto activities = Manager::self()->activities();
|
||||
|
||||
connect(activities, &Activities::ActivityAdded, this, &ActivitiesCache::updateActivity);
|
||||
connect(activities, &Activities::ActivityChanged, this, &ActivitiesCache::updateActivity);
|
||||
connect(activities, &Activities::ActivityRemoved, this, &ActivitiesCache::removeActivity);
|
||||
|
||||
connect(activities, &Activities::ActivityNameChanged, this, &ActivitiesCache::setActivityName);
|
||||
connect(activities, &Activities::ActivityDescriptionChanged, this, &ActivitiesCache::setActivityDescription);
|
||||
connect(activities, &Activities::ActivityIconChanged, this, &ActivitiesCache::setActivityIcon);
|
||||
|
||||
connect(activities, &Activities::CurrentActivityChanged, this, &ActivitiesCache::setCurrentActivity);
|
||||
|
||||
connect(Manager::self(), &Manager::serviceStatusChanged, this, &ActivitiesCache::setServiceStatus);
|
||||
|
||||
// These are covered by ActivityStateChanged
|
||||
// signal void org.kde.ActivityManager.Activities.ActivityStarted(QString activity)
|
||||
// signal void org.kde.ActivityManager.Activities.ActivityStopped(QString activity)
|
||||
|
||||
setServiceStatus(Manager::self()->serviceStatus());
|
||||
}
|
||||
|
||||
void ActivitiesCache::setServiceStatus(Manager::ServiceStatus status)
|
||||
{
|
||||
loadOfflineDefaults();
|
||||
|
||||
auto oldStatus = m_status;
|
||||
switch (status) {
|
||||
case Manager::NotRunning:
|
||||
m_status = Consumer::NotRunning;
|
||||
break;
|
||||
case Manager::Starting:
|
||||
m_status = Consumer::Unknown;
|
||||
break;
|
||||
case Manager::Running:
|
||||
// will become running once loaded
|
||||
m_status = Consumer::Unknown;
|
||||
updateAllActivities();
|
||||
break;
|
||||
}
|
||||
if (m_status != oldStatus) {
|
||||
Q_EMIT serviceStatusChanged(m_status);
|
||||
}
|
||||
}
|
||||
|
||||
void ActivitiesCache::loadOfflineDefaults()
|
||||
{
|
||||
m_activities.clear();
|
||||
m_activities << ActivityInfo(nulluuid, QString(), QString(), QString());
|
||||
m_currentActivity = nulluuid;
|
||||
|
||||
Q_EMIT activityListChanged();
|
||||
}
|
||||
|
||||
ActivitiesCache::~ActivitiesCache()
|
||||
{
|
||||
// qDebug() << "ActivitiesCache: Destroying the instance";
|
||||
}
|
||||
|
||||
void ActivitiesCache::removeActivity(const QString &id)
|
||||
{
|
||||
// qDebug() << "Removing the activity";
|
||||
|
||||
// Since we are sorting the activities by name now,
|
||||
// we can not use lower_bound to search for an activity
|
||||
// with a specified id
|
||||
const auto where = find(id);
|
||||
|
||||
if (where != m_activities.end() && where->id == id) {
|
||||
m_activities.erase(where);
|
||||
Q_EMIT activityRemoved(id);
|
||||
Q_EMIT activityListChanged();
|
||||
|
||||
} else {
|
||||
// qFatal("Requested to delete an non-existent activity");
|
||||
}
|
||||
}
|
||||
|
||||
void ActivitiesCache::updateAllActivities()
|
||||
{
|
||||
// Loading the current activity
|
||||
auto call = Manager::self()->activities()->asyncCall(QStringLiteral("CurrentActivity"));
|
||||
|
||||
onCallFinished(call, SLOT(setCurrentActivityFromReply(QDBusPendingCallWatcher *)));
|
||||
|
||||
// Loading all the activities
|
||||
call = Manager::self()->activities()->asyncCall(QStringLiteral("ListActivitiesWithInformation"));
|
||||
|
||||
onCallFinished(call, SLOT(setAllActivitiesFromReply(QDBusPendingCallWatcher *)));
|
||||
}
|
||||
|
||||
void ActivitiesCache::updateActivity(const QString &id)
|
||||
{
|
||||
// qDebug() << "Updating activity" << id;
|
||||
|
||||
auto call = Manager::self()->activities()->asyncCall(QStringLiteral("ActivityInformation"), id);
|
||||
|
||||
onCallFinished(call, SLOT(setActivityInfoFromReply(QDBusPendingCallWatcher *)));
|
||||
}
|
||||
|
||||
template<typename _Result, typename _Functor>
|
||||
void ActivitiesCache::passInfoFromReply(QDBusPendingCallWatcher *watcher, _Functor f)
|
||||
{
|
||||
QDBusPendingReply<_Result> reply = *watcher;
|
||||
|
||||
if (!reply.isError()) {
|
||||
auto replyValue = reply.template argumentAt<0>();
|
||||
// qDebug() << "Got some reply" << replyValue;
|
||||
|
||||
((*this).*f)(replyValue);
|
||||
}
|
||||
|
||||
watcher->deleteLater();
|
||||
}
|
||||
|
||||
void ActivitiesCache::setActivityInfoFromReply(QDBusPendingCallWatcher *watcher)
|
||||
{
|
||||
// qDebug() << "reply...";
|
||||
passInfoFromReply<ActivityInfo>(watcher, &ActivitiesCache::setActivityInfo);
|
||||
}
|
||||
|
||||
void ActivitiesCache::setAllActivitiesFromReply(QDBusPendingCallWatcher *watcher)
|
||||
{
|
||||
// qDebug() << "reply...";
|
||||
passInfoFromReply<ActivityInfoList>(watcher, &ActivitiesCache::setAllActivities);
|
||||
}
|
||||
|
||||
void ActivitiesCache::setCurrentActivityFromReply(QDBusPendingCallWatcher *watcher)
|
||||
{
|
||||
// qDebug() << "reply...";
|
||||
passInfoFromReply<QString>(watcher, &ActivitiesCache::setCurrentActivity);
|
||||
}
|
||||
|
||||
void ActivitiesCache::setActivityInfo(const ActivityInfo &info)
|
||||
{
|
||||
// qDebug() << "Setting activity info" << info.id;
|
||||
|
||||
// Are we updating an existing activity, or adding a new one?
|
||||
const auto iter = find(info.id);
|
||||
const auto present = iter != m_activities.end();
|
||||
// If there is an activity with the specified id,
|
||||
// we are going to remove it, temporarily.
|
||||
if (present) {
|
||||
m_activities.erase(iter);
|
||||
}
|
||||
|
||||
// Now, we need to find where to insert the activity
|
||||
// and keep the cache sorted by name
|
||||
const auto where = lower_bound(info);
|
||||
|
||||
m_activities.insert(where, info);
|
||||
|
||||
if (present) {
|
||||
Q_EMIT activityChanged(info.id);
|
||||
} else {
|
||||
Q_EMIT activityAdded(info.id);
|
||||
Q_EMIT activityListChanged();
|
||||
}
|
||||
}
|
||||
// clang-format off
|
||||
#define CREATE_SETTER(WHAT, What) \
|
||||
void ActivitiesCache::setActivity##WHAT(const QString &id, \
|
||||
const QString &value) \
|
||||
{ \
|
||||
auto where = getInfo<Mutable>(id); \
|
||||
\
|
||||
if (where) { \
|
||||
where->What = value; \
|
||||
Q_EMIT activity##WHAT##Changed(id, value); \
|
||||
} \
|
||||
}
|
||||
// clang-format on
|
||||
|
||||
CREATE_SETTER(Name, name)
|
||||
CREATE_SETTER(Description, description)
|
||||
CREATE_SETTER(Icon, icon)
|
||||
|
||||
#undef CREATE_SETTER
|
||||
|
||||
void ActivitiesCache::setAllActivities(const ActivityInfoList &_activities)
|
||||
{
|
||||
// qDebug() << "Setting all activities";
|
||||
|
||||
m_activities.clear();
|
||||
|
||||
const ActivityInfoList activities = _activities;
|
||||
|
||||
for (const ActivityInfo &info : activities) {
|
||||
m_activities << info;
|
||||
}
|
||||
|
||||
std::sort(m_activities.begin(), m_activities.end(), &infoLessThan);
|
||||
|
||||
m_status = Consumer::Running;
|
||||
Q_EMIT serviceStatusChanged(m_status);
|
||||
Q_EMIT activityListChanged();
|
||||
}
|
||||
|
||||
void ActivitiesCache::setCurrentActivity(const QString &activity)
|
||||
{
|
||||
// qDebug() << "Setting current activity to" << activity;
|
||||
|
||||
if (m_currentActivity == activity) {
|
||||
return;
|
||||
}
|
||||
|
||||
m_currentActivity = activity;
|
||||
|
||||
Q_EMIT currentActivityChanged(activity);
|
||||
}
|
||||
|
||||
} // namespace KActivities
|
||||
|
||||
#include "moc_activitiescache_p.cpp"
|
||||
@@ -0,0 +1,117 @@
|
||||
/*
|
||||
SPDX-FileCopyrightText: 2013-2016 Ivan Cukic <ivan.cukic(at)kde.org>
|
||||
|
||||
SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
|
||||
*/
|
||||
|
||||
#ifndef ACTIVITIES_CACHE_P_H
|
||||
#define ACTIVITIES_CACHE_P_H
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include <QObject>
|
||||
|
||||
#include <common/dbus/org.kde.ActivityManager.Activities.h>
|
||||
#include <utils/ptr_to.h>
|
||||
|
||||
#include "activities_interface.h"
|
||||
#include "consumer.h"
|
||||
#include "manager_p.h"
|
||||
|
||||
namespace KActivities
|
||||
{
|
||||
class ActivitiesCache : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
static std::shared_ptr<ActivitiesCache> self();
|
||||
|
||||
~ActivitiesCache() override;
|
||||
|
||||
Q_SIGNALS:
|
||||
void activityAdded(const QString &id);
|
||||
void activityChanged(const QString &id);
|
||||
void activityRemoved(const QString &id);
|
||||
|
||||
void activityNameChanged(const QString &id, const QString &name);
|
||||
void activityDescriptionChanged(const QString &id, const QString &description);
|
||||
void activityIconChanged(const QString &id, const QString &icon);
|
||||
|
||||
void currentActivityChanged(const QString &id);
|
||||
void serviceStatusChanged(Consumer::ServiceStatus status);
|
||||
void activityListChanged();
|
||||
|
||||
private Q_SLOTS:
|
||||
void updateAllActivities();
|
||||
void loadOfflineDefaults();
|
||||
|
||||
void updateActivity(const QString &id);
|
||||
void removeActivity(const QString &id);
|
||||
|
||||
void setActivityInfoFromReply(QDBusPendingCallWatcher *watcher);
|
||||
void setAllActivitiesFromReply(QDBusPendingCallWatcher *watcher);
|
||||
void setCurrentActivityFromReply(QDBusPendingCallWatcher *watcher);
|
||||
|
||||
void setActivityName(const QString &id, const QString &name);
|
||||
void setActivityDescription(const QString &id, const QString &description);
|
||||
void setActivityIcon(const QString &id, const QString &icon);
|
||||
|
||||
void setActivityInfo(const ActivityInfo &info);
|
||||
void setAllActivities(const ActivityInfoList &activities);
|
||||
void setCurrentActivity(const QString &activity);
|
||||
|
||||
void setServiceStatus(Manager::ServiceStatus status);
|
||||
|
||||
public:
|
||||
template<typename _Result, typename _Functor>
|
||||
void passInfoFromReply(QDBusPendingCallWatcher *watcher, _Functor f);
|
||||
|
||||
static bool infoLessThan(const ActivityInfo &info, const ActivityInfo &other)
|
||||
{
|
||||
const auto comp = QString::compare(info.name, other.name, Qt::CaseInsensitive);
|
||||
return comp < 0 || (comp == 0 && info.id < other.id);
|
||||
}
|
||||
|
||||
ActivityInfoList::iterator find(const QString &id)
|
||||
{
|
||||
return std::find_if(m_activities.begin(), m_activities.end(), [&id](const ActivityInfo &info) {
|
||||
return info.id == id;
|
||||
});
|
||||
}
|
||||
|
||||
ActivityInfoList::iterator lower_bound(const ActivityInfo &info)
|
||||
{
|
||||
return std::lower_bound(m_activities.begin(), m_activities.end(), info, &infoLessThan);
|
||||
}
|
||||
|
||||
template<int Policy = kamd::utils::Const>
|
||||
inline typename kamd::utils::ptr_to<ActivityInfo, Policy>::type getInfo(const QString &id)
|
||||
{
|
||||
const auto where = find(id);
|
||||
|
||||
if (where != m_activities.end()) {
|
||||
return &(*where);
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
template<typename TargetSlot>
|
||||
void onCallFinished(QDBusPendingCall &call, TargetSlot slot)
|
||||
{
|
||||
auto watcher = new QDBusPendingCallWatcher(call, this);
|
||||
|
||||
connect(watcher, SIGNAL(finished(QDBusPendingCallWatcher *)), this, slot);
|
||||
}
|
||||
|
||||
ActivitiesCache();
|
||||
|
||||
QList<ActivityInfo> m_activities;
|
||||
QString m_currentActivity;
|
||||
Consumer::ServiceStatus m_status;
|
||||
};
|
||||
|
||||
} // namespace KActivities
|
||||
|
||||
#endif /* ACTIVITIES_CACHE_P_H */
|
||||
@@ -0,0 +1,329 @@
|
||||
/*
|
||||
SPDX-FileCopyrightText: 2012-2016 Ivan Cukic <ivan.cukic(at)kde.org>
|
||||
|
||||
SPDX-License-Identifier: GPL-2.0-or-later
|
||||
*/
|
||||
|
||||
// Self
|
||||
#include "activitiesmodel.h"
|
||||
#include "activitiesmodel_p.h"
|
||||
|
||||
// Qt
|
||||
#include <QByteArray>
|
||||
#include <QDBusPendingCall>
|
||||
#include <QDBusPendingCallWatcher>
|
||||
#include <QDebug>
|
||||
#include <QFutureWatcher>
|
||||
#include <QHash>
|
||||
#include <QModelIndex>
|
||||
|
||||
namespace KActivities
|
||||
{
|
||||
namespace Private
|
||||
{
|
||||
template<typename _Container>
|
||||
struct ActivityPosition {
|
||||
ActivityPosition()
|
||||
: isValid(false)
|
||||
, index(0)
|
||||
, iterator()
|
||||
{
|
||||
}
|
||||
|
||||
ActivityPosition(unsigned int index, typename _Container::const_iterator iterator)
|
||||
: isValid(true)
|
||||
, index(index)
|
||||
, iterator(iterator)
|
||||
{
|
||||
}
|
||||
|
||||
operator bool() const
|
||||
{
|
||||
return isValid;
|
||||
}
|
||||
|
||||
const bool isValid;
|
||||
const unsigned int index;
|
||||
const typename _Container::const_iterator iterator;
|
||||
|
||||
typedef typename _Container::value_type ContainerElement;
|
||||
};
|
||||
|
||||
/**
|
||||
* Searches for the activity.
|
||||
* Returns an option(index, iterator) for the found activity.
|
||||
*/
|
||||
template<typename _Container>
|
||||
inline ActivityPosition<_Container> activityPosition(const _Container &container, const QString &activityId)
|
||||
{
|
||||
auto position = std::find_if(container.begin(), container.end(), [&](const typename ActivityPosition<_Container>::ContainerElement &activity) {
|
||||
return activity->id() == activityId;
|
||||
});
|
||||
|
||||
return (position != container.end()) ? ActivityPosition<_Container>(position - container.begin(), position) : ActivityPosition<_Container>();
|
||||
}
|
||||
|
||||
/**
|
||||
* Notifies the model that an activity was updated
|
||||
*/
|
||||
template<typename _Model, typename _Container>
|
||||
inline void emitActivityUpdated(_Model *model, const _Container &container, const QString &activity, int role)
|
||||
{
|
||||
auto position = Private::activityPosition(container, activity);
|
||||
|
||||
if (position) {
|
||||
Q_EMIT model->q->dataChanged(model->q->index(position.index),
|
||||
model->q->index(position.index),
|
||||
role == Qt::DecorationRole ? QList<int>{role, ActivitiesModel::ActivityIconSource} : QList<int>{role});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Notifies the model that an activity was updated
|
||||
*/
|
||||
template<typename _Model, typename _Container>
|
||||
inline void emitActivityUpdated(_Model *model, const _Container &container, QObject *activityInfo, int role)
|
||||
{
|
||||
const auto activity = static_cast<Info *>(activityInfo);
|
||||
emitActivityUpdated(model, container, activity->id(), role);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
ActivitiesModelPrivate::ActivitiesModelPrivate(ActivitiesModel *parent)
|
||||
: q(parent)
|
||||
{
|
||||
}
|
||||
|
||||
ActivitiesModel::ActivitiesModel(QObject *parent)
|
||||
: QAbstractListModel(parent)
|
||||
, d(new ActivitiesModelPrivate(this))
|
||||
{
|
||||
// Initializing role names for qml
|
||||
connect(&d->activities, &Consumer::serviceStatusChanged, this, [this](Consumer::ServiceStatus status) {
|
||||
d->setServiceStatus(status);
|
||||
});
|
||||
|
||||
connect(&d->activities, &Consumer::activityAdded, this, [this](const QString &activity) {
|
||||
d->onActivityAdded(activity);
|
||||
});
|
||||
connect(&d->activities, &Consumer::activityRemoved, this, [this](const QString &activity) {
|
||||
d->onActivityRemoved(activity);
|
||||
});
|
||||
connect(&d->activities, &Consumer::currentActivityChanged, this, [this](const QString &activity) {
|
||||
d->onCurrentActivityChanged(activity);
|
||||
});
|
||||
|
||||
d->setServiceStatus(d->activities.serviceStatus());
|
||||
}
|
||||
|
||||
ActivitiesModel::~ActivitiesModel() = default;
|
||||
|
||||
QHash<int, QByteArray> ActivitiesModel::roleNames() const
|
||||
{
|
||||
return {{ActivityName, "name"},
|
||||
{ActivityId, "id"},
|
||||
{ActivityIconSource, "iconSource"},
|
||||
{ActivityDescription, "description"},
|
||||
{ActivityBackground, "background"},
|
||||
{ActivityIsCurrent, "isCurrent"}};
|
||||
}
|
||||
|
||||
void ActivitiesModelPrivate::setServiceStatus(Consumer::ServiceStatus)
|
||||
{
|
||||
replaceActivities(activities.activities());
|
||||
}
|
||||
|
||||
void ActivitiesModelPrivate::replaceActivities(const QStringList &activities)
|
||||
{
|
||||
q->beginResetModel();
|
||||
|
||||
knownActivities.clear();
|
||||
shownActivities.clear();
|
||||
|
||||
for (const QString &activity : activities) {
|
||||
onActivityAdded(activity, false);
|
||||
}
|
||||
|
||||
q->endResetModel();
|
||||
}
|
||||
|
||||
void ActivitiesModelPrivate::onActivityAdded(const QString &id, bool notifyClients)
|
||||
{
|
||||
auto info = registerActivity(id);
|
||||
|
||||
showActivity(info, notifyClients);
|
||||
}
|
||||
|
||||
void ActivitiesModelPrivate::onActivityRemoved(const QString &id)
|
||||
{
|
||||
hideActivity(id);
|
||||
unregisterActivity(id);
|
||||
}
|
||||
|
||||
void ActivitiesModelPrivate::onCurrentActivityChanged(const QString &id)
|
||||
{
|
||||
Q_UNUSED(id);
|
||||
|
||||
for (const auto &activity : shownActivities) {
|
||||
Private::emitActivityUpdated(this, shownActivities, activity->id(), ActivitiesModel::ActivityIsCurrent);
|
||||
}
|
||||
}
|
||||
|
||||
ActivitiesModelPrivate::InfoPtr ActivitiesModelPrivate::registerActivity(const QString &id)
|
||||
{
|
||||
auto position = Private::activityPosition(knownActivities, id);
|
||||
|
||||
if (position) {
|
||||
return *(position.iterator);
|
||||
|
||||
} else {
|
||||
auto activityInfo = std::make_shared<Info>(id);
|
||||
|
||||
auto ptr = activityInfo.get();
|
||||
|
||||
connect(ptr, &Info::nameChanged, this, &ActivitiesModelPrivate::onActivityNameChanged);
|
||||
connect(ptr, &Info::descriptionChanged, this, &ActivitiesModelPrivate::onActivityDescriptionChanged);
|
||||
connect(ptr, &Info::iconChanged, this, &ActivitiesModelPrivate::onActivityIconChanged);
|
||||
|
||||
knownActivities.insert(InfoPtr(activityInfo));
|
||||
|
||||
return activityInfo;
|
||||
}
|
||||
}
|
||||
|
||||
void ActivitiesModelPrivate::unregisterActivity(const QString &id)
|
||||
{
|
||||
auto position = Private::activityPosition(knownActivities, id);
|
||||
|
||||
if (position) {
|
||||
if (auto shown = Private::activityPosition(shownActivities, id)) {
|
||||
q->beginRemoveRows(QModelIndex(), shown.index, shown.index);
|
||||
shownActivities.removeAt(shown.index);
|
||||
q->endRemoveRows();
|
||||
}
|
||||
|
||||
knownActivities.removeAt(position.index);
|
||||
}
|
||||
}
|
||||
|
||||
void ActivitiesModelPrivate::showActivity(InfoPtr activityInfo, bool notifyClients)
|
||||
{
|
||||
// Is it already shown?
|
||||
if (std::binary_search(shownActivities.cbegin(), shownActivities.cend(), activityInfo, InfoPtrComparator())) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto registeredPosition = Private::activityPosition(knownActivities, activityInfo->id());
|
||||
|
||||
if (!registeredPosition) {
|
||||
qDebug() << "Got a request to show an unknown activity, ignoring";
|
||||
return;
|
||||
}
|
||||
|
||||
const auto activityInfoPtr = *(registeredPosition.iterator);
|
||||
|
||||
// In C++17, this would be:
|
||||
// const auto [iterator, index, found] = shownActivities.insert(...);
|
||||
const auto _result = shownActivities.insert(activityInfoPtr);
|
||||
// const auto iterator = std::get<0>(_result);
|
||||
const auto index = _result.insertedIndex;
|
||||
|
||||
if (notifyClients) {
|
||||
q->beginInsertRows(QModelIndex(), index, index);
|
||||
q->endInsertRows();
|
||||
}
|
||||
}
|
||||
|
||||
void ActivitiesModelPrivate::hideActivity(const QString &id)
|
||||
{
|
||||
auto position = Private::activityPosition(shownActivities, id);
|
||||
|
||||
if (position) {
|
||||
q->beginRemoveRows(QModelIndex(), position.index, position.index);
|
||||
shownActivities.removeAt(position.index);
|
||||
q->endRemoveRows();
|
||||
}
|
||||
}
|
||||
|
||||
// clang-format off
|
||||
#define CREATE_SIGNAL_EMITTER(What,Role) \
|
||||
void ActivitiesModelPrivate::onActivity##What##Changed(const QString &) \
|
||||
{ \
|
||||
Private::emitActivityUpdated(this, shownActivities, sender(), Role); \
|
||||
}
|
||||
// clang-format on
|
||||
|
||||
CREATE_SIGNAL_EMITTER(Name, Qt::DisplayRole)
|
||||
CREATE_SIGNAL_EMITTER(Description, ActivitiesModel::ActivityDescription)
|
||||
CREATE_SIGNAL_EMITTER(Icon, Qt::DecorationRole)
|
||||
|
||||
#undef CREATE_SIGNAL_EMITTER
|
||||
|
||||
int ActivitiesModel::rowCount(const QModelIndex &parent) const
|
||||
{
|
||||
if (parent.isValid()) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return d->shownActivities.size();
|
||||
}
|
||||
|
||||
QVariant ActivitiesModel::data(const QModelIndex &index, int role) const
|
||||
{
|
||||
const int row = index.row();
|
||||
const auto &item = d->shownActivities.at(row);
|
||||
|
||||
switch (role) {
|
||||
case Qt::DisplayRole:
|
||||
case ActivityName:
|
||||
return item->name();
|
||||
|
||||
case ActivityId:
|
||||
return item->id();
|
||||
|
||||
case Qt::DecorationRole:
|
||||
case ActivityIconSource: {
|
||||
const QString &icon = item->icon();
|
||||
|
||||
// We need a default icon for activities
|
||||
return icon.isEmpty() ? QStringLiteral("activities") : icon;
|
||||
}
|
||||
|
||||
case ActivityDescription:
|
||||
return item->description();
|
||||
|
||||
case ActivityIsCurrent:
|
||||
return d->activities.currentActivity() == item->id();
|
||||
|
||||
default:
|
||||
return QVariant();
|
||||
}
|
||||
}
|
||||
|
||||
QVariant ActivitiesModel::headerData(int section, Qt::Orientation orientation, int role) const
|
||||
{
|
||||
Q_UNUSED(section);
|
||||
Q_UNUSED(orientation);
|
||||
Q_UNUSED(role);
|
||||
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
ActivitiesModelPrivate::InfoPtr ActivitiesModelPrivate::findActivity(QObject *ptr) const
|
||||
{
|
||||
auto info = std::find_if(knownActivities.cbegin(), knownActivities.cend(), [ptr](const InfoPtr &info) {
|
||||
return ptr == info.get();
|
||||
});
|
||||
|
||||
if (info == knownActivities.end()) {
|
||||
return nullptr;
|
||||
} else {
|
||||
return *info;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace KActivities
|
||||
|
||||
#include "moc_activitiesmodel.cpp"
|
||||
#include "moc_activitiesmodel_p.cpp"
|
||||
@@ -0,0 +1,81 @@
|
||||
/*
|
||||
SPDX-FileCopyrightText: 2012, 2013, 2014 Ivan Cukic <ivan.cukic(at)kde.org>
|
||||
|
||||
SPDX-License-Identifier: GPL-2.0-or-later
|
||||
*/
|
||||
|
||||
#ifndef ACTIVITIES_ACTIVITIESMODEL_H
|
||||
#define ACTIVITIES_ACTIVITIESMODEL_H
|
||||
|
||||
// Qt
|
||||
#include <QAbstractListModel>
|
||||
#include <QObject>
|
||||
|
||||
// STL
|
||||
#include <memory>
|
||||
|
||||
// Local
|
||||
#include "info.h"
|
||||
|
||||
class QModelIndex;
|
||||
class QDBusPendingCallWatcher;
|
||||
|
||||
namespace KActivities
|
||||
{
|
||||
class ActivitiesModelPrivate;
|
||||
|
||||
/*!
|
||||
* \class KActivities::ActivitiesModel
|
||||
* \inmodule PlasmaActivities
|
||||
* \inheaderfile PlasmaActivities/ActivitiesModel
|
||||
*
|
||||
* \brief Data model that shows existing activities.
|
||||
*/
|
||||
class PLASMA_ACTIVITIES_EXPORT ActivitiesModel : public QAbstractListModel
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
/*!
|
||||
*
|
||||
*/
|
||||
explicit ActivitiesModel(QObject *parent = nullptr);
|
||||
|
||||
~ActivitiesModel() override;
|
||||
|
||||
int rowCount(const QModelIndex &parent = QModelIndex()) const override;
|
||||
|
||||
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
|
||||
|
||||
QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override;
|
||||
|
||||
QHash<int, QByteArray> roleNames() const override;
|
||||
|
||||
/*!
|
||||
* \value ActivityId UUID of the activity
|
||||
* \value ActivityName Activity name
|
||||
* \value ActivityDescription Activity description
|
||||
* \value ActivityIconSource Activity icon source name
|
||||
* \value ActivityBackground Activity wallpaper (currently unsupported)
|
||||
* \value ActivityIsCurrent Is this activity the current one current
|
||||
* \value UserRole To be used by models that inherit this one
|
||||
*/
|
||||
enum Roles {
|
||||
ActivityId = Qt::UserRole,
|
||||
ActivityName = Qt::UserRole + 1,
|
||||
ActivityDescription = Qt::UserRole + 2,
|
||||
ActivityIconSource = Qt::UserRole + 3,
|
||||
ActivityBackground = Qt::UserRole + 5,
|
||||
ActivityIsCurrent = Qt::UserRole + 6,
|
||||
|
||||
UserRole = Qt::UserRole + 32,
|
||||
};
|
||||
|
||||
private:
|
||||
friend class ActivitiesModelPrivate;
|
||||
const std::unique_ptr<ActivitiesModelPrivate> d;
|
||||
};
|
||||
|
||||
} // namespace KActivities
|
||||
|
||||
#endif // ACTIVITIES_ACTIVITIESMODEL_H
|
||||
@@ -0,0 +1,73 @@
|
||||
/*
|
||||
SPDX-FileCopyrightText: 2016 Ivan Čukić <ivan.cukic(at)kde.org>
|
||||
|
||||
SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
|
||||
*/
|
||||
|
||||
#ifndef ACTIVITIES_ACTIVITIESMODEL_P_H
|
||||
#define ACTIVITIES_ACTIVITIESMODEL_P_H
|
||||
|
||||
#include "activitiesmodel.h"
|
||||
|
||||
#include "consumer.h"
|
||||
|
||||
#include "utils/qflatset.h"
|
||||
|
||||
#include <QCollator>
|
||||
|
||||
namespace KActivities
|
||||
{
|
||||
class ActivitiesModelPrivate : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
ActivitiesModelPrivate(ActivitiesModel *parent);
|
||||
|
||||
public Q_SLOTS:
|
||||
void onActivityNameChanged(const QString &name);
|
||||
void onActivityDescriptionChanged(const QString &description);
|
||||
void onActivityIconChanged(const QString &icon);
|
||||
|
||||
void replaceActivities(const QStringList &activities);
|
||||
void onActivityAdded(const QString &id, bool notifyClients = true);
|
||||
void onActivityRemoved(const QString &id);
|
||||
void onCurrentActivityChanged(const QString &id);
|
||||
|
||||
void setServiceStatus(KActivities::Consumer::ServiceStatus status);
|
||||
|
||||
public:
|
||||
KActivities::Consumer activities;
|
||||
|
||||
typedef std::shared_ptr<Info> InfoPtr;
|
||||
|
||||
struct InfoPtrComparator {
|
||||
bool operator()(const InfoPtr &left, const InfoPtr &right) const
|
||||
{
|
||||
QCollator c;
|
||||
c.setCaseSensitivity(Qt::CaseInsensitive);
|
||||
c.setNumericMode(true);
|
||||
int rc = c.compare(left->name(), right->name());
|
||||
if (rc == 0) {
|
||||
return left->id() < right->id();
|
||||
}
|
||||
return rc < 0;
|
||||
}
|
||||
};
|
||||
|
||||
QFlatSet<InfoPtr, InfoPtrComparator> knownActivities;
|
||||
QFlatSet<InfoPtr, InfoPtrComparator> shownActivities;
|
||||
|
||||
InfoPtr registerActivity(const QString &id);
|
||||
void unregisterActivity(const QString &id);
|
||||
void showActivity(InfoPtr activityInfo, bool notifyClients);
|
||||
void hideActivity(const QString &id);
|
||||
void backgroundsUpdated(const QStringList &activities);
|
||||
|
||||
InfoPtr findActivity(QObject *ptr) const;
|
||||
|
||||
ActivitiesModel *const q;
|
||||
};
|
||||
|
||||
} // namespace KActivities
|
||||
|
||||
#endif // ACTIVITIES_ACTIVITIESMODEL_P_H
|
||||
@@ -0,0 +1,65 @@
|
||||
/*
|
||||
SPDX-FileCopyrightText: 2010-2016 Ivan Cukic <ivan.cukic(at)kde.org>
|
||||
|
||||
SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
|
||||
*/
|
||||
|
||||
#include "consumer.h"
|
||||
#include "consumer_p.h"
|
||||
#include "manager_p.h"
|
||||
|
||||
namespace KActivities
|
||||
{
|
||||
ConsumerPrivate::ConsumerPrivate()
|
||||
: cache(ActivitiesCache::self())
|
||||
{
|
||||
}
|
||||
|
||||
void ConsumerPrivate::setServiceStatus(Consumer::ServiceStatus status)
|
||||
{
|
||||
Q_EMIT serviceStatusChanged(status);
|
||||
}
|
||||
|
||||
Consumer::Consumer(QObject *parent)
|
||||
: QObject(parent)
|
||||
, d(new ConsumerPrivate())
|
||||
{
|
||||
connect(d->cache.get(), &KActivities::ActivitiesCache::currentActivityChanged, this, &Consumer::currentActivityChanged);
|
||||
connect(d->cache.get(), &KActivities::ActivitiesCache::activityAdded, this, &Consumer::activityAdded);
|
||||
connect(d->cache.get(), &KActivities::ActivitiesCache::activityRemoved, this, &Consumer::activityRemoved);
|
||||
connect(d->cache.get(), &KActivities::ActivitiesCache::serviceStatusChanged, this, &Consumer::serviceStatusChanged);
|
||||
|
||||
connect(d->cache.get(), &ActivitiesCache::activityListChanged, this, [=, this]() {
|
||||
Q_EMIT activitiesChanged(activities());
|
||||
});
|
||||
}
|
||||
|
||||
Consumer::~Consumer() = default;
|
||||
|
||||
QString Consumer::currentActivity() const
|
||||
{
|
||||
return d->cache->m_currentActivity;
|
||||
}
|
||||
|
||||
QStringList Consumer::activities() const
|
||||
{
|
||||
QStringList result;
|
||||
|
||||
result.reserve(d->cache->m_activities.size());
|
||||
|
||||
for (const auto &info : std::as_const(d->cache->m_activities)) {
|
||||
result << info.id;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
Consumer::ServiceStatus Consumer::serviceStatus()
|
||||
{
|
||||
return d->cache->m_status;
|
||||
}
|
||||
|
||||
} // namespace KActivities
|
||||
|
||||
#include "moc_consumer.cpp"
|
||||
#include "moc_consumer_p.cpp"
|
||||
@@ -0,0 +1,174 @@
|
||||
/*
|
||||
SPDX-FileCopyrightText: 2010-2016 Ivan Cukic <ivan.cukic(at)kde.org>
|
||||
|
||||
SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
|
||||
*/
|
||||
|
||||
#ifndef ACTIVITIES_CONSUMER_H
|
||||
#define ACTIVITIES_CONSUMER_H
|
||||
|
||||
#include <QObject>
|
||||
#include <QString>
|
||||
#include <QStringList>
|
||||
|
||||
#include "info.h"
|
||||
|
||||
#include "plasma_activities_export.h"
|
||||
|
||||
#include <memory>
|
||||
|
||||
namespace KActivities
|
||||
{
|
||||
class ConsumerPrivate;
|
||||
|
||||
/*!
|
||||
* \class KActivities::Consumer
|
||||
* \inmodule PlasmaActivities
|
||||
* \inheaderfile PlasmaActivities/Consumer
|
||||
*
|
||||
* \brief Read-only information about activities.
|
||||
*
|
||||
* Contextual information can be, from the user's point of view, divided
|
||||
* into three aspects - "who am I?", "where am I?" (what are my surroundings?)
|
||||
* and "what am I doing?".
|
||||
*
|
||||
* Activities deal with the last one - "what am I doing?". The current activity
|
||||
* refers to what the user is doing at the moment, while the other activities
|
||||
* represent things that he/she was doing before, and probably will be doing
|
||||
* again.
|
||||
*
|
||||
* Activity is an abstract concept whose meaning can differ from one user to
|
||||
* another. Typical examples of activities are "developing a KDE project",
|
||||
* "studying the 19th century art", "composing music", "lazing on a Sunday
|
||||
* afternoon" etc.
|
||||
*
|
||||
* Consumer provides read-only information about activities.
|
||||
*
|
||||
* Before relying on the values retrieved by the class, make sure that the
|
||||
* serviceStatus is set to Running. Otherwise, you can get invalid data either
|
||||
* because the service is not functioning properly (or at all) or because
|
||||
* the class did not have enough time to synchronize the data with it.
|
||||
*
|
||||
* For example, if this is the only existing instance of the Consumer class,
|
||||
* the listActivities method will return an empty list.
|
||||
*
|
||||
* \code
|
||||
* void someMethod() {
|
||||
* // Do not copy. This approach is not a good one!
|
||||
* Consumer c;
|
||||
* doSomethingWith(c.listActivities());
|
||||
* }
|
||||
* \endcode
|
||||
*
|
||||
* Instances of the Consumer class should be long-lived. For example, members
|
||||
* of the classes that use them, and you should listen for the changes in the
|
||||
* provided properties.
|
||||
*
|
||||
* \since 4.5
|
||||
*/
|
||||
class PLASMA_ACTIVITIES_EXPORT Consumer : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
/*!
|
||||
* \property KActivities::Consumer::currentActivity
|
||||
*/
|
||||
Q_PROPERTY(QString currentActivity READ currentActivity NOTIFY currentActivityChanged)
|
||||
|
||||
/*!
|
||||
* \property KActivities::Consumer::activities
|
||||
*/
|
||||
Q_PROPERTY(QStringList activities READ activities NOTIFY activitiesChanged)
|
||||
|
||||
/*!
|
||||
* \property KActivities::Consumer::serviceStatus
|
||||
*/
|
||||
Q_PROPERTY(ServiceStatus serviceStatus READ serviceStatus NOTIFY serviceStatusChanged)
|
||||
|
||||
public:
|
||||
/*!
|
||||
* Different states of the activities service
|
||||
*
|
||||
* \value NotRunning Service is not running
|
||||
* \value Unknown Unable to determine the status of the service
|
||||
* \value Running Service is running properly
|
||||
*/
|
||||
enum ServiceStatus {
|
||||
NotRunning,
|
||||
Unknown,
|
||||
Running,
|
||||
};
|
||||
|
||||
/*!
|
||||
*
|
||||
*/
|
||||
explicit Consumer(QObject *parent = nullptr);
|
||||
|
||||
~Consumer() override;
|
||||
|
||||
/*!
|
||||
* Returns the id of the current activity
|
||||
*
|
||||
* \note Activity ID is a UUID-formatted string. If the serviceStatus
|
||||
* is not Running, a null UUID is returned. The ID can also be an empty
|
||||
* string in the case there is no current activity.
|
||||
*/
|
||||
QString currentActivity() const;
|
||||
|
||||
/*!
|
||||
* Returns the list of all existing activities
|
||||
*
|
||||
* \note If the serviceStatus is not Running, only a null activity will be
|
||||
* returned.
|
||||
*/
|
||||
QStringList activities() const;
|
||||
|
||||
/*!
|
||||
* Returns status of the activities service
|
||||
*/
|
||||
ServiceStatus serviceStatus();
|
||||
|
||||
Q_SIGNALS:
|
||||
/*!
|
||||
* This signal is emitted when the current activity is changed
|
||||
*
|
||||
* \a id id of the new current activity
|
||||
*/
|
||||
void currentActivityChanged(const QString &id);
|
||||
|
||||
/*!
|
||||
* This signal is emitted when the activity service goes online or offline,
|
||||
* or when the class manages to synchronize the data with the service.
|
||||
*
|
||||
* \a status new status of the service
|
||||
*/
|
||||
void serviceStatusChanged(Consumer::ServiceStatus status);
|
||||
|
||||
/*!
|
||||
* This signal is emitted when a new activity is added
|
||||
*
|
||||
* \a id id of the new activity
|
||||
*/
|
||||
void activityAdded(const QString &id);
|
||||
|
||||
/*!
|
||||
* This signal is emitted when an activity has been removed
|
||||
*
|
||||
* \a id id of the removed activity
|
||||
*/
|
||||
void activityRemoved(const QString &id);
|
||||
|
||||
/*!
|
||||
* This signal is emitted when the activity list changes
|
||||
*
|
||||
* \a activities list of activities
|
||||
*/
|
||||
void activitiesChanged(const QStringList &activities);
|
||||
|
||||
private:
|
||||
const std::unique_ptr<ConsumerPrivate> d;
|
||||
};
|
||||
|
||||
} // namespace KActivities
|
||||
|
||||
#endif // ACTIVITIES_CONSUMER_H
|
||||
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
SPDX-FileCopyrightText: 2010-2016 Ivan Cukic <ivan.cukic(at)kde.org>
|
||||
|
||||
SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
|
||||
*/
|
||||
|
||||
#ifndef ACTIVITIES_CONSUMER_P_H
|
||||
#define ACTIVITIES_CONSUMER_P_H
|
||||
|
||||
#include "consumer.h"
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include "activitiescache_p.h"
|
||||
|
||||
namespace KActivities
|
||||
{
|
||||
class ConsumerPrivate : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
ConsumerPrivate();
|
||||
|
||||
std::shared_ptr<ActivitiesCache> cache;
|
||||
|
||||
public Q_SLOTS:
|
||||
void setServiceStatus(Consumer::ServiceStatus status);
|
||||
|
||||
Q_SIGNALS:
|
||||
void serviceStatusChanged(Consumer::ServiceStatus status);
|
||||
};
|
||||
|
||||
} // namespace KActivities
|
||||
|
||||
#endif // ACTIVITIES_CONSUMER_P_H
|
||||
@@ -0,0 +1,85 @@
|
||||
/*
|
||||
SPDX-FileCopyrightText: 2010-2016 Ivan Cukic <ivan.cukic(at)kde.org>
|
||||
|
||||
SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
|
||||
*/
|
||||
|
||||
#include "controller.h"
|
||||
#include "consumer_p.h"
|
||||
#include "manager_p.h"
|
||||
|
||||
#include "utils/dbusfuture_p.h"
|
||||
|
||||
namespace KActivities
|
||||
{
|
||||
class ControllerPrivate
|
||||
{
|
||||
};
|
||||
|
||||
Controller::Controller(QObject *parent)
|
||||
: Consumer(parent)
|
||||
{
|
||||
}
|
||||
|
||||
Controller::~Controller() = default;
|
||||
|
||||
// clang-format off
|
||||
#define CREATE_SETTER(What) \
|
||||
QFuture<void> Controller::setActivity##What(const QString &id, \
|
||||
const QString &value) \
|
||||
{ \
|
||||
return Manager::isServiceRunning() \
|
||||
? DBusFuture::asyncCall<void>( \
|
||||
Manager::activities(), \
|
||||
QString::fromLatin1("SetActivity" #What), id, value) \
|
||||
: DBusFuture::fromVoid(); \
|
||||
}
|
||||
// clang-format on
|
||||
|
||||
CREATE_SETTER(Name)
|
||||
CREATE_SETTER(Description)
|
||||
CREATE_SETTER(Icon)
|
||||
|
||||
#undef CREATE_SETTER
|
||||
|
||||
QFuture<bool> Controller::setCurrentActivity(const QString &id)
|
||||
{
|
||||
// Q_ASSERT_X(activities().contains(id), "Controller::setCurrentActivity",
|
||||
// "You can not set a non-existent activity to be the current");
|
||||
|
||||
// return Manager::activities()->SetCurrentActivity(id);
|
||||
return Manager::isServiceRunning() ? DBusFuture::asyncCall<bool>(Manager::activities(), QStringLiteral("SetCurrentActivity"), id)
|
||||
: DBusFuture::fromValue(false);
|
||||
}
|
||||
|
||||
QFuture<QString> Controller::addActivity(const QString &name)
|
||||
{
|
||||
Q_ASSERT_X(!name.isEmpty(), "Controller::addActivity", "The activity name can not be an empty string");
|
||||
|
||||
// return Manager::activities()->AddActivity(name);
|
||||
return Manager::isServiceRunning() ? DBusFuture::asyncCall<QString>(Manager::activities(), QStringLiteral("AddActivity"), name)
|
||||
: DBusFuture::fromValue(QString());
|
||||
}
|
||||
|
||||
QFuture<void> Controller::removeActivity(const QString &id)
|
||||
{
|
||||
// Q_ASSERT_X(activities().contains(id), "Controller::removeActivity",
|
||||
// "You can not remove a non-existent activity");
|
||||
|
||||
// Manager::activities()->RemoveActivity(id);
|
||||
return Manager::isServiceRunning() ? DBusFuture::asyncCall<void>(Manager::activities(), QStringLiteral("RemoveActivity"), id) : DBusFuture::fromVoid();
|
||||
}
|
||||
|
||||
QFuture<void> Controller::previousActivity()
|
||||
{
|
||||
return Manager::isServiceRunning() ? DBusFuture::asyncCall<void>(Manager::activities(), QStringLiteral("PreviousActivity")) : DBusFuture::fromVoid();
|
||||
}
|
||||
|
||||
QFuture<void> Controller::nextActivity()
|
||||
{
|
||||
return Manager::isServiceRunning() ? DBusFuture::asyncCall<void>(Manager::activities(), QStringLiteral("NextActivity")) : DBusFuture::fromVoid();
|
||||
}
|
||||
|
||||
} // namespace KActivities
|
||||
|
||||
#include "moc_controller.cpp"
|
||||
@@ -0,0 +1,124 @@
|
||||
/*
|
||||
SPDX-FileCopyrightText: 2010-2016 Ivan Cukic <ivan.cukic(at)kde.org>
|
||||
|
||||
SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
|
||||
*/
|
||||
|
||||
#ifndef ACTIVITIES_CONTROLLER_H
|
||||
#define ACTIVITIES_CONTROLLER_H
|
||||
|
||||
#include <QFuture>
|
||||
#include <QObject>
|
||||
#include <QString>
|
||||
|
||||
#include "consumer.h"
|
||||
|
||||
#include "plasma_activities_export.h"
|
||||
|
||||
#include <memory>
|
||||
|
||||
namespace KActivities
|
||||
{
|
||||
class ControllerPrivate;
|
||||
|
||||
/*!
|
||||
* \class KActivities::Controller
|
||||
* \inmodule PlasmaActivities
|
||||
* \inheaderfile PlasmaActivities/Controller
|
||||
*
|
||||
* \brief Methods for controlling and managing
|
||||
* the activities.
|
||||
*
|
||||
* \note The QFuture objects returned by these methods are not thread-based,
|
||||
* you can not call synchronous methods like waitForFinished, cancel, pause on
|
||||
* them. You need either to register watchers to check when those have finished,
|
||||
* or to check whether they are ready from time to time manually.
|
||||
*
|
||||
* \since 5.0
|
||||
*/
|
||||
class PLASMA_ACTIVITIES_EXPORT Controller : public Consumer
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
/*!
|
||||
* \property KActivities::Controller::currentActivity
|
||||
*/
|
||||
Q_PROPERTY(QString currentActivity READ currentActivity WRITE setCurrentActivity)
|
||||
|
||||
public:
|
||||
/*!
|
||||
*
|
||||
*/
|
||||
explicit Controller(QObject *parent = nullptr);
|
||||
|
||||
~Controller() override;
|
||||
|
||||
/*!
|
||||
* Sets the name of the specified activity
|
||||
*
|
||||
* \a id id of the activity
|
||||
*
|
||||
* \a name name to be set
|
||||
*/
|
||||
QFuture<void> setActivityName(const QString &id, const QString &name);
|
||||
|
||||
/*!
|
||||
* Sets the description of the specified activity
|
||||
*
|
||||
* \a id id of the activity
|
||||
*
|
||||
* \a description description to be set
|
||||
*/
|
||||
QFuture<void> setActivityDescription(const QString &id, const QString &description);
|
||||
|
||||
/*!
|
||||
* Sets the icon of the specified activity
|
||||
*
|
||||
* \a id id of the activity
|
||||
*
|
||||
* \a icon icon to be set - freedesktop.org name or file path
|
||||
*/
|
||||
QFuture<void> setActivityIcon(const QString &id, const QString &icon);
|
||||
|
||||
/*!
|
||||
* Sets the current activity
|
||||
*
|
||||
* \a id id of the activity to make current
|
||||
*
|
||||
* Returns \c true if successful
|
||||
*/
|
||||
QFuture<bool> setCurrentActivity(const QString &id);
|
||||
|
||||
/*!
|
||||
* Adds a new activity
|
||||
*
|
||||
* \a name name of the activity
|
||||
*
|
||||
* Returns the id of the newly created activity
|
||||
*/
|
||||
QFuture<QString> addActivity(const QString &name);
|
||||
|
||||
/*!
|
||||
* Removes the specified activity
|
||||
*
|
||||
* \a id id of the activity to delete
|
||||
*/
|
||||
QFuture<void> removeActivity(const QString &id);
|
||||
|
||||
/*!
|
||||
* Switches to the previous activity
|
||||
*/
|
||||
QFuture<void> previousActivity();
|
||||
|
||||
/*!
|
||||
* Switches to the next activity
|
||||
*/
|
||||
QFuture<void> nextActivity();
|
||||
|
||||
private:
|
||||
const std::unique_ptr<ControllerPrivate> d;
|
||||
};
|
||||
|
||||
} // namespace KActivities
|
||||
|
||||
#endif // ACTIVITIES_CONTROLLER_H
|
||||
@@ -0,0 +1,155 @@
|
||||
/*
|
||||
SPDX-FileCopyrightText: 2010-2016 Ivan Cukic <ivan.cukic(at)kde.org>
|
||||
|
||||
SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
|
||||
*/
|
||||
|
||||
#include "info.h"
|
||||
#include "info_p.h"
|
||||
#include "manager_p.h"
|
||||
|
||||
#include "utils/dbusfuture_p.h"
|
||||
|
||||
#include <QFileSystemWatcher>
|
||||
|
||||
namespace KActivities
|
||||
{
|
||||
// InfoPrivate
|
||||
|
||||
InfoPrivate::InfoPrivate(Info *info, const QString &activity)
|
||||
: q(info)
|
||||
, cache(ActivitiesCache::self())
|
||||
, id(activity)
|
||||
{
|
||||
}
|
||||
|
||||
// clang-format off
|
||||
// Filters out signals for only this activity
|
||||
#define IMPLEMENT_SIGNAL_HANDLER(INTERNAL) \
|
||||
void InfoPrivate::INTERNAL(const QString &_id) const \
|
||||
{ if (id == _id) Q_EMIT q->INTERNAL(); }
|
||||
|
||||
IMPLEMENT_SIGNAL_HANDLER(added)
|
||||
IMPLEMENT_SIGNAL_HANDLER(removed)
|
||||
IMPLEMENT_SIGNAL_HANDLER(infoChanged)
|
||||
|
||||
#undef IMPLEMENT_SIGNAL_HANDLER
|
||||
|
||||
#define IMPLEMENT_SIGNAL_HANDLER(INTERNAL) \
|
||||
void InfoPrivate::INTERNAL##Changed(const QString &_id, \
|
||||
const QString &val) const \
|
||||
{ \
|
||||
if (id == _id) { \
|
||||
Q_EMIT q->INTERNAL##Changed(val); \
|
||||
} \
|
||||
}
|
||||
|
||||
IMPLEMENT_SIGNAL_HANDLER(name)
|
||||
IMPLEMENT_SIGNAL_HANDLER(description)
|
||||
IMPLEMENT_SIGNAL_HANDLER(icon)
|
||||
|
||||
#undef IMPLEMENT_SIGNAL_HANDLER
|
||||
|
||||
void InfoPrivate::setCurrentActivity(const QString ¤tActivity)
|
||||
{
|
||||
if (isCurrent) {
|
||||
if (currentActivity != id) {
|
||||
// We are no longer the current activity
|
||||
isCurrent = false;
|
||||
Q_EMIT q->isCurrentChanged(false);
|
||||
}
|
||||
} else {
|
||||
if (currentActivity == id) {
|
||||
// We are the current activity
|
||||
isCurrent = true;
|
||||
Q_EMIT q->isCurrentChanged(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Info
|
||||
Info::Info(const QString &activity, QObject *parent)
|
||||
: QObject(parent)
|
||||
, d(new InfoPrivate(this, activity))
|
||||
{
|
||||
// qDebug() << "Created an instance of Info: " << (void*)this;
|
||||
#define PASS_SIGNAL_HANDLER(SIGNAL_NAME,SLOT_NAME) \
|
||||
connect(d->cache.get(), SIGNAL(SIGNAL_NAME(QString)), \
|
||||
this, SLOT(SLOT_NAME(QString)));
|
||||
|
||||
PASS_SIGNAL_HANDLER(activityAdded,added)
|
||||
PASS_SIGNAL_HANDLER(activityRemoved,removed)
|
||||
PASS_SIGNAL_HANDLER(activityChanged,infoChanged)
|
||||
#undef PASS_SIGNAL_HANDLER
|
||||
|
||||
#define PASS_SIGNAL_HANDLER(SIGNAL_NAME,SLOT_NAME,TYPE) \
|
||||
connect(d->cache.get(), SIGNAL(SIGNAL_NAME(QString,TYPE)), \
|
||||
this, SLOT(SLOT_NAME(QString,TYPE))); \
|
||||
|
||||
PASS_SIGNAL_HANDLER(activityNameChanged,nameChanged,QString);
|
||||
PASS_SIGNAL_HANDLER(activityDescriptionChanged,descriptionChanged,QString);
|
||||
PASS_SIGNAL_HANDLER(activityIconChanged,iconChanged,QString);
|
||||
// clang-format on
|
||||
#undef PASS_SIGNAL_HANDLER
|
||||
connect(d->cache.get(), SIGNAL(currentActivityChanged(QString)), this, SLOT(setCurrentActivity(QString)));
|
||||
|
||||
d->isCurrent = (d->cache.get()->m_currentActivity == activity);
|
||||
}
|
||||
|
||||
Info::~Info()
|
||||
{
|
||||
// qDebug() << "Deleted an instance of Info: " << (void*)this;
|
||||
}
|
||||
|
||||
QString Info::uri() const
|
||||
{
|
||||
return QStringLiteral("activities://") + d->id;
|
||||
}
|
||||
|
||||
QString Info::id() const
|
||||
{
|
||||
return d->id;
|
||||
}
|
||||
|
||||
bool Info::isCurrent() const
|
||||
{
|
||||
return d->isCurrent;
|
||||
}
|
||||
|
||||
Info::Availability Info::availability() const
|
||||
{
|
||||
Availability result = Nothing;
|
||||
|
||||
if (!Manager::isServiceRunning()) {
|
||||
return result;
|
||||
}
|
||||
|
||||
if (Manager::activities()->ListActivities().value().contains(d->id)) {
|
||||
result = BasicInfo;
|
||||
|
||||
if (Manager::features()->IsFeatureOperational(QStringLiteral("resources/linking"))) {
|
||||
result = Everything;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// clang-format off
|
||||
#define CREATE_GETTER(What) \
|
||||
QString Info::What() const \
|
||||
{ \
|
||||
auto info = d->cache->getInfo(d->id); \
|
||||
return info ? info->What : QString(); \
|
||||
}
|
||||
// clang-format on
|
||||
|
||||
CREATE_GETTER(name)
|
||||
CREATE_GETTER(description)
|
||||
CREATE_GETTER(icon)
|
||||
|
||||
#undef CREATE_GETTER
|
||||
|
||||
} // namespace KActivities
|
||||
|
||||
#include "moc_info.cpp"
|
||||
@@ -0,0 +1,201 @@
|
||||
/*
|
||||
SPDX-FileCopyrightText: 2010-2016 Ivan Cukic <ivan.cukic(at)kde.org>
|
||||
|
||||
SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
|
||||
*/
|
||||
|
||||
#ifndef ACTIVITIES_INFO_H
|
||||
#define ACTIVITIES_INFO_H
|
||||
|
||||
#include <QFuture>
|
||||
#include <QObject>
|
||||
#include <QString>
|
||||
|
||||
#include "plasma_activities_export.h"
|
||||
|
||||
#include <memory>
|
||||
|
||||
namespace KActivities
|
||||
{
|
||||
class InfoPrivate;
|
||||
|
||||
/*!
|
||||
* \class KActivities::Info
|
||||
* \inmodule PlasmaActivities
|
||||
* \inheaderfile PlasmaActivities/Info
|
||||
*
|
||||
* \brief Info about an activity.
|
||||
*
|
||||
* Most methods in it require a
|
||||
* semantic backend running to function properly.
|
||||
*
|
||||
* This class is not thread-safe.
|
||||
*
|
||||
* The API of the class is synchronous, but the most used properties
|
||||
* are pre-fetched and cached. This means that, in order to get the least
|
||||
* amount of d-bus related locks, you should declare long-lived instances
|
||||
* of this class.
|
||||
*
|
||||
* Before relying on the values retrieved by the class, make sure that the
|
||||
* state is not Info::Unknown. You can get invalid data either because the
|
||||
* service is not functioning properly (or at all) or because the class did
|
||||
* not have enough time to synchronize the data with it.
|
||||
*
|
||||
* For example, if this is the only existing instance of the Info class, the
|
||||
* name method will return an empty string.
|
||||
*
|
||||
* For example, this is wrong (works, but blocks):
|
||||
* \code
|
||||
* void someMethod(const QString & activity) {
|
||||
* // Do not copy. This approach is not a good one!
|
||||
* Info info(activity);
|
||||
* doSomethingWith(info.name());
|
||||
* }
|
||||
* \endcode
|
||||
*
|
||||
* Instances of the Info class should be long-lived. For example, members
|
||||
* of the classes that use them, and you should listen for the changes in the
|
||||
* provided properties.
|
||||
*
|
||||
* \since 4.5
|
||||
*/
|
||||
class PLASMA_ACTIVITIES_EXPORT Info : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
/*!
|
||||
* \property KActivities::Info::id
|
||||
*/
|
||||
Q_PROPERTY(QString id READ id)
|
||||
|
||||
/*!
|
||||
* \property KActivities::Info::name
|
||||
*/
|
||||
Q_PROPERTY(QString name READ name NOTIFY nameChanged)
|
||||
|
||||
/*!
|
||||
* \property KActivities::Info::description
|
||||
*/
|
||||
Q_PROPERTY(QString description READ description NOTIFY descriptionChanged)
|
||||
|
||||
/*!
|
||||
* \property KActivities::Info::icon
|
||||
*/
|
||||
Q_PROPERTY(QString icon READ icon NOTIFY iconChanged)
|
||||
|
||||
/*!
|
||||
* \property KActivities::Info::isCurrent
|
||||
*/
|
||||
Q_PROPERTY(bool isCurrent READ isCurrent NOTIFY isCurrentChanged)
|
||||
|
||||
public:
|
||||
/*!
|
||||
*
|
||||
*/
|
||||
explicit Info(const QString &activity, QObject *parent = nullptr);
|
||||
~Info() override;
|
||||
|
||||
/*!
|
||||
* Specifies which parts of this class are functional
|
||||
*
|
||||
* \value Nothing No activity info provided (isValid is false)
|
||||
* \value BasicInfo Basic info is provided
|
||||
* \value Everything Everything is available
|
||||
*/
|
||||
enum Availability {
|
||||
Nothing = 0,
|
||||
BasicInfo = 1,
|
||||
Everything = 2,
|
||||
};
|
||||
|
||||
/*!
|
||||
* Returns what info is provided by this instance of Info
|
||||
*/
|
||||
Availability availability() const;
|
||||
|
||||
/*!
|
||||
* Returns the URI of this activity. The same URI is used by activities
|
||||
* KIO worker.
|
||||
*/
|
||||
QString uri() const;
|
||||
|
||||
/*!
|
||||
* Returns the id of the activity
|
||||
*/
|
||||
QString id() const;
|
||||
|
||||
/*!
|
||||
* Returns whether this activity is the current one
|
||||
*/
|
||||
bool isCurrent() const;
|
||||
|
||||
/*!
|
||||
* Returns the name of the activity
|
||||
*/
|
||||
QString name() const;
|
||||
|
||||
/*!
|
||||
* Returns the description of the activity
|
||||
*/
|
||||
QString description() const;
|
||||
|
||||
/*!
|
||||
* Returns the icon of the activity. Icon can be a freedesktop.org name or
|
||||
* a file path. Or empty if no icon is set.
|
||||
*/
|
||||
QString icon() const;
|
||||
|
||||
Q_SIGNALS:
|
||||
/*!
|
||||
* Emitted when the activity's name, icon or some custom property is changed
|
||||
*/
|
||||
void infoChanged();
|
||||
|
||||
/*!
|
||||
* Emitted when the name is changed
|
||||
*/
|
||||
void nameChanged(const QString &name);
|
||||
|
||||
/*!
|
||||
* Emitted when the activity becomes the current one, or when it stops
|
||||
* being the current one
|
||||
*/
|
||||
void isCurrentChanged(bool current);
|
||||
|
||||
/*!
|
||||
* Emitted when the description is changed
|
||||
*/
|
||||
void descriptionChanged(const QString &description);
|
||||
|
||||
/*!
|
||||
* Emitted when the icon was changed
|
||||
*/
|
||||
void iconChanged(const QString &icon);
|
||||
|
||||
/*!
|
||||
* Emitted when the activity is added
|
||||
*/
|
||||
void added();
|
||||
|
||||
/*!
|
||||
* Emitted when the activity is removed
|
||||
*/
|
||||
void removed();
|
||||
|
||||
private:
|
||||
const std::unique_ptr<InfoPrivate> d;
|
||||
|
||||
Q_PRIVATE_SLOT(d, void added(const QString &))
|
||||
Q_PRIVATE_SLOT(d, void removed(const QString &))
|
||||
Q_PRIVATE_SLOT(d, void infoChanged(const QString &))
|
||||
Q_PRIVATE_SLOT(d, void nameChanged(const QString &, const QString &))
|
||||
Q_PRIVATE_SLOT(d, void descriptionChanged(const QString &, const QString &))
|
||||
Q_PRIVATE_SLOT(d, void iconChanged(const QString &, const QString &))
|
||||
Q_PRIVATE_SLOT(d, void setCurrentActivity(const QString &))
|
||||
|
||||
friend class InfoPrivate;
|
||||
};
|
||||
|
||||
} // namespace KActivities
|
||||
|
||||
#endif // ACTIVITIES_INFO_H
|
||||
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
SPDX-FileCopyrightText: 2010-2016 Ivan Cukic <ivan.cukic(at)kde.org>
|
||||
|
||||
SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
|
||||
*/
|
||||
|
||||
#ifndef KACTIVITIESINFO_P_H
|
||||
#define KACTIVITIESINFO_P_H
|
||||
|
||||
#include "info.h"
|
||||
#include <memory>
|
||||
|
||||
#include "activitiescache_p.h"
|
||||
|
||||
namespace KActivities
|
||||
{
|
||||
class InfoPrivate
|
||||
{
|
||||
public:
|
||||
InfoPrivate(Info *info, const QString &activity);
|
||||
|
||||
void added(const QString &) const;
|
||||
void removed(const QString &) const;
|
||||
void infoChanged(const QString &) const;
|
||||
void nameChanged(const QString &, const QString &) const;
|
||||
void descriptionChanged(const QString &, const QString &) const;
|
||||
void iconChanged(const QString &, const QString &) const;
|
||||
void setCurrentActivity(const QString ¤tActivity);
|
||||
|
||||
Info *const q;
|
||||
std::shared_ptr<ActivitiesCache> cache;
|
||||
bool isCurrent;
|
||||
|
||||
const QString id;
|
||||
};
|
||||
|
||||
} // namespace KActivities
|
||||
|
||||
#endif // KACTIVITIESINFO_P_H
|
||||
@@ -0,0 +1,50 @@
|
||||
/*
|
||||
SPDX-FileCopyrightText: 2014-2016 Ivan Cukic <ivan.cukic(at)kde.org>
|
||||
|
||||
SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
|
||||
*/
|
||||
|
||||
#include "mainthreadexecutor_p.h"
|
||||
|
||||
#include <mutex>
|
||||
|
||||
#include <QCoreApplication>
|
||||
#include <QMetaObject>
|
||||
#include <QThread>
|
||||
|
||||
namespace KActivities
|
||||
{
|
||||
namespace detail
|
||||
{
|
||||
MainThreadExecutor::MainThreadExecutor(std::function<void()> &&f)
|
||||
: m_function(std::forward<std::function<void()>>(f))
|
||||
{
|
||||
}
|
||||
|
||||
void MainThreadExecutor::start()
|
||||
{
|
||||
m_function();
|
||||
deleteLater();
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
|
||||
void runInMainThread(std::function<void()> &&f)
|
||||
{
|
||||
static auto mainThread = QCoreApplication::instance()->thread();
|
||||
|
||||
if (QThread::currentThread() == mainThread) {
|
||||
f();
|
||||
|
||||
} else {
|
||||
auto executor = new detail::MainThreadExecutor(std::forward<std::function<void()>>(f));
|
||||
|
||||
executor->moveToThread(mainThread);
|
||||
|
||||
QMetaObject::invokeMethod(executor, "start", Qt::BlockingQueuedConnection);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace KActivities
|
||||
|
||||
#include "moc_mainthreadexecutor_p.cpp"
|
||||
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
SPDX-FileCopyrightText: 2014-2016 Ivan Cukic <ivan.cukic(at)kde.org>
|
||||
|
||||
SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
|
||||
*/
|
||||
|
||||
#ifndef ACTIVITIES_MAINTHREADEXECUTOR_P
|
||||
#define ACTIVITIES_MAINTHREADEXECUTOR_P
|
||||
|
||||
#include <functional>
|
||||
|
||||
#include <QObject>
|
||||
|
||||
namespace KActivities
|
||||
{
|
||||
namespace detail
|
||||
{
|
||||
class MainThreadExecutor : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
MainThreadExecutor(std::function<void()> &&f);
|
||||
|
||||
Q_INVOKABLE void start();
|
||||
|
||||
private:
|
||||
std::function<void()> m_function;
|
||||
};
|
||||
} // namespace detail
|
||||
|
||||
void runInMainThread(std::function<void()> &&f);
|
||||
|
||||
} // namespace KActivities
|
||||
|
||||
#endif // ACTIVITIES_MAINTHREADEXECUTOR_P
|
||||
@@ -0,0 +1,161 @@
|
||||
/*
|
||||
SPDX-FileCopyrightText: 2010-2016 Ivan Cukic <ivan.cukic(at)kde.org>
|
||||
|
||||
SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
|
||||
*/
|
||||
|
||||
#include "manager_p.h"
|
||||
|
||||
#include <mutex>
|
||||
#include <optional>
|
||||
|
||||
#include <QCoreApplication>
|
||||
#include <QDBusConnection>
|
||||
#include <QFutureWatcher>
|
||||
#include <QFutureWatcherBase>
|
||||
|
||||
#include "debug_p.h"
|
||||
#include "mainthreadexecutor_p.h"
|
||||
|
||||
#include "common/dbus/common.h"
|
||||
#include "utils/continue_with.h"
|
||||
#include "utils/dbusfuture_p.h"
|
||||
#include "version.h"
|
||||
|
||||
namespace KActivities
|
||||
{
|
||||
Manager *Manager::s_instance = nullptr;
|
||||
|
||||
Manager::Manager()
|
||||
: QObject()
|
||||
, m_watcher(KAMD_DBUS_SERVICE, QDBusConnection::sessionBus())
|
||||
, m_service(new KAMD_DBUS_CLASS_INTERFACE("/", Application, this))
|
||||
, m_activities(new KAMD_DBUS_CLASS_INTERFACE("Activities", Activities, this))
|
||||
, m_resources(new KAMD_DBUS_CLASS_INTERFACE("Resources", Resources, this))
|
||||
, m_resourcesLinking(new KAMD_DBUS_CLASS_INTERFACE("Resources/Linking", ResourcesLinking, this))
|
||||
, m_features(new KAMD_DBUS_CLASS_INTERFACE("Features", Features, this))
|
||||
, m_serviceStatus(Manager::NotRunning)
|
||||
{
|
||||
connect(&m_watcher, &QDBusServiceWatcher::serviceOwnerChanged, this, &Manager::serviceOwnerChanged);
|
||||
|
||||
if (serviceStatus()) {
|
||||
serviceOwnerChanged(KAMD_DBUS_SERVICE, QString(), KAMD_DBUS_SERVICE);
|
||||
}
|
||||
}
|
||||
|
||||
Manager *Manager::self()
|
||||
{
|
||||
static std::mutex singleton;
|
||||
std::lock_guard<std::mutex> singleton_lock(singleton);
|
||||
|
||||
if (!s_instance) {
|
||||
runInMainThread([]() {
|
||||
// check if the activity manager is already running
|
||||
// creating a new instance of the class
|
||||
Manager::s_instance = new Manager();
|
||||
|
||||
if (QDBusConnection::sessionBus().interface()->isServiceRegistered(KAMD_DBUS_SERVICE)) { // already running
|
||||
s_instance->m_serviceStatus = Running;
|
||||
} else { // not running
|
||||
bool disableAutolaunch = QCoreApplication::instance()->property("org.kde.KActivities.core.disableAutostart").toBool();
|
||||
|
||||
qCDebug(KAMD_CORELIB) << "Should we start the daemon?";
|
||||
// start only if not disabled and we have a dbus connection at all
|
||||
if (!disableAutolaunch && QDBusConnection::sessionBus().interface()) {
|
||||
qCDebug(KAMD_CORELIB) << "Starting the activity manager daemon";
|
||||
auto busInterface = QDBusConnection::sessionBus().interface();
|
||||
auto pending = busInterface->asyncCall(QStringLiteral("StartServiceByName"), KAMD_DBUS_SERVICE, uint(0));
|
||||
s_instance->m_serviceStatus = Manager::Starting;
|
||||
QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(pending, s_instance);
|
||||
connect(watcher, &QDBusPendingCallWatcher::finished, watcher, []() {
|
||||
const bool isRunning = QDBusConnection::sessionBus().interface()->isServiceRegistered(KAMD_DBUS_SERVICE);
|
||||
s_instance->m_serviceStatus = isRunning ? Manager::Running : Manager::NotRunning;
|
||||
Q_EMIT s_instance->serviceStatusChanged(s_instance->m_serviceStatus);
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
return s_instance;
|
||||
}
|
||||
|
||||
bool Manager::isServiceRunning()
|
||||
{
|
||||
return s_instance && s_instance->m_serviceStatus == Manager::Running;
|
||||
}
|
||||
|
||||
Manager::ServiceStatus Manager::serviceStatus()
|
||||
{
|
||||
return s_instance ? s_instance->m_serviceStatus : NotRunning;
|
||||
}
|
||||
|
||||
void Manager::serviceOwnerChanged(const QString &serviceName, const QString &oldOwner, const QString &newOwner)
|
||||
{
|
||||
Q_UNUSED(oldOwner);
|
||||
|
||||
if (serviceName == KAMD_DBUS_SERVICE) {
|
||||
const bool isRunning = QDBusConnection::sessionBus().interface()->isServiceRegistered(KAMD_DBUS_SERVICE);
|
||||
m_serviceStatus = isRunning ? Manager::Running : Manager::NotRunning;
|
||||
Q_EMIT serviceStatusChanged(m_serviceStatus);
|
||||
|
||||
if (isRunning) {
|
||||
using namespace kamd::utils;
|
||||
|
||||
continue_with(DBusFuture::fromReply(m_service->serviceVersion()), [this](const std::optional<QString> &serviceVersion) {
|
||||
// Test whether the service is older than the library.
|
||||
// If it is, we need to end this
|
||||
|
||||
if (!serviceVersion.has_value()) {
|
||||
qWarning() << "KActivities: FATAL ERROR: Failed to contact the activity manager daemon";
|
||||
m_serviceStatus = NotRunning;
|
||||
return;
|
||||
}
|
||||
|
||||
auto split = serviceVersion->split(QLatin1Char('.'));
|
||||
QList<int> version;
|
||||
|
||||
// We require kactivitymanagerd version to be at least the
|
||||
// one before the repository split
|
||||
const int requiredVersion[] = {6, 2, 0};
|
||||
|
||||
std::transform(split.cbegin(), split.cend(), std::back_inserter(version), [](const QString &component) {
|
||||
return component.toInt();
|
||||
});
|
||||
|
||||
// if required version is greater than the current version
|
||||
if (std::lexicographical_compare(version.cbegin(), version.cend(), std::begin(requiredVersion), std::end(requiredVersion))) {
|
||||
QString libraryVersion = QString::number(requiredVersion[0]) + QLatin1Char('.') + QString::number(requiredVersion[1]) + QLatin1Char('.')
|
||||
+ QString::number(requiredVersion[2]);
|
||||
|
||||
qDebug() << "KActivities service version: " << serviceVersion.value();
|
||||
qDebug() << "KActivities library version: " << libraryVersion;
|
||||
qFatal("KActivities: FATAL ERROR: The service is older than the library");
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Service::Activities *Manager::activities()
|
||||
{
|
||||
return self()->m_activities;
|
||||
}
|
||||
|
||||
Service::Resources *Manager::resources()
|
||||
{
|
||||
return self()->m_resources;
|
||||
}
|
||||
|
||||
Service::ResourcesLinking *Manager::resourcesLinking()
|
||||
{
|
||||
return self()->m_resourcesLinking;
|
||||
}
|
||||
|
||||
Service::Features *Manager::features()
|
||||
{
|
||||
return self()->m_features;
|
||||
}
|
||||
|
||||
} // namespace KActivities
|
||||
|
||||
#include "moc_manager_p.cpp"
|
||||
@@ -0,0 +1,70 @@
|
||||
/*
|
||||
SPDX-FileCopyrightText: 2010-2016 Ivan Cukic <ivan.cukic(at)kde.org>
|
||||
|
||||
SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
|
||||
*/
|
||||
|
||||
#ifndef ACTIVITIES_MANAGER_P
|
||||
#define ACTIVITIES_MANAGER_P
|
||||
|
||||
#include <common/dbus/org.kde.ActivityManager.Activities.h>
|
||||
|
||||
#include "activities_interface.h"
|
||||
#include "application_interface.h"
|
||||
#include "features_interface.h"
|
||||
#include "resources_interface.h"
|
||||
#include "resources_linking_interface.h"
|
||||
|
||||
#include <QDBusServiceWatcher>
|
||||
|
||||
namespace Service = org::kde::ActivityManager;
|
||||
|
||||
namespace KActivities
|
||||
{
|
||||
class Manager : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
enum ServiceStatus {
|
||||
NotRunning,
|
||||
Starting,
|
||||
Running,
|
||||
};
|
||||
|
||||
static Manager *self();
|
||||
|
||||
static bool isServiceRunning();
|
||||
static ServiceStatus serviceStatus();
|
||||
|
||||
static Service::Activities *activities();
|
||||
static Service::Resources *resources();
|
||||
static Service::ResourcesLinking *resourcesLinking();
|
||||
static Service::Features *features();
|
||||
|
||||
public Q_SLOTS:
|
||||
void serviceOwnerChanged(const QString &serviceName, const QString &oldOwner, const QString &newOwner);
|
||||
|
||||
Q_SIGNALS:
|
||||
void serviceStatusChanged(ServiceStatus status);
|
||||
|
||||
private:
|
||||
Manager();
|
||||
|
||||
QDBusServiceWatcher m_watcher;
|
||||
|
||||
static Manager *s_instance;
|
||||
|
||||
Service::Application *const m_service;
|
||||
Service::Activities *const m_activities;
|
||||
Service::Resources *const m_resources;
|
||||
Service::ResourcesLinking *const m_resourcesLinking;
|
||||
Service::Features *const m_features;
|
||||
ServiceStatus m_serviceStatus;
|
||||
|
||||
friend class ManagerInstantiator;
|
||||
};
|
||||
|
||||
} // namespace KActivities
|
||||
|
||||
#endif // ACTIVITIES_MANAGER_P
|
||||
@@ -0,0 +1,21 @@
|
||||
/*!
|
||||
\page plasmaactivities-index.html
|
||||
\title Plasma Activities
|
||||
|
||||
Library for interacting with Plasma Activities.
|
||||
|
||||
\section1 Using the Module
|
||||
|
||||
\include {module-use.qdocinc} {using the c++ api}
|
||||
|
||||
\section2 Building with CMake
|
||||
|
||||
\include {module-use.qdocinc} {building with cmake nomodule} {PlasmaActivities} {Plasma::Activities}
|
||||
|
||||
\section1 API Reference
|
||||
|
||||
\list
|
||||
\li \l{Plasma Activities C++ Classes}
|
||||
\li \l{Plasma Activities QML Types}
|
||||
\endlist
|
||||
*/
|
||||
@@ -0,0 +1,9 @@
|
||||
/*!
|
||||
\module PlasmaActivities
|
||||
\title Plasma Activities C++ Classes
|
||||
\ingroup modules
|
||||
\cmakepackage Plasma
|
||||
\cmakecomponent Activities
|
||||
|
||||
\brief Library for interacting with Plasma Activities.
|
||||
*/
|
||||
@@ -0,0 +1,35 @@
|
||||
include($KDE_DOCS/global/qt-module-defaults.qdocconf)
|
||||
|
||||
project = PlasmaActivities
|
||||
description = Library for interacting with Plasma Activities
|
||||
|
||||
documentationinheaders = true
|
||||
|
||||
headerdirs += .
|
||||
sourcedirs += .
|
||||
|
||||
outputformats = HTML
|
||||
|
||||
depends += \
|
||||
kde \
|
||||
qtcore \
|
||||
qtgui \
|
||||
plasmaactivitiesqml
|
||||
|
||||
navigation.landingpage = "PlasmaActivities"
|
||||
|
||||
qhp.projects = PlasmaActivities
|
||||
|
||||
qhp.PlasmaActivities.file = plasmaactivities.qhp
|
||||
qhp.PlasmaActivities.namespace = org.kde.plasmaactivities.$QT_VERSION_TAG
|
||||
qhp.PlasmaActivities.virtualFolder = plasmaactivities
|
||||
qhp.PlasmaActivities.indexTitle = Plasma Activities
|
||||
qhp.PlasmaActivities.indexRoot =
|
||||
|
||||
qhp.PlasmaActivities.subprojects = classes
|
||||
qhp.PlasmaActivities.subprojects.classes.title = C++ Classes
|
||||
qhp.PlasmaActivities.subprojects.classes.indexTitle = Plasma Activities C++ Classes
|
||||
qhp.PlasmaActivities.subprojects.classes.selectors = class fake:headerfile
|
||||
qhp.PlasmaActivities.subprojects.classes.sortPages = true
|
||||
|
||||
tagfile = plasmaactivities.tags
|
||||
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
SPDX-FileCopyrightText: 2011-2016 Ivan Cukic <ivan.cukic(at)kde.org>
|
||||
|
||||
SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
|
||||
*/
|
||||
|
||||
#include "resourceinstance.h"
|
||||
#include "manager_p.h"
|
||||
|
||||
#include <QCoreApplication>
|
||||
|
||||
namespace KActivities::ResourceInstance
|
||||
{
|
||||
|
||||
void notifyAccessed(const QUrl &uri, const QString &application)
|
||||
{
|
||||
if (uri.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (uri.fileName().startsWith('.')) {
|
||||
// skip hidden files
|
||||
return;
|
||||
}
|
||||
|
||||
if (uri.path().contains(QStringLiteral("/."))) {
|
||||
// skip files in hidden directories
|
||||
return;
|
||||
}
|
||||
|
||||
Manager::resources()->RegisterResourceEvent(application.isEmpty() ? QCoreApplication::instance()->applicationName() : application,
|
||||
0,
|
||||
uri.toString(),
|
||||
0 /* Accessed */);
|
||||
}
|
||||
|
||||
} // namespace KActivities::ResourceInstance
|
||||
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
SPDX-FileCopyrightText: 2011-2016 Ivan Cukic <ivan.cukic(at)kde.org>
|
||||
|
||||
SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
|
||||
*/
|
||||
|
||||
#ifndef ACTIVITIES_RESOURCEINSTANCE_H
|
||||
#define ACTIVITIES_RESOURCEINSTANCE_H
|
||||
|
||||
#include <QObject>
|
||||
#include <QUrl>
|
||||
|
||||
#include "plasma_activities_export.h"
|
||||
|
||||
/*!
|
||||
* \namespace KActivities::ResourceInstance
|
||||
* \inmodule PlasmaActivities
|
||||
* \inheaderfile KActivities/ResourceInstance
|
||||
*/
|
||||
namespace KActivities::ResourceInstance
|
||||
{
|
||||
/*!
|
||||
* This function is used to notify the system that a file, web page
|
||||
* or some other resource has been accessed.
|
||||
*
|
||||
* \a uri URI of the resource
|
||||
*
|
||||
* \a application application's name (the name used for the .desktop file).
|
||||
* If not specified, QCoreApplication::applicationName is used
|
||||
*/
|
||||
PLASMA_ACTIVITIES_EXPORT void notifyAccessed(const QUrl &uri, const QString &application = QString());
|
||||
}
|
||||
|
||||
#endif // ACTIVITIES_RESOURCEINSTANCE_H
|
||||
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
SPDX-FileCopyrightText: 2008 Aaron Seigo <aseigo@kde.org>
|
||||
|
||||
SPDX-License-Identifier: LGPL-2.0-or-later
|
||||
*/
|
||||
|
||||
#include "version.h"
|
||||
|
||||
namespace KActivities
|
||||
{
|
||||
unsigned int version()
|
||||
{
|
||||
return PLASMA_ACTIVITIES_VERSION;
|
||||
}
|
||||
|
||||
unsigned int versionMajor()
|
||||
{
|
||||
return PLASMA_ACTIVITIES_VERSION_MAJOR;
|
||||
}
|
||||
|
||||
unsigned int versionMinor()
|
||||
{
|
||||
return PLASMA_ACTIVITIES_VERSION_MINOR;
|
||||
}
|
||||
|
||||
unsigned int versionRelease()
|
||||
{
|
||||
return PLASMA_ACTIVITIES_VERSION_RELEASE;
|
||||
}
|
||||
|
||||
const char *versionString()
|
||||
{
|
||||
return PLASMA_ACTIVITIES_VERSION_STRING;
|
||||
}
|
||||
|
||||
} // KActivities namespace
|
||||
@@ -0,0 +1,51 @@
|
||||
/*
|
||||
SPDX-FileCopyrightText: 2008-2016 Aaron Seigo <aseigo@kde.org>
|
||||
|
||||
SPDX-License-Identifier: LGPL-2.0-or-later
|
||||
*/
|
||||
|
||||
#ifndef PLASMA_ACTIVITIES_VERSION_BIN_H
|
||||
#define PLASMA_ACTIVITIES_VERSION_BIN_H
|
||||
|
||||
#include "plasma_activities_export.h"
|
||||
#include <plasma_activities_version.h>
|
||||
|
||||
#define PLASMA_ACTIVITIES_VERSION_RELEASE PLASMA_ACTIVITIES_VERSION_PATCH
|
||||
|
||||
/*!
|
||||
* \namespace KActivities
|
||||
* \inmodule PlasmaActivities
|
||||
* \inheaderfile KActivities/Version
|
||||
*
|
||||
* \brief Namespace for everything in libkactivities.
|
||||
*/
|
||||
namespace KActivities
|
||||
{
|
||||
/*!
|
||||
* The runtime version of libkactivities
|
||||
*/
|
||||
PLASMA_ACTIVITIES_EXPORT unsigned int version();
|
||||
|
||||
/*!
|
||||
* The runtime major version of libkactivities
|
||||
*/
|
||||
PLASMA_ACTIVITIES_EXPORT unsigned int versionMajor();
|
||||
|
||||
/*!
|
||||
* The runtime major version of libkactivities
|
||||
*/
|
||||
PLASMA_ACTIVITIES_EXPORT unsigned int versionMinor();
|
||||
|
||||
/*!
|
||||
* The runtime major version of libkactivities
|
||||
*/
|
||||
PLASMA_ACTIVITIES_EXPORT unsigned int versionRelease();
|
||||
|
||||
/*!
|
||||
* The runtime version string of libkactivities
|
||||
*/
|
||||
PLASMA_ACTIVITIES_EXPORT const char *versionString();
|
||||
|
||||
} // KActivities namespace
|
||||
|
||||
#endif // PLASMA_ACTIVITIES_VERSION_BIN_H
|
||||
@@ -0,0 +1,91 @@
|
||||
/*
|
||||
SPDX-FileCopyrightText: 2014-2016 Ivan Cukic <ivan.cukic(at)kde.org>
|
||||
|
||||
SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
|
||||
*/
|
||||
|
||||
#ifndef UTILS_CONTINUE_WITH_H
|
||||
#define UTILS_CONTINUE_WITH_H
|
||||
|
||||
#include <QDebug>
|
||||
#include <QFuture>
|
||||
#include <QFutureWatcher>
|
||||
|
||||
#include <optional>
|
||||
|
||||
#ifdef ENABLE_QJSVALUE_CONTINUATION
|
||||
#include <QJSValue>
|
||||
#endif
|
||||
|
||||
namespace kamd
|
||||
{
|
||||
namespace utils
|
||||
{
|
||||
namespace detail
|
||||
{ //_
|
||||
#ifdef ENABLE_QJSVALUE_CONTINUATION
|
||||
inline void test_continuation(const QJSValue &continuation)
|
||||
{
|
||||
if (!continuation.isCallable()) {
|
||||
qWarning() << "Passed handler is not callable: " << continuation.toString();
|
||||
}
|
||||
}
|
||||
|
||||
template<typename _ReturnType>
|
||||
inline void pass_value(const QFuture<_ReturnType> &future, QJSValue continuation)
|
||||
{
|
||||
auto result = continuation.call({future.result()});
|
||||
if (result.isError()) {
|
||||
qWarning() << "Handler returned this error: " << result.toString();
|
||||
}
|
||||
}
|
||||
|
||||
inline void pass_value(const QFuture<void> &future, QJSValue continuation)
|
||||
{
|
||||
Q_UNUSED(future);
|
||||
auto result = continuation.call({});
|
||||
if (result.isError()) {
|
||||
qWarning() << "Handler returned this error: " << result.toString();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
template<typename _Continuation>
|
||||
inline void test_continuation(_Continuation &&continuation)
|
||||
{
|
||||
Q_UNUSED(continuation);
|
||||
}
|
||||
|
||||
template<typename _ReturnType, typename _Continuation>
|
||||
inline void pass_value(const QFuture<_ReturnType> &future, _Continuation &&continuation)
|
||||
{
|
||||
using namespace kamd::utils;
|
||||
continuation(future.resultCount() > 0 ? std::optional(future.result()) : std::nullopt);
|
||||
}
|
||||
|
||||
template<typename _Continuation>
|
||||
inline void pass_value(_Continuation &&continuation)
|
||||
{
|
||||
continuation();
|
||||
}
|
||||
|
||||
} //^ namespace detail
|
||||
|
||||
template<typename _ReturnType, typename _Continuation>
|
||||
inline void continue_with(const QFuture<_ReturnType> &future, _Continuation &&continuation)
|
||||
{
|
||||
detail::test_continuation(continuation);
|
||||
|
||||
auto watcher = new QFutureWatcher<_ReturnType>();
|
||||
QObject::connect(watcher, &QFutureWatcherBase::finished, [=]() mutable {
|
||||
watcher->deleteLater();
|
||||
detail::pass_value(future, continuation);
|
||||
});
|
||||
|
||||
watcher->setFuture(future);
|
||||
}
|
||||
|
||||
} // namespace utils
|
||||
} // namespace kamd
|
||||
|
||||
#endif /* !UTILS_CONTINUE_WITH_H */
|
||||
@@ -0,0 +1,50 @@
|
||||
/*
|
||||
SPDX-FileCopyrightText: 2012-2016 Ivan Cukic <ivan.cukic(at)kde.org>
|
||||
|
||||
SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
|
||||
*/
|
||||
|
||||
#include "dbusfuture_p.h"
|
||||
|
||||
namespace DBusFuture
|
||||
{
|
||||
namespace detail
|
||||
{ //_
|
||||
|
||||
template<>
|
||||
void DBusCallFutureInterface<void>::callFinished()
|
||||
{
|
||||
deleteLater();
|
||||
|
||||
// qDebug() << "This is call end";
|
||||
|
||||
this->reportFinished();
|
||||
}
|
||||
|
||||
ValueFutureInterface<void>::ValueFutureInterface()
|
||||
{
|
||||
}
|
||||
|
||||
QFuture<void> ValueFutureInterface<void>::start()
|
||||
{
|
||||
auto future = this->future();
|
||||
|
||||
this->reportFinished();
|
||||
|
||||
deleteLater();
|
||||
|
||||
return future;
|
||||
}
|
||||
|
||||
} //^ namespace detail
|
||||
|
||||
QFuture<void> fromVoid()
|
||||
{
|
||||
using namespace detail;
|
||||
|
||||
auto valueFutureInterface = new ValueFutureInterface<void>();
|
||||
|
||||
return valueFutureInterface->start();
|
||||
}
|
||||
|
||||
} // namespace DBusFuture
|
||||
@@ -0,0 +1,155 @@
|
||||
/*
|
||||
SPDX-FileCopyrightText: 2013-2016 Ivan Cukic <ivan.cukic(at)kde.org>
|
||||
|
||||
SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
|
||||
*/
|
||||
|
||||
#ifndef ACTIVITIES_DBUSFUTURE_P_H
|
||||
#define ACTIVITIES_DBUSFUTURE_P_H
|
||||
|
||||
#include <QDBusAbstractInterface>
|
||||
#include <QDBusPendingCallWatcher>
|
||||
#include <QDBusPendingReply>
|
||||
#include <QDBusServiceWatcher>
|
||||
#include <QFuture>
|
||||
#include <QFutureInterface>
|
||||
#include <QFutureWatcherBase>
|
||||
|
||||
#include "debug_p.h"
|
||||
|
||||
namespace DBusFuture
|
||||
{
|
||||
namespace detail
|
||||
{ //_
|
||||
|
||||
template<typename _Result>
|
||||
class DBusCallFutureInterface : public QObject, public QFutureInterface<_Result>
|
||||
{
|
||||
public:
|
||||
DBusCallFutureInterface(QDBusPendingReply<_Result> reply)
|
||||
: reply(reply)
|
||||
, replyWatcher(nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
~DBusCallFutureInterface() override
|
||||
{
|
||||
delete replyWatcher;
|
||||
}
|
||||
|
||||
void callFinished();
|
||||
|
||||
QFuture<_Result> start()
|
||||
{
|
||||
replyWatcher = new QDBusPendingCallWatcher(reply);
|
||||
|
||||
QObject::connect(replyWatcher, &QDBusPendingCallWatcher::finished, [this]() {
|
||||
callFinished();
|
||||
});
|
||||
|
||||
this->reportStarted();
|
||||
|
||||
if (reply.isFinished()) {
|
||||
this->callFinished();
|
||||
}
|
||||
|
||||
return this->future();
|
||||
}
|
||||
|
||||
private:
|
||||
QDBusPendingReply<_Result> reply;
|
||||
QDBusPendingCallWatcher *replyWatcher;
|
||||
};
|
||||
|
||||
template<typename _Result>
|
||||
void DBusCallFutureInterface<_Result>::callFinished()
|
||||
{
|
||||
deleteLater();
|
||||
|
||||
if (!reply.isError()) {
|
||||
this->reportResult(reply.value());
|
||||
}
|
||||
|
||||
this->reportFinished();
|
||||
}
|
||||
|
||||
template<>
|
||||
void DBusCallFutureInterface<void>::callFinished();
|
||||
|
||||
template<typename _Result>
|
||||
class ValueFutureInterface : public QObject, QFutureInterface<_Result>
|
||||
{
|
||||
public:
|
||||
ValueFutureInterface(const _Result &value)
|
||||
: value(value)
|
||||
{
|
||||
}
|
||||
|
||||
QFuture<_Result> start()
|
||||
{
|
||||
auto future = this->future();
|
||||
|
||||
this->reportResult(value);
|
||||
this->reportFinished();
|
||||
|
||||
deleteLater();
|
||||
|
||||
return future;
|
||||
}
|
||||
|
||||
private:
|
||||
_Result value;
|
||||
};
|
||||
|
||||
template<>
|
||||
class ValueFutureInterface<void> : public QObject, QFutureInterface<void>
|
||||
{
|
||||
public:
|
||||
ValueFutureInterface();
|
||||
|
||||
QFuture<void> start();
|
||||
// {
|
||||
// auto future = this->future();
|
||||
// this->reportFinished();
|
||||
// deleteLater();
|
||||
// return future;
|
||||
// }
|
||||
};
|
||||
|
||||
} //^ namespace detail
|
||||
|
||||
template<typename _Result, typename... Args>
|
||||
QFuture<_Result> asyncCall(QDBusAbstractInterface *interface, const QString &method, Args &&...args)
|
||||
{
|
||||
using namespace detail;
|
||||
|
||||
auto callFutureInterface = new DBusCallFutureInterface<_Result>(interface->asyncCall(method, std::forward<Args>(args)...));
|
||||
|
||||
return callFutureInterface->start();
|
||||
}
|
||||
|
||||
template<typename _Result>
|
||||
QFuture<_Result> fromValue(const _Result &value)
|
||||
{
|
||||
using namespace detail;
|
||||
|
||||
auto valueFutureInterface = new ValueFutureInterface<_Result>(value);
|
||||
|
||||
return valueFutureInterface->start();
|
||||
}
|
||||
|
||||
template<typename _Result>
|
||||
QFuture<_Result> fromReply(const QDBusPendingReply<_Result> &reply)
|
||||
{
|
||||
using namespace detail;
|
||||
|
||||
auto callFutureInterface = new DBusCallFutureInterface<_Result>(reply);
|
||||
|
||||
return callFutureInterface->start();
|
||||
}
|
||||
|
||||
QFuture<void> fromVoid();
|
||||
|
||||
} // namespace DBusFuture
|
||||
|
||||
#endif /* ACTIVITIES_DBUSFUTURE_P_H */
|
||||
@@ -0,0 +1,64 @@
|
||||
/*
|
||||
SPDX-FileCopyrightText: 2012 Ivan Cukic <ivan.cukic(at)kde.org>
|
||||
|
||||
SPDX-License-Identifier: GPL-2.0-or-later
|
||||
*/
|
||||
|
||||
#ifndef KACTIVITIES_MODEL_UPDATERS_H
|
||||
#define KACTIVITIES_MODEL_UPDATERS_H
|
||||
|
||||
// -----------------------------------------
|
||||
// RAII classes for model updates ----------
|
||||
// -----------------------------------------
|
||||
|
||||
// clang-format off
|
||||
#define DECLARE_RAII_MODEL_UPDATERS(Class) \
|
||||
template <typename T> class _model_reset { \
|
||||
T *model; \
|
||||
\
|
||||
public: \
|
||||
_model_reset(T *m) : model(m) \
|
||||
{ \
|
||||
model->beginResetModel(); \
|
||||
} \
|
||||
~_model_reset() \
|
||||
{ \
|
||||
model->endResetModel(); \
|
||||
} \
|
||||
}; \
|
||||
template <typename T> class _model_insert { \
|
||||
T *model; \
|
||||
\
|
||||
public: \
|
||||
_model_insert(T *m, const QModelIndex &parent, int first, int last) \
|
||||
: model(m) \
|
||||
{ \
|
||||
model->beginInsertRows(parent, first, last); \
|
||||
} \
|
||||
~_model_insert() \
|
||||
{ \
|
||||
model->endInsertRows(); \
|
||||
} \
|
||||
}; \
|
||||
template <typename T> class _model_remove { \
|
||||
T *model; \
|
||||
\
|
||||
public: \
|
||||
_model_remove(T *m, const QModelIndex &parent, int first, int last) \
|
||||
: model(m) \
|
||||
{ \
|
||||
model->beginRemoveRows(parent, first, last); \
|
||||
} \
|
||||
~_model_remove() \
|
||||
{ \
|
||||
model->endRemoveRows(); \
|
||||
} \
|
||||
}; \
|
||||
typedef _model_reset<Class> model_reset; \
|
||||
typedef _model_remove<Class> model_remove; \
|
||||
typedef _model_insert<Class> model_insert;
|
||||
|
||||
// -----------------------------------------
|
||||
|
||||
#endif // KACTIVITIES_MODEL_UPDATERS_H
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
SPDX-FileCopyrightText: 2015-2016 Ivan Cukic <ivan.cukic(at)kde.org>
|
||||
|
||||
SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
|
||||
*/
|
||||
|
||||
#ifndef PTR_TO_H
|
||||
#define PTR_TO_H
|
||||
|
||||
namespace kamd
|
||||
{
|
||||
namespace utils
|
||||
{
|
||||
enum {
|
||||
Const = 0,
|
||||
Mutable = 1,
|
||||
};
|
||||
|
||||
template<typename T, int Policy = Const>
|
||||
struct ptr_to {
|
||||
typedef const T *const type;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct ptr_to<T, Mutable> {
|
||||
typedef T *const type;
|
||||
};
|
||||
|
||||
} // namespace utils
|
||||
} // namespace kamd
|
||||
|
||||
#endif // PTR_TO_H
|
||||
@@ -0,0 +1,60 @@
|
||||
/*
|
||||
SPDX-FileCopyrightText: 2016 Ivan Čukić <ivan.cukic(at)kde.org>
|
||||
|
||||
SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
|
||||
*/
|
||||
|
||||
#ifndef KACTIVITIES_STATS_QFLATSET_H
|
||||
#define KACTIVITIES_STATS_QFLATSET_H
|
||||
|
||||
#include <QList>
|
||||
#include <QPair>
|
||||
|
||||
namespace KActivities
|
||||
{
|
||||
template<typename T, typename LessThan>
|
||||
class QFlatSet : public QList<T>
|
||||
{
|
||||
public:
|
||||
QFlatSet()
|
||||
{
|
||||
}
|
||||
|
||||
struct InsertionResult {
|
||||
typename QList<T>::iterator insertedIterator;
|
||||
int insertedIndex{};
|
||||
bool didInsert{};
|
||||
};
|
||||
|
||||
inline InsertionResult insert(const T &value)
|
||||
{
|
||||
auto lessThan = LessThan();
|
||||
|
||||
if (this->begin() == this->end()) {
|
||||
QList<T>::insert(0, value);
|
||||
|
||||
return InsertionResult{QList<T>::begin(), 0, true};
|
||||
|
||||
} else {
|
||||
auto iterator = std::lower_bound(this->begin(), this->end(), value, lessThan);
|
||||
|
||||
if (iterator != this->end()) {
|
||||
if (!lessThan(value, *iterator)) {
|
||||
// Already present
|
||||
return InsertionResult{iterator, int(iterator - this->begin()), false};
|
||||
}
|
||||
}
|
||||
|
||||
auto newIterator = QList<T>::insert(iterator, value);
|
||||
|
||||
return InsertionResult{newIterator, int(newIterator - this->begin()), true};
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
QFlatSet(const QFlatSet &original); // = delete
|
||||
};
|
||||
|
||||
} // namespace KActivities
|
||||
|
||||
#endif // KACTIVITIES_STATS_QFLATSET_H
|
||||
@@ -0,0 +1,3 @@
|
||||
# vim:set softtabstop=3 shiftwidth=3 tabstop=3 expandtab:
|
||||
|
||||
# add_subdirectory(slc-interface)
|
||||
@@ -0,0 +1,77 @@
|
||||
/*
|
||||
SPDX-FileCopyrightText: 2013 Heena Mahour <heena393@gmail.com>
|
||||
SPDX-FileCopyrightText: 2013 Sebastian Kügler <sebas@kde.org>
|
||||
|
||||
SPDX-License-Identifier: GPL-2.0-or-later
|
||||
*/
|
||||
import QtQuick 2.0
|
||||
import org.kde.plasma.core as PlasmaCore
|
||||
import org.kde.plasma.components 2.0 as PlasmaComponents
|
||||
import org.kde.plasma.extras 2.0 as PlasmaExtras
|
||||
import org.kde.activities 0.1 as Activities
|
||||
|
||||
ListView {
|
||||
id: main
|
||||
|
||||
property int minimumWidth: 32
|
||||
property int minimumHeight: 32 // theme.mSize(theme.defaultFont).height * 14
|
||||
property int implicitWidth: minimumWidth * 1.5
|
||||
property int implicitHeight: minimumHeight * 1.5
|
||||
|
||||
property int formFactor: plasmoid.formFactor
|
||||
|
||||
|
||||
|
||||
model: modelMain
|
||||
|
||||
Activities.ActivityModel {
|
||||
id: modelMain
|
||||
}
|
||||
|
||||
add: Transition {
|
||||
NumberAnimation { properties: "x"; from: 300; duration: 1000 }
|
||||
}
|
||||
|
||||
addDisplaced: Transition {
|
||||
NumberAnimation { properties: "x,y"; duration: 1000 }
|
||||
}
|
||||
|
||||
remove: Transition {
|
||||
NumberAnimation { properties: "x"; to: 300; duration: 1000 }
|
||||
}
|
||||
|
||||
removeDisplaced: Transition {
|
||||
NumberAnimation { properties: "x,y"; duration: 1000 }
|
||||
}
|
||||
|
||||
ListModel {
|
||||
id: modelDummy
|
||||
|
||||
ListElement {
|
||||
name: "Bill Smith"
|
||||
number: "555 3264"
|
||||
}
|
||||
ListElement {
|
||||
name: "John Brown"
|
||||
number: "555 8426"
|
||||
}
|
||||
ListElement {
|
||||
name: "Sam Wise"
|
||||
number: "555 0473"
|
||||
}
|
||||
}
|
||||
|
||||
delegate: Column {
|
||||
height: 32
|
||||
Text {
|
||||
text: name
|
||||
height: 16
|
||||
font.bold: true
|
||||
}
|
||||
Text {
|
||||
text: " id: " + id
|
||||
height: 16
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
+77
@@ -0,0 +1,77 @@
|
||||
/*
|
||||
SPDX-FileCopyrightText: 2013 Heena Mahour <heena393@gmail.com>
|
||||
SPDX-FileCopyrightText: 2013 Sebastian Kügler <sebas@kde.org>
|
||||
|
||||
SPDX-License-Identifier: GPL-2.0-or-later
|
||||
*/
|
||||
import QtQuick 2.0
|
||||
import org.kde.plasma.core as PlasmaCore
|
||||
import org.kde.plasma.components 2.0 as PlasmaComponents
|
||||
import org.kde.plasma.extras 2.0 as PlasmaExtras
|
||||
import org.kde.activities 0.1 as Activities
|
||||
|
||||
ListView {
|
||||
id: main
|
||||
|
||||
property int minimumWidth: 32
|
||||
property int minimumHeight: 32 // theme.mSize(theme.defaultFont).height * 14
|
||||
property int implicitWidth: minimumWidth * 1.5
|
||||
property int implicitHeight: minimumHeight * 1.5
|
||||
|
||||
property int formFactor: plasmoid.formFactor
|
||||
|
||||
|
||||
|
||||
model: modelMain
|
||||
|
||||
Activities.ActivityModel {
|
||||
id: modelMain
|
||||
}
|
||||
|
||||
add: Transition {
|
||||
NumberAnimation { properties: "x"; from: 300; duration: 1000 }
|
||||
}
|
||||
|
||||
addDisplaced: Transition {
|
||||
NumberAnimation { properties: "x,y"; duration: 1000 }
|
||||
}
|
||||
|
||||
remove: Transition {
|
||||
NumberAnimation { properties: "x"; to: 300; duration: 1000 }
|
||||
}
|
||||
|
||||
removeDisplaced: Transition {
|
||||
NumberAnimation { properties: "x,y"; duration: 1000 }
|
||||
}
|
||||
|
||||
ListModel {
|
||||
id: modelDummy
|
||||
|
||||
ListElement {
|
||||
name: "Bill Smith"
|
||||
number: "555 3264"
|
||||
}
|
||||
ListElement {
|
||||
name: "John Brown"
|
||||
number: "555 8426"
|
||||
}
|
||||
ListElement {
|
||||
name: "Sam Wise"
|
||||
number: "555 0473"
|
||||
}
|
||||
}
|
||||
|
||||
delegate: Column {
|
||||
height: 32
|
||||
Text {
|
||||
text: name
|
||||
height: 16
|
||||
font.bold: true
|
||||
}
|
||||
Text {
|
||||
text: " id: " + id
|
||||
height: 16
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user